summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorDudemanguy <random342@airmail.cc>2022-05-12 16:26:49 -0500
committerDudemanguy <random342@airmail.cc>2023-07-04 19:16:43 +0000
commitdbc0fcea1bcd3b5ea0319f74a6310f2691c1d371 (patch)
treec4048328397dd550bdb9ddb9e90218b010a8476f /video
parent3ba446d0b065f867ca262a2e05e4e8d24c7c0783 (diff)
downloadmpv-dbc0fcea1bcd3b5ea0319f74a6310f2691c1d371.tar.bz2
mpv-dbc0fcea1bcd3b5ea0319f74a6310f2691c1d371.tar.xz
player: add --input-cursor-passthrough option
Add an option for allowing pointer events to pass through the mpv window. This could be useful in cases where a user wants to display transparent images/video with mpv and interact with applications beneath the window. This commit implements this functionality for x11 and wayland. Note that whether or not this actually works likely depends on your window manager and/or compositor. E.g. sway ignores pointer events but the entire window becomes draggable when you float it (nothing under the mpv window receives events). Weston behaves as expected however so that is a compositor bug. Excuse the couple of completely unrelated style fixes (both were originally done by me).
Diffstat (limited to 'video')
-rw-r--r--video/out/wayland_common.c19
-rw-r--r--video/out/x11_common.c27
2 files changed, 44 insertions, 2 deletions
diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c
index ed9c7a911a..28cd6eb55b 100644
--- a/video/out/wayland_common.c
+++ b/video/out/wayland_common.c
@@ -1548,7 +1548,8 @@ static void greatest_common_divisor(struct vo_wayland_state *wl, int a, int b) {
}
}
-static void guess_focus(struct vo_wayland_state *wl) {
+static void guess_focus(struct vo_wayland_state *wl)
+{
// We can't actually know if the window is focused or not in wayland,
// so just guess it with some common sense. Obviously won't work if
// the user has no keyboard.
@@ -1717,6 +1718,17 @@ static void set_geometry(struct vo_wayland_state *wl, bool resize)
}
}
+static void set_input_region(struct vo_wayland_state *wl, bool passthrough)
+{
+ if (passthrough) {
+ struct wl_region *region = wl_compositor_create_region(wl->compositor);
+ wl_surface_set_input_region(wl->surface, region);
+ wl_region_destroy(region);
+ } else {
+ wl_surface_set_input_region(wl->surface, NULL);
+ }
+}
+
static int set_screensaver_inhibitor(struct vo_wayland_state *wl, int state)
{
if (!wl->idle_inhibit_manager)
@@ -1967,6 +1979,8 @@ int vo_wayland_control(struct vo *vo, int *events, int request, void *arg)
}
if (opt == &opts->content_type)
set_content_type(wl);
+ if (opt == &opts->cursor_passthrough)
+ set_input_region(wl, opts->cursor_passthrough);
if (opt == &opts->fullscreen)
toggle_fullscreen(wl);
if (opt == &opts->hidpi_window_scale)
@@ -2255,6 +2269,9 @@ bool vo_wayland_reconfig(struct vo *vo)
wl->geometry = wl->window_size;
}
+ if (wl->vo_opts->cursor_passthrough)
+ set_input_region(wl, true);
+
if (wl->vo_opts->fullscreen)
toggle_fullscreen(wl);
diff --git a/video/out/x11_common.c b/video/out/x11_common.c
index 3faae5ef19..b3bdf1c014 100644
--- a/video/out/x11_common.c
+++ b/video/out/x11_common.c
@@ -35,6 +35,7 @@
#include <X11/extensions/scrnsaver.h>
#include <X11/extensions/dpms.h>
+#include <X11/extensions/shape.h>
#include <X11/extensions/Xinerama.h>
#include <X11/extensions/Xpresent.h>
#include <X11/extensions/Xrandr.h>
@@ -149,6 +150,7 @@ static void vo_x11_move_resize(struct vo *vo, bool move, bool resize,
struct mp_rect rc);
static void vo_x11_maximize(struct vo *vo);
static void vo_x11_minimize(struct vo *vo);
+static void vo_x11_set_input_region(struct vo *vo, bool passthrough);
static void vo_x11_sticky(struct vo *vo, bool sticky);
#define XA(x11, s) (XInternAtom((x11)->display, # s, False))
@@ -1641,6 +1643,9 @@ static void vo_x11_map_window(struct vo *vo, struct mp_rect rc)
vo_x11_selectinput_witherr(vo, x11->display, x11->window, events);
XMapWindow(x11->display, x11->window);
+ if (x11->opts->cursor_passthrough)
+ vo_x11_set_input_region(vo, true);
+
if (x11->opts->window_maximized) // don't override WM default on "no"
vo_x11_maximize(vo);
if (x11->opts->window_minimized) // don't override WM default on "no"
@@ -1978,7 +1983,8 @@ static void vo_x11_set_geometry(struct vo *vo)
vo_x11_config_vo_window(vo);
}
-bool vo_x11_check_visible(struct vo *vo) {
+bool vo_x11_check_visible(struct vo *vo)
+{
struct vo_x11_state *x11 = vo->x11;
struct mp_vo_opts *opts = x11->opts;
@@ -1987,6 +1993,23 @@ bool vo_x11_check_visible(struct vo *vo) {
return render;
}
+static void vo_x11_set_input_region(struct vo *vo, bool passthrough)
+{
+ struct vo_x11_state *x11 = vo->x11;
+
+ if (passthrough) {
+ XRectangle rect = {0, 0, 0, 0};
+ Region region = XCreateRegion();
+ XUnionRectWithRegion(&rect, region, region);
+ XShapeCombineRegion(x11->display, x11->window, ShapeInput, 0, 0,
+ region, ShapeSet);
+ XDestroyRegion(region);
+ } else {
+ XShapeCombineMask(x11->display, x11->window, ShapeInput, 0, 0,
+ 0, ShapeSet);
+ }
+}
+
int vo_x11_control(struct vo *vo, int *events, int request, void *arg)
{
struct vo_x11_state *x11 = vo->x11;
@@ -2012,6 +2035,8 @@ int vo_x11_control(struct vo *vo, int *events, int request, void *arg)
vo_x11_minimize(vo);
if (opt == &opts->window_maximized)
vo_x11_maximize(vo);
+ if (opt == &opts->cursor_passthrough)
+ vo_x11_set_input_region(vo, opts->cursor_passthrough);
if (opt == &opts->x11_present)
xpresent_set(x11);
if (opt == &opts->geometry || opt == &opts->autofit ||