From e1fad994da9565b43c7fb139cb2fb7bf404cc320 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Tue, 2 Sep 2025 08:07:22 +0300 Subject: Implement maximize-to-edges (true Wayland maximize) --- niri-config/src/binds.rs | 7 + niri-config/src/lib.rs | 1 + niri-config/src/window_rule.rs | 2 + niri-ipc/src/lib.rs | 8 + niri-visual-tests/src/cases/layout.rs | 6 +- niri-visual-tests/src/cases/window.rs | 10 +- niri-visual-tests/src/test_window.rs | 18 +- src/handlers/compositor.rs | 91 ++++-- src/handlers/mod.rs | 14 + src/handlers/xdg_shell.rs | 234 ++++++++++++- src/input/mod.rs | 17 + src/layout/floating.rs | 13 +- src/layout/mod.rs | 73 ++++- src/layout/scrolling.rs | 363 ++++++++++++++++----- src/layout/tests.rs | 163 +++++++-- src/layout/tile.rs | 171 +++++++--- src/layout/workspace.rs | 131 ++++++-- src/niri.rs | 13 +- src/protocols/foreign_toplevel.rs | 8 +- src/tests/client.rs | 8 + src/tests/floating.rs | 279 ++++++++++++++++ src/tests/fullscreen.rs | 42 ++- ..._window_opening__check_fullscreen_maximize.snap | 10 + ...heck_fullscreen_maximize@fsF-tmF-wfsAN-wmA.snap | 18 + ...eck_fullscreen_maximize@fsF-tmF-wfsAN-wmAU.snap | 15 + ...heck_fullscreen_maximize@fsF-tmF-wfsAN-wmB.snap | 14 + ...eck_fullscreen_maximize@fsF-tmF-wfsAN-wmBU.snap | 14 + ...g__check_fullscreen_maximize@fsF-tmF-wfsAN.snap | 14 + ...heck_fullscreen_maximize@fsF-tmF-wfsAU-wmA.snap | 15 + ...eck_fullscreen_maximize@fsF-tmF-wfsAU-wmAU.snap | 12 + ...heck_fullscreen_maximize@fsF-tmF-wfsAU-wmB.snap | 11 + ...eck_fullscreen_maximize@fsF-tmF-wfsAU-wmBU.snap | 11 + ...g__check_fullscreen_maximize@fsF-tmF-wfsAU.snap | 11 + ...heck_fullscreen_maximize@fsF-tmF-wfsBN-wmA.snap | 14 + ...eck_fullscreen_maximize@fsF-tmF-wfsBN-wmAU.snap | 11 + ...heck_fullscreen_maximize@fsF-tmF-wfsBN-wmB.snap | 10 + ...eck_fullscreen_maximize@fsF-tmF-wfsBN-wmBU.snap | 10 + ...g__check_fullscreen_maximize@fsF-tmF-wfsBN.snap | 10 + ...heck_fullscreen_maximize@fsF-tmF-wfsBU-wmA.snap | 14 + ...eck_fullscreen_maximize@fsF-tmF-wfsBU-wmAU.snap | 11 + ...heck_fullscreen_maximize@fsF-tmF-wfsBU-wmB.snap | 10 + ...eck_fullscreen_maximize@fsF-tmF-wfsBU-wmBU.snap | 10 + ...g__check_fullscreen_maximize@fsF-tmF-wfsBU.snap | 10 + ...ing__check_fullscreen_maximize@fsF-tmF-wmA.snap | 14 + ...ng__check_fullscreen_maximize@fsF-tmF-wmAU.snap | 11 + ...ing__check_fullscreen_maximize@fsF-tmF-wmB.snap | 10 + ...ng__check_fullscreen_maximize@fsF-tmF-wmBU.snap | 10 + ...opening__check_fullscreen_maximize@fsF-tmF.snap | 10 + ...heck_fullscreen_maximize@fsF-tmT-wfsAN-wmA.snap | 18 + ...eck_fullscreen_maximize@fsF-tmT-wfsAN-wmAU.snap | 15 + ...heck_fullscreen_maximize@fsF-tmT-wfsAN-wmB.snap | 17 + ...eck_fullscreen_maximize@fsF-tmT-wfsAN-wmBU.snap | 17 + ...g__check_fullscreen_maximize@fsF-tmT-wfsAN.snap | 17 + ...heck_fullscreen_maximize@fsF-tmT-wfsAU-wmA.snap | 15 + ...eck_fullscreen_maximize@fsF-tmT-wfsAU-wmAU.snap | 12 + ...heck_fullscreen_maximize@fsF-tmT-wfsAU-wmB.snap | 14 + ...eck_fullscreen_maximize@fsF-tmT-wfsAU-wmBU.snap | 14 + ...g__check_fullscreen_maximize@fsF-tmT-wfsAU.snap | 14 + ...heck_fullscreen_maximize@fsF-tmT-wfsBN-wmA.snap | 14 + ...eck_fullscreen_maximize@fsF-tmT-wfsBN-wmAU.snap | 11 + ...heck_fullscreen_maximize@fsF-tmT-wfsBN-wmB.snap | 13 + ...eck_fullscreen_maximize@fsF-tmT-wfsBN-wmBU.snap | 13 + ...g__check_fullscreen_maximize@fsF-tmT-wfsBN.snap | 13 + ...heck_fullscreen_maximize@fsF-tmT-wfsBU-wmA.snap | 14 + ...eck_fullscreen_maximize@fsF-tmT-wfsBU-wmAU.snap | 11 + ...heck_fullscreen_maximize@fsF-tmT-wfsBU-wmB.snap | 13 + ...eck_fullscreen_maximize@fsF-tmT-wfsBU-wmBU.snap | 13 + ...g__check_fullscreen_maximize@fsF-tmT-wfsBU.snap | 13 + ...ing__check_fullscreen_maximize@fsF-tmT-wmA.snap | 14 + ...ng__check_fullscreen_maximize@fsF-tmT-wmAU.snap | 11 + ...ing__check_fullscreen_maximize@fsF-tmT-wmB.snap | 13 + ...ng__check_fullscreen_maximize@fsF-tmT-wmBU.snap | 13 + ...opening__check_fullscreen_maximize@fsF-tmT.snap | 13 + ...g__check_fullscreen_maximize@fsF-wfsAN-wmA.snap | 18 + ...__check_fullscreen_maximize@fsF-wfsAN-wmAU.snap | 15 + ...g__check_fullscreen_maximize@fsF-wfsAN-wmB.snap | 17 + ...__check_fullscreen_maximize@fsF-wfsAN-wmBU.snap | 14 + ...ening__check_fullscreen_maximize@fsF-wfsAN.snap | 14 + ...g__check_fullscreen_maximize@fsF-wfsAU-wmA.snap | 15 + ...__check_fullscreen_maximize@fsF-wfsAU-wmAU.snap | 12 + ...g__check_fullscreen_maximize@fsF-wfsAU-wmB.snap | 14 + ...__check_fullscreen_maximize@fsF-wfsAU-wmBU.snap | 11 + ...ening__check_fullscreen_maximize@fsF-wfsAU.snap | 11 + ...g__check_fullscreen_maximize@fsF-wfsBN-wmA.snap | 14 + ...__check_fullscreen_maximize@fsF-wfsBN-wmAU.snap | 11 + ...g__check_fullscreen_maximize@fsF-wfsBN-wmB.snap | 13 + ...__check_fullscreen_maximize@fsF-wfsBN-wmBU.snap | 10 + ...ening__check_fullscreen_maximize@fsF-wfsBN.snap | 10 + ...g__check_fullscreen_maximize@fsF-wfsBU-wmA.snap | 14 + ...__check_fullscreen_maximize@fsF-wfsBU-wmAU.snap | 11 + ...g__check_fullscreen_maximize@fsF-wfsBU-wmB.snap | 13 + ...__check_fullscreen_maximize@fsF-wfsBU-wmBU.snap | 10 + ...ening__check_fullscreen_maximize@fsF-wfsBU.snap | 10 + ...opening__check_fullscreen_maximize@fsF-wmA.snap | 14 + ...pening__check_fullscreen_maximize@fsF-wmAU.snap | 11 + ...opening__check_fullscreen_maximize@fsF-wmB.snap | 13 + ...pening__check_fullscreen_maximize@fsF-wmBU.snap | 10 + ...dow_opening__check_fullscreen_maximize@fsF.snap | 10 + ...heck_fullscreen_maximize@fsT-tmF-wfsAN-wmA.snap | 18 + ...eck_fullscreen_maximize@fsT-tmF-wfsAN-wmAU.snap | 15 + ...heck_fullscreen_maximize@fsT-tmF-wfsAN-wmB.snap | 14 + ...eck_fullscreen_maximize@fsT-tmF-wfsAN-wmBU.snap | 14 + ...g__check_fullscreen_maximize@fsT-tmF-wfsAN.snap | 14 + ...heck_fullscreen_maximize@fsT-tmF-wfsAU-wmA.snap | 15 + ...eck_fullscreen_maximize@fsT-tmF-wfsAU-wmAU.snap | 12 + ...heck_fullscreen_maximize@fsT-tmF-wfsAU-wmB.snap | 11 + ...eck_fullscreen_maximize@fsT-tmF-wfsAU-wmBU.snap | 11 + ...g__check_fullscreen_maximize@fsT-tmF-wfsAU.snap | 11 + ...heck_fullscreen_maximize@fsT-tmF-wfsBN-wmA.snap | 17 + ...eck_fullscreen_maximize@fsT-tmF-wfsBN-wmAU.snap | 14 + ...heck_fullscreen_maximize@fsT-tmF-wfsBN-wmB.snap | 13 + ...eck_fullscreen_maximize@fsT-tmF-wfsBN-wmBU.snap | 13 + ...g__check_fullscreen_maximize@fsT-tmF-wfsBN.snap | 13 + ...heck_fullscreen_maximize@fsT-tmF-wfsBU-wmA.snap | 17 + ...eck_fullscreen_maximize@fsT-tmF-wfsBU-wmAU.snap | 14 + ...heck_fullscreen_maximize@fsT-tmF-wfsBU-wmB.snap | 13 + ...eck_fullscreen_maximize@fsT-tmF-wfsBU-wmBU.snap | 13 + ...g__check_fullscreen_maximize@fsT-tmF-wfsBU.snap | 13 + ...ing__check_fullscreen_maximize@fsT-tmF-wmA.snap | 17 + ...ng__check_fullscreen_maximize@fsT-tmF-wmAU.snap | 14 + ...ing__check_fullscreen_maximize@fsT-tmF-wmB.snap | 13 + ...ng__check_fullscreen_maximize@fsT-tmF-wmBU.snap | 13 + ...opening__check_fullscreen_maximize@fsT-tmF.snap | 13 + ...heck_fullscreen_maximize@fsT-tmT-wfsAN-wmA.snap | 18 + ...eck_fullscreen_maximize@fsT-tmT-wfsAN-wmAU.snap | 15 + ...heck_fullscreen_maximize@fsT-tmT-wfsAN-wmB.snap | 17 + ...eck_fullscreen_maximize@fsT-tmT-wfsAN-wmBU.snap | 17 + ...g__check_fullscreen_maximize@fsT-tmT-wfsAN.snap | 17 + ...heck_fullscreen_maximize@fsT-tmT-wfsAU-wmA.snap | 15 + ...eck_fullscreen_maximize@fsT-tmT-wfsAU-wmAU.snap | 12 + ...heck_fullscreen_maximize@fsT-tmT-wfsAU-wmB.snap | 14 + ...eck_fullscreen_maximize@fsT-tmT-wfsAU-wmBU.snap | 14 + ...g__check_fullscreen_maximize@fsT-tmT-wfsAU.snap | 14 + ...heck_fullscreen_maximize@fsT-tmT-wfsBN-wmA.snap | 17 + ...eck_fullscreen_maximize@fsT-tmT-wfsBN-wmAU.snap | 14 + ...heck_fullscreen_maximize@fsT-tmT-wfsBN-wmB.snap | 16 + ...eck_fullscreen_maximize@fsT-tmT-wfsBN-wmBU.snap | 16 + ...g__check_fullscreen_maximize@fsT-tmT-wfsBN.snap | 16 + ...heck_fullscreen_maximize@fsT-tmT-wfsBU-wmA.snap | 17 + ...eck_fullscreen_maximize@fsT-tmT-wfsBU-wmAU.snap | 14 + ...heck_fullscreen_maximize@fsT-tmT-wfsBU-wmB.snap | 16 + ...eck_fullscreen_maximize@fsT-tmT-wfsBU-wmBU.snap | 16 + ...g__check_fullscreen_maximize@fsT-tmT-wfsBU.snap | 16 + ...ing__check_fullscreen_maximize@fsT-tmT-wmA.snap | 17 + ...ng__check_fullscreen_maximize@fsT-tmT-wmAU.snap | 14 + ...ing__check_fullscreen_maximize@fsT-tmT-wmB.snap | 16 + ...ng__check_fullscreen_maximize@fsT-tmT-wmBU.snap | 16 + ...opening__check_fullscreen_maximize@fsT-tmT.snap | 16 + ...g__check_fullscreen_maximize@fsT-wfsAN-wmA.snap | 18 + ...__check_fullscreen_maximize@fsT-wfsAN-wmAU.snap | 15 + ...g__check_fullscreen_maximize@fsT-wfsAN-wmB.snap | 17 + ...__check_fullscreen_maximize@fsT-wfsAN-wmBU.snap | 14 + ...ening__check_fullscreen_maximize@fsT-wfsAN.snap | 14 + ...g__check_fullscreen_maximize@fsT-wfsAU-wmA.snap | 15 + ...__check_fullscreen_maximize@fsT-wfsAU-wmAU.snap | 12 + ...g__check_fullscreen_maximize@fsT-wfsAU-wmB.snap | 14 + ...__check_fullscreen_maximize@fsT-wfsAU-wmBU.snap | 11 + ...ening__check_fullscreen_maximize@fsT-wfsAU.snap | 11 + ...g__check_fullscreen_maximize@fsT-wfsBN-wmA.snap | 17 + ...__check_fullscreen_maximize@fsT-wfsBN-wmAU.snap | 14 + ...g__check_fullscreen_maximize@fsT-wfsBN-wmB.snap | 16 + ...__check_fullscreen_maximize@fsT-wfsBN-wmBU.snap | 13 + ...ening__check_fullscreen_maximize@fsT-wfsBN.snap | 13 + ...g__check_fullscreen_maximize@fsT-wfsBU-wmA.snap | 17 + ...__check_fullscreen_maximize@fsT-wfsBU-wmAU.snap | 14 + ...g__check_fullscreen_maximize@fsT-wfsBU-wmB.snap | 16 + ...__check_fullscreen_maximize@fsT-wfsBU-wmBU.snap | 13 + ...ening__check_fullscreen_maximize@fsT-wfsBU.snap | 13 + ...opening__check_fullscreen_maximize@fsT-wmA.snap | 17 + ...pening__check_fullscreen_maximize@fsT-wmAU.snap | 14 + ...opening__check_fullscreen_maximize@fsT-wmB.snap | 16 + ...pening__check_fullscreen_maximize@fsT-wmBU.snap | 13 + ...dow_opening__check_fullscreen_maximize@fsT.snap | 13 + ...g__check_fullscreen_maximize@tmF-wfsAN-wmA.snap | 18 + ...__check_fullscreen_maximize@tmF-wfsAN-wmAU.snap | 15 + ...g__check_fullscreen_maximize@tmF-wfsAN-wmB.snap | 14 + ...__check_fullscreen_maximize@tmF-wfsAN-wmBU.snap | 14 + ...ening__check_fullscreen_maximize@tmF-wfsAN.snap | 14 + ...g__check_fullscreen_maximize@tmF-wfsAU-wmA.snap | 15 + ...__check_fullscreen_maximize@tmF-wfsAU-wmAU.snap | 12 + ...g__check_fullscreen_maximize@tmF-wfsAU-wmB.snap | 11 + ...__check_fullscreen_maximize@tmF-wfsAU-wmBU.snap | 11 + ...ening__check_fullscreen_maximize@tmF-wfsAU.snap | 11 + ...g__check_fullscreen_maximize@tmF-wfsBN-wmA.snap | 17 + ...__check_fullscreen_maximize@tmF-wfsBN-wmAU.snap | 14 + ...g__check_fullscreen_maximize@tmF-wfsBN-wmB.snap | 13 + ...__check_fullscreen_maximize@tmF-wfsBN-wmBU.snap | 13 + ...ening__check_fullscreen_maximize@tmF-wfsBN.snap | 13 + ...g__check_fullscreen_maximize@tmF-wfsBU-wmA.snap | 14 + ...__check_fullscreen_maximize@tmF-wfsBU-wmAU.snap | 11 + ...g__check_fullscreen_maximize@tmF-wfsBU-wmB.snap | 10 + ...__check_fullscreen_maximize@tmF-wfsBU-wmBU.snap | 10 + ...ening__check_fullscreen_maximize@tmF-wfsBU.snap | 10 + ...opening__check_fullscreen_maximize@tmF-wmA.snap | 14 + ...pening__check_fullscreen_maximize@tmF-wmAU.snap | 11 + ...opening__check_fullscreen_maximize@tmF-wmB.snap | 10 + ...pening__check_fullscreen_maximize@tmF-wmBU.snap | 10 + ...dow_opening__check_fullscreen_maximize@tmF.snap | 10 + ...g__check_fullscreen_maximize@tmT-wfsAN-wmA.snap | 18 + ...__check_fullscreen_maximize@tmT-wfsAN-wmAU.snap | 15 + ...g__check_fullscreen_maximize@tmT-wfsAN-wmB.snap | 17 + ...__check_fullscreen_maximize@tmT-wfsAN-wmBU.snap | 17 + ...ening__check_fullscreen_maximize@tmT-wfsAN.snap | 17 + ...g__check_fullscreen_maximize@tmT-wfsAU-wmA.snap | 15 + ...__check_fullscreen_maximize@tmT-wfsAU-wmAU.snap | 12 + ...g__check_fullscreen_maximize@tmT-wfsAU-wmB.snap | 14 + ...__check_fullscreen_maximize@tmT-wfsAU-wmBU.snap | 14 + ...ening__check_fullscreen_maximize@tmT-wfsAU.snap | 14 + ...g__check_fullscreen_maximize@tmT-wfsBN-wmA.snap | 17 + ...__check_fullscreen_maximize@tmT-wfsBN-wmAU.snap | 14 + ...g__check_fullscreen_maximize@tmT-wfsBN-wmB.snap | 16 + ...__check_fullscreen_maximize@tmT-wfsBN-wmBU.snap | 16 + ...ening__check_fullscreen_maximize@tmT-wfsBN.snap | 16 + ...g__check_fullscreen_maximize@tmT-wfsBU-wmA.snap | 14 + ...__check_fullscreen_maximize@tmT-wfsBU-wmAU.snap | 11 + ...g__check_fullscreen_maximize@tmT-wfsBU-wmB.snap | 13 + ...__check_fullscreen_maximize@tmT-wfsBU-wmBU.snap | 13 + ...ening__check_fullscreen_maximize@tmT-wfsBU.snap | 13 + ...opening__check_fullscreen_maximize@tmT-wmA.snap | 14 + ...pening__check_fullscreen_maximize@tmT-wmAU.snap | 11 + ...opening__check_fullscreen_maximize@tmT-wmB.snap | 13 + ...pening__check_fullscreen_maximize@tmT-wmBU.snap | 13 + ...dow_opening__check_fullscreen_maximize@tmT.snap | 13 + ...ening__check_fullscreen_maximize@wfsAN-wmA.snap | 18 + ...ning__check_fullscreen_maximize@wfsAN-wmAU.snap | 15 + ...ening__check_fullscreen_maximize@wfsAN-wmB.snap | 17 + ...ning__check_fullscreen_maximize@wfsAN-wmBU.snap | 14 + ...w_opening__check_fullscreen_maximize@wfsAN.snap | 14 + ...ening__check_fullscreen_maximize@wfsAU-wmA.snap | 15 + ...ning__check_fullscreen_maximize@wfsAU-wmAU.snap | 12 + ...ening__check_fullscreen_maximize@wfsAU-wmB.snap | 14 + ...ning__check_fullscreen_maximize@wfsAU-wmBU.snap | 11 + ...w_opening__check_fullscreen_maximize@wfsAU.snap | 11 + ...ening__check_fullscreen_maximize@wfsBN-wmA.snap | 17 + ...ning__check_fullscreen_maximize@wfsBN-wmAU.snap | 14 + ...ening__check_fullscreen_maximize@wfsBN-wmB.snap | 16 + ...ning__check_fullscreen_maximize@wfsBN-wmBU.snap | 13 + ...w_opening__check_fullscreen_maximize@wfsBN.snap | 13 + ...ening__check_fullscreen_maximize@wfsBU-wmA.snap | 14 + ...ning__check_fullscreen_maximize@wfsBU-wmAU.snap | 11 + ...ening__check_fullscreen_maximize@wfsBU-wmB.snap | 13 + ...ning__check_fullscreen_maximize@wfsBU-wmBU.snap | 10 + ...w_opening__check_fullscreen_maximize@wfsBU.snap | 10 + ...dow_opening__check_fullscreen_maximize@wmA.snap | 14 + ...ow_opening__check_fullscreen_maximize@wmAU.snap | 11 + ...dow_opening__check_fullscreen_maximize@wmB.snap | 13 + ...ow_opening__check_fullscreen_maximize@wmBU.snap | 10 + src/tests/window_opening.rs | 233 ++++++++++++- src/window/mapped.rs | 154 +++++++-- src/window/mod.rs | 8 + src/window/unmapped.rs | 11 + 251 files changed, 4858 insertions(+), 280 deletions(-) create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wfsAN-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wfsAN-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wfsAN-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wfsAN-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wfsAN.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wfsAU-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wfsAU-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wfsAU-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wfsAU-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wfsAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wfsBN-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wfsBN-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wfsBN-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wfsBN-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wfsBN.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wfsBU-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wfsBU-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wfsBU-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wfsBU-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wfsBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmF.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wfsAN-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wfsAN-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wfsAN-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wfsAN-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wfsAN.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wfsAU-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wfsAU-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wfsAU-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wfsAU-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wfsAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wfsBN-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wfsBN-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wfsBN-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wfsBN-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wfsBN.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wfsBU-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wfsBU-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wfsBU-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wfsBU-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wfsBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-tmT.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wfsAN-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wfsAN-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wfsAN-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wfsAN-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wfsAN.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wfsAU-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wfsAU-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wfsAU-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wfsAU-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wfsAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wfsBN-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wfsBN-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wfsBN-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wfsBN-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wfsBN.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wfsBU-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wfsBU-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wfsBU-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wfsBU-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wfsBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsF.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wfsAN-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wfsAN-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wfsAN-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wfsAN-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wfsAN.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wfsAU-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wfsAU-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wfsAU-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wfsAU-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wfsAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wfsBN-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wfsBN-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wfsBN-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wfsBN-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wfsBN.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wfsBU-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wfsBU-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wfsBU-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wfsBU-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wfsBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmF.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wfsAN-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wfsAN-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wfsAN-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wfsAN-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wfsAN.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wfsAU-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wfsAU-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wfsAU-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wfsAU-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wfsAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wfsBN-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wfsBN-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wfsBN-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wfsBN-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wfsBN.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wfsBU-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wfsBU-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wfsBU-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wfsBU-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wfsBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-tmT.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wfsAN-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wfsAN-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wfsAN-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wfsAN-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wfsAN.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wfsAU-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wfsAU-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wfsAU-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wfsAU-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wfsAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wfsBN-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wfsBN-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wfsBN-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wfsBN-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wfsBN.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wfsBU-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wfsBU-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wfsBU-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wfsBU-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wfsBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@fsT.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wfsAN-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wfsAN-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wfsAN-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wfsAN-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wfsAN.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wfsAU-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wfsAU-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wfsAU-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wfsAU-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wfsAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wfsBN-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wfsBN-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wfsBN-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wfsBN-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wfsBN.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wfsBU-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wfsBU-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wfsBU-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wfsBU-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wfsBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmF.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wfsAN-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wfsAN-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wfsAN-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wfsAN-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wfsAN.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wfsAU-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wfsAU-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wfsAU-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wfsAU-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wfsAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wfsBN-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wfsBN-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wfsBN-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wfsBN-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wfsBN.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wfsBU-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wfsBU-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wfsBU-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wfsBU-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wfsBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@tmT.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wfsAN-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wfsAN-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wfsAN-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wfsAN-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wfsAN.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wfsAU-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wfsAU-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wfsAU-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wfsAU-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wfsAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wfsBN-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wfsBN-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wfsBN-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wfsBN-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wfsBN.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wfsBU-wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wfsBU-wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wfsBU-wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wfsBU-wmBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wfsBU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wmA.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wmAU.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wmB.snap create mode 100644 src/tests/snapshots/niri__tests__window_opening__check_fullscreen_maximize@wmBU.snap diff --git a/niri-config/src/binds.rs b/niri-config/src/binds.rs index 8a09445d..37ac1665 100644 --- a/niri-config/src/binds.rs +++ b/niri-config/src/binds.rs @@ -303,6 +303,9 @@ pub enum Action { #[knuffel(skip)] SwitchPresetWindowHeightBackById(u64), MaximizeColumn, + MaximizeWindowToEdges, + #[knuffel(skip)] + MaximizeWindowToEdgesById(u64), SetColumnWidth(#[knuffel(argument, str)] SizeChange), ExpandColumnToAvailableWidth, SwitchLayout(#[knuffel(argument, str)] LayoutSwitchTarget), @@ -568,6 +571,10 @@ impl From for Action { Self::SwitchPresetWindowHeightBackById(id) } niri_ipc::Action::MaximizeColumn {} => Self::MaximizeColumn, + niri_ipc::Action::MaximizeWindowToEdges { id: None } => Self::MaximizeWindowToEdges, + niri_ipc::Action::MaximizeWindowToEdges { id: Some(id) } => { + Self::MaximizeWindowToEdgesById(id) + } niri_ipc::Action::SetColumnWidth { change } => Self::SetColumnWidth(change), niri_ipc::Action::ExpandColumnToAvailableWidth {} => Self::ExpandColumnToAvailableWidth, niri_ipc::Action::SwitchLayout { layout } => Self::SwitchLayout(layout), diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs index eb6d48b3..e939f0c3 100644 --- a/niri-config/src/lib.rs +++ b/niri-config/src/lib.rs @@ -1578,6 +1578,7 @@ mod tests { open_maximized: Some( true, ), + open_maximized_to_edges: None, open_fullscreen: Some( false, ), diff --git a/niri-config/src/window_rule.rs b/niri-config/src/window_rule.rs index e4a69ccd..0465d28f 100644 --- a/niri-config/src/window_rule.rs +++ b/niri-config/src/window_rule.rs @@ -24,6 +24,8 @@ pub struct WindowRule { #[knuffel(child, unwrap(argument))] pub open_maximized: Option, #[knuffel(child, unwrap(argument))] + pub open_maximized_to_edges: Option, + #[knuffel(child, unwrap(argument))] pub open_fullscreen: Option, #[knuffel(child, unwrap(argument))] pub open_floating: Option, diff --git a/niri-ipc/src/lib.rs b/niri-ipc/src/lib.rs index 5ce0c23d..080db620 100644 --- a/niri-ipc/src/lib.rs +++ b/niri-ipc/src/lib.rs @@ -713,6 +713,14 @@ pub enum Action { }, /// Toggle the maximized state of the focused column. MaximizeColumn {}, + /// Toggle the maximized-to-edges state of the focused window. + MaximizeWindowToEdges { + /// Id of the window to maximize. + /// + /// If `None`, uses the focused window. + #[cfg_attr(feature = "clap", arg(long))] + id: Option, + }, /// Change the width of the focused column. SetColumnWidth { /// How to change the width. diff --git a/niri-visual-tests/src/cases/layout.rs b/niri-visual-tests/src/cases/layout.rs index 5fa522d8..3b864964 100644 --- a/niri-visual-tests/src/cases/layout.rs +++ b/niri-visual-tests/src/cases/layout.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use std::time::Duration; use niri::animation::Clock; -use niri::layout::{ActivateWindow, AddWindowTarget, LayoutElement as _, Options}; +use niri::layout::{ActivateWindow, AddWindowTarget, LayoutElement as _, Options, SizingMode}; use niri::render_helpers::RenderTarget; use niri_config::{Color, OutputName, PresetSize}; use smithay::backend::renderer::element::RenderElement; @@ -168,7 +168,7 @@ impl Layout { let max_size = window.max_size(); window.request_size( ws.new_window_size(width, None, false, window.rules(), (min_size, max_size)), - false, + SizingMode::Normal, false, None, ); @@ -197,7 +197,7 @@ impl Layout { let max_size = window.max_size(); window.request_size( ws.new_window_size(width, None, false, window.rules(), (min_size, max_size)), - false, + SizingMode::Normal, false, None, ); diff --git a/niri-visual-tests/src/cases/window.rs b/niri-visual-tests/src/cases/window.rs index 51d5c962..26244b3b 100644 --- a/niri-visual-tests/src/cases/window.rs +++ b/niri-visual-tests/src/cases/window.rs @@ -1,4 +1,4 @@ -use niri::layout::LayoutElement; +use niri::layout::{LayoutElement, SizingMode}; use niri::render_helpers::RenderTarget; use smithay::backend::renderer::element::RenderElement; use smithay::backend::renderer::gles::GlesRenderer; @@ -14,14 +14,14 @@ pub struct Window { impl Window { pub fn freeform(args: Args) -> Self { let mut window = TestWindow::freeform(0); - window.request_size(args.size, false, false, None); + window.request_size(args.size, SizingMode::Normal, false, None); window.communicate(); Self { window } } pub fn fixed_size(args: Args) -> Self { let mut window = TestWindow::fixed_size(0); - window.request_size(args.size, false, false, None); + window.request_size(args.size, SizingMode::Normal, false, None); window.communicate(); Self { window } } @@ -29,7 +29,7 @@ impl Window { pub fn fixed_size_with_csd_shadow(args: Args) -> Self { let mut window = TestWindow::fixed_size(0); window.set_csd_shadow_width(64); - window.request_size(args.size, false, false, None); + window.request_size(args.size, SizingMode::Normal, false, None); window.communicate(); Self { window } } @@ -38,7 +38,7 @@ impl Window { impl TestCase for Window { fn resize(&mut self, width: i32, height: i32) { self.window - .request_size(Size::from((width, height)), false, false, None); + .request_size(Size::from((width, height)), SizingMode::Normal, false, None); self.window.communicate(); } diff --git a/niri-visual-tests/src/test_window.rs b/niri-visual-tests/src/test_window.rs index 7fee44c6..fa96860a 100644 --- a/niri-visual-tests/src/test_window.rs +++ b/niri-visual-tests/src/test_window.rs @@ -4,7 +4,7 @@ use std::rc::Rc; use niri::layout::{ ConfigureIntent, InteractiveResizeData, LayoutElement, LayoutElementRenderElement, - LayoutElementRenderSnapshot, + LayoutElementRenderSnapshot, SizingMode, }; use niri::render_helpers::offscreen::OffscreenData; use niri::render_helpers::renderer::NiriRenderer; @@ -24,7 +24,7 @@ struct TestWindowInner { min_size: Size, max_size: Size, buffer: SolidColorBuffer, - pending_fullscreen: bool, + pending_sizing_mode: SizingMode, csd_shadow_width: i32, csd_shadow_buffer: SolidColorBuffer, } @@ -50,7 +50,7 @@ impl TestWindow { min_size, max_size, buffer, - pending_fullscreen: false, + pending_sizing_mode: SizingMode::Normal, csd_shadow_width: 0, csd_shadow_buffer: SolidColorBuffer::new((0., 0.), [0., 0., 0., 0.3]), })), @@ -182,12 +182,12 @@ impl LayoutElement for TestWindow { fn request_size( &mut self, size: Size, - is_fullscreen: bool, + mode: SizingMode, _animate: bool, _transaction: Option, ) { self.inner.borrow_mut().requested_size = Some(size); - self.inner.borrow_mut().pending_fullscreen = is_fullscreen; + self.inner.borrow_mut().pending_sizing_mode = mode; } fn min_size(&self) -> Size { @@ -232,12 +232,12 @@ impl LayoutElement for TestWindow { fn send_pending_configure(&mut self) {} - fn is_fullscreen(&self) -> bool { - false + fn pending_sizing_mode(&self) -> SizingMode { + self.inner.borrow().pending_sizing_mode } - fn is_pending_fullscreen(&self) -> bool { - self.inner.borrow().pending_fullscreen + fn sizing_mode(&self) -> SizingMode { + SizingMode::Normal } fn requested_size(&self) -> Option> { diff --git a/src/handlers/compositor.rs b/src/handlers/compositor.rs index cf2efaaf..a7761824 100644 --- a/src/handlers/compositor.rs +++ b/src/handlers/compositor.rs @@ -20,7 +20,7 @@ use smithay::{delegate_compositor, delegate_shm}; use super::xdg_shell::add_mapped_toplevel_pre_commit_hook; use crate::handlers::XDG_ACTIVATION_TOKEN_TIMEOUT; -use crate::layout::{ActivateWindow, AddWindowTarget}; +use crate::layout::{ActivateWindow, AddWindowTarget, LayoutElement as _}; use crate::niri::{CastTarget, ClientState, LockState, State}; use crate::utils::transaction::Transaction; use crate::utils::{is_mapped, send_scale_transform}; @@ -91,35 +91,59 @@ impl CompositorHandler for State { let toplevel = window.toplevel().expect("no X11 support"); - let (rules, width, height, is_full_width, output, workspace_id) = - if let InitialConfigureState::Configured { + let ( + rules, + width, + height, + is_full_width, + output, + workspace_id, + is_pending_maximized, + ) = if let InitialConfigureState::Configured { + rules, + width, + height, + floating_width: _, + floating_height: _, + is_full_width, + output, + workspace_name, + is_pending_maximized, + } = state + { + // Check that the output is still connected. + let output = + output.filter(|o| self.niri.layout.monitor_for_output(o).is_some()); + + // Check that the workspace still exists. + let workspace_id = workspace_name + .as_deref() + .and_then(|n| self.niri.layout.find_workspace_by_name(n)) + .map(|(_, ws)| ws.id()); + + ( rules, width, height, - floating_width: _, - floating_height: _, 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()); - - // Check that the workspace still exists. - let workspace_id = workspace_name - .as_deref() - .and_then(|n| self.niri.layout.find_workspace_by_name(n)) - .map(|(_, ws)| ws.id()); - - (rules, width, height, is_full_width, output, workspace_id) - } else { - // Can happen when a surface unmaps by attaching a null buffer while - // there are in-flight pending configures. - debug!("window mapped without proper initial configure"); - (ResolvedWindowRules::empty(), None, None, false, None, None) - }; + workspace_id, + is_pending_maximized, + ) + } else { + // Can happen when a surface unmaps by attaching a null buffer while + // there are in-flight pending configures. + debug!("window mapped without proper initial configure"); + ( + ResolvedWindowRules::empty(), + None, + None, + false, + None, + None, + false, + ) + }; // The GTK about dialog sets min/max size after the initial configure but // before mapping, so we need to compute open_floating at the last possible @@ -169,7 +193,7 @@ impl CompositorHandler for State { .map(|(mapped, _)| mapped.window.clone()); // The mapped pre-commit hook deals with dma-bufs on its own. - self.remove_default_dmabuf_pre_commit_hook(toplevel.wl_surface()); + self.remove_default_dmabuf_pre_commit_hook(surface); let hook = add_mapped_toplevel_pre_commit_hook(toplevel); let mapped = Mapped::new(window, rules, hook); let window = mapped.window.clone(); @@ -193,8 +217,21 @@ impl CompositorHandler for State { is_floating, activate, ); + let output = output.cloned(); + + // The window state cannot contain Fullscreen and Maximized at once. Therefore, + // if the window ended up fullscreen, then we only know that it is also + // maximized from the is_pending_maximized variable. Tell the layout about it + // here so that unfullscreening the window makes it maximized. + if let Some((mapped, _)) = self.niri.layout.find_window_and_output(surface) { + if mapped.pending_sizing_mode().is_fullscreen() && is_pending_maximized { + self.niri.layout.set_maximized(&window, true); + } + } else { + error!("layout is missing the window that we just added"); + } - if let Some(output) = output.cloned() { + if let Some(output) = output { self.niri.layout.start_open_animation_for_window(&window); let new_focus = self.niri.layout.focus().map(|m| &m.window); diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index 3b673fa0..73575b45 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -550,6 +550,20 @@ impl ForeignToplevelHandler for State { self.niri.layout.set_fullscreen(&window, false); } } + + fn set_maximized(&mut self, wl_surface: WlSurface) { + if let Some((mapped, _)) = self.niri.layout.find_window_and_output(&wl_surface) { + let window = mapped.window.clone(); + self.niri.layout.set_maximized(&window, true); + } + } + + fn unset_maximized(&mut self, wl_surface: WlSurface) { + if let Some((mapped, _)) = self.niri.layout.find_window_and_output(&wl_surface) { + let window = mapped.window.clone(); + self.niri.layout.set_maximized(&window, false); + } + } } delegate_foreign_toplevel!(State); diff --git a/src/handlers/xdg_shell.rs b/src/handlers/xdg_shell.rs index 5d8adc06..e5d91f16 100644 --- a/src/handlers/xdg_shell.rs +++ b/src/handlers/xdg_shell.rs @@ -428,18 +428,205 @@ impl XdgShellHandler for State { }); } - fn maximize_request(&mut self, surface: ToplevelSurface) { - // FIXME + fn maximize_request(&mut self, toplevel: ToplevelSurface) { + if let Some((mapped, _)) = self + .niri + .layout + .find_window_and_output_mut(toplevel.wl_surface()) + { + // A configure is required in response to this event regardless if there are pending + // changes. + mapped.set_needs_configure(); - // A configure is required in response to this event. However, if an initial configure - // wasn't sent, then we will send this as part of the initial configure later. - if surface.is_initial_configure_sent() { - surface.send_configure(); + let window = mapped.window.clone(); + self.niri.layout.set_maximized(&window, true); + } else if let Some(unmapped) = self.niri.unmapped_windows.get_mut(toplevel.wl_surface()) { + match &mut unmapped.state { + InitialConfigureState::NotConfigured { + wants_maximized, .. + } => { + *wants_maximized = true; + + // The required configure will be the initial configure. + } + InitialConfigureState::Configured { + rules, + output, + is_pending_maximized, + .. + } => { + // 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)) + .and_then(|(_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 { + // If the window is pending fullscreen, then this will do nothing. But + // that's expected: the window remains fullscreen, and we simply remember + // that it is now pending maximized. + *is_pending_maximized = true; + toplevel.with_pending_state(|state| { + if !state.states.contains(xdg_toplevel::State::Fullscreen) { + state.states.set(xdg_toplevel::State::Maximized); + } + }); + ws.configure_new_window(&unmapped.window, None, None, false, rules); + } + + // We already sent the initial configure, so we need to reconfigure. + toplevel.send_configure(); + } + } + } else { + error!("couldn't find the toplevel in maximize_request()"); + toplevel.send_configure(); } } - fn unmaximize_request(&mut self, _surface: ToplevelSurface) { - // FIXME + fn unmaximize_request(&mut self, toplevel: ToplevelSurface) { + if let Some((mapped, _)) = self + .niri + .layout + .find_window_and_output_mut(toplevel.wl_surface()) + { + // A configure is required in response to this event regardless if there are pending + // changes. + mapped.set_needs_configure(); + + let window = mapped.window.clone(); + self.niri.layout.set_maximized(&window, false); + } else if let Some(unmapped) = self.niri.unmapped_windows.get_mut(toplevel.wl_surface()) { + match &mut unmapped.state { + InitialConfigureState::NotConfigured { + wants_maximized, .. + } => { + *wants_maximized = false; + + // The required configure will be the initial configure. + } + InitialConfigureState::Configured { + rules, + width, + height, + floating_width, + floating_height, + is_full_width, + output, + workspace_name, + is_pending_maximized, + } => { + // Figure out the monitor following a similar logic to initial configure. + // FIXME: deduplicate. + 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) + }) + .and_then(|(_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 = 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 { + // If the window is pending fullscreen, then this will do nothing since + // then the Maximized state is already unset. But that's expected: the + // window remains fullscreen, and we simply remember that it is no + // longer pending maximized. + *is_pending_maximized = false; + toplevel.with_pending_state(|state| { + state.states.unset