fix: the touchpad moves a game's own cursor when it locks the pointer (#772)

This commit is contained in:
Gustash authored and GitHub committed 2026-10-14 11:30:54 -04:00
1 parent 9796525449
commit 82f04fb22e
2 files changed
+32 -2

No files matched your search

@@ -2194,6 +2194,7 @@ struct constraint {
int pending_region_set;
int hint_set, pending_hint_set;
double hint_x, hint_y, pending_hint_x, pending_hint_y;
int gave_keys;
};
static struct wl_list g_constraints;
static struct constraint *g_active_constraint;
@@ -2272,6 +2273,14 @@ static void constraint_end(struct constraint *k, int tell_client, const char *wh
g_ptr_y = oy + k->hint_y;
}
g_raw_valid = 0;
if (k->gave_keys) {
k->gave_keys = 0;
for (int i = 0; i < g_nkbs; i++) {
if (!k->surface || g_kbs[i].focus != k->surface->resource) continue;
wl_keyboard_send_leave(g_kbs[i].kb, wl_display_next_serial(g_display), g_kbs[i].focus);
g_kbs[i].focus = NULL;
}
}
if (tell_client) constraint_send_state(k, 0);
constraint_describe(k, name, sizeof(name));
droiddeck_log("pointer", "%s: %s (%s), pointer at %d,%d", k->is_lock ? "unlocked" : "unconfined",
@@ -2290,6 +2299,12 @@ static void constraint_activate(struct constraint *k) {
if (!k->is_lock) confine_clamp(k, &g_ptr_x, &g_ptr_y);
constraint_origin(k, &ox, &oy);
pointer_focus(k->surface->resource, wl_fixed_from_double(g_ptr_x - ox), wl_fixed_from_double(g_ptr_y - oy));
int focused = 0;
for (int i = 0; i < g_nkbs; i++) if (g_kbs[i].focus) focused = 1;
if (k->is_lock && !focused && keyboard_for(wl_resource_get_client(k->surface->resource))) {
keyboard_focus(k->surface->resource);
k->gave_keys = 1;
}
constraint_send_state(k, 1);
constraint_describe(k, name, sizeof(name));
if (k->is_lock)
@@ -177,6 +177,11 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback {
if (pointerLocked == locked) return@post
pointerLocked = locked
Log.i(TAG, "pointer lock " + if (locked) "taken by a program" else "released")
// Touchpad deltas are measured from the middle while locked (moveLockedPointer).
if (locked && ::touchpad.isInitialized) {
drawnRect()?.let { touchpad.place(it.centerX(), it.centerY()) }
cursorVisible = false
}
updatePointerCapture()
}
}
@@ -1705,9 +1710,11 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback {
}
private val pointerListener = object : PointerGestures.Listener {
override fun onMove(x: Float, y: Float) = movePointer(x, y)
override fun onMove(x: Float, y: Float) {
if (pointerLocked) moveLockedPointer(x, y) else movePointer(x, y)
}
override fun onButton(button: Int, pressed: Boolean, x: Float, y: Float) {
movePointer(x, y)
if (!pointerLocked) movePointer(x, y)
WaylandCompositor.nativeSendSceneInput(3, button, if (pressed) 1 else 0)
}
override fun onWheel(steps: Int) { WaylandCompositor.nativeSendSceneInput(4, steps, 0) }
@@ -1717,6 +1724,14 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback {
}
}
private fun moveLockedPointer(x: Float, y: Float) {
val rect = drawnRect() ?: return
val scale = SessionState.outputSize.first / rect.width()
WaylandCompositor.sendPointerDelta((x - rect.centerX()) * scale, (y - rect.centerY()) * scale)
touchpad.place(rect.centerX(), rect.centerY())
cursorVisible = false
}
private fun movePointer(x: Float, y: Float) {
val rect = drawnRect() ?: return
val cx = x.coerceIn(rect.left, rect.right)