mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-23 02:05:33 +07:00
Reimplement focus-previous-window with MRU focus timestamps
Makes it consistent with the MRU and improves the behavior: - considers MRU's debounce - fixes problematic cases where focus changes to non-Layout and back
This commit is contained in:
+13
-1
@@ -779,7 +779,19 @@ impl State {
|
|||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::FocusWindowPrevious => {
|
Action::FocusWindowPrevious => {
|
||||||
if let Some(window) = self.niri.previously_focused_window.clone() {
|
let current = self.niri.layout.focus().map(|win| win.id());
|
||||||
|
if let Some(window) = self
|
||||||
|
.niri
|
||||||
|
.layout
|
||||||
|
.windows()
|
||||||
|
.map(|(_, win)| win)
|
||||||
|
.filter(|win| Some(win.id()) != current)
|
||||||
|
.max_by_key(|win| win.get_focus_timestamp())
|
||||||
|
.map(|win| win.window.clone())
|
||||||
|
{
|
||||||
|
// Commit current focus so repeated focus-window-previous works as expected.
|
||||||
|
self.niri.mru_apply_keyboard_commit();
|
||||||
|
|
||||||
self.focus_window(&window);
|
self.focus_window(&window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-29
@@ -325,7 +325,6 @@ pub struct Niri {
|
|||||||
pub bind_repeat_timer: Option<RegistrationToken>,
|
pub bind_repeat_timer: Option<RegistrationToken>,
|
||||||
pub keyboard_focus: KeyboardFocus,
|
pub keyboard_focus: KeyboardFocus,
|
||||||
pub layer_shell_on_demand_focus: Option<LayerSurface>,
|
pub layer_shell_on_demand_focus: Option<LayerSurface>,
|
||||||
pub previously_focused_window: Option<Window>,
|
|
||||||
pub idle_inhibiting_surfaces: HashSet<WlSurface>,
|
pub idle_inhibiting_surfaces: HashSet<WlSurface>,
|
||||||
pub is_fdo_idle_inhibited: Arc<AtomicBool>,
|
pub is_fdo_idle_inhibited: Arc<AtomicBool>,
|
||||||
pub keyboard_shortcuts_inhibiting_surfaces: HashMap<WlSurface, KeyboardShortcutsInhibitor>,
|
pub keyboard_shortcuts_inhibiting_surfaces: HashMap<WlSurface, KeyboardShortcutsInhibitor>,
|
||||||
@@ -1232,14 +1231,12 @@ impl State {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Tell the windows their new focus state for window rule purposes.
|
// Tell the windows their new focus state for window rule purposes.
|
||||||
let mut previous_focus = None;
|
|
||||||
if let KeyboardFocus::Layout {
|
if let KeyboardFocus::Layout {
|
||||||
surface: Some(surface),
|
surface: Some(surface),
|
||||||
} = &self.niri.keyboard_focus
|
} = &self.niri.keyboard_focus
|
||||||
{
|
{
|
||||||
if let Some((mapped, _)) = self.niri.layout.find_window_and_output_mut(surface) {
|
if let Some((mapped, _)) = self.niri.layout.find_window_and_output_mut(surface) {
|
||||||
mapped.set_is_focused(false);
|
mapped.set_is_focused(false);
|
||||||
previous_focus = Some(mapped.window.clone());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let KeyboardFocus::Layout {
|
if let KeyboardFocus::Layout {
|
||||||
@@ -1283,31 +1280,6 @@ impl State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the previous focus but only when staying focused on the layout.
|
|
||||||
//
|
|
||||||
// Case 1: opening and closing exclusive-keyboard layer-shell (e.g. app launcher). This
|
|
||||||
// involves going from Layout to LayerShell, then from LayerShell to Layout. The
|
|
||||||
// previously focused window should stay unchanged.
|
|
||||||
//
|
|
||||||
// Case 1.5: opening layer-shell, in the background switching layout focus, closing
|
|
||||||
// layer-shell. With the current logic, this won't update the previously focused
|
|
||||||
// window, which is incorrect. But this case should be rare.
|
|
||||||
//
|
|
||||||
// Case 2: switching to an empty workspace, then hitting FocusWindowPrevious. The focus
|
|
||||||
// should go to the window that was just focused. The keyboard focus goes from Layout
|
|
||||||
// (with Some surface) to Layout (with None surface), so we update the previously
|
|
||||||
// focused window.
|
|
||||||
//
|
|
||||||
// FIXME: Ideally this should happen inside Layout itself, then there wouldn't be any
|
|
||||||
// problems with layer-shell, etc. Or a similar problem now with the Overview where we
|
|
||||||
// don't update the previously focused window because the keyboard focus is on the
|
|
||||||
// Overview rather than on the Layout.
|
|
||||||
if matches!(self.niri.keyboard_focus, KeyboardFocus::Layout { .. })
|
|
||||||
&& matches!(focus, KeyboardFocus::Layout { .. })
|
|
||||||
{
|
|
||||||
self.niri.previously_focused_window = previous_focus;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(grab) = self.niri.popup_grab.as_mut() {
|
if let Some(grab) = self.niri.popup_grab.as_mut() {
|
||||||
if grab.has_keyboard_grab && Some(&grab.root) != focus.surface() {
|
if grab.has_keyboard_grab && Some(&grab.root) != focus.surface() {
|
||||||
trace!(
|
trace!(
|
||||||
@@ -2787,7 +2759,6 @@ impl Niri {
|
|||||||
seat,
|
seat,
|
||||||
keyboard_focus: KeyboardFocus::Layout { surface: None },
|
keyboard_focus: KeyboardFocus::Layout { surface: None },
|
||||||
layer_shell_on_demand_focus: None,
|
layer_shell_on_demand_focus: None,
|
||||||
previously_focused_window: None,
|
|
||||||
idle_inhibiting_surfaces: HashSet::new(),
|
idle_inhibiting_surfaces: HashSet::new(),
|
||||||
is_fdo_idle_inhibited: Arc::new(AtomicBool::new(false)),
|
is_fdo_idle_inhibited: Arc::new(AtomicBool::new(false)),
|
||||||
keyboard_shortcuts_inhibiting_surfaces: HashMap::new(),
|
keyboard_shortcuts_inhibiting_surfaces: HashMap::new(),
|
||||||
|
|||||||
Reference in New Issue
Block a user