summaryrefslogtreecommitdiffstats
path: root/video/out/wayland_common.c
Commit message (Collapse)AuthorAgeFilesLines
* wayland: always resize when scale changes on surface enterDudemanguy2022-01-271-0/+1
| | | | | | | | | | | | a02901cae77c86fb9de997a418296d1fc0e3eada changed how mpv was handling wl_surface_set_buffer_scale. It's correct in that constantly setting the surface scale on every resize (which mpv was previously doing) is unneccessary and not right. However, it introduced a slight regression if someone moved a surface to a new monitor with the same resolution but a different scale. It did not trigger a resize and thus the video would have incorrect dimensions. A later refactor changed how things looked inside here, but this regression wasn't fixed. A resize should always be triggered if the scale changes in this surface event. Fixes #9426.
* wayland: support extra mouse buttonsRyan Hendrickson2022-01-281-18/+22
| | | | | | | | | | | | | Mouse button event codes above `BTN_EXTRA` (the ones currently defined in `input-event-codes.h` are `BTN_FORWARD`, `BTN_BACK`, and `BTN_TASK`) are mapped to `MP_MBTN9` and up. (Reminder that due to historical reasons, the names `BTN_FORWARD` and `BTN_BACK` are completely misleading; the real forward and back buttons are `BTN_SIDE` and `BTN_EXTRA` and are already mapped correctly by mpv.) This functionality is analogous to what the X11 backend supports in `video/out/x11_common.c` and what the Cocoa backend supports in `video/out/cocoa/events_view.m`.
* wayland: actually handle 0x0 resizes correctlyDudemanguy2022-01-271-0/+8
| | | | | | | | | | | According to the xdg-shell protocol spec, a 0x0 size from the compositor means that "the client should decide its own window dimension". We were not doing this correctly. What should happen is that mpv should simply reuse the old window size if it is not maximized or fullscreened. This should work on all (reasonably recent) versions of mutter and an compositor that follows the spec. https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/main/stable/xdg-shell/xdg-shell.xml#L1050
* Revert "wayland: ignore 0x0 resizes"Dudemanguy2022-01-271-3/+2
| | | | | | | | | | | | | | | So actually according to the xdg-shell spec, a 0x0 resize is meant to indicate that "the client should decide its own window dimension". Previously, this just accidentally worked. In mutter 41.3, they changed how 0x0 resizes were sent and what actually happened was that mpv tried to resize itself to 0x0. This was obviously broken, so the reverted commit naively just ignored 0x0. It actually seemed to work, but it ended up breaking older versions of mutter. It's also not exactly the correct fix so it deserves a revert. This reverts commit d16defac27fcfe3e5fc43af6e42c2e590988cd3d. https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/main/stable/xdg-shell/xdg-shell.xml#L1050
* wayland: sanitize toplevel title to UTF-8Dudemanguy2022-01-241-1/+5
| | | | | | | The xdg-shell protocol requires that the toplevel title is UTF-8*. Go ahead and leverage existing mpv tools to sanitize the title. Fixes #9694 *: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/0aaf12157ede8fdf6eda49963da313bd1a7d930f/stable/xdg-shell/xdg-shell.xml#L638
* wayland: ignore 0x0 resizesDudemanguy2022-01-231-2/+3
| | | | | | | | | Apparently mutter can send us 0x0 resizes* for whatever reason. Probably there's some interal reason why this occurs, but for us trying to resize to 0x0 is obviously terrible and results in all kinds of brokenness. Just ignore any 0 values. Fixes #9748. *: https://gitlab.gnome.org/GNOME/mutter/-/issues/2091
* wayland: use `xkb_keymap_new_from_buffer`Julian Orth2022-01-081-1/+2
| | | | | | | | | | | Instead of `xkb_keymap_new_from_string`. The protocol does not require the keymap to be null terminated and if the size of the keymap is a multiple of the page size, using `_from_string` could lead to problems. Some compositors include a null byte and even include the null byte in `size`. Therefore we have to use `strnlen` to find the real length of the string. Note that `_from_string` internally uses `strlen` and then calls `_from_buffer`.
* wayland: map keymaps with `MAP_PRIVATE`Julian Orth2022-01-081-1/+1
| | | | | | | | | | While mpv uses version 1 of the `wl_seat` protocol and `MAP_PRIVATE` is only required from version 7 on, using `MAP_PRIVATE` allows us to be compatible with compositors that have only been tested with newer applications. Since the keymap is not modified after `mmap`, using `MAP_SHARED` has no advantage over `MAP_PRIVATE`.
* wayland: avoid doing unneccesary window resizesDudemanguy2021-12-201-7/+0
| | | | | | | | | | | | | | | | | Commits 04018c306196888861775b248a8596ae494f122b cd7a7a1de8d8bffa05170befef25b251711c994a introduced behavior that updated window geometry during wayland events (specifically surface and output). This is good but they also are too aggressive with automatically resizing. For example, if a window is manually resized by the user and then dragged to a different monitor with different geometry than the initial monitor, mpv will automatically resize itself to the window's resolution. The initial thought behind this logic was for autofit to automatically readjust itself on a new monitor, but doing that breaks other common use cases. An attempt could be made to distinguish between autofit and a manual resize but that introduces a lot of complexity for an edge case. It's better to simply not change the window geometry here. Internal values are recalculated and scaled of course, but wl->window_size and wl->geometry should not change.
* wayland: increase the vblank waiting timeDudemanguy2021-11-251-0/+2
| | | | | | | | | | | This commit sucks bad, but everything else is worse is other ways. Basically, the current vblank waiting time in the vo_wayland_wait_frame function (calculated very carefully using presentation statistics) is randomly too short. Some compositors are quite variable when they actually return callback so our timeout expires too quickly and throws everything off. The fix? Add an arbitrary 5% to the vblank value and pray that nothing gets off that much. Why did they have to make swapinterval 1/fifo mode indefinitely block? Fixes #9504.
* wayland: initialize presentation time values as 0Dudemanguy2021-11-241-0/+3
| | | | | | | Better to avoid any wonky calculations on startup with garbage values. The others end up being derived from last_ust/last_msc. refresh_interval is referenced exactly once and could, in theory, result in some terribly erroneous vblank time.
* wayland: cancel prepared reads when no eventsKurt Kartaltepe2021-11-251-6/+8
| | | | | | | | | | | | | A read can be prepared on the wayland display FD that is never actually read. This occurs when events are triggered on other FDs in the fd set. This change cancels a prepared read if poll reported no events for it. This fixes some hangs due to how nvidia's EGL implementation polls on the wayland fd unlike mesa implementations. It is based on nvidia's proposed fix for qt's similar message pump in https://codereview.qt-project.org/c/qt/qtwayland/+/373473 Signed-off-by: Kurt Kartaltepe <kkartaltepe@gmail.com>
* wayland: fix a potential segfault on surface enterDudemanguy2021-11-201-0/+3
| | | | | | | | | | | | | | | | | | This possibility actually existed for years. The wayland protocol is asynchronous and there's no restriction on when a compositor can send a surface enter event. In mpv's case, the surface enter event is used to set some vital things regarded geometry/scaling etc. However, this implictly assumes that wl->current_output is actually initialized. The vast majority of the time, vo_wayland_reconfig will happen first which is where wl->current_output is, and should, be created. There's no rule/law that the ordering of events will always occur in this order. Plasma with certain auto-profile conditions can send the surface enter event before mpv does its initial reconfig. That segfaults of course. Just add a check to make sure we have wl->current_output here and return if we don't. This assumes that the compositor will send us another surface enterance event when mpv actually does the initial surface commit and roundtrip request later. Wayland logs indicate this does happen. Fixes #9492.
* wayland: support modifiers during axis eventsDudemanguy2021-11-201-4/+5
| | | | | | It was never implemented before but it's trivial. As an aside, touch events currently don't support modifiers either (is this a thing?). Well if someone complains that can be done later. Fixes #9490.
* wayland: remove bogus scale_change variableDudemanguy2021-11-081-23/+1
| | | | | | | | | This was originally added in f2afae55e95b4b1eec1aeb828ba6ff1f0695d993 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.
* player: fix autofit/geometry related segfaultDudemanguy2021-11-031-5/+8
| | | | | | | | | | | | | | | | | | | | | | | Back when runtime updating of autofit/geometry was added for wayland and x11 (commits: 4445ac828dca0298543103094357e64f8828ef56 and ced92ba607ebd98687b26ef3d8c09d5f6e22cf4b respectively), the naive assumption was that window-related geometry would always be available. While this is true 99% of the time, this isn't a guarentee. It is possible for certain things such as loading shaders to delay starting up the player. This causes autofit/geometry options to be registered as a runtime update and triggers VOCTRL_VO_OPTS_CHANGED. This ends up calling some geometry-related functions but this happens before the actual values are available. Hence, a nullptr was accessed which segfaults. At least one user experienced this with a combination of options in wayland but in theory the same thing could happen under x11. The fix is simple. Just be sure to check that the required geometry is available before doing any calculations. In wayland, this would be wl->current_output. Additionally add an assert to set_geometry (we should never use this function without wl->current_output) to be extra sure. In x11, the check is on x11->window. Later when the reconfig for each backend actually happens, the autofit/geometry set by the user happens anyway so ignoring it in this case does no harm. Fixes #9381.
* wayland: remove incorrect keepaspect checkDudemanguy2021-10-261-2/+1
| | | | | | | | | | | In the reconfig event, the keepaspect option was checked before setting the window_size geometry to the new params obtained from the vo. This is incorrect. If a user disabled keepaspect on wayland, the video's size would not change on a reconfigure event (i.e. loading a new video in the playlist with a different size). No other windowing backend (x11, win32, etc.) behaves like this or uses keepaspect in its code like wayland did in this case. Clearly, this is not correct. Such functionality should be handled by a separate option entirely. Just remove this if statement.
* wayland: further xdg-decoration/border refinementsDudemanguy2021-09-281-26/+39
| | | | | | | | | | | | 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").
* wayland: report correct window size when maximizedDudemanguy2021-09-131-2/+7
| | | | | | | | | In wayland_common, wl->window_size keeps track of the window's size when it is not in the fullscreen or maximized state. GET_UNFS_WINDOW_SIZE is meant to report the size except for when it is fullscreen (hence UNFS). However, the actual function was merely returning the wl->window_size so it was wrong for maximized windows. Workaround this by returning wl->geometry instead when we have the maximized case. Fixes #9207.
* wayland: set default cursor size to 24Ivan2021-08-281-1/+1
| | | | | Set it to 24 if it couldn't be read frome $XCURSOR_SIZE for some reason. Since it seems to be the default value for most distros/DE.
* wayland: read XCURSOR_THEME to get cursor themeIvan2021-08-281-1/+2
| | | | | Read $XCURSOR_THEME environment variable if set and if not then fall back to "default" (/usr/share/icons/default and ~/.icons/default)
* wayland: check for xkb state in handle modifiersDudemanguy2021-08-151-3/+4
| | | | | | | | | | | | | | | | | | Normally in wayland, you receive a keymap event from the compositor which is what allows the client to setup what is needed for xkb. However, it turns out that this doesn't occur in the case of virtual keyboards, such as from wtype, that come from the custom virtual-keyboard protocol. What happens in this case is that mpv only receives a keyboard entrance event. According to the wayland protocol documentation [1], "the compositor must send wl_keyboard.modifiers event after [the wl_keyboard.enter] event". It is possible for this to occur before the physical keyboard is properly mapped (i.e: using a virtual keyboard to start mpv). What this results in is a segfault once xkb_state_update_mask is called in the modifiers event. The fix is to simply not always assume we have created the xkb state if we get this event and check for its existence first. Closes #9119. https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_keyboard
* wayland: fix wrong opts structDudemanguy2021-08-101-1/+1
|
* wayland: request xdg-decoration mode on startupDudemanguy2021-08-101-0/+2
| | | | | | Right after the listener is constructed, request a mode based on the value of the border option. If border, then request SSD. If no border, request CSD. The decoration listener handles it from there.
* wayland: check for xdg-decoration on border updateDudemanguy2021-08-091-1/+1
| | | | | Oversight in 69c64f5. If there is no xdg_toplevel_decoration, don't attempt to set the mode.
* wayland: handle xdg-decoration protocol betterDudemanguy2021-08-091-9/+22
| | | | | | | | | | | | | | | | | | | | | The current usage of the xdg-decoration protocol is quite a bit crude. There's a specific listener struct for this like with most wayland things, but mpv wasn't even using it. It also made no attempt to detect if the compositor was telling mpv to use client side decorations. To implement this correctly, first of all we need to create the decoration listener object and add it like how most wayland things work. Secondly, set_border_decorations needs to be changed to accept the uint32_t mode given by the compositor. When we get the decoration event, pass the mode obtained from the compositor to set_border_decorations. Update the mpv border option, based on whether or not we have server side decorations (yes if we have them; no if we don't). mpv can actually request either client side or server side decorations with this protocol. This function doesn't belong in set_border_decorations but rather it should be called when the border option changes. Whether or not this request actually works depends on the compositor (Plasma appears to allow it; sway does not). If the compositor allows this request, then it gets handled by configure_decorations. Note that the enum strangely starts at 1 hence why there is an extra +1.
* wayland: fix keepaspect-window during resizeDudemanguy2021-08-081-9/+6
| | | | | | | | | | | | So the resizing mechanism is actually supposed to match the video size to the window size while preserving the aspect ratio. In wayland, the current logic behaves as if --no-keepaspect-window was set. Fix this by simply multiplying the height by the same scale factor the width is multiplied by. Also get rid of the pointless (width > height) test (it makes no difference in any case) as well as some unneccesary checks for the keepaspect-window option. The use of ceil here is to make sure the window coordinates can never possibly have be 0 due to truncation (weston can still give you a 1x1 window which is fun). Fixes #9098.
* wayland: improve behavior with touch eventsDudemanguy2021-08-081-18/+9
| | | | | | | | | | | | | | | | | | | | | | | 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).
* wayland: correct window-scale behaviorDudemanguy2021-08-071-3/+10
| | | | | | | | | | | | | | The way the window-scale option is supposed to behave wasn't really ever documented until 25cfc81. It turns out that different OS/WMs may do slightly different things. For wayland, we need to fix two things. First, only return the wl->window_size in GET_UNFS (aka don't return the fullscreen size). For SET_UNFS, we need to change the behavior for the maximized window case. If the window is maximized, first attempt to unmaximize it and send the wayland event. If the compositor allows this to happen, then go ahead and set the new dimensions and resize it. In the case that the attempt to unmaximize is not successful, then don't attempt the resize and just save the window size dimensions for later to be used when the user unmaximizes the window.
* wayland: keep track of toplevel width/height againDudemanguy2021-08-061-1/+7
| | | | | | | | | | | | | | 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).
* wayland: cleanup handle_toplevel_configDudemanguy2021-08-031-11/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* wayland: unset hidden state in frame callbackDudemanguy2021-07-261-8/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | More wayland weirdness. So previously, flipping a hidden state from true to false was done in vo_wayland_wait_frame. In theory, this would be after you get the frame callback and all those events so there's no problem. However since the function also does a bunch of flushing/dispatching/etc. to the default display queue so a lot of unknown things can happen before we actually set the hidden variable back to false. For example if a single image was paused and left on another virtual desktop long enough (~5 minutes) while also not having focus, switching back to that desktop could render it a black frame. This edge case was supposed to be handled by the surface being activated again in the toplevel event but apparently that doesn't always work. The fix is to just delete all of that junk and set wl->hidden = false in the frame callback. What's actually happening is kind of a mystery honestly. Probably the compositor drops the buffers after a while as an optimization (sensible) and forces a repaint if you switch back to the virtual desktop. Somehow wl->hidden not being set to false would not properly trigger a repaint (likely because it also sends a toplevel event which does stuff) thus you just get a black window. If you just make sure to set hidden in the frame callback, it appears like all of these problems and edge cases are solved. Since this event must happen first, that makes sense. That simplifies a lot of stuff and fixes some subtle bugs at the same time so just go with this approach.
* wayland: refactor surface scalingDudemanguy2021-06-301-33/+55
| | | | | | | | | | | | | | | 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.
* wayland: fix wl_surface_set_buffer_scale usageDudemanguy2021-06-271-0/+2
| | | | | | | | | | | The wl_surface lives for the entire lifetime of the vo. It's only neccesary to set the scale initially and when the output scaling changes (the surface moves to a different output with a different scale or the output itself changes it scale). All of the calls that were being made in the egl/vulkan resize functions are not needed. vo_wlshm wasn't correctly rescaling itself before this commit since it had no logic to handle scale changes. This should all be shared, common code in the surface/output listeners.
* wayland: always be sure to initially try to renderDudemanguy2021-06-271-4/+3
| | | | | | | | | | | | | | | | | | | 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.
* wayland: handle app id option less stupidlyDudemanguy2021-06-261-4/+0
| | | | | | Not sure what I was on when I wrote this. wayland-app-id is supposed to default to "mpv". Just set that in the vo_sub_opts and don't do this weird m_config_cache_write_opt thing. Also make the doc entry nicer.
* wayland: reorganize wayland common codeDudemanguy2021-06-261-868/+905
| | | | | | | 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).
* wayland: refactor dispatching eventsDudemanguy2021-05-281-46/+34
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This was originally just a bugfix for a race condition, but the scope expanded a bit. Currently, the wayland code does a prepare_read -> dispatch_pending -> display_flush -> read_events -> dispatch_pending routine that's basically straight from the wayland client API documentation. This essentially just queues up all the wayland events mpv has and dispatches them to the compositor. We do this for blocking purposes on every frame we render. A very similar thing is done for wait_events from the VO. This code can pretty easily be unified and split off into a separate function, vo_wayland_dispatch_events. vo_wayland_wait_frame will call this function in a while loop (which will break either on timeout or if we receive frame callback from the compositor). wait_events needs to just check this in case we get some state change on the wakeup_pipe (i.e. waking up from the paused state). As for the actual bugfix part of this, it's a slight regression from c26d833. The toplevel config event always forced a redraw when a surface became activated again. This is for something like displaying cover art on a music file. If the window was originally out of view and then later brought back into focus, no picture would be rendered (i.e. the window is just black). That's because something like cover art is just 1 frame and the VO stops doing any other additional rendering. If you miss that 1 frame, nothing would show up ever again. The fix in this case is to always just force a redraw when the mpv window comes back into view. Well with the aforementioned commit, we stopped doing wl_display_roundtrip calls on every frame. That means we no longer do roundtrip blocking calls. We just be sure to queue up all of the events we have and then dispatch them. Because wayland is fundamentall