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
https://github.com/user-attachments/assets/bdbea9f8-0dde-414b-8eec-30ff09af3bf9
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
https://github.com/user-attachments/assets/c0c0c2ef-a8a4-4c8d-8621-a277f7ad2307
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)
https://github.com/user-attachments/assets/5a511a6e-65cd-4a7a-888a-4e440cb033ec
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
Activity
20Please replicate in sway and cosmic-comp
Please replicate in sway and cosmic-comp
Ah forgot to mention it. Cosmic is the same as niri; sway's the same as Hyprland.
Ah forgot to mention it. Cosmic is the same as niri; sway's the same as Hyprland.
Ah forgot to mention it. Cosmic is the same as niri; sway's the same as Hyprland.
Does the protocol say anything? What does mutter do?
Does the protocol say anything? What does mutter do?
Does the protocol say anything? What does mutter do?
I have kwin_wayland installed so I tested with it. Kwin_wayland is the same as sway, Hyprland: moving over the surface that has requested a locked constraint but is not keyboard-focused, will hide the cursor (only when moving over it) but will not reactivate the constraint unless I click it.
In the wayland protocol, I can find this:
A surface may receive pointer focus without the lock being activated.
so I think the wayland definitely is not enforcing an immediately pointer constraint reactivation when the surface is just having a pointer focus (e.g. mouse just goes over it) instead of a keyboard focus.
I have kwin_wayland installed so I tested with it. Kwin_wayland is the same as sway, Hyprland: moving over the surface that has requested a locked constraint but is not keyboard-focused, will hide the cursor (only when moving over it) but will not reactivate the constraint unless I click it.
In the wayland protocol, I can find this:
A surface may receive pointer focus without the lock being activated.
so I think wayland definitely is not enforcing an immediate pointer constraint reactivation when the surface is just having a pointer focus (e.g. mouse just goes over it) instead of a keyboard focus.
I have kwin_wayland installed so I tested with it. Kwin_wayland is the same as sway, Hyprland: moving over the surface that has requested a locked constraint but is not keyboard-focused, will hide the cursor (only when moving over it) but will not reactivate the constraint unless I click it.
In the wayland protocol, I can find this:
A surface may receive pointer focus without the lock being activated.
so I think wayland definitely is not enforcing an immediate pointer constraint reactivation when the surface is just having a pointer focus (e.g. mouse just goes over it) instead of a keyboard focus.
Though in this case I think a better user intent is that the pointer should not hide when moving over the keyboard-unfocused surface unless a click. This is a new question: should the pointer change its cursor_image when moving over a keyboard-unfocused surface? I'm not sure.. (well. Maybe it should) Also I'm interested in what mutter does so later when I have time, will test it later.
And since the patch above fixes it so that niri does exactly as sway, Hyprland and kwin, i'll be happy if it "looks good to u" then I can do this contribution.? :)
Though in this case I think a better user intent is that the pointer should not hide when moving over the keyboard-unfocused surface unless a click. This is a new question: should the pointer change its cursor_image when moving over a keyboard-unfocused surface? I'm not sure.. (well. Maybe it should) Also I'm interested in what mutter does so later when I have time, will test it later.
And since the patch above fixes it so that niri does exactly as sway, Hyprland and kwin, i'll be happy if it "looks good to u" then I can do this contribution.? :)
Though in this case I think a better user intent is that the pointer should not hide when moving over the keyboard-unfocused surface unless a click. This is a new question: should the pointer change its cursor_image when moving over a keyboard-unfocused surface? I'm not sure.. (well. Maybe it should) Also I'm interested in what mutter does so later when I have time, will test it later.
And since the patch above fixes it so that niri does exactly as sway, Hyprland and kwin, i'll be happy if it "looks good to u" then I can do this contribution.? :)
Test mutter but it sounds ok to me to only give pointer constraint to (surface of a) window with keyboard focus (your patch will probably only work on the main surface and not on a subsurface)
Test mutter but it sounds ok to me to only give pointer constraint to (surface of a) window with keyboard focus (your patch will probably only work on the main surface and not on a subsurface)
Test mutter
Done. Same as Sway, Hyprland, kwin.
https://github.com/user-attachments/assets/a8b33f8b-d1f2-4a6a-992d-031a210cb0a8
Test mutter
Done. Same as Sway, Hyprland, kwin.
https://github.com/user-attachments/assets/a8b33f8b-d1f2-4a6a-992d-031a210cb0a8
Do we have a working pull request for this?
Please replicate in sway and cosmic-comp