From e09fcec9f3f0cf147990e473dd84dd22eb932ab8 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Wed, 1 Oct 2025 13:40:39 -0700 Subject: [PATCH] Use keyboard focus target rather than `focus_stack` in keybindings `Action::Close` already used the keyboard focus target, but some other bindings didn't. Presumably it's most intuitive if all "current window" key bindings affect the window with keyboard focus. These used the focus stack on the `focused_output()` (the one with keyboard focus), so I guess the main impact is when the keyboard target is a window being dragged? Then the binding will operate on that window, or have no effect. This seems related to some of the behaviors discussed in https://github.com/pop-os/cosmic-comp/issues/453. --- src/input/actions.rs | 36 ++++++++++++++---------------------- src/shell/focus/target.rs | 8 ++++++++ src/shell/seats.rs | 3 +-- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/input/actions.rs b/src/input/actions.rs index 9fa356b4..5f14e60a 100644 --- a/src/input/actions.rs +++ b/src/input/actions.rs @@ -873,26 +873,22 @@ impl State { } Action::Minimize => { - let Some(focused_output) = seat.focused_output() else { - return; - }; let mut shell = self.common.shell.write(); - let workspace = shell.active_space_mut(&focused_output).unwrap(); - let focus_stack = workspace.focus_stack.get(seat); - if let Some(surface) = focus_stack.last().and_then(FocusTarget::wl_surface) { - shell.minimize_request(&surface); + if let Some(focused_window) = seat + .get_keyboard() + .unwrap() + .current_focus() + .and_then(|f| f.active_window()) + { + shell.minimize_request(&focused_window); } } Action::Maximize => { - let Some(focused_output) = seat.focused_output() else { - return; - }; let mut shell = self.common.shell.write(); - let workspace = shell.active_space(&focused_output).unwrap(); - let focus_stack = workspace.focus_stack.get(seat); - let focused_window = focus_stack.last().cloned(); - if let Some(FocusTarget::Window(window)) = focused_window { + if let Some(KeyboardFocusTarget::Element(window)) = + seat.get_keyboard().unwrap().current_focus() + { shell.maximize_toggle(&window, seat, &self.common.event_loop_handle); } } @@ -902,22 +898,18 @@ impl State { return; }; let mut shell = self.common.shell.write(); - let workspace = shell.active_space(&focused_output).unwrap(); - let focus_stack = workspace.focus_stack.get(seat); - let focused_window = focus_stack.last().cloned(); - match focused_window { - Some(FocusTarget::Window(window)) => { - let output = workspace.output.clone(); + match seat.get_keyboard().unwrap().current_focus() { + Some(KeyboardFocusTarget::Element(window)) => { if let Some(target) = shell.fullscreen_request( &window.active_window(), - output, + focused_output, &self.common.event_loop_handle, ) { std::mem::drop(shell); Shell::set_focus(self, Some(&target), seat, Some(serial), true); } } - Some(FocusTarget::Fullscreen(surface)) => { + Some(KeyboardFocusTarget::Fullscreen(surface)) => { if let Some(target) = shell.unfullscreen_request(&surface, &self.common.event_loop_handle) { diff --git a/src/shell/focus/target.rs b/src/shell/focus/target.rs index c2d270b4..c3c78ffb 100644 --- a/src/shell/focus/target.rs +++ b/src/shell/focus/target.rs @@ -220,6 +220,14 @@ impl KeyboardFocusTarget { } } + pub fn active_window(&self) -> Option { + match self { + KeyboardFocusTarget::Element(mapped) => Some(mapped.active_window()), + KeyboardFocusTarget::Fullscreen(surface) => Some(surface.clone()), + _ => None, + } + } + fn x11_surface(&self) -> Option { match self { KeyboardFocusTarget::Element(mapped) => mapped.active_window().x11_surface().cloned(), diff --git a/src/shell/seats.rs b/src/shell/seats.rs index 4a40f9af..4434be95 100644 --- a/src/shell/seats.rs +++ b/src/shell/seats.rs @@ -268,8 +268,7 @@ impl SeatExt for Seat { } /// Returns the output that contains the cursor associated with a seat. Note that the window which has keyboard focus - /// may be on a different output. Currently, to get the focused output, first get the keyboard focus target and pass - /// it to get_focused_output in the shell. + /// may be on a different output. Currently, to get the focused output, use [`Self::focused_output`]. fn active_output(&self) -> Output { self.user_data() .get::()