Wayland protocol only guarantees the delivery of modifier information after
the enter event. To handle it properly for keys pressed in the enter
event, save those keys for later processing in the modifier event.
This is required by the wayland protocol to keep the logical keyboard
state consistent.
Quoting 9e4f256927:
> In the wl_keyboard logical state, this event sets the active surface to
> the surface argument and the keys currently logically down to the keys
> in the keys argument.
The idle inhibit protocol specifies that the compositor may ignore the
idle inhibitor if the surface is occluded. In the case of
vo_dmabuf_wayland, wl->surface corresponds to typical black bars when
the video aspect ratio is different than the display's. So in many
cases, wl->surface is actually occluded by wl->video_surface which sits
above it. Change this so that the idle inhibitor is created on
wl->callback_surface instead which is either wl->surface for the gpu VOs
or wl->video_surface for vo_dmabuf_wayland. Fixes#14206.
If we get either preferred_scale or preferred_buffer_scale this early
during initialization the wl->scaling value should be immediately
updated instead of being deferred until later for correct geometry.
Fixes#14019.
The protocol strongly implies that this only happens when the value
changes, and it's also what you would naturally expect. But maybe it's
worth guarding this in cause for some reason the same value twice in a
row happens.
The mpv window overlapping multiple outputs with different scale values
can result in some weird behavior when dragging it from one monitor to
another one. This is due to the way some compositors implement
preferred_scale or preferred_buffer_scale (integer scale equivalent).
Depending on the scale values, mpv window has to be resized to match the
new scaling value (due to fractional scaling requiring a viewport). This
can cause the window to become smaller and no longer overlap the monitor
you were just trying to drag it to. Repeat this and the window will
become smaller and smaller. Depending on the layout, the reverse can
also happen (the window becomes larger). This can cause additional
events to fire as the preferred_scale value may change again which does
more weird things.
It seems kwin is not affected by this because their implementation of
preferred_scale sends the event only if the window is fully on the new
monitor. Honestly, this is probably more logical anyway but we should at
least deal with the other implementations better. Try to deal with it by
reworking scaling changes so they only occur when the mpv window is
fully on one monitor. If we get a preferred_scale event and there is an
overlap, save it as a pending change to be performed on the next
surface_enter or surface_leave event (whichever results in there being
only one monitor. Some weird rendering glitches can still happen during
overlap but this makes it usable again.
Previously if mpv's size was constrained by the compositor's configure
bounds event, there was no attempt to preserve the aspect ratio of the
given coordinates if --keepaspect (the default) was used. Be sure to
apply keepaspect to the bounded widths and heights if we are using this
event.
The reconfigure event handles setting fullscreen, maximize, etc. We were
implictly relying on the compositor to just ignore mpv if we set a
redundant state (e.g. setting fullscreen when we're already fullscreen),
but kwin actually doesn't and operates again. This causes some subtle
issues when handling geometry on state changes. Rework the state change
calls so they are only executed if wl->geometry_configured isn't set yet
(i.e. the window just opened up for the first time). It's the only time
this is actually needed.
If mpv is coming out of some locked size state (fullscreen, maximized,
tiled), the window size given by the reconfigure event should be used
assuming the --auto-window-size option is set.
Fixes 8a9749b8a5
At least on some compositors, when the pointer enters a surface,
only a wl_pointer_enter event is generated, but not wl_pointer_motion.
This results in the initial mouse position being lost, which is
especially problematic when input simulation is used.
Fix this by setting the mouse position on pointer enter event.
Currently mpv always uses the previous window size when unmaximizing
or exiting fullscreen. This disregards compositor's preferenced size in
the configure event, resulting in wrong window size if changing window
state and size are delivered in the same configure event.
It's better to always respect the preferenced size instead, unless
the state change is due to runtime geometry change, where we want
to use our preference.
In the xdg_toplevel_configure handler, in some cases the geometry is
not equal to the width and height in the event. This can happen
when runtime geometry change is requested (a new size is set),
or in the case of wl->state_change || width == 0 || height == 0
(the old size is used).
However, prepare_resize always uses the width and height in the event
and not the corrected geometry here. This causes
xdg_surface_set_window_geometry using the wrong value resulting in
wrong size of window decoration. Amusingly, the debug message right
above it uses the correct size.
Fix this by using the updated geometry size instead. Since now all
prepare_resize have parameters of 0, the width and height parameters
are no longer needed.
Fixes: 828dd65ef8
Segfaults otherwise on uninit because some objects are created while
others are not. Move it to the very top since the purpose of this is to
skip wayland initialization entirely while autoprobing.
Fixes f6f1721101.
Currently, Wayland is above X11 and DRM in probe order. The success
of automatic probing depends on the fact that unsuitable backends
would fail to initialize. For example, X11 backend (which uses Xlib)
fails to initialize if DISPLAY environment variable is not set, so
starting mpv in VT console will pick the DRM backend as expected,
even when an X server is running in another VT.
However, libwayland-client used by the Wayland backend has the
"helpful" behavior of falling back to "wayland-0" if WAYLAND_DISPLAY
is not set. This breaks autoprobing if mpv is started from X server
or VT console while a running Wayland compositor running in another
VT (or even running as an X client) is using "wayland-0" for protocol
socket name: mpv will start playing in the Wayland compsitor instead
of using the X11 or DRM backends.
Similar to DISPLAY for X server, We should consider exporting
WAYLAND_DISPLAY to child processes the responsibility of Wayland
compositors, and any compositor not doing this should be considered
broken. Thus we now require WAYLAND_DISPLAY to be set for the
backend initialization to succeed to make sure that autoprobing
works as intended.
This should only be a problem during initialization. If in a
multi-monitor setup, mpv guesses the wrong scale value and the user
passes --fs, the scaled size will be wrong and you have to unfullscreen
and fullscreen again to fix it. This is because rescale geometry won't
do anything if the value of hidpi-window-scale is false (the default) so
the geometry is never rescaled to the correct value thus the wrong size.
Normally, mpv will just correct itself after subsequent events occur but
because it is considered a locked size (as it should be), we avoid doing
any other resizing events thus it never gets corrected. Fix this by just
always rescaling the geometry in the locked size case. It shouldn't
matter elsewhere because mpv will always have the correct scale value
and the possibility of having the wrong one is only possible on startup.
Fixes ded181f642
c2129c18f8 saves the button down serial to
pointer_serial of the seat so that it can be used for window dragging
later. However, this overwrites the serial saved at the enter event.
Since the serial in wl_pointer_set_cursor must be the latest
wl_pointer_enter serial number sent to the client, if a button down
serial overwrites that, setting cursor no longer works until the cursor
enters the window next time.
Fix this by using separate serials for these two types of events.
It's been a longstanding issue in wayland* that the first frame on a
hidpi screen will have wrong scaling. A well behaved client immediately
corrects this, but it's noticeable and also can affect window placement
due to the way resizng works. Preferred scale from the fractional
protocol and preferred buffer scale can actually solve this problem. It
depends on compositors mostly, but one could simply send the event
before the client maps its surface so it knows what the correct scale is
in the first place. I'm not sure if any compositors currently behave
like this (sway seems to still require the client to render before
sending any scaling information at least), but it makes to sense to
account for this possibility.
*: https://gitlab.freedesktop.org/wayland/wayland/-/issues/133
Explicitly send an UP event after the client finishes a resize for
touch event, don't resize if locked_size is set for touch event,
and use the correct type for resize edges.
This allows begin-vo-dragging command to initialize a vo dragging request
for wayland. The last mouse button press seat and serial is used for the
request if it is not consumed by interactive resizing.
Not sure why all of these single line if's were being braced. Probably
some cargo cult from years ago but might as well fix it now since it's
bothering me.
Could have been done in e32554cd57, but I
skipped it there. However, using viewporter is actually a win here.
There's been a longstanding issue in upstream wayland* exactly related
to this. I even forgot about cd7a7a1de8
which was made for this exactly problem and explains the random
spawn_cursor calls. Anyways, just not using buffer scale and instead
scaling the cursor surface via viewporter works just fine and completely
sidesteps this problem. This means we can drop the random looking
spawn_cursor calls and some additional checks.
*: https://gitlab.freedesktop.org/wayland/wayland/-/issues/194
We don't want to use this if we have fractional scaling or version 6 of
the wl_surface interface which has a preferred buffer scale event which
is superior to this. We were checking in the important place (surface
entrance events) but not technically in the output. So just move the
conditional to set_surface_scaling itself. Also through the VO_EVENT_DPI
in there for convenience.
It's actually been like this for years, but wlroots doesn't keep track
of resizes a client does independent of the compositor. When using sway,
this leads to weird behavior with floating clients resizing themselves
back to the old size if you unfocus it. mpv has been working around this
for a long time, but it's really annoying to selectively ignore events
based on a weird heuristic. Since Sway finally fixed this bug, let's go
ahead and drop this crap. Note that other wlroots compositors may
possibly experience a regression if they didn't correct for this like
sway does, but it's for their own good.
This commit adds a DND_INSERT_NEXT action option for drag-and-drop,
allows for selecting it through the --drag-and-drop=insert-next option,
and adds the necessary plumbing to make that happen when something is
dragged onto the player.
Wayland was the only backend that attempted this, but it can be done in
a centralized place for anything that supports this. hidpi-window-scale
is just the same as a normal window scale but with the OS DPI as the
factor.
It's only necessary to check the existance of cursor_shape_manager.
Also drop the pointer check to handle multi-seat since a removed seat
sets the cursor_seat to NULL.
For VOCTRL_SET_CURSOR_VISIBILITY, set cursors visibility for all seats.
The return is VO_NOTAVAIL is none of the seats have cursor, and
VO_FALSE if setting visibility failed for at least one seat.
The cursor_shape_device is per pointer, which is per seat. Handle it
together with other seat objects. This in turn also handles cursor
visibility per seat.