mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-20 06:50:05 +01:00
debug-gui: pointer locking on Wayland
Use the pointer constraints protocol to lock the pointer on Wayland. Signed-off-by: José Expósito <jose.exposito89@gmail.com>
This commit is contained in:
parent
895e866da6
commit
a9b334ebb5
4 changed files with 172 additions and 12 deletions
|
|
@ -92,7 +92,7 @@ variables:
|
||||||
UBUNTU_PACKAGES: 'git gcc g++ pkg-config meson check libudev-dev libevdev-dev doxygen graphviz python3-sphinx python3-recommonmark python3-sphinx-rtd-theme python3-pytest-xdist libwacom-dev libcairo2-dev libgtk-3-dev libglib2.0-dev libmtdev-dev'
|
UBUNTU_PACKAGES: 'git gcc g++ pkg-config meson check libudev-dev libevdev-dev doxygen graphviz python3-sphinx python3-recommonmark python3-sphinx-rtd-theme python3-pytest-xdist libwacom-dev libcairo2-dev libgtk-3-dev libglib2.0-dev libmtdev-dev'
|
||||||
ARCH_PACKAGES: 'git gcc pkgconfig meson check libsystemd libevdev doxygen graphviz python-sphinx python-recommonmark python-sphinx_rtd_theme python-pytest-xdist libwacom gtk3 mtdev diffutils'
|
ARCH_PACKAGES: 'git gcc pkgconfig meson check libsystemd libevdev doxygen graphviz python-sphinx python-recommonmark python-sphinx_rtd_theme python-pytest-xdist libwacom gtk3 mtdev diffutils'
|
||||||
ALPINE_PACKAGES: 'git gcc build-base pkgconfig meson check-dev eudev-dev libevdev-dev libwacom-dev cairo-dev gtk+3.0-dev mtdev-dev bash'
|
ALPINE_PACKAGES: 'git gcc build-base pkgconfig meson check-dev eudev-dev libevdev-dev libwacom-dev cairo-dev gtk+3.0-dev mtdev-dev bash'
|
||||||
FREEBSD_PACKAGES: 'git pkgconf meson libepoll-shim libudev-devd libevdev libwacom gtk3 libmtdev bash'
|
FREEBSD_PACKAGES: 'git pkgconf meson libepoll-shim libudev-devd libevdev libwacom gtk3 libmtdev bash wayland'
|
||||||
############################ end of package lists #############################
|
############################ end of package lists #############################
|
||||||
|
|
||||||
# these tags should be updated each time the list of packages is updated
|
# these tags should be updated each time the list of packages is updated
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,7 @@ distributions:
|
||||||
- gtk3
|
- gtk3
|
||||||
- libmtdev
|
- libmtdev
|
||||||
- bash
|
- bash
|
||||||
|
- wayland
|
||||||
build:
|
build:
|
||||||
extra_variables:
|
extra_variables:
|
||||||
- "MESON_ARGS: '-Dtests=false -Ddocumentation=false' # doxygen drags down too many deps"
|
- "MESON_ARGS: '-Dtests=false -Ddocumentation=false' # doxygen drags down too many deps"
|
||||||
|
|
|
||||||
27
meson.build
27
meson.build
|
|
@ -559,12 +559,39 @@ if get_option('debug-gui')
|
||||||
|
|
||||||
dep_cairo = dependency('cairo')
|
dep_cairo = dependency('cairo')
|
||||||
dep_glib = dependency('glib-2.0')
|
dep_glib = dependency('glib-2.0')
|
||||||
|
dep_wayland_client = dependency('wayland-client', required : false)
|
||||||
|
dep_wayland_protocols = dependency('wayland-protocols', required : false)
|
||||||
|
|
||||||
debug_gui_sources = [ 'tools/libinput-debug-gui.c' ]
|
debug_gui_sources = [ 'tools/libinput-debug-gui.c' ]
|
||||||
|
|
||||||
|
if dep_wayland_client.found() and dep_wayland_protocols.found()
|
||||||
|
wayland_scanner = find_program('wayland-scanner')
|
||||||
|
wlproto_dir = dep_wayland_protocols.get_pkgconfig_variable('pkgdatadir')
|
||||||
|
|
||||||
|
proto_name = 'pointer-constraints-unstable-v1'
|
||||||
|
input = files(join_paths(wlproto_dir, 'unstable/pointer-constraints/@0@.xml'.format(proto_name)))
|
||||||
|
|
||||||
|
wayland_headers = custom_target('@0@ client header'.format(proto_name),
|
||||||
|
input: input,
|
||||||
|
output: '@0@-client-protocol.h'.format(proto_name),
|
||||||
|
command: [wayland_scanner, 'client-header', '@INPUT@', '@OUTPUT@'],
|
||||||
|
)
|
||||||
|
|
||||||
|
wayland_sources = custom_target('@0@ source'.format(proto_name),
|
||||||
|
input: input,
|
||||||
|
output: '@0@-protocol.c'.format(proto_name),
|
||||||
|
command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'],
|
||||||
|
)
|
||||||
|
|
||||||
|
debug_gui_sources += [ wayland_headers, wayland_sources ]
|
||||||
|
endif
|
||||||
|
|
||||||
deps_debug_gui = [
|
deps_debug_gui = [
|
||||||
dep_gtk,
|
dep_gtk,
|
||||||
dep_cairo,
|
dep_cairo,
|
||||||
dep_glib,
|
dep_glib,
|
||||||
|
dep_wayland_client,
|
||||||
|
dep_wayland_protocols,
|
||||||
] + deps_tools
|
] + deps_tools
|
||||||
executable('libinput-debug-gui',
|
executable('libinput-debug-gui',
|
||||||
debug_gui_sources,
|
debug_gui_sources,
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,16 @@
|
||||||
|
|
||||||
#include "shared.h"
|
#include "shared.h"
|
||||||
|
|
||||||
|
#ifdef GDK_WINDOWING_WAYLAND
|
||||||
|
#include <wayland-client.h>
|
||||||
|
#include "pointer-constraints-unstable-v1-client-protocol.h"
|
||||||
|
#if HAVE_GTK4
|
||||||
|
#include <gdk/wayland/gdkwayland.h>
|
||||||
|
#else
|
||||||
|
#include <gdk/gdkwayland.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#define clip(val_, min_, max_) min((max_), max((min_), (val_)))
|
#define clip(val_, min_, max_) min((max_), max((min_), (val_)))
|
||||||
|
|
||||||
enum touch_state {
|
enum touch_state {
|
||||||
|
|
@ -100,6 +110,16 @@ struct window {
|
||||||
/* abs position */
|
/* abs position */
|
||||||
struct point abs;
|
struct point abs;
|
||||||
|
|
||||||
|
/* Wayland and X11 pointer locking */
|
||||||
|
struct {
|
||||||
|
bool locked;
|
||||||
|
|
||||||
|
#ifdef GDK_WINDOWING_WAYLAND
|
||||||
|
struct zwp_pointer_constraints_v1 *wayland_pointer_constraints;
|
||||||
|
struct zwp_locked_pointer_v1 *wayland_locked_pointer;
|
||||||
|
#endif
|
||||||
|
} lock_pointer;
|
||||||
|
|
||||||
/* scroll bar positions */
|
/* scroll bar positions */
|
||||||
struct {
|
struct {
|
||||||
double vx, vy;
|
double vx, vy;
|
||||||
|
|
@ -181,6 +201,125 @@ struct window {
|
||||||
struct libinput_device *devices[50];
|
struct libinput_device *devices[50];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef GDK_WINDOWING_WAYLAND
|
||||||
|
static void
|
||||||
|
wayland_registry_global(void *data,
|
||||||
|
struct wl_registry *registry,
|
||||||
|
uint32_t name,
|
||||||
|
const char *interface,
|
||||||
|
uint32_t version)
|
||||||
|
{
|
||||||
|
struct window *w = data;
|
||||||
|
|
||||||
|
if (!g_strcmp0(interface, "zwp_pointer_constraints_v1")) {
|
||||||
|
w->lock_pointer.wayland_pointer_constraints =
|
||||||
|
wl_registry_bind(registry,
|
||||||
|
name,
|
||||||
|
&zwp_pointer_constraints_v1_interface,
|
||||||
|
1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wayland_registry_global_remove(void *data,
|
||||||
|
struct wl_registry *wl_registry,
|
||||||
|
uint32_t name)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wl_registry_listener registry_listener = {
|
||||||
|
wayland_registry_global,
|
||||||
|
wayland_registry_global_remove
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool
|
||||||
|
wayland_lock_pointer(struct window *w)
|
||||||
|
{
|
||||||
|
GdkDisplay *gdk_display;
|
||||||
|
GdkSeat *gdk_seat;
|
||||||
|
GdkDevice *gdk_device;
|
||||||
|
struct wl_display *display;
|
||||||
|
struct wl_registry *registry;
|
||||||
|
struct wl_pointer *wayland_pointer;
|
||||||
|
struct wl_surface *surface;
|
||||||
|
|
||||||
|
w->lock_pointer.wayland_pointer_constraints = NULL;
|
||||||
|
|
||||||
|
gdk_display = gdk_display_get_default();
|
||||||
|
display = gdk_wayland_display_get_wl_display(gdk_display);
|
||||||
|
|
||||||
|
gdk_seat = gdk_display_get_default_seat(gdk_display);
|
||||||
|
gdk_device = gdk_seat_get_pointer(gdk_seat);
|
||||||
|
wayland_pointer = gdk_wayland_device_get_wl_pointer(gdk_device);
|
||||||
|
|
||||||
|
registry = wl_display_get_registry(display);
|
||||||
|
wl_registry_add_listener(registry, ®istry_listener, w);
|
||||||
|
wl_display_roundtrip(display);
|
||||||
|
|
||||||
|
if (!w->lock_pointer.wayland_pointer_constraints)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#if HAVE_GTK4
|
||||||
|
GtkNative *window = gtk_widget_get_native(w->win);
|
||||||
|
GdkSurface *gdk_surface = gtk_native_get_surface(window);
|
||||||
|
surface = gdk_wayland_surface_get_wl_surface(gdk_surface);
|
||||||
|
#else
|
||||||
|
GdkWindow *window = gtk_widget_get_window(w->win);
|
||||||
|
surface = gdk_wayland_window_get_wl_surface(window);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
w->lock_pointer.wayland_locked_pointer =
|
||||||
|
zwp_pointer_constraints_v1_lock_pointer(w->lock_pointer.wayland_pointer_constraints,
|
||||||
|
surface,
|
||||||
|
wayland_pointer,
|
||||||
|
NULL,
|
||||||
|
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wayland_unlock_pointer(struct window *w)
|
||||||
|
{
|
||||||
|
w->lock_pointer.wayland_pointer_constraints = NULL;
|
||||||
|
zwp_locked_pointer_v1_destroy(w->lock_pointer.wayland_locked_pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
backend_is_wayland(void)
|
||||||
|
{
|
||||||
|
return GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default());
|
||||||
|
}
|
||||||
|
#endif /* GDK_WINDOWING_WAYLAND */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
window_lock_pointer(struct window *w)
|
||||||
|
{
|
||||||
|
w->lock_pointer.locked = false;
|
||||||
|
|
||||||
|
#ifdef GDK_WINDOWING_WAYLAND
|
||||||
|
if (backend_is_wayland())
|
||||||
|
w->lock_pointer.locked = wayland_lock_pointer(w);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return w->lock_pointer.locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
window_unlock_pointer(struct window *w)
|
||||||
|
{
|
||||||
|
if (!w->lock_pointer.locked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
w->lock_pointer.locked = false;
|
||||||
|
|
||||||
|
#ifdef GDK_WINDOWING_WAYLAND
|
||||||
|
if (backend_is_wayland())
|
||||||
|
wayland_unlock_pointer(w);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
LIBINPUT_ATTRIBUTE_PRINTF(1, 2)
|
LIBINPUT_ATTRIBUTE_PRINTF(1, 2)
|
||||||
static inline void
|
static inline void
|
||||||
msg(const char *fmt, ...)
|
msg(const char *fmt, ...)
|
||||||
|
|
@ -852,6 +991,8 @@ map_event_cb(GtkDrawingArea *widget, int width, int height, gpointer data)
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
gtk_widget_set_cursor_from_name(w->win, "none");
|
gtk_widget_set_cursor_from_name(w->win, "none");
|
||||||
|
|
||||||
|
window_lock_pointer(w);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void
|
static void
|
||||||
|
|
@ -859,7 +1000,6 @@ map_event_cb(GtkWidget *widget, GdkEvent *event, gpointer data)
|
||||||
{
|
{
|
||||||
struct window *w = data;
|
struct window *w = data;
|
||||||
GdkDisplay *display;
|
GdkDisplay *display;
|
||||||
GdkSeat *seat;
|
|
||||||
GdkWindow *window;
|
GdkWindow *window;
|
||||||
|
|
||||||
window_place_ui_elements(widget, w);
|
window_place_ui_elements(widget, w);
|
||||||
|
|
@ -873,16 +1013,7 @@ map_event_cb(GtkWidget *widget, GdkEvent *event, gpointer data)
|
||||||
gdk_cursor_new_for_display(display,
|
gdk_cursor_new_for_display(display,
|
||||||
GDK_BLANK_CURSOR));
|
GDK_BLANK_CURSOR));
|
||||||
|
|
||||||
seat = gdk_display_get_default_seat(display);
|
window_lock_pointer(w);
|
||||||
gdk_seat_grab(seat,
|
|
||||||
window,
|
|
||||||
GDK_SEAT_CAPABILITY_ALL_POINTING,
|
|
||||||
FALSE, /* owner-events */
|
|
||||||
NULL, /* cursor */
|
|
||||||
NULL, /* triggering event */
|
|
||||||
NULL, /* prepare_func */
|
|
||||||
NULL /* prepare_func_data */
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -1781,6 +1912,7 @@ main(int argc, char **argv)
|
||||||
w.event_loop = g_main_loop_new(NULL, FALSE);
|
w.event_loop = g_main_loop_new(NULL, FALSE);
|
||||||
g_main_loop_run(w.event_loop);
|
g_main_loop_run(w.event_loop);
|
||||||
|
|
||||||
|
window_unlock_pointer(&w);
|
||||||
window_cleanup(&w);
|
window_cleanup(&w);
|
||||||
libinput_unref(li);
|
libinput_unref(li);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue