diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2025-09-02 08:07:22 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2025-10-15 09:04:16 +0300 |
| commit | e1fad994da9565b43c7fb139cb2fb7bf404cc320 (patch) | |
| tree | 305fa0714d66ad2b4346b3aee6eb785099b29fa1 /src/tests/window_opening.rs | |
| parent | e5d4e7c1b1a0b61770b6711a53fe41920d56452d (diff) | |
| download | niri-e1fad994da9565b43c7fb139cb2fb7bf404cc320.tar.gz niri-e1fad994da9565b43c7fb139cb2fb7bf404cc320.tar.bz2 niri-e1fad994da9565b43c7fb139cb2fb7bf404cc320.zip | |
Implement maximize-to-edges (true Wayland maximize)
Diffstat (limited to 'src/tests/window_opening.rs')
| -rw-r--r-- | src/tests/window_opening.rs | 233 |
1 files changed, 230 insertions, 3 deletions
diff --git a/src/tests/window_opening.rs b/src/tests/window_opening.rs index 9a2ff6da..fb546e59 100644 --- a/src/tests/window_opening.rs +++ b/src/tests/window_opening.rs @@ -5,7 +5,7 @@ use niri_config::Config; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use super::*; -use crate::layout::LayoutElement; +use crate::layout::LayoutElement as _; use crate::utils::with_toplevel_role; #[test] @@ -106,6 +106,28 @@ impl fmt::Display for WantFullscreen { } #[derive(Clone, Copy)] +enum WantMaximized { + No, + UnsetBeforeInitial, + BeforeInitial, + UnsetAfterInitial, + AfterInitial, +} + +impl fmt::Display for WantMaximized { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + WantMaximized::No => write!(f, "U")?, + WantMaximized::UnsetBeforeInitial => write!(f, "BU")?, + WantMaximized::UnsetAfterInitial => write!(f, "AU")?, + WantMaximized::BeforeInitial => write!(f, "B")?, + WantMaximized::AfterInitial => write!(f, "A")?, + } + Ok(()) + } +} + +#[derive(Clone, Copy)] enum SetParent { BeforeInitial(&'static str), AfterInitial(&'static str), @@ -369,7 +391,7 @@ window-rule {{ }) }) .unwrap(); - let is_fullscreen = mapped.is_fullscreen(); + let is_fullscreen = mapped.sizing_mode().is_fullscreen(); let win = mapped.window.clone(); let mon = mon.unwrap().output_name().clone(); let ws = ws.name().cloned().unwrap_or(String::from("unnamed")); @@ -629,7 +651,7 @@ layout { // If the window ended up fullscreen, unfullscreen it and output the configure. let mut post_unfullscreen = String::new(); let mapped = f.niri().layout.windows().next().unwrap().1; - let is_fullscreen = mapped.is_fullscreen(); + let is_fullscreen = mapped.sizing_mode().is_fullscreen(); let win = mapped.window.clone(); if is_fullscreen { f.niri().layout.set_fullscreen(&win, false); @@ -657,3 +679,208 @@ post-map configures: let _guard = settings.bind_to_scope(); assert_snapshot!(snapshot); } + +#[test] +fn fullscreen_maximize() { + let open_fullscreen = [None, Some("false"), Some("true")]; + let want_fullscreen = [ + WantFullscreen::No, + WantFullscreen::UnsetBeforeInitial, // GTK 4 + WantFullscreen::BeforeInitial(None), + WantFullscreen::UnsetAfterInitial, + // mpv, osu! + WantFullscreen::AfterInitial(None), + ]; + let open_maximized = [None, Some("false"), Some("true")]; + let want_maximized = [ + WantMaximized::No, + WantMaximized::UnsetBeforeInitial, + WantMaximized::BeforeInitial, + WantMaximized::UnsetAfterInitial, + WantMaximized::AfterInitial, + ]; + + let mut powerset = Vec::new(); + for fs in open_fullscreen { + for wfs in want_fullscreen { + for tm in open_maximized { + for wm in want_maximized { + powerset.push((fs, wfs, tm, wm)); + } + } + } + } + + powerset.into_par_iter().for_each(|(fs, wfs, tm, wm)| { + check_fullscreen_maximize(fs, wfs, tm, wm); + }); +} + +fn check_fullscreen_maximize( + open_fullscreen: Option<&str>, + want_fullscreen: WantFullscreen, + open_maximized: Option<&str>, + want_maximized: WantMaximized, +) { + let mut snapshot_desc = Vec::new(); + let mut snapshot_suffix = Vec::new(); + + let mut config = String::from( + r##" +window-rule { +"##, + ); + + if let Some(x) = open_fullscreen { + writeln!(config, " open-fullscreen {x}").unwrap(); + + let x = if x == "true" { "T" } else { "F" }; + snapshot_suffix.push(format!("fs{x}")); + } + + if let Some(x) = open_maximized { + writeln!(config, " open-maximized-to-edges {x}").unwrap(); + + let x = if x == "true" { "T" } else { "F" }; + snapshot_suffix.push(format!("tm{x}")); + } + + config.push('}'); + + match &want_fullscreen { + WantFullscreen::No => (), + x => { + snapshot_desc.push(format!("want fullscreen: {x}")); + snapshot_suffix.push(format!("wfs{x}")); + } + } + + match &want_maximized { + WantMaximized::No => (), + x => { + snapshot_desc.push(format!("want maximized: {x}")); + snapshot_suffix.push(format!("wm{x}")); + } + } + + snapshot_desc.push(format!("config:{config}")); + + let config = Config::parse_mem(&config).unwrap(); + + let mut f = Fixture::with_config(config); + f.add_output(1, (1280, 720)); + f.add_output(2, (1920, 1080)); + + let id = f.add_client(); + + // To get output names. + f.roundtrip(id); + + let client = f.client(id); + let window = client.create_window(); + let surface = window.surface.clone(); + + if let WantMaximized::UnsetBeforeInitial = want_maximized { + client.window(&surface).unset_maximized(); + } else if let WantMaximized::BeforeInitial = want_maximized { + client.window(&surface).set_maximized(); + } + + if let WantFullscreen::UnsetBeforeInitial = want_fullscreen { + client.window(&surface).unset_fullscreen(); + } else if let WantFullscreen::BeforeInitial(mon) = want_fullscreen { + let output = mon.map(|mon| client.output(&format!("headless-{mon}"))); + client.window(&surface).set_fullscreen(output.as_ref()); + } + + client.window(&surface).commit(); + f.roundtrip(id); + + let client = f.client(id); + let initial = client.window(&surface).format_recent_configures(); + + if let WantMaximized::UnsetAfterInitial = want_maximized { + client.window(&surface).unset_maximized(); + } else if let WantMaximized::AfterInitial = want_maximized { + client.window(&surface).set_maximized(); + } + + if let WantFullscreen::UnsetAfterInitial = want_fullscreen { + client.window(&surface).unset_fullscreen(); + } else if let WantFullscreen::AfterInitial(mon) = want_fullscreen { + let output = mon.map(|mon| client.output(&format!("headless-{mon}"))); + client.window(&surface).set_fullscreen(output.as_ref()); + } + + let window = client.window(&surface); + window.attach_new_buffer(); + let serial = window.configures_received.last().unwrap().0; + window.ack_last_and_commit(); + f.double_roundtrip(id); + + // Commit to the post-initial configures. + let window = f.client(id).window(&surface); + let new_serial = window.configures_received.last().unwrap().0; + if new_serial != serial { + window.ack_last_and_commit(); + f.double_roundtrip(id); + } + + let window = f.client(id).window(&surface); + let post_map = window.format_recent_configures(); + + // If the window ended up fullscreen, unfullscreen it and output the configure. + let mut post_unfullscreen = String::new(); + let mapped = f.niri().layout.windows().next().unwrap().1; + let is_fullscreen = mapped.sizing_mode().is_fullscreen(); + let win = mapped.window.clone(); + if is_fullscreen { + f.niri().layout.set_fullscreen(&win, false); + f.double_roundtrip(id); + + let window = f.client(id).window(&surface); + window.ack_last_and_commit(); + f.double_roundtrip(id); + + let window = f.client(id).window(&surface); + post_unfullscreen = format!( + "\n\nunfullscreen configure:\n{}", + window.format_recent_configures() + ); + } + + // If the window ended up maximized, unmaximize it and output the configure. + let mut post_unmaximize = String::new(); + let mapped = f.niri().layout.windows().next().unwrap().1; + let is_maximized = mapped.sizing_mode().is_maximized(); + let win = mapped.window.clone(); + if is_maximized { + f.niri().layout.set_maximized(&win, false); + f.double_roundtrip(id); + + let window = f.client(id).window(&surface); + window.ack_last_and_commit(); + f.double_roundtrip(id); + + let window = f.client(id).window(&surface); + post_unmaximize = format!( + "\n\nunmaximize configure:\n{}", + window.format_recent_configures() + ); + } + + let snapshot = format!( + "\ +initial configure: +{initial} + +post-map configures: +{post_map}{post_unfullscreen}{post_unmaximize}", + ); + + let mut settings = insta::Settings::clone_current(); + settings.set_snapshot_suffix(snapshot_suffix.join("-")); + settings.set_description(snapshot_desc.join("\n")); + let _guard = settings.bind_to_scope(); + assert_snapshot!(snapshot); +} |
