Commit Graph

98 Commits

Author SHA1 Message Date
Dudemanguy 7ce26dd324 vo: move wayland presentation to separate files
Wayland had some specific code that it used for implementing the
presentation time protocol. It turns out that xorg's present extension
is extremely similar, so it would be silly to duplicate this whole mess
again. Factor this out to separate, independent code and introduce the
mp_present struct which is used for handling the ust/msc values and some
other associated values. Also, add in some helper functions so all the
dirty details live specifically in present_sync. The only
wayland-specific part is actually obtaining ust/msc values. Since only
wayland or xorg are expected to use this, add a conditional to the build
that only adds this file when either one of those are present.

You may observe that sbc is completely omitted. This field existed in
wayland, but was completely unused (presentation time doesn't return
this). Xorg's present extension also doesn't use this so just get rid of
it all together. The actual calculation is slightly altered so it is
correct for our purposes. We want to get the presentation event of the
last frame that was just occured (this function executes right after the
buffer swap). The adjustment is to just remove the vsync_duration
subtraction. Also, The overly-complicated queue approach is removed.
This has no actual use in practice (on wayland or xorg). Presentation
statistics are only ever used after the immediate preceding swap to
update vsync timings or thrown away.
2022-06-19 18:13:55 +00:00
Aaron Boxer 3536b53ed1 vo: move allocate_memfd method to wayland_common 2022-05-30 19:51:46 +00:00
Dudemanguy 38eda3804f vo_vaapi_wayland/wayland_common: code style fixes
A bad person (AKA me) merged this stuff without paying close enough
attention to the code style. Reformat this to be in-line with the rest
of the wayland code and general mpv style (braces for functions on the
next line, horizontally aligning arguments, some cosmetic cleanups for
wayland_common.h, etc.).
2022-05-30 19:51:46 +00:00
Aaron Boxer defb02daa4 vo: add new vaapi-wayland driver
This driver makes use of dmabuffer and viewporter interfaces
to enable efficient display of vaapi surfaces, avoiding
any unnecessary colour space conversion, and avoiding scaling
or colour conversion using GPU shader resources.
2022-05-24 21:39:34 +00:00
Dudemanguy 2c2a856f25 wayland: unify visibility checking code
A bit of a personal pet peeve. vulkan, opengl, and wlshm all had
different methods for doing wayland's "check for visibility before
drawing" thing. The specific backend doesn't matter in this case and the
logic should all be shared. Additionally, the external swapchain that
the opengl code on wayland uses is done away with and it instead copies
vulkan by using a param. This keeps things looking more uniform across
backends and also makes it easier to extend to other platforms (see the
next couple of commits).
2022-04-11 18:14:22 +00:00
Dudemanguy f5d545c917 wayland: remove bogus scale_change variable
This was originally added in f2afae55e9
for unclear reasons (way to go me). This concept is clearly incorrect.
It doesn't matter what state the window is in. As soon as mpv detects a
scale change, it needs to reset the buffer scale of the window. Just
remove all this junk and put wl_surface_set_buffer_scale in
set_surface_scaling like it should be. Related issue: #9426.
2021-11-08 09:49:49 -06:00
Dudemanguy 2d348980cb wayland: further xdg-decoration/border refinements
The value of the border option should always match what the actual state
of the window is. Previously if a compositor rejected the request by
mpv, it did not correct itself. Also add some code to keep track of
decoration requests. Anytime the state is changed, make the last saved
request again (doesn't hurt and seems like intuitive behavior).
Unfortunately, this isn't foolproof since options only send callback if
the value is changed. (ex. on sway if the floating window has no border,
and then is titled, setting the border value to "yes" does nothing since
tiling the window already set the border value to "yes").
2021-09-28 16:54:09 +00:00
Dudemanguy 8300830951 wayland: improve behavior with touch events
There's currently some touch related code in mpv wayland, but clearly
nobody actually uses because it's a broken mess. Initially an attempt to
distinguish between two finger touches and one finger touch was made,
but there's not a good way to make this work. For whatever reason,
initiating either xdg_toplevel_resize or xdg_toplevel_move blocks any
other touch events from occurring (at least in plasma). Trying to call
these functions anywhere else is not really useful since the serial will
be invalid outside of the touch down events (well it would work in the
touch up event but that's just silly).

Anyways, let's just make this work sanely. Eliminate the touch entries
variable completely because it's pointless. Only one finger event is
ever considered at a time. Touches besides the initial one are all
ignored. If a user touches and drags within the touch edge radius, then
a resize event occurs. If the user touches and drags elsewhere on the
window, a move event occurs. A single tap displays the osc (which is
clickable if you tap again). A double tap toggles fullscreen.
Additionally, the default touch edge radius of 64 pixels is way too big
(at least I think so). Cut this in half to 32 which feels a lot better
(on a pinephone using plasma mobile anyway).
2021-08-08 03:42:26 +00:00
Dudemanguy 19c4ae004a wayland: keep track of toplevel width/height again
Regression from 24357cb. It's ugly but unfortunately keeping tracking of
the last toplevel width and height really is the best way to solve this
problem and removing it was a mistake. Compositors don't always send
width/height coordinates of the actual window. The easiest way to
trigger this is by changing window-scale/current-window-scale and then
unfocusing the window. The compositor will send another toplevel
configure event with coordinates of the window before the resize. Maybe
compositors could be smarter but multiple ones do this (sway, gnome,
plasma), so just keep the old workaround. The only difference this time
is that the toplevel width/height is saved at the very beginning which
also covers the case where it equals 0 (i.e. weston).
2021-08-06 11:53:59 -05:00
Dudemanguy 24357cb7b5 wayland: cleanup handle_toplevel_config
The source of many geometry woes. There's some loosely related toplevel
things that should be cleaned up/fixed. First of all,
VO_EVENT_LIVE_RESIZING is actually completely useless. It might have
been useful sometime in the past, but there's no point. It doesn't
"speed up" resizing in any way and appears to be originally for cocoa.
Just remove it.

Way back in the day, toplevel_width/height was added as a workaround for
when we got uncoorperative (i.e. wrong) width/height coordinates from
the compositor in this event. Basically it could happen due to numerous
reasons but a lack of atomic commits was part of the reason and also
mpv's geometry handling then was a lot rougher. We *shouldn't* need this
workaround anymore. The width/height values are only used exactly when
we need them. If mpv sets geometry on its own, it should still be the
right dimensions.

Related to the above, mpv never actually propertly handled the case
where width or height was equal to 0. According to the xdg-shell spec,
"If the width or height arguments are zero, it means the client should
decided its own window dimension." An example of a compositor doing this
is weston. It's, unsurprisingly, broken. Getting out of fullscreen or a
maximized state does not restore the old window size like it should. The
right way to handle this is to just return near the end of the function
if we have a 0 for either argument and before any geometry is set
(wl->geometry's width or height can never be zero). Luckily, state
changes are already being detected so they just trigger the goto when
needed.

Finally, e2c24ad mistakenly removed the VO_EVENT_EXPOSE. There are edge
cases where this is needed and it's safer to just force a redraw here
when the window gets activated again. Just force wl->hidden to false
first and then trigger the expose.
2021-08-03 14:53:27 +00:00
Dudemanguy f2afae55e9 wayland: refactor surface scaling
Another day, another wayland refactor. Way back when, dcc3c2e added
support for the hidpi-window-scale option (something you probably should
never set to no but whatever) to wayland. Well technically, it never had
any runtime toggling support (don't remember if detecting when vo_opts
changed was possible or not then; maybe not). Anyways in the process of
fixing that, I went ahead and refactored how this is all handled. The
key difference is that when hidpi-window-scale is disabled, wl->scaling
is directly set to 1 instead of forcibly setting
wl->current_output->scale to 1. Note that scaling operations don't
always require a geometry reset/resize so set_surface_scaling needs to
be separate from set_geometry. The logic here is kind of complicated but
it (should) be correct.
2021-06-30 16:37:36 +00:00
Dudemanguy 76bddaccd6 wayland: always be sure to initially try to render
A subtle regression from c26d833. On sway if mpv was set to be a
floating window in the config, set_buffer_scale would actually get
applied twice according to the wayland log. That meant a 1920x1080
window would appear as a 960x540 window if the scale of the wl_output
was set to 2. This only affected egl on sway (didn't occur on weston and
was too lazy to try anything else; probably they were fine). Since
wl->render is initially false, that meant that the very first run
through the render loop returns false. This probably caused something
weird to happen with the set_buffer_scale calls (the egl window gets
created and everything but mpv doesn't write to it just yet) which makes
the set_buffer_scale call happen an extra time. Since it was always
intended for mpv to initally render, this is worth fixing. Just chnage
wl->render to wl->hidden (again) and flip the bools around. That way,
the initial false value results in render == true and mpv tries to draw
on the first pass. This fixes the weird scaling behavior because
reasons.
2021-06-27 10:58:42 -05:00
Dudemanguy 488581912d wayland: reorganize wayland common code
Mostly a cosmetic change that (hopefully) makes things look better. Some
functions and structs that were previously being exported in the wayland
header were made static to the wayland_common.c file (these shouldn't be
accessed by anyone else).
2021-06-26 17:24:44 -05:00
Dudemanguy c26d83348b wayland: shuffle around the render loop again
Take two. f4e89dd went wrong by moving vo_wayland_wait_frame before
start_frame was called. Whether or not this matters depends on the
compositor, but some weird things can happen. Basically, it's a
scheduling issue. vo_wayland_wait_frame queues all events and sends them
to the server to process (with no blocking if presentation time is
available). If mpv changes state while rendering (and this function is
called before every frame is drawn), then that event also gets
dispatched and sent to the compositor. This, in some cases, can cause
some funny behavior because the next frame gets attached to the surface
while the old buffer is getting released. It's safer to call this
function after the swap already happens and well before mpv calls its
next draw. There's no weird scheduling of events, and the compositor log
is more normal.

The second part of this is to fix some stuttering issues. This is mostly
just conjecture, but probably what was happening was this thing called
"composition". The easiest way to see this is to play a video on the
default audio sync mode (probably easiest to see on a typical 23.976
video). Have that in a window and float it over firefox (floating
windows are bloat on a tiling wm anyway). Then in firefox, do some short
bursts of smooth scrolling (likely uses egl). Some stutter in video
rendering could be observed, particularly in panning shots.

Compositors are supposed to prevent tearing so what likely was happening
was that the compositor was simply holding the buffer a wee bit longer
to make sure it happened in sync with the smooth scrolling. Because the
mpv code waits precisely on presentation time, the loop would timeout on
occasion instead of receiving the frame callback. This would then lead
to a skipped frame when rendering and thus causing stuttering.

The fix is simple: just only count consecutive timeouts as not receiving
frame callback. If a compositor holds the mpv buffer slightly longer to
avoid tearing, then we will definitely receive frame callback on the
next round of the render loop. This logic also appears to be sound for
plasma (funfact: Plasma always returns frame callback even when the
window is hidden. Not sure what's up with that, but luckily it doesn't
matter to us.), so get rid of the goofy 1/vblank_time thing and just
keep it a simple > 1 check.
2021-05-24 19:20:31 +00:00
Dudemanguy f4e89dde36 wayland: simplify render loop
This is actually a very nice simplification that should have been
thought of years ago (sue me). In a nutshell, the story with the
wayland code is that the frame callback and swap buffer behavior doesn't
fit very well with mpv's rendering loop. It's been refactored/changed
quite a few times over the years and works well enough but things could
be better. The current iteration works with an external swapchain to
check if we have frame callback before deciding whether or not to
render. This logic was implemented in both egl and vulkan.

This does have its warts however. There's some hidden state detection
logic which works but is kind of ugly. Since wayland doesn't allow
clients to know if they are actually visible (questionable but
whatever), you can just reasonably assume that if a bunch of callbacks
are missed in a row, you're probably not visible. That's fine, but it is
indeed less than ideal since the threshold is basically entirely
arbitrary and mpv does do a few wasteful renders before it decides that
the window is actually hidden.

The biggest urk in the vo_wayland_wait_frame is the use of
wl_display_roundtrip. Wayland developers would probably be offended by
the way mpv abuses that function, but essentially it was a way to have
semi-blocking behavior needed for display-resample to work. Since the
swap interval must be 0 on wayland (otherwise it will block the entire
player's rendering loop), we need some other way to wait on vsync. The
idea here was to dispatch and poll a bunch of wayland events, wait (with
a timeout) until we get frame callback, and then wait for the compositor
to process it. That pretty much perfectly waits on vsync and lets us
keep all the good timings and all that jazz that we want for mpv. The
problem is that wl_display_roundtrip is conceptually a bad function. It
can internally call wl_display_dispatch which in certain instances,
empty event queue, will block forever. Now strictly speaking, this
probably will never, ever happen (once I was able to to trigger it by
hardcoding an error into a compositor), but ideally
vo_wayland_wait_frame should never infinitely block and stall the
player. Unfortunately, removing that function always lead to problems
with timings and unsteady vsync intervals so it survived many refactors.

Until now, of course. In wayland, the ideal is to never do wasteful
rendering (i.e. don't render if the window isn't visible). Instead of
wrestling around with hidden states and possible missed vblanks, let's
rearrange the wayland rendering logic so we only ever draw a frame when
the frame callback is returned to use (within a reasonable timeout to
avoid blocking forever).

This slight rearrangement of the wait allows for several simplifications
to be made. Namely, wl_display_roundtrip stops being needed. Instead, we
can rely entirely on totally nonblocking calls (dispatch_pending, flush,
and so on). We still need to poll the fd here to actually get the frame
callback event from the compositor, but there's no longer any reason to
do extra waiting. As soon as we get the callback, we immediately draw.
This works quite well and has stable vsync (display-resample and audio).
Additionally, all of the logic about hidden states is no longer needed.
If vo_wayland_wait_frame times out, it's okay to assume immediately that
the window is not visible and skip rendering.

Unfortunately, there's one limitation on this new approach. It will only
work correctly if the compositor implements presentation time. That
means a reduced version of the old way still has to be carried around in
vo_wayland_wait_frame. So if the compositor has no presentation time,
then we are forced to use wl_display_roundtrip and juggle some funny
assumptions about whether or not the window is hidden or not. Plasma is
the only real notable compositor without presentation time at this stage
so perhaps this "legacy" mechanism could be removed in the future.
2021-05-22 00:59:56 +00:00
Dudemanguy 2a1a092bc9 wayland: workaround hidden state detection badness
The wayland code uses a heuristic to determine whether or not the mpv
window is hidden since the xdg-shell protocol does not provide a way for
a client to directly know this. We don't render with the frame callback
function for various, complicated reasons but the tl;dr is that it
doesn't work well with mpv's core (maybe an essay should be written on
this one day).

Currently, the aforementioned heuristic considers a window hidden if we
miss more frames in a row than the display's current refresh rate
(completely arbitrary number). However, the wayland protocol does allow
for the display's refresh rate to be 0 in certain cases (like a virtual
output). This completely wrecks the heuristic and basically causes only
every other frame to be rendered (real world example: nested sway
sessions).

Instead let's slightly redesign this mechanism to be a little smarter.
For coming up with the vblank time (to predict when to timeout on the
wait function), instead use the vsync interval calculated using
presentation time. That is the most accurate measure available. If that
number is not available/invalid, then we try to use the vsync interval
predicted by the presentation event.

If we still don't have that (i.e. no presentation time supported by the
compositor), we can instead use the old way of using the expected vsync
interval from the display's reported refresh rate. If somehow we still
do not have a usable number, then just give up and makeup shit. Note
that at this point we could technically ask the vo for the estimated
vsync jitter, but that would involve locking/unlocking vo which sounds
horrifying. Ideally, you never reach here.

See https://github.com/swaywm/wlroots/issues/2566 for the actual target
of this fix. wlroots uses presentation time so in practice we are mostly
just using that calculated vsync interval number.
2021-04-18 16:45:40 +00:00
Dudemanguy bff5416dae wayland: remove unused function declaration
It looks this line was added over 3 years ago, but said function never
actually existed or was used. Funny stuff.
2020-12-13 18:30:19 -06:00
Dudemanguy cf00b0b990 wayland: check for modifier keys on pointer events
The pointer button event had no code to handle any modifier keys. So
this meant input combinations like Shift+MTBN_LEFT did not work. Fix
this by ripping out the modifier-checking code in keyboard key event to
a separate function and using it for both the keyboard and mouse events.
In the case of the mouse, it is possible that the keyboard may not exist
so be sure to check before trying to get any modifiers. Fixes #8239.
2020-11-08 15:59:09 +00:00
Dudemanguy b60545bdc6 wayland: update opaque region on runtime
Made possible with 00b9c81. 34b8adc let the wayland surface set an
opaque region depending on if alpha was set by the user or not. However,
there was no attempted detection for runtime changes and it is possible
(at least in wayland vulkan) to toggle the alpha on and off. So this
meant, we could be incorrectly signalling an opaque region if the user
happened to change the alpha. Additionally, add a helper function for
this and use it everywhere we want to set the opaque region.
2020-10-15 13:43:45 +00:00
Dudemanguy deaea70630 wayland: be less strict about when to render
efb0c5c changed the rendering logic of mpv on wayland and made it skip
rendering when it did not receive frame callback in time. The idea was
to skip rendering when the surface was hidden and be less wasteful. This
unfortunately had issues in certain instances where a frame callback
could be missed (but the window was still in view) due to imprecise
rendering (like the default audio video-sync mode). This would lead to
the video appearing to stutter since mpv would skip rendering in those
cases.

To account for this case, simply re-add an old heuristic for detecting
if a window is hidden or not since the goal is to simply not render when
a window is hidden. If the wait on the frame callback times out enough
times in a row, then we consider the window hidden and thus begin to
skip rendering then. The actual threshold to consider a surface as
hidden is completely arbitrary (greater than your monitor's refresh
rate), but it's safe enough since realistically you're not going to miss
60+ frame callbacks in a row unless the surface actually is hidden.
Fixes #8169.
2020-10-15 13:36:49 +00:00
Dudemanguy 5dc16a4a18 Revert "wayland: add wayland-display-socket option"
Pointless feature that can be done with environment variables. It was
also implemented incorrectly and broke autoprobing.

This reverts commit 015b676875.
2020-10-07 08:41:47 -05:00
Dudemanguy 015b676875 wayland: add wayland-display-socket option
As per the client API, a client can connect to any arbitrary wayland
socket. mpv has always just passed NULL which connected to the
compositor currently in use, but one could just as easily pass the name
of a different socket (i.e. the value of WAYLAND_DISPLAY). Here, we just
expose this argument as a user configurable option. If the user passes a
socket name that does not exist, then print a warning and fall back to
NULL.
2020-10-06 17:45:59 +00:00
Dudemanguy efb0c5c446 wayland: only render if we have frame callback
Back in the olden days, mpv's wayland backend was driven by the frame
callback. This had several issues and was removed in favor of the
current approach which allowed some advanced features (like
display-resample and presentation time) to actually work properly.
However as a consequence, it meant that mpv always rendered, even if the
surface was hidden. Wayland people consider this "wasteful" (and well
they aren't wrong). This commit aims to avoid wasteful rendering by
doing some additional checks in the swapchain. There's three main parts
to this.

1. Wayland EGL now uses an external swapchain (like the drm context).
Before we start a new frame, we check to see if we are waiting on a
callback from the compositor. If there is no wait, then go ahead and
proceed to render the frame, swap buffers, and then initiate
vo_wayland_wait_frame to poll (with a timeout) for the next potential
callback. If we are still waiting on callback from the compositor when
starting a new frame, then we simple skip rendering it entirely until
the surface comes back into view.

2. Wayland on vulkan has essentially the same approach although the
details are a little different. The ra_vk_ctx does not have support for
an external swapchain and although such a mechanism could theoretically
be added, it doesn't make much sense with libplacebo. Instead,
start_frame was added as a param and used to check for callback.

3. For wlshm, it's simply a matter of adding frame callback to it,
leveraging vo_wayland_wait_frame, and using the frame callback value to
whether or not to draw the image.
2020-09-21 20:42:17 +00:00
Guido Cella 9b9ce74afa command: add read-only focused property
Add a property that returns whether the window is focused, currently
only for X11 and Wayland.

My use cause for this is having an equivalent of pause-when-minimize.lua
for tiling window managers: make mpv play only while it's in the current
workspace or is focused (I'm fine with either one but prefer focus).
On X I do this by observing display-names, which is empty when the
rectangles of the display and mpv don't intersect, but on Wayland its
value doesn't change when mpv leaves the current workspace (and the same
check doesn't work since the geometries still intersect).

This could later be made writable as requested in #6252.

Note that on Wayland se shouldn't consider an unactivated window with
keyboard input focused.

The wlroots compositors I tested set activated after changing the
keyboard focus, so if you set wl->focused only in
keyboard_handle_enter() and keyboard_handle_leave() to avoid adding the
"has_keyboard_input" member, focused isn't set to true when first
opening mpv until you focus another window and focus mpv again.

Conversely, if that order can't be assumed for all compositors, we
should toggle wl->focused when necessary in keyboard_handle_enter() and
keyboard_handle_leave() as well as in handle_toplevel_config().
2020-09-08 20:09:17 +02:00
Dudemanguy b0f0be7678 wayland: simplify presentation time
Why on earth did I ever bother with this dumb crap? If we do not have
any presentation statistics, just set the relevant vo_sync_info values
to -1 to disable it. It's much simpler than using mp deltas and trying
to keep up with mpv's clock. This also appears to fix audio/video
desynchronization if you start a video with the pause flag, move it out
of view, and then unpause it. Technically harmless since the video
wasn't even in view and putting back in view recovered it, but a quieter
terminal is better.
2020-08-22 20:43:49 +00:00
Dudemanguy db0f9fab67 wayland: refactor geometry/window handling
The original goal was to simplify all this logic to make it less fragile
and breaky. Unfortunately, that didn't exactly happen and things might
actually be more complicated in some ways (well in other ways it's
simplier). There's a lot of negotiation back and forth between the
client and the compositor regarding sizes. The client (aka mpv) can do a
resize on its own. But also the compositor can request its own resize
(which we should be nice and listen to of course). The older method had
a lot of breakfalls/edgecases that were gradually patched up as time
went on, but that approach is really fragile. This refactor should,
hopefully, be on a more solid foundation.

Don't call any of the xdg toplevel state changing functions
(fullscreen, maximized, etc.) directly. Use the toggle wrapper
functions. These signal that the state was changed which is later
handled in the toplevel listener.

Introduce a new vdparams variable that stores the actual dimensions of
the video. This does create some new (but neccesary) complexity.
wl->vdparams stores what the actual dimensions of the video are
(according to mpv). wl->window_size stores the last size of the window
(so it includes any manual resizes for instance). wl->geometry is the
actual size of the output that gets displayed on the screen.
2020-08-20 01:34:45 +00:00
Dudemanguy 486516f723 wayland: don't rely on presentation discarded
When using presentation time, we have to be sure to update the ust when
no presentation events are received to make sure playback is still
smooth and in sync. Part of the recent presentation time refactor was to
use the presentation discarded event to signal that the window is
hidden. Evidently, this doesn't work the same everywhere for whatever
reason (drivers?? hardware??) and at least one user experienced issues
with playback getting out of sync since (presumably) the discarded event
didn't occur when hiding the window. Instead, let's just go back to the
old way of checking if the last_ust is equal to the ust value of the
last member in the wayland sync queue. Fixes #8010.
2020-08-16 16:29:00 -05:00
Dudemanguy e9cde72536 wayland: refactor presentation time
The motivation for this change was a segfault caused by e107342 which
has complicated reasons for occuring (i.e. I'm not 100% sure but I think
it is a really weird race). The major part of this commit is moving the
initialization of presentation listener to the frame_callback function.
Calling it in swap_buffers worked fine but in practice it meant a lot of
meaningless function calls if a window was hidden (the presentation
would just be immediately discarded). By calling it in frame_callback,
we ensure the listener is only created when it is possible to receive a
presentation event.

Of course calling the presentation listener in feedback_presented or
feedback_discarded was considered, but ultimately these events are too
slow. Receiving the ust/msc/sbc triplet here and then passing it to mpv
results in higher vsync judder since there is (likely) not enough time
before the next pageflip. By design, the frame callback is meant to give
us as much time as possible before the next repaint so calling it here
is probably optimal.

Additionally, we can make better use of the feedback_discarded event.
The wp_presentation_feedback should not be destroyed here. It will be
taken care of either when we get feedback again or when the player
quits. Instead what we can do is set a bool that tells wayland_sync_swap
to update itself based on mp_time delta. In practice, the result is not
any different than before, but it should be more understandable what is
going on now.

Of course, the segfault mentioned at the beginning is fixed with this as
well.
2020-08-16 18:34:09 +00:00
Dudemanguy fb55ee99e3 wayland: don't set mouse pos on state change
Sway 1.5 started sending more pointer motion events to mpv which broke
the autohiding behavior. The cursor would appear again if you
fullscreened. Sway had a good reason to do this because certain
applications had inconsistencies between hardware cursor and software
cursor without rebasing on state changes[1]. So mpv needs to take this
special case into consideration.

Initially, simply checking mouse coordinates for changes was considered,
but this doesn't work. All coordinates are surface-local in wayland so
something can appear to move in the local coordinate space but not
globally. You're not allowed to know global mouse coordinates in
wayland, and we don't care about local coordinate changes in mpv so this
approach isn't viable.

Instead, let's just keep track of a local state change. If the toplevel
surface changes in some way (fullscreen, maximized, etc.), then just set
a bool that lets us ignore the mp_input_set_mouse_pos function. This
keeps the cursor from appearing simply because the state was changed
(i.e. fullscreening). For compositors that don't send pointer motion
events on a state change, this does technically mean that the initial
mp_input_set_mouse_pos is never set. In practice, this isn't a
noticeable difference though because moving a mouse generates a ton of
motion events so you'll immediately see it on the second motion event.

[1] https://github.com/swaywm/sway/issues/5594
2020-08-02 17:06:51 -05:00
Dudemanguy c9742413ac wayland: remove unused declaration
Should have been removed in 055a490 but was forgetten.
2020-07-19 15:21:05 -05:00
Dudemanguy 055a490cef wayland: use mp_time deltas for presentation time
One not-so-nice hack in the wayland code is the assumption of when a
window is hidden (out of view from the compositor) and an arbitrary
delay for enabling/disabling the usage of presentation time. Since you
do not receive any presentation feedback when a window is hidden on
wayland (a feature or misfeature depending on who you ask), the ust is
updated based on the refresh_nsec statistic gathered from the previous
feedback event.

The flaw with this is that refresh_nsec basically just reports back the
display's refresh rate (1 / refresh_rate * 10^9). It doesn't tell you
how long the vsync interval really was. So as a video is left playing
out of view, the wl->last_queue_display_time becomes increasingly
inaccurate. This led to a vsync spike when bringing the mpv window back
into sight after it was hidden for a period of time. The hack for
working around this is to just wait a while before enabling presentation
time again. The discrepancy between the "bogus"
wl->last_queue_display_time and the actual value you get from the
feedback only happens initially after a switch. If you just discard
those values, you avoid the dramatic vsync spike.

It turns out that there's a smarter way to do this. Just use mp_time_us
deltas. The whole reason for these hacks is because
wl->last_queue_display_time wasn't close enough to how long it would
take for a frame to actually display if it wasn't hidden. Instead, mpv's
internal timer can be used, and the difference between wayland_sync_swap
calls is a close enough proxy for the vsync interval (certainly better
than using the monitor's refresh rate). This avoids the entire conundrum
of massive vsync spikes when bringing the player back into view, and it
means we can get rid of extra crap like wl->hidden.
2020-04-20 21:02:02 +00:00
Dudemanguy 83efdb5a01 wayland: make resizing better
Resizing the window while preserving the aspect ratio actually kind of
sucked. The window size could make big dramatic changes which was pretty
unintuitive with respect to where the mouse was actually located.
Instead, let's just do some math to ensure that the window size is
always contained inside the width/height reported by
handle_toplevel_config while preserving the aspect ratio. Fixes #7426.
2020-02-13 20:28:59 +00:00
Dudemanguy 2aaf531720 wayland: toplevel config fixes
There were a couple of erroneous things in the handle_toplevel_config
function. Firstly, looping through the different states was not handled
correctly. Launching a window as maximized (can happen in sway for
example) was always stuck on true and would never be set to false. Fix
this by always checking if XDG_TOPLEVEL_STATE_MAXIMIZED is found or not.
Also do a similar thing for the fullscreen state.

Additionally, there were some issues with resizing windows and
window-scale going back to old sizes. The root of this problem is that
the width and height arguments of handle_toplevel_config aren't actually
guarenteed to be the actual width and height of the surface. There are
times when mpv will set the surface size on its own (like with
window-scale) which will be unknown to the toplevel listener. To
complicate matters, there are times when we do want to use the width and
height arguments (like when resizing with the mouse).

Fix this by checking if the width and height arguments reported by
handle_toplevel_config changed from the previous call of the function.
If the value is different, then we go ahead and use them when setting
mpv's geometry. If not, then we just ignore it.
2020-02-06 16:17:25 +00:00
dudemanguy b926f18938 wayland: remove wayland-frame-wait-offset option
This originally existed as a hack for weston. In certain scenarios, a
frame taking too long to render would cause vo_wayland_wait_frame to
timeout which would result in a ton of dropped frames. The naive
solution was to just to add a slight delay to the time value. If a
frame took too long, it would likely to fall under the timeout value and
all was well. This was exposed to the user since the default delay
(1000) was completely arbitrary.

However with presentation time, this doesn't appear to be neccesary.
Fresh frames that take longer than the display's refresh rate (16.666 ms
in most cases) behave well in Weston. In the other two main compositors
without presentation time (GNOME and Plasma), they also do not
experience any ill effects. It's better not to overcomplicate things, so
this "feature" can be removed now.
2020-01-31 00:40:44 +00:00
dudemanguy 7f300a00e9 wayland: fix cursor behavior on an edge case
This small regression was introduced by #7216. Previously, the wayland
backend used a trick which kept track of the previous fullscreen state
and used that logic for showing the cursor. Since vo_opts now keeps
track of the current fullscreen state, most of this stopped being
neccessary.

However, there was one edge case where the cursor didn't
behave the same: passing a fullscreen flag for the inital window. The
cursor would initially be visible here which is not desirable. This can
be remedied pretty easily by just setting the cursor visiblity to false
if the pointer entry event occurs on fullscreen. The only thing we need
to do is to make sure that the autohide delay isn't completely disabled
(i.e. the cursor is always visible). Hence the need for the previous
commit.
2019-12-04 00:47:05 +00:00
Philip Langdale b6f605285c wayland: update remaining legacy VOCTRL usage to options
The remaining legacy VOCTRLs are for the fullscreen and border
properties. For fullscreen this largely just replacing the private
state field with the vo option but there are small semantic
differences that we need to be careful of.

For the border setting, it's trivial as we don't have external
mechanisms for changing the state, but I also can't test it as
I'm not using a compositor that supports it.
2019-12-02 14:14:09 +00:00
Philip Langdale 61b8e1d436 wayland: update Maximize and Minimize handling to use new options
I wanted to get this done quickly as I introduced the new VOCTRL
behaviour for minimize and maximize and it was immediately made
legacy, so best to purge it before anyone gets confused.

I did not sort out fullscreen as that's more involved and not something
I've educated myself about yet. But I did replace the VOCTRL_FULLSCREEN
usage with the new option change mechanism as that seemed simple
enough.
2019-12-01 09:39:51 +08:00
Philip Langdale 5e3eb03ecf wayland: make the edge grab zone width user configurable
Rather than hard-coding the edge grab zone width, we can make it
user configurable. It seems worthwhile to have separate configs
for pointer and touch usage as the defaults should be different,
and a user might have both input methods in use.
2019-11-29 16:56:20 +08:00
Philip Langdale 4c179a27c2 wayland: add grab zone for resizing window with mouse
Today, we support resizing wayland windows when we detect a touch
event in a defined grab zone. As part of implementing
pseudo-decorations, we should have equivalent functionality for
mouse input. And if we detect support for actual decorations we
will not activate the grab zone as the decorations will provide this.
2019-11-29 16:56:20 +08:00
Dudemanguy911 9dead2b932 wayland: fix presentation time
There's 2 stupid things here that need to be fixed. First of all,
vulkan wasn't actually using presentation time because somehow the
get_vsync function in context.c disappeared. Secondly, if the mpv window
was hidden it was updating the ust time based on the refresh_usec but
really it should simply just not feed any information to the vsync info
structure. So this adds some logic to assume whether or not a window is
hidden.
2019-10-20 19:50:10 +00:00
dudemanguy 027ca4fb85 wayland: add various render-related options
The newest wayland changes have some new logic that make sense to expose
to users as configurable options.
2019-10-20 15:34:57 +00:00
dudemanguy bedca07a02 wayland: add presentation time
Use ust/msc/refresh values from wayland's presentation time in mpv's
ra_swapchain_fns.get_vsync for the wayland contexts.
2019-10-20 15:34:57 +00:00
dudemanguy ea4685b233 wayland: use callback flag + poll for buffer swap
The old way of using wayland in mpv relied on an external renderloop for
semi-accurate timings. This had multiple issues though. Display sync
would break whenever the window was hidden (since the frame callback
stopped being executed) which was really annoying. Also the entire
external renderloop logic was kind of fragile and didn't play well with
mpv's internal structure (i.e. using presentation time in that old
paradigm breaks stats.lua).

Basically the problem is that swap buffers blocks on wayland which is
crap whenever you hide the mpv window since it looks up the entire
player. So you have to make swap buffers not block, but this has a
different problem. Timings will be terrible if you use the unblocked
swap buffers call.

Based on some discussion in #wayland, the trick here is relatively
simple and works well enough for our purposes. Instead we basically
build a way to block with a timeout in the wayland buffer swap
functions.

A bool is set in the frame callback function that indicates whether or
not mpv is waiting for a frame to be displayed. In the actual buffer
swap function, we enter into a while loop waiting for this flag to be
set. At the same time, the wl_display is polled to block the thread and
wakeup if it receives any events from the compositor. This loop only
breaks if enough time has passed or if the frame callback bool is
received.

In the near future, it is better to set whether or not frame a frame has
been displayed in the presentation feedback. However as a first pass,
doing it in the frame callback is more than good enough.

The "downside" is that we render frames that aren't actually shown on
screen when the player is hidden (it seems like wayland people don't
like that). But who cares. Accurate timings are way more important. It's
probably not too hard to add that behavior back in the player though.
2019-10-10 17:41:19 +00:00
dudemanguy cdad5cc65f wayland: don't show cursor when fullscreening 2019-09-21 15:24:06 +02:00
Thomas Weißschuh 9e304ab974 wayland: reconfigure cursor on pointer enter event
On wayland the cursor has to be configured each time the pointer enters.
Currently if the window (re)gains the focus, the pointer is not hidden,
even when configured. After the mouse has been moved the pointer hides
correctly.

https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_pointer:

    wl_pointer::enter - enter event

    ...

    When a seat's focus enters a surface, the pointer image is undefined
    and a client should respond to this event by setting an appropriate
    pointer image with the set_cursor request.

Fixes #6185.

Signed-off-by: Thomas Weißschuh <thomas@t-8ch.de>
2019-09-21 15:24:06 +02:00
Emmanuel Gil Peyrot 36600ff163 wayland_common: rename “shell” into “wm_base”
This is the naming xdg-shell stable adopted, it doesn’t make much sense
to keep using “shell” everywhere with all functions calling it
“wm_base”.

Finishes what 76211609e3 started.
2019-02-17 23:44:34 +02:00
emersion 95589fd4f8 wayland: remove KDE server-decoration support 2018-11-19 00:15:31 +02:00
emersion 6d2be82094 wayland: use xdg-decoration if available 2018-11-19 00:15:31 +02:00
Rostislav Pehlivanov 43d575616c wayland_common: fix maximized state
Window size should not change if the window has been maximized or tiled.
2018-05-20 02:48:23 +03:00
Emmanuel Gil Peyrot 76211609e3 wayland_common: update to stable xdg-shell
This removes support for older compositors using the unstable version,
but those will still use Xwayland by default, so not a big loss.
2018-04-29 12:33:12 +03:00