diff --git a/app/src/main/cpp/waylandcomp/src/compositor.c b/app/src/main/cpp/waylandcomp/src/compositor.c index 677937b52..7d74dce39 100644 --- a/app/src/main/cpp/waylandcomp/src/compositor.c +++ b/app/src/main/cpp/waylandcomp/src/compositor.c @@ -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) diff --git a/app/src/main/java/com/droiddeck/launcher/SessionActivity.kt b/app/src/main/java/com/droiddeck/launcher/SessionActivity.kt index 1c6d32ddf..61d9fd80d 100644 --- a/app/src/main/java/com/droiddeck/launcher/SessionActivity.kt +++ b/app/src/main/java/com/droiddeck/launcher/SessionActivity.kt @@ -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)