From 51df1aba019dde896d32f32d7a8b21b71064ada3 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Sun, 24 Sep 2023 10:08:43 +0400 Subject: [PATCH] layout: Focus prev column when removing just created column This works similar to tabs in Firefox: when you create a tab and then close it without focusing any other tabs, the focus returns to the previously-focused tab, rather than the usual next tab. The logic is that in this case, the new tab was likely transient, and the user wants to get right back to what they were doing. In niri's case, this also serves as a workaround for wl-clipboard spawning and destroying a window, messing up the focus. --- src/layout.rs | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/layout.rs b/src/layout.rs index dbcc50833..e5caa1079 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -145,6 +145,16 @@ pub struct Workspace { /// Animation of the view offset, if one is currently ongoing. view_offset_anim: Option, + + /// Whether to activate the previous, rather than the next, column upon column removal. + /// + /// When a new column is created and removed with no focus changes in-between, it is more + /// natural to activate the previously-focused column. This variable tracks that. + /// + /// Since we only create-and-activate columns immediately to the right of the active column (in + /// contrast to tabs in Firefox, for example), we can track this as a bool, rather than an + /// index of the previous column to activate. + activate_prev_column_on_removal: bool, } /// Width of a column. @@ -1303,6 +1313,7 @@ impl Workspace { active_column_idx: 0, view_offset: 0, view_offset_anim: None, + activate_prev_column_on_removal: false, } } @@ -1315,6 +1326,7 @@ impl Workspace { active_column_idx: 0, view_offset: 0, view_offset_anim: None, + activate_prev_column_on_removal: false, } } @@ -1387,6 +1399,9 @@ impl Workspace { self.active_column_idx = idx; + // A different column was activated; reset the flag. + self.activate_prev_column_on_removal = false; + let new_x = self.column_x(idx) - PADDING; let new_view_offset = compute_new_view_offset( current_x, @@ -1441,6 +1456,7 @@ impl Workspace { if activate { self.activate_column(idx); + self.activate_prev_column_on_removal = true; } } @@ -1459,6 +1475,12 @@ impl Workspace { let window_idx = column.windows.iter().position(|win| win == window).unwrap(); column.windows.remove(window_idx); if column.windows.is_empty() { + if column_idx + 1 == self.active_column_idx { + // The previous column, that we were going to activate upon removal of the active + // column, has just been itself removed. + self.activate_prev_column_on_removal = false; + } + // FIXME: activate_column below computes current view position to compute the new view // position, which can include the column we're removing here. This leads to unwanted // view jumps. @@ -1467,9 +1489,13 @@ impl Workspace { return; } - if self.active_column_idx > column_idx { + if self.active_column_idx > column_idx + || (self.active_column_idx == column_idx && self.activate_prev_column_on_removal) + { // A column to the left was removed; preserve the current position. - self.activate_column(self.active_column_idx - 1); + // FIXME: preserve activate_prev_column_on_removal. + // Or, the active column was removed, and we needed to activate the previous column. + self.activate_column(self.active_column_idx.saturating_sub(1)); } else { self.activate_column(min(self.active_column_idx, self.columns.len() - 1)); }