From e8b06b832cd4f14c3245743d21243b681757fd58 Mon Sep 17 00:00:00 2001 From: Nikolai Nechaev Date: Tue, 10 Mar 2026 19:09:47 +0900 Subject: [PATCH] compositor: When processing fullscreen states, only use effective mode where necessary (#13607) Simplify the compositor fullscreen state processing: use the complete fullscreen mode value except when the effective fullscreen mode value is needed. Fixes #13041. --- hyprtester/src/tests/main/misc.cpp | 32 ++++++++++++++++++++++++++++++ src/Compositor.cpp | 30 +++++++++++++++++----------- 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/hyprtester/src/tests/main/misc.cpp b/hyprtester/src/tests/main/misc.cpp index 471eef7a5..0c7c9ec13 100644 --- a/hyprtester/src/tests/main/misc.cpp +++ b/hyprtester/src/tests/main/misc.cpp @@ -177,6 +177,7 @@ static bool test() { { auto str = getFromSocket("/activewindow"); EXPECT_CONTAINS(str, "fullscreen: 2"); + EXPECT_CONTAINS(str, "fullscreenClient: 2"); EXPECT_CONTAINS(str, "kitty_A"); } @@ -185,6 +186,7 @@ static bool test() { { auto str = getFromSocket("/activewindow"); EXPECT_CONTAINS(str, "fullscreen: 2"); + EXPECT_CONTAINS(str, "fullscreenClient: 2"); EXPECT_CONTAINS(str, "kitty_A"); } @@ -194,6 +196,7 @@ static bool test() { // should be ignored as per focus_under_fullscreen 0 auto str = getFromSocket("/activewindow"); EXPECT_CONTAINS(str, "fullscreen: 2"); + EXPECT_CONTAINS(str, "fullscreenClient: 2"); EXPECT_CONTAINS(str, "kitty_A"); } @@ -204,6 +207,7 @@ static bool test() { { auto str = getFromSocket("/activewindow"); EXPECT_CONTAINS(str, "fullscreen: 2"); + EXPECT_CONTAINS(str, "fullscreenClient: 2"); EXPECT_CONTAINS(str, "kitty_C"); } @@ -214,6 +218,7 @@ static bool test() { { auto str = getFromSocket("/activewindow"); EXPECT_CONTAINS(str, "fullscreen: 0"); + EXPECT_CONTAINS(str, "fullscreenClient: 0"); EXPECT_CONTAINS(str, "kitty_D"); } @@ -233,6 +238,7 @@ static bool test() { { auto str = getFromSocket("/activewindow"); EXPECT_CONTAINS(str, "fullscreen: 2"); + EXPECT_CONTAINS(str, "fullscreenClient: 2"); } OK(getFromSocket("/dispatch killwindow activewindow")); @@ -241,6 +247,7 @@ static bool test() { { auto str = getFromSocket("/activewindow"); EXPECT_CONTAINS(str, "fullscreen: 0"); + EXPECT_CONTAINS(str, "fullscreenClient: 0"); } Tests::spawnKitty("kitty_B"); @@ -253,6 +260,7 @@ static bool test() { { auto str = getFromSocket("/activewindow"); EXPECT_CONTAINS(str, "fullscreen: 2"); + EXPECT_CONTAINS(str, "fullscreenClient: 2"); } Tests::killAllWindows(); @@ -268,6 +276,7 @@ static bool test() { { auto str = getFromSocket("/activewindow"); EXPECT_CONTAINS(str, "fullscreen: 2"); + EXPECT_CONTAINS(str, "fullscreenClient: 2"); } OK(getFromSocket("/dispatch fullscreen 0 unset")); @@ -275,6 +284,7 @@ static bool test() { { auto str = getFromSocket("/activewindow"); EXPECT_CONTAINS(str, "fullscreen: 0"); + EXPECT_CONTAINS(str, "fullscreenClient: 0"); } OK(getFromSocket("/dispatch fullscreen 1 toggle")); @@ -282,6 +292,7 @@ static bool test() { { auto str = getFromSocket("/activewindow"); EXPECT_CONTAINS(str, "fullscreen: 1"); + EXPECT_CONTAINS(str, "fullscreenClient: 1"); } OK(getFromSocket("/dispatch fullscreen 1 toggle")); @@ -289,6 +300,23 @@ static bool test() { { auto str = getFromSocket("/activewindow"); EXPECT_CONTAINS(str, "fullscreen: 0"); + EXPECT_CONTAINS(str, "fullscreenClient: 0"); + } + + OK(getFromSocket("/dispatch fullscreenstate 3 3 set")); + + { + auto str = getFromSocket("/activewindow"); + EXPECT_CONTAINS(str, "fullscreen: 3"); + EXPECT_CONTAINS(str, "fullscreenClient: 3"); + } + + OK(getFromSocket("/dispatch fullscreenstate 3 3 set")); + + { + auto str = getFromSocket("/activewindow"); + EXPECT_CONTAINS(str, "fullscreen: 3"); + EXPECT_CONTAINS(str, "fullscreenClient: 3"); } OK(getFromSocket("/dispatch fullscreenstate 2 2 set")); @@ -296,6 +324,7 @@ static bool test() { { auto str = getFromSocket("/activewindow"); EXPECT_CONTAINS(str, "fullscreen: 2"); + EXPECT_CONTAINS(str, "fullscreenClient: 2"); } OK(getFromSocket("/dispatch fullscreenstate 2 2 set")); @@ -303,6 +332,7 @@ static bool test() { { auto str = getFromSocket("/activewindow"); EXPECT_CONTAINS(str, "fullscreen: 2"); + EXPECT_CONTAINS(str, "fullscreenClient: 2"); } OK(getFromSocket("/dispatch fullscreenstate 2 2 toggle")); @@ -310,6 +340,7 @@ static bool test() { { auto str = getFromSocket("/activewindow"); EXPECT_CONTAINS(str, "fullscreen: 0"); + EXPECT_CONTAINS(str, "fullscreenClient: 0"); } OK(getFromSocket("/dispatch fullscreenstate 2 2 toggle")); @@ -317,6 +348,7 @@ static bool test() { { auto str = getFromSocket("/activewindow"); EXPECT_CONTAINS(str, "fullscreen: 2"); + EXPECT_CONTAINS(str, "fullscreenClient: 2"); } // Ensure that the process autostarted in the config does not diff --git a/src/Compositor.cpp b/src/Compositor.cpp index b0fc15453..4f8809aa7 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2115,13 +2115,10 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, Desktop::Vie state.internal = std::clamp(state.internal, sc(0), FSMODE_MAX); state.client = std::clamp(state.client, sc(0), FSMODE_MAX); - const auto PMONITOR = PWINDOW->m_monitor.lock(); - const auto PWORKSPACE = PWINDOW->m_workspace; + const auto PMONITOR = PWINDOW->m_monitor.lock(); + const auto PWORKSPACE = PWINDOW->m_workspace; - const eFullscreenMode CURRENT_EFFECTIVE_MODE = sc(std::bit_floor(sc(PWINDOW->m_fullscreenState.internal))); - const eFullscreenMode EFFECTIVE_MODE = sc(std::bit_floor(sc(state.internal))); - - if (PWINDOW->m_isFloating && CURRENT_EFFECTIVE_MODE == FSMODE_NONE && EFFECTIVE_MODE != FSMODE_NONE) + if (PWINDOW->m_isFloating && PWINDOW->m_fullscreenState.internal == FSMODE_NONE && state.internal != FSMODE_NONE) g_pHyprRenderer->damageWindow(PWINDOW); if (*PALLOWPINFULLSCREEN && !PWINDOW->m_pinFullscreened && !PWINDOW->isFullscreen() && PWINDOW->m_pinned) { @@ -2132,7 +2129,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, Desktop::Vie if (PWORKSPACE->m_hasFullscreenWindow && !PWINDOW->isFullscreen()) setWindowFullscreenInternal(PWORKSPACE->getFullscreenWindow(), FSMODE_NONE); - const bool CHANGEINTERNAL = !PWINDOW->m_pinned && CURRENT_EFFECTIVE_MODE != EFFECTIVE_MODE; + const bool CHANGEINTERNAL = !PWINDOW->m_pinned && PWINDOW->m_fullscreenState.internal != state.internal; if (*PALLOWPINFULLSCREEN && PWINDOW->m_pinFullscreened && PWINDOW->isFullscreen() && !PWINDOW->m_pinned && state.internal == FSMODE_NONE) { PWINDOW->m_pinned = true; @@ -2154,14 +2151,23 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, Desktop::Vie return; } - PWORKSPACE->m_fullscreenMode = EFFECTIVE_MODE; - PWORKSPACE->m_hasFullscreenWindow = EFFECTIVE_MODE != FSMODE_NONE; + // "Effective mode" is the fullscreen mode according to which a window is rendered. + // For fullscreen modes `FSMODE_NONE` (0), `FSMODE_MAXIMIZED` (1), and `FSMODE_FULLSCREEN` (2), + // the effective mode is the same as the fullscreen mode; + // for fullscreen mode `FSMODE_MAXIMIZED|FSMODE_FULLSCREEN` (a window is maximized then fullscreened), + // the effective mode is `FSMODE_FULLSCREEN` (2), since the window is rendered as a fullscreen window. + // But when the latter window exists fullscreen, it will return to `FSMODE_MAXIMIZED`, rather than `FSMODE_NONE`. + const eFullscreenMode OLD_EFFECTIVE_MODE = sc(std::bit_floor(sc(PWINDOW->m_fullscreenState.internal))); + const eFullscreenMode NEW_EFFECTIVE_MODE = sc(std::bit_floor(sc(state.internal))); - g_layoutManager->fullscreenRequestForTarget(PWINDOW->layoutTarget(), CURRENT_EFFECTIVE_MODE, EFFECTIVE_MODE); + PWORKSPACE->m_fullscreenMode = NEW_EFFECTIVE_MODE; + PWORKSPACE->m_hasFullscreenWindow = NEW_EFFECTIVE_MODE != FSMODE_NONE; + + g_layoutManager->fullscreenRequestForTarget(PWINDOW->layoutTarget(), OLD_EFFECTIVE_MODE, NEW_EFFECTIVE_MODE); PWINDOW->m_fullscreenState.internal = state.internal; - g_pEventManager->postEvent(SHyprIPCEvent{.event = "fullscreen", .data = std::to_string(sc(EFFECTIVE_MODE) != FSMODE_NONE)}); + g_pEventManager->postEvent(SHyprIPCEvent{.event = "fullscreen", .data = std::to_string(sc(NEW_EFFECTIVE_MODE) != FSMODE_NONE)}); Event::bus()->m_events.window.fullscreen.emit(PWINDOW); PWINDOW->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_FULLSCREEN | Desktop::Rule::RULE_PROP_FULLSCREENSTATE_CLIENT | @@ -2198,7 +2204,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, Desktop::Vie if (*PDIRECTSCANOUT == 1 || (*PDIRECTSCANOUT == 2 && PWINDOW->getContentType() == CONTENT_TYPE_GAME)) { auto surf = PWINDOW->getSolitaryResource(); if (surf) - g_pHyprRenderer->setSurfaceScanoutMode(surf, EFFECTIVE_MODE != FSMODE_NONE ? PMONITOR->m_self.lock() : nullptr); + g_pHyprRenderer->setSurfaceScanoutMode(surf, NEW_EFFECTIVE_MODE != FSMODE_NONE ? PMONITOR->m_self.lock() : nullptr); } g_pConfigManager->ensureVRR(PMONITOR);