diff --git a/src/Window.hpp b/src/Window.hpp index d4a34c8d..38eb857c 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -37,7 +37,15 @@ enum eGetWindowProperties { FULL_EXTENTS = 1 << 2, FLOATING_ONLY = 1 << 3, ALLOW_FLOATING = 1 << 4, - USE_PROP_TILED = 1 << 5 + USE_PROP_TILED = 1 << 5, +}; + +enum eSuppressEvents { + SUPPRESS_NONE = 0, + SUPPRESS_FULLSCREEN = 1 << 0, + SUPPRESS_MAXIMIZE = 1 << 1, + SUPPRESS_ACTIVATE = 1 << 2, + SUPPRESS_ACTIVATE_FOCUSONLY = 1 << 3, }; class IWindowTransformer; @@ -264,9 +272,10 @@ class CWindow { bool m_bNoInitialFocus = false; // Fullscreen and Maximize - bool m_bWantsInitialFullscreen = false; - bool m_bNoFullscreenRequest = false; - bool m_bNoMaximizeRequest = false; + bool m_bWantsInitialFullscreen = false; + + // bitfield eSuppressEvents + uint64_t m_eSuppressedEvents = SUPPRESS_NONE; SSurfaceTreeNode* m_pSurfaceTree = nullptr; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index fa9e0122..97bc647c 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -971,7 +971,7 @@ bool windowRuleValid(const std::string& RULE) { RULE == "nomaximizerequest" || RULE == "fakefullscreen" || RULE == "nomaxsize" || RULE == "pin" || RULE == "noanim" || RULE == "dimaround" || RULE == "windowdance" || RULE == "maximize" || RULE == "keepaspectratio" || RULE.starts_with("animation") || RULE.starts_with("rounding") || RULE.starts_with("workspace") || RULE.starts_with("bordercolor") || RULE == "forcergbx" || RULE == "noinitialfocus" || RULE == "stayfocused" || RULE.starts_with("bordersize") || RULE.starts_with("xray") || - RULE.starts_with("center") || RULE.starts_with("group") || RULE == "immediate" || RULE == "nearestneighbor"; + RULE.starts_with("center") || RULE.starts_with("group") || RULE == "immediate" || RULE == "nearestneighbor" || RULE.starts_with("suppressevent"); } bool layerRuleValid(const std::string& RULE) { diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 2df99284..750a18ff 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -177,9 +177,23 @@ void Events::listener_mapWindow(void* owner, void* data) { } else if (r.szRule.starts_with("noinitialfocus")) { PWINDOW->m_bNoInitialFocus = true; } else if (r.szRule.starts_with("nofullscreenrequest")) { - PWINDOW->m_bNoFullscreenRequest = true; + PWINDOW->m_eSuppressedEvents |= SUPPRESS_FULLSCREEN; } else if (r.szRule.starts_with("nomaximizerequest")) { - PWINDOW->m_bNoMaximizeRequest = true; + PWINDOW->m_eSuppressedEvents |= SUPPRESS_MAXIMIZE; + } else if (r.szRule.starts_with("suppressevent")) { + CVarList vars(r.szRule, 0, 's', true); + for (size_t i = 1; i < vars.size(); ++i) { + if (vars[i] == "fullscreen") + PWINDOW->m_eSuppressedEvents |= SUPPRESS_FULLSCREEN; + else if (vars[i] == "maximize") + PWINDOW->m_eSuppressedEvents |= SUPPRESS_MAXIMIZE; + else if (vars[i] == "activate") + PWINDOW->m_eSuppressedEvents |= SUPPRESS_ACTIVATE; + else if (vars[i] == "activatefocus") + PWINDOW->m_eSuppressedEvents |= SUPPRESS_ACTIVATE_FOCUSONLY; + else + Debug::log(ERR, "Error while parsing suppressevent windowrule: unknown event type {}", vars[i]); + } } else if (r.szRule == "fullscreen") { requestsFullscreen = true; overridingNoFullscreen = true; @@ -504,8 +518,8 @@ void Events::listener_mapWindow(void* owner, void* data) { "XWayland Window Late"); } - if ((requestsFullscreen && (!PWINDOW->m_bNoFullscreenRequest || overridingNoFullscreen)) || (requestsMaximize && (!PWINDOW->m_bNoMaximizeRequest || overridingNoMaximize)) || - requestsFakeFullscreen) { + if ((requestsFullscreen && (!(PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN) || overridingNoFullscreen)) || + (requestsMaximize && (!(PWINDOW->m_eSuppressedEvents & SUPPRESS_MAXIMIZE) || overridingNoMaximize)) || requestsFakeFullscreen) { // fix fullscreen on requested (basically do a switcheroo) if (PWORKSPACE->m_bHasFullscreenWindow) { const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); @@ -905,7 +919,7 @@ void Events::listener_fullscreenWindow(void* owner, void* data) { return; } - if (PWINDOW->isHidden() || PWINDOW->m_bNoFullscreenRequest) + if (PWINDOW->isHidden() || (PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN)) return; bool requestedFullState = false; @@ -968,7 +982,7 @@ void Events::listener_activateXDG(wl_listener* listener, void* data) { const auto PWINDOW = g_pCompositor->getWindowFromSurface(E->surface); - if (!PWINDOW || PWINDOW == g_pCompositor->m_pLastWindow) + if (!PWINDOW || PWINDOW == g_pCompositor->m_pLastWindow || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE)) return; g_pEventManager->postEvent(SHyprIPCEvent{"urgent", std::format("{:x}", (uintptr_t)PWINDOW)}); @@ -976,7 +990,7 @@ void Events::listener_activateXDG(wl_listener* listener, void* data) { PWINDOW->m_bIsUrgent = true; - if (!*PFOCUSONACTIVATE) + if (!*PFOCUSONACTIVATE || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY)) return; if (PWINDOW->m_bIsFloating) @@ -1004,13 +1018,13 @@ void Events::listener_activateX11(void* owner, void* data) { return; } - if (PWINDOW == g_pCompositor->m_pLastWindow) + if (PWINDOW == g_pCompositor->m_pLastWindow || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE)) return; g_pEventManager->postEvent(SHyprIPCEvent{"urgent", std::format("{:x}", (uintptr_t)PWINDOW)}); EMIT_HOOK_EVENT("urgent", PWINDOW); - if (!*PFOCUSONACTIVATE) + if (!*PFOCUSONACTIVATE || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY)) return; if (PWINDOW->m_bIsFloating) @@ -1206,7 +1220,7 @@ void Events::listener_NewXDGDeco(wl_listener* listener, void* data) { void Events::listener_requestMaximize(void* owner, void* data) { const auto PWINDOW = (CWindow*)owner; - if (PWINDOW->m_bNoMaximizeRequest) + if (PWINDOW->m_eSuppressedEvents & SUPPRESS_MAXIMIZE) return; Debug::log(LOG, "Maximize request for {}", PWINDOW);