ref: 4e32a9fa6e58c1474f747a99083303c4a2f14ea7
parent: 8e6fe7002686d88b0c15f2c47e6cd345b1dd4cda
author: mia soweli <mia@soweli.net>
date: Fri Jun 13 11:07:53 EDT 2025
gui-wl: Use pointer constraints for warping This is a neat trick borrowed from Ethan Burns' proposed plan9port wayland backend that warps the pointer by locking the cursor, setting a position hint, and then unlocking the cursor. It works across compositors, and allows us to drop the dependency on wlroots protocols. Also fixed bugs in previous commit for handling close and events on the decor surfaces.
--- a/gui-wl/Makefile
+++ b/gui-wl/Makefile
@@ -3,17 +3,16 @@
LIB=libgui.a
PROTO_DIR=`pkg-config --variable=pkgdatadir wayland-protocols`
-WLR_DIR=`pkg-config --variable=pkgdatadir wlr-protocols`
XDG_SHELL=$(PROTO_DIR)/stable/xdg-shell/xdg-shell.xml
XDG_DECO=$(PROTO_DIR)/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml
XDG_PRIMSEL=$(PROTO_DIR)/unstable/primary-selection/primary-selection-unstable-v1.xml
-WLR_VIRTUAL_POINTER=$(WLR_DIR)/unstable/wlr-virtual-pointer-unstable-v1.xml
+WP_POINTER_CONSTRAINTS=$(PROTO_DIR)/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml
HFILES=\
xdg-shell-protocol.h\
xdg-decoration-protocol.h\
xdg-primary-selection-protocol.h\
- wlr-virtual-pointer.h\
+ wp-pointer-constraints.h\
wl-inc.h\
OFILES=\
@@ -20,16 +19,16 @@
xdg-shell-protocol.$O\
xdg-decoration-protocol.$O\
xdg-primary-selection-protocol.$O\
- wlr-virtual-pointer.$O\
+ wp-pointer-constraints.$O\
wl-cb.$O\
wl-screen.$O\
wl-util.$O\
-wlr-virtual-pointer.c:
- wayland-scanner private-code < $(WLR_VIRTUAL_POINTER) > $@ || { rm -f $@; exit 1; }
+wp-pointer-constraints.c:
+ wayland-scanner private-code < $(WP_POINTER_CONSTRAINTS) > $@ || { rm -f $@; exit 1; }
-wlr-virtual-pointer.h:
- wayland-scanner client-header < $(WLR_VIRTUAL_POINTER) > $@ || { rm -f $@; exit 1; }
+wp-pointer-constraints.h:
+ wayland-scanner client-header < $(WP_POINTER_CONSTRAINTS) > $@ || { rm -f $@; exit 1; }
xdg-shell-protocol.c:
wayland-scanner private-code < $(XDG_SHELL) > $@ || { rm -f $@; exit 1; }
--- a/gui-wl/wl-cb.c
+++ b/gui-wl/wl-cb.c
@@ -19,7 +19,7 @@
#include "xdg-shell-protocol.h"
#include "xdg-decoration-protocol.h"
#include "xdg-primary-selection-protocol.h"
-#include "wlr-virtual-pointer.h"
+#include "wp-pointer-constraints.h"
#include "screen.h"
#include "wl-inc.h"
@@ -328,7 +328,11 @@
Wlwin *wl;
int m;
+ /* ignore buttons on the window decor */
wl = data;
+ if (wl->surface != wl->surfaceover)
+ return;
+
switch(button){
case BTN_LEFT: m = P9Mouse1; break;
case BTN_MIDDLE: m = P9Mouse2; break;
@@ -351,7 +355,11 @@
{
Wlwin *wl;
+ /* ignore motion on the window decor */
wl = data;
+ if (wl->surface != wl->surfaceover)
+ return;
+
wl->mouse.xy.x = surface_x / 256;
wl->mouse.xy.y = surface_y / 256;
wl->mouse.msec = time;
@@ -365,11 +373,13 @@
wl = data;
wl->pointerserial = serial;
- pointer_handle_motion(data, wl_pointer, wl->mouse.msec, surface_x, surface_y);
+ /* track surface so we can ignore events for the window decor */
+ wl->surfaceover = surface;
+ if (wl->surface != wl->surfaceover)
+ return;
- /* let libdecor handle the cursor for it's surfaces */
- if (wl->surface == surface)
- setcursor();
+ pointer_handle_motion(data, wl_pointer, wl->mouse.msec, surface_x, surface_y);
+ setcursor();
}
static void
@@ -639,8 +649,8 @@
wl->data_device_manager = wl_registry_bind(registry, name, &wl_data_device_manager_interface, 3);
} else if(strcmp(interface, zwp_primary_selection_device_manager_v1_interface.name) == 0){
wl->primsel = wl_registry_bind(registry, name, &zwp_primary_selection_device_manager_v1_interface, 1);
- } else if(strcmp(interface, zwlr_virtual_pointer_manager_v1_interface.name) == 0){
- wl->vpmgr = wl_registry_bind(registry, name, &zwlr_virtual_pointer_manager_v1_interface, 1);
+ } else if(strcmp(interface, zwp_pointer_constraints_v1_interface.name) == 0){
+ wl->constraints = wl_registry_bind(registry, name, &zwp_pointer_constraints_v1_interface, 1);
}
}
@@ -660,7 +670,7 @@
panic("libdecor error");
}
-const struct libdecor_interface decor_interface = {
+struct libdecor_interface decor_interface = {
.error = handle_decor_error,
};
@@ -697,9 +707,16 @@
wl_surface_commit(wl->surface);
}
-const struct libdecor_frame_interface decor_frame_interface = {
+static void
+handle_decor_frame_close(struct libdecor_frame *frame, void *aux)
+{
+ exit(0);
+}
+
+struct libdecor_frame_interface decor_frame_interface = {
.configure = handle_decor_frame_configure,
.commit = handle_decor_frame_commit,
+ .close = handle_decor_frame_close,
};
void
@@ -723,9 +740,6 @@
if(wl->shm == nil || wl->compositor == nil || wl->xdg_wm_base == nil || wl->seat == nil)
panic("required wayland capabilities not met");
- if(wl->vpmgr != nil)
- wl->vpointer = zwlr_virtual_pointer_manager_v1_create_virtual_pointer(wl->vpmgr, wl->seat);
-
wlallocbuffer(wl);
wl->surface = wl_compositor_create_surface(wl->compositor);
@@ -794,13 +808,14 @@
void
wlsetmouse(Wlwin *wl, Point p)
{
- Point delta;
- if(wl->vpointer == nil)
+ struct zwp_locked_pointer_v1 *pointer;
+ if(wl->constraints == nil)
return;
- delta.x = p.x - wl->mouse.xy.x;
- delta.y = p.y - wl->mouse.xy.y;
+ pointer = zwp_pointer_constraints_v1_lock_pointer(wl->constraints, wl->surface, wl->pointer, NULL, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
+ zwp_locked_pointer_v1_set_cursor_position_hint(pointer, wl_fixed_from_int (p.x), wl_fixed_from_int (p.y));
+ wl_surface_commit(wl->surface);
+ zwp_locked_pointer_v1_destroy(pointer);
+
wl->mouse.xy = p;
- zwlr_virtual_pointer_v1_motion(wl->vpointer, time(nil) * 1000, delta.x * 256, delta.y * 256);
- zwlr_virtual_pointer_v1_frame(wl->vpointer);
}
--- a/gui-wl/wl-inc.h
+++ b/gui-wl/wl-inc.h
@@ -51,6 +51,7 @@
struct wl_compositor *compositor;
struct wl_display *display;
struct wl_surface *surface;
+ struct wl_surface *surfaceover;
struct wl_surface *cursorsurface;
struct xdg_wm_base *xdg_wm_base;
struct xdg_toplevel *xdg_toplevel;
@@ -75,8 +76,7 @@
struct zwp_primary_selection_device_manager_v1 *primsel;
struct zwp_primary_selection_device_v1 *primsel_device;
- struct zwlr_virtual_pointer_manager_v1 *vpmgr;
- struct zwlr_virtual_pointer_v1 *vpointer;
+ struct zwp_pointer_constraints_v1 *constraints;
};
void wlallocbuffer(Wlwin*);
--
⑨