Skip to content

Cursor constraints get activated when it's not keyboard focused #4121

Description

@bczhc

The surface will activate its pointer constraint even if it's not keyboard focused. See the demonstration video:

First, the typical scenario - 3D games:

Game

game.mp4

The scrolling layout has two windows, but I'm in the floating space, and once I move the pointer above the 3D game, it just "enters" into the game and starts controlling the 3D camera - my keyboard focus is still on gedit but the mouse is controlling the game. Keys like WASD and Esc all won't be sent to the game thus the only way to leave this awkward, is to use niri's Alt+Tab (recent windows) or Overview.

I may suppose this is not expected and for these cases, it's annoying. Say, I'm playing a 3D game at fullscreen, then I use a keybind to open a floating window and do something with it. But I need to carefully notice the pointer not going outside the floating window, or it will be "consumed" or "captured" by the game immediately (in this case the keyboard focused is still on the floating app, game's Esc won't work) and the only way to leave the game's grabbing is to use Alt+Tab or Overview or something similar.

More technical findings below.

niri

niri.mp4

See another niri demonstration video. The window rightside is a demo app which toggles its pointer locked constraint on Space pressed. It literally simulates what a 3D game does: on lock, lock the pointer then hide the pointer; on unlock, unlock the pointer then unhide the pointer.

In the screenrecord above, after the demo app locks the pointer, I use Alt+Tab to switch to the left window. The keyboard focus is also on the left one. But when I move the cursor over the right one, it immediately gets captured by the right one and I can't go back. The keyboard focus is still on the left. This exhibits an inconsistency.

Hyprland doesn't show the issue. (config: layout = scrolling; follow_mouse = 2)

hyprland.mp4

Note when the keyboard focus is on the left and I move the cursor over the right, the cursor disappears, but it still is not locked and I'm able to move to the left again. This is a more correct behavior to me except the cursor disappearing.

If I apply this patch, niri behaves the same with Hyprland and I'm just using this as a workaround.

diff --git a/src/niri.rs b/src/niri.rs
index 0b190ab1..9a3d9267 100644
--- a/src/niri.rs
+++ b/src/niri.rs
@@ -6816,6 +6816,10 @@ impl Niri {
             return;
         }
 
+        if self.keyboard_focus.surface() != pointer.current_focus().as_ref() {
+            return;
+        }
+
         with_pointer_constraint(surface, &pointer, |constraint| {
             let Some(constraint) = constraint else { return };
 

System Information

  • niri version: niri 26.04 (v26.04-72-gd0c4d596-modified)
  • Distro: Arch Linux rolling
  • GPU: NVIDIA RTX GeForce 3060 Mobile
  • CPU: Intel i7-11800H

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:inputKeyboard, mouse, touchpad, tablet, gestures, pointer

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions