aboutsummaryrefslogtreecommitdiff
path: root/src/layout
diff options
context:
space:
mode:
authorChristian Meissl <meissl.christian@gmail.com>2024-11-16 22:35:34 +0100
committerIvan Molodetskikh <yalterz@gmail.com>2024-11-29 21:57:36 -0800
commit305fc3b5576c4c6e3d899b3413dbbb8727922cfe (patch)
tree718972dcc035e6d5bb264e519a92d92884bbcf4f /src/layout
parent61f2ac01d782f1142aefb78d1286db005021a7a0 (diff)
downloadniri-305fc3b5576c4c6e3d899b3413dbbb8727922cfe.tar.gz
niri-305fc3b5576c4c6e3d899b3413dbbb8727922cfe.tar.bz2
niri-305fc3b5576c4c6e3d899b3413dbbb8727922cfe.zip
Activate newly mapped windows with a valid activation token
most of the time the activation token is passed while the window is still unmapped. in this case store the intend to activate the window for later retrieval on map.
Diffstat (limited to 'src/layout')
-rw-r--r--src/layout/mod.rs110
1 files changed, 78 insertions, 32 deletions
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index ad6f1b2b..c2424ba8 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -358,6 +358,18 @@ pub struct RemovedTile<W: LayoutElement> {
is_full_width: bool,
}
+/// Whether to activate a newly added window.
+#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
+pub enum ActivateWindow {
+ /// Activate unconditionally.
+ Yes,
+ /// Activate based on heuristics.
+ #[default]
+ Smart,
+ /// Do not activate.
+ No,
+}
+
impl<W: LayoutElement> InteractiveMoveState<W> {
fn moving(&self) -> Option<&InteractiveMoveData<W>> {
match self {
@@ -383,6 +395,16 @@ impl<W: LayoutElement> InteractiveMoveData<W> {
}
}
+impl ActivateWindow {
+ pub fn map_smart(self, f: impl FnOnce() -> bool) -> bool {
+ match self {
+ ActivateWindow::Yes => true,
+ ActivateWindow::Smart => f(),
+ ActivateWindow::No => false,
+ }
+ }
+}
+
impl Options {
fn from_config(config: &Config) -> Self {
let layout = &config.layout;
@@ -753,6 +775,7 @@ impl<W: LayoutElement> Layout<W> {
window: W,
width: Option<ColumnWidth>,
is_full_width: bool,
+ activate: ActivateWindow,
) -> Option<&Output> {
let width = self.resolve_default_width(&window, width);
@@ -771,20 +794,27 @@ impl<W: LayoutElement> Layout<W> {
})
.unwrap();
- // Don't steal focus from an active fullscreen window.
- let mut activate = true;
- let ws = &mon.workspaces[ws_idx];
- if mon_idx == *active_monitor_idx
- && !ws.columns.is_empty()
- && ws.columns[ws.active_column_idx].is_fullscreen
- {
- activate = false;
+ if activate == ActivateWindow::Yes {
+ *active_monitor_idx = mon_idx;
}
- // Don't activate if on a different workspace.
- if mon.active_workspace_idx != ws_idx {
- activate = false;
- }
+ let activate = activate.map_smart(|| {
+ // Don't steal focus from an active fullscreen window.
+ let ws = &mon.workspaces[ws_idx];
+ if mon_idx == *active_monitor_idx
+ && !ws.columns.is_empty()
+ && ws.columns[ws.active_column_idx].is_fullscreen
+ {
+ return false;
+ }
+
+ // Don't activate if on a different workspace.
+ if mon.active_workspace_idx != ws_idx {
+ return false;
+ }
+
+ true
+ });
mon.add_window(ws_idx, window, activate, width, is_full_width);
Some(&mon.output)
@@ -798,7 +828,8 @@ impl<W: LayoutElement> Layout<W> {
.map_or(false, |name| name.eq_ignore_ascii_case(workspace_name))
})
.unwrap();
- ws.add_window(None, window, true, width, is_full_width);
+ let activate = activate.map_smart(|| true);
+ ws.add_window(None, window, activate, width, is_full_width);
None
}
}
@@ -835,6 +866,7 @@ impl<W: LayoutElement> Layout<W> {
window: W,
width: Option<ColumnWidth>,
is_full_width: bool,
+ activate: ActivateWindow,
) -> Option<&Output> {
let width = self.resolve_default_width(&window, width);
@@ -846,12 +878,11 @@ impl<W: LayoutElement> Layout<W> {
} => {
let mon = &mut monitors[*active_monitor_idx];
- // Don't steal focus from an active fullscreen window.
- let mut activate = true;
- let ws = &mon.workspaces[mon.active_workspace_idx];
- if !ws.columns.is_empty() && ws.columns[ws.active_column_idx].is_fullscreen {
- activate = false;
- }
+ let activate = activate.map_smart(|| {
+ // Don't steal focus from an active fullscreen window.
+ let ws = &mon.workspaces[mon.active_workspace_idx];
+ ws.columns.is_empty() || !ws.columns[ws.active_column_idx].is_fullscreen
+ });
mon.add_window(
mon.active_workspace_idx,
@@ -872,7 +903,8 @@ impl<W: LayoutElement> Layout<W> {
));
&mut workspaces[0]
};
- ws.add_window(None, window, true, width, is_full_width);
+ let activate = activate.map_smart(|| true);
+ ws.add_window(None, window, activate, width, is_full_width);
None
}
}
@@ -893,11 +925,12 @@ impl<W: LayoutElement> Layout<W> {
if let Some(InteractiveMoveState::Moving(move_)) = &self.interactive_move {
if right_of == move_.tile.window().id() {
let output = move_.output.clone();
+ let activate = ActivateWindow::default();
if self.monitor_for_output(&output).is_some() {
- self.add_window_on_output(&output, window, width, is_full_width);
+ self.add_window_on_output(&output, window, width, is_full_width, activate);
return Some(&self.monitor_for_output(&output).unwrap().output);
} else {
- return self.add_window(window, width, is_full_width);
+ return self.add_window(window, width, is_full_width, activate);
}
}
}
@@ -932,6 +965,7 @@ impl<W: LayoutElement> Layout<W> {
window: W,
width: Option<ColumnWidth>,
is_full_width: bool,
+ activate: ActivateWindow,
) {
let width = self.resolve_default_width(&window, width);
@@ -950,16 +984,22 @@ impl<W: LayoutElement> Layout<W> {
.find(|(_, mon)| mon.output == *output)
.unwrap();
- // Don't steal focus from an active fullscreen window.
- let mut activate = true;
- let ws = &mon.workspaces[mon.active_workspace_idx];
- if mon_idx == *active_monitor_idx
- && !ws.columns.is_empty()
- && ws.columns[ws.active_column_idx].is_fullscreen
- {
- activate = false;
+ if activate == ActivateWindow::Yes {
+ *active_monitor_idx = mon_idx;
}
+ let activate = activate.map_smart(|| {
+ // Don't steal focus from an active fullscreen window.
+ let ws = &mon.workspaces[mon.active_workspace_idx];
+ if mon_idx == *active_monitor_idx
+ && !ws.columns.is_empty()
+ && ws.columns[ws.active_column_idx].is_fullscreen
+ {
+ return false;
+ }
+ true
+ });
+
mon.add_window(
mon.active_workspace_idx,
window,
@@ -4365,7 +4405,7 @@ mod tests {
}
let win = TestWindow::new(id, bbox, min_max_size.0, min_max_size.1);
- layout.add_window(win, None, false);
+ layout.add_window(win, None, false, ActivateWindow::default());
}
Op::AddWindowRightOf {
id,
@@ -4482,7 +4522,13 @@ mod tests {
}
let win = TestWindow::new(id, bbox, min_max_size.0, min_max_size.1);
- layout.add_window_to_named_workspace(&ws_name, win, None, false);
+ layout.add_window_to_named_workspace(
+ &ws_name,
+ win,
+ None,
+ false,
+ ActivateWindow::default(),
+ );
}
Op::CloseWindow(id) => {
layout.remove_window(&id, Transaction::new());