diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-02-23 17:40:46 +0400 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-02-23 17:47:12 +0400 |
| commit | 506dcd99d7fafbe94f0444aed46c2f89f29612da (patch) | |
| tree | 9b07548afdbdac9a22ce19ec6e73ffa79cb63c66 /src | |
| parent | dfbc0241274317e0a90b5ca86fd6b5f3cab2e2bf (diff) | |
| download | niri-506dcd99d7fafbe94f0444aed46c2f89f29612da.tar.gz niri-506dcd99d7fafbe94f0444aed46c2f89f29612da.tar.bz2 niri-506dcd99d7fafbe94f0444aed46c2f89f29612da.zip | |
Handle un-/fullscreen after initial configure
Diffstat (limited to 'src')
| -rw-r--r-- | src/handlers/xdg_shell.rs | 101 |
1 files changed, 95 insertions, 6 deletions
diff --git a/src/handlers/xdg_shell.rs b/src/handlers/xdg_shell.rs index 155e893a..02468518 100644 --- a/src/handlers/xdg_shell.rs +++ b/src/handlers/xdg_shell.rs @@ -267,6 +267,8 @@ impl XdgShellHandler for State { toplevel: ToplevelSurface, wl_output: Option<wl_output::WlOutput>, ) { + let requested_output = wl_output.as_ref().and_then(Output::from_resource); + if let Some((window, current_output)) = self .niri .layout @@ -274,7 +276,7 @@ impl XdgShellHandler for State { { let window = window.clone(); - if let Some(requested_output) = wl_output.as_ref().and_then(Output::from_resource) { + if let Some(requested_output) = requested_output { if &requested_output != current_output { self.niri .layout @@ -290,12 +292,51 @@ impl XdgShellHandler for State { } else if let Some(unmapped) = self.niri.unmapped_windows.get_mut(toplevel.wl_surface()) { match &mut unmapped.state { InitialConfigureState::NotConfigured { wants_fullscreen } => { - *wants_fullscreen = Some(wl_output.as_ref().and_then(Output::from_resource)); + *wants_fullscreen = Some(requested_output); // The required configure will be the initial configure. } - InitialConfigureState::Configured { .. } => { - // FIXME: implement this once I figure out a good way without code duplication. + InitialConfigureState::Configured { output, .. } => { + // Figure out the monitor following a similar logic to initial configure. + // FIXME: deduplicate. + let mon = requested_output + .as_ref() + // If none requested, try currently configured output. + .or(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()); + + if let Some(ws) = ws { + toplevel.with_pending_state(|state| { + state.states.set(xdg_toplevel::State::Fullscreen); + }); + ws.configure_new_window(&unmapped.window, None); + } // We already sent the initial configure, so we need to reconfigure. toplevel.send_configure(); @@ -326,8 +367,56 @@ impl XdgShellHandler for State { // The required configure will be the initial configure. } - InitialConfigureState::Configured { .. } => { - // FIXME: implement this once I figure out a good way without code duplication. + InitialConfigureState::Configured { + width, + is_full_width, + output, + .. + } => { + // 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)) + }); + + *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()); + + if let Some(ws) = ws { + toplevel.with_pending_state(|state| { + state.states.unset(xdg_toplevel::State::Fullscreen); + }); + + let configure_width = if *is_full_width { + Some(ColumnWidth::Proportion(1.)) + } else { + *width + }; + ws.configure_new_window(&unmapped.window, configure_width); + } // We already sent the initial configure, so we need to reconfigure. toplevel.send_configure(); |
