wayland: implement pointer warp via pointer-constraints hint
Native Wayland clients (e.g. plan9port acme/devdraw) warp the pointer by locking it via zwp_pointer_constraints_v1, setting a cursor_position_hint, then immediately destroying the lock. The compositor is expected to warp the cursor to the hint on unlock. Our handler just activated the constraint and ignored the hint. Now we listen for the constraint destroy event and warp the cursor to the hint position (converted from surface-local to global coordinates).
This commit is contained in:
parent
1ef79265e7
commit
9da620d443
|
|
@ -9,6 +9,7 @@
|
|||
#include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h>
|
||||
#include <wlr/types/wlr_data_device.h>
|
||||
#include <wlr/types/wlr_pointer_constraints_v1.h>
|
||||
#include <wlr/types/wlr_xdg_shell.h>
|
||||
#include <wlr/types/wlr_primary_selection.h>
|
||||
#include <wlr/types/wlr_scene.h>
|
||||
#include <wlr/types/wlr_seat.h>
|
||||
|
|
@ -99,16 +100,54 @@ handle_pointer_axis(struct wl_listener *listener, void *data)
|
|||
* In headless mode the pointer is virtual so there is nothing physically
|
||||
* to lock, but activating keeps the client happy.
|
||||
*/
|
||||
struct wl_constraint_ctx {
|
||||
struct wlr_pointer_constraint_v1 *constraint;
|
||||
struct wl_listener destroy;
|
||||
};
|
||||
|
||||
static void
|
||||
handle_pointer_constraint_destroy(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct wl_constraint_ctx *ctx =
|
||||
wl_container_of(listener, ctx, destroy);
|
||||
struct wlr_pointer_constraint_v1 *constraint = ctx->constraint;
|
||||
(void)data;
|
||||
|
||||
if (constraint->current.cursor_hint.enabled && constraint->surface) {
|
||||
/* Convert surface-local hint to global coordinates */
|
||||
double sx = constraint->current.cursor_hint.x;
|
||||
double sy = constraint->current.cursor_hint.y;
|
||||
int gx = 0, gy = 0;
|
||||
/* Find the toplevel view owning this surface to get global pos */
|
||||
struct wl_toplevel_view *v;
|
||||
wl_list_for_each(v, &wl_state.toplevel_list, link) {
|
||||
if (v->xdg_surface && v->xdg_surface->surface == constraint->surface) {
|
||||
gx = v->x;
|
||||
gy = v->y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
wl_pointer_warp_to(gx + (int)sx, gy + (int)sy);
|
||||
}
|
||||
|
||||
wl_list_remove(&ctx->destroy.link);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
void
|
||||
handle_new_pointer_constraint(struct wl_listener *listener, void *data)
|
||||
{
|
||||
(void)listener;
|
||||
struct wlr_pointer_constraint_v1 *constraint = data;
|
||||
(void)constraint;
|
||||
/* Activate immediately — in nested mode the real pointer is bounded
|
||||
* by the host compositor's window anyway. */
|
||||
|
||||
wlr_pointer_constraint_v1_send_activated(constraint);
|
||||
wwarning("wl_backend: pointer constraint activated");
|
||||
|
||||
struct wl_constraint_ctx *ctx = calloc(1, sizeof(*ctx));
|
||||
if (ctx) {
|
||||
ctx->constraint = constraint;
|
||||
ctx->destroy.notify = handle_pointer_constraint_destroy;
|
||||
wl_signal_add(&constraint->events.destroy, &ctx->destroy);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue