aboutsummaryrefslogtreecommitdiff
path: root/src/handlers
diff options
context:
space:
mode:
Diffstat (limited to 'src/handlers')
-rw-r--r--src/handlers/compositor.rs18
-rw-r--r--src/handlers/xdg_shell.rs88
2 files changed, 73 insertions, 33 deletions
diff --git a/src/handlers/compositor.rs b/src/handlers/compositor.rs
index 7d3f0419..2afb8fe8 100644
--- a/src/handlers/compositor.rs
+++ b/src/handlers/compositor.rs
@@ -119,22 +119,27 @@ impl CompositorHandler for State {
let toplevel = window.toplevel().expect("no X11 support");
- let (rules, width, is_full_width, output) =
+ let (rules, width, is_full_width, output, workspace_name) =
if let InitialConfigureState::Configured {
rules,
width,
is_full_width,
output,
+ workspace_name,
} = state
{
// Check that the output is still connected.
let output =
output.filter(|o| self.niri.layout.monitor_for_output(o).is_some());
- (rules, width, is_full_width, output)
+ // Chech that the workspace still exists.
+ let workspace_name = workspace_name
+ .filter(|n| self.niri.layout.find_workspace_by_name(n).is_some());
+
+ (rules, width, is_full_width, output, workspace_name)
} else {
error!("window map must happen after initial configure");
- (ResolvedWindowRules::empty(), None, false, None)
+ (ResolvedWindowRules::empty(), None, false, None, None)
};
let parent = toplevel
@@ -160,6 +165,13 @@ impl CompositorHandler for State {
self.niri
.layout
.add_window_right_of(&p, mapped, width, is_full_width)
+ } else if let Some(workspace_name) = &workspace_name {
+ self.niri.layout.add_window_to_named_workspace(
+ workspace_name,
+ mapped,
+ width,
+ is_full_width,
+ )
} else if let Some(output) = &output {
self.niri
.layout
diff --git a/src/handlers/xdg_shell.rs b/src/handlers/xdg_shell.rs
index 44f07839..30df1d5f 100644
--- a/src/handlers/xdg_shell.rs
+++ b/src/handlers/xdg_shell.rs
@@ -369,38 +369,52 @@ impl XdgShellHandler for State {
width,
is_full_width,
output,
+ workspace_name,
} => {
// Figure out the monitor following a similar logic to initial configure.
// FIXME: deduplicate.
- let mon = output
- .as_ref()
- .and_then(|o| self.niri.layout.monitor_for_output(o))
- .map(|mon| (mon, false))
- // If not, check if we have a parent with a monitor.
- .or_else(|| {
- toplevel
- .parent()
- .and_then(|parent| self.niri.layout.find_window_and_output(&parent))
- .map(|(_win, output)| output)
- .and_then(|o| self.niri.layout.monitor_for_output(o))
- .map(|mon| (mon, true))
- })
- // If not, fall back to the active monitor.
- .or_else(|| {
- self.niri
- .layout
- .active_monitor_ref()
- .map(|mon| (mon, false))
- });
+ let mon = workspace_name
+ .as_deref()
+ .and_then(|name| self.niri.layout.monitor_for_workspace(name))
+ .map(|mon| (mon, false));
+
+ let mon = mon.or_else(|| {
+ output
+ .as_ref()
+ .and_then(|o| self.niri.layout.monitor_for_output(o))
+ .map(|mon| (mon, false))
+ // If not, check if we have a parent with a monitor.
+ .or_else(|| {
+ toplevel
+ .parent()
+ .and_then(|parent| {
+ self.niri.layout.find_window_and_output(&parent)
+ })
+ .map(|(_win, output)| output)
+ .and_then(|o| self.niri.layout.monitor_for_output(o))
+ .map(|mon| (mon, true))
+ })
+ // If not, fall back to the active monitor.
+ .or_else(|| {
+ self.niri
+ .layout
+ .active_monitor_ref()
+ .map(|mon| (mon, false))
+ })
+ });
*output = mon
.filter(|(_, parent)| !parent)
.map(|(mon, _)| mon.output.clone());
let mon = mon.map(|(mon, _)| mon);
- let ws = mon
- .map(|mon| mon.active_workspace_ref())
- .or_else(|| self.niri.layout.active_workspace());
+ let ws = workspace_name
+ .as_deref()
+ .and_then(|name| mon.map(|mon| mon.find_named_workspace(name)))
+ .unwrap_or_else(|| {
+ mon.map(|mon| mon.active_workspace_ref())
+ .or_else(|| self.niri.layout.active_workspace())
+ });
if let Some(ws) = ws {
toplevel.with_pending_state(|state| {
@@ -577,12 +591,20 @@ impl State {
return;
};
- // Pick the target monitor. First, check if we had an output set in the window rules.
+ // Pick the target monitor. First, check if we had a workspace set in the window rules.
let mon = rules
- .open_on_output
+ .open_on_workspace
.as_deref()
- .and_then(|name| self.niri.output_by_name.get(name))
- .and_then(|o| self.niri.layout.monitor_for_output(o));
+ .and_then(|name| self.niri.layout.monitor_for_workspace(name));
+
+ // If not, check if we had an output set in the window rules.
+ let mon = mon.or_else(|| {
+ rules
+ .open_on_output
+ .as_deref()
+ .and_then(|name| self.niri.output_by_name.get(name))
+ .and_then(|o| self.niri.layout.monitor_for_output(o))
+ });
// If not, check if the window requested one for fullscreen.
let mon = mon.or_else(|| {
@@ -622,9 +644,14 @@ impl State {
let is_full_width = rules.open_maximized.unwrap_or(false);
// Tell the surface the preferred size and bounds for its likely output.
- let ws = mon
- .map(|mon| mon.active_workspace_ref())
- .or_else(|| self.niri.layout.active_workspace());
+ let ws = rules
+ .open_on_workspace
+ .as_deref()
+ .and_then(|name| mon.map(|mon| mon.find_named_workspace(name)))
+ .unwrap_or_else(|| {
+ mon.map(|mon| mon.active_workspace_ref())
+ .or_else(|| self.niri.layout.active_workspace())
+ });
if let Some(ws) = ws {
// Set a fullscreen state based on window request and window rule.
@@ -663,6 +690,7 @@ impl State {
width,
is_full_width,
output,
+ workspace_name: ws.and_then(|w| w.name.clone()),
};
toplevel.send_configure();