diff --git a/docs/user/keybinds.md b/docs/user/keybinds.md index 08135f79..bd141ce5 100644 --- a/docs/user/keybinds.md +++ b/docs/user/keybinds.md @@ -114,7 +114,7 @@ These take no argument. | `window-cycle-width-back` | Cycle the focused column through its preset widths in reverse. | | `window-toggle-fullscreen` | Toggle fullscreen for the focused window. | | `window-toggle-maximize` | Toggle the focused column's full-width state. | -| `window-toggle-maximize-to-edges` | Toggle maximization of the focused window to the usable area's edges, without gaps or borders. Layer-shell exclusive zones remain visible. | +| `window-toggle-maximize-to-edges` | Toggle maximization of the focused window to the usable area's edges, without gaps or borders. Layer-shell exclusive zones remain visible. A column's full-width restore state is preserved when this is toggled or when fullscreen is entered and left. | | `layout-scroll-left` / `layout-scroll-right` | Scroll the active workspace's scrolling-layout viewport; a no-op on a dwindle workspace. | | `layout-scroll-up` / `layout-scroll-down` | Scroll toward strip start or end. These are first-class synonyms for `layout-scroll-left` and `layout-scroll-right`. | | `config-reload` | Reload the config file, the same reload that runs automatically when the file changes on disk. | diff --git a/src/view/view.cpp b/src/view/view.cpp index ab58c187..6b63c2e4 100644 --- a/src/view/view.cpp +++ b/src/view/view.cpp @@ -1934,16 +1934,15 @@ namespace umbriel { m_unfullscreenGraceStartMsec = 0; } cancelSizeAnimation(); - if (m_tiled && m_workspace != nullptr && maximized) { - const int column = m_workspace->layout().columnOf(this); - if (column >= 0 && m_workspace->layout().isFullWidth(column)) { - m_workspace->layout().clearFullWidthState(column); - } - } m_maximizedToEdges = maximized; + bool columnFullWidth = false; + if (!maximized && m_tiled && m_workspace != nullptr && !m_toplevel->scheduled.fullscreen) { + const int column = m_workspace->layout().columnOf(this); + columnFullWidth = column >= 0 && m_workspace->layout().isFullWidth(column); + } if (m_tiled) { - wlr_xdg_toplevel_set_maximized(m_toplevel, maximized); + wlr_xdg_toplevel_set_maximized(m_toplevel, maximized || columnFullWidth); } else { setMaximized(maximized); } @@ -2288,15 +2287,6 @@ namespace umbriel { if (!fullscreen) { m_refullscreenOnTile = false; } - // Leaving column maximize when entering real fullscreen avoids a stale - // widthFrac=1.0 column after the client leaves fullscreen. - if (fullscreen && m_tiled && m_workspace != nullptr) { - const int column = m_workspace->layout().columnOf(this); - if (m_workspace->layout().isFullWidth(column)) { - m_workspace->layout().clearFullWidthState(column); - wlr_xdg_toplevel_set_maximized(m_toplevel, false); - } - } if (fullscreen) { if (m_pinned) { m_pinned = false; diff --git a/tests/unit/scrolling_layout.cpp b/tests/unit/scrolling_layout.cpp index ede68626..b59c1c3e 100644 --- a/tests/unit/scrolling_layout.cpp +++ b/tests/unit/scrolling_layout.cpp @@ -406,6 +406,24 @@ UMBRIEL_TEST(maximizedToEdgesColumnFillsTheViewportIgnoringFractions) { CHECK(!fixture.layout.isFullWidth(1)); } +UMBRIEL_TEST(preservedFullWidthSurvivesEdgeMaximizeToggle) { + Fixture fixture; + fixture.addColumns(1); + CHECK(fixture.layout.setWidthFraction(0, 0.5)); + CHECK(fixture.layout.toggleFullWidth(0)); + + fixture.layout.setConstraints([](const View* view) { + return LayoutConstraints{.maximizedToEdges = view == stub(0)}; + }); + CHECK_EQ(fixture.layout.columnWidth(0, kViewport), kViewport); + + fixture.layout.setConstraints([](const View*) { return LayoutConstraints{}; }); + CHECK(fixture.layout.isFullWidth(0)); + CHECK_EQ(fixture.layout.columnWidth(0, kViewport), kViewport); + CHECK(!fixture.layout.toggleFullWidth(0)); + CHECK(std::fabs(fixture.layout.widthFraction(0) - 0.5) < 1e-6); +} + UMBRIEL_TEST(unsetConstraintsMeanUnconstrained) { Fixture fixture; fixture.addColumns(1);