diff options
author | Vaxry <[email protected]> | 2024-08-30 17:37:52 +0200 |
---|---|---|
committer | GitHub <[email protected]> | 2024-08-30 17:37:52 +0200 |
commit | c5fd5771814958ad274ea9abb961fff621a35b9c (patch) | |
tree | e955a8465ef0b8680603b8f7860b012b2991a09f | |
parent | fbd63543930417f3cefe36bdb9f2cdd20fc3693a (diff) | |
download | Hyprland-c5fd5771814958ad274ea9abb961fff621a35b9c.tar.gz Hyprland-c5fd5771814958ad274ea9abb961fff621a35b9c.zip |
config: Add a window rule to render while unfocused (#7582)
-rw-r--r-- | src/config/ConfigDescriptions.hpp | 6 | ||||
-rw-r--r-- | src/config/ConfigManager.cpp | 3 | ||||
-rw-r--r-- | src/desktop/Window.cpp | 5 | ||||
-rw-r--r-- | src/desktop/Window.hpp | 1 | ||||
-rw-r--r-- | src/managers/eventLoop/EventLoopTimer.cpp | 4 | ||||
-rw-r--r-- | src/managers/eventLoop/EventLoopTimer.hpp | 1 | ||||
-rw-r--r-- | src/render/Renderer.cpp | 50 | ||||
-rw-r--r-- | src/render/Renderer.hpp | 4 |
8 files changed, 73 insertions, 1 deletions
diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 73b995ae..73f3c9a3 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1037,6 +1037,12 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{true}, }, + SConfigOptionDescription{ + .value = "misc:render_unfocused_fps", + .description = "the maximum limit for renderunfocused windows' fps in the background", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{15, 1, 120}, + }, /* * binds: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index f402958b..5940a6fe 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -357,6 +357,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("misc:exit_window_retains_fullscreen", Hyprlang::INT{0}); m_pConfig->addConfigValue("misc:initial_workspace_tracking", Hyprlang::INT{1}); m_pConfig->addConfigValue("misc:middle_click_paste", Hyprlang::INT{1}); + m_pConfig->addConfigValue("misc:render_unfocused_fps", Hyprlang::INT{15}); m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1}); @@ -2155,7 +2156,7 @@ std::optional<std::string> CConfigManager::handleUnbind(const std::string& comma bool windowRuleValid(const std::string& RULE) { static const auto rules = std::unordered_set<std::string>{ - "float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", + "float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", "renderunfocused", }; static const auto rulesPrefix = std::vector<std::string>{ "animation", "bordercolor", "bordersize", "center", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor", diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 7623d45e..a9e389a6 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -757,6 +757,9 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { if (m_sGroupData.pNextWindow.expired()) setHidden(false); } catch (std::exception& e) { Debug::log(ERR, "minsize rule \"{}\" failed with: {}", r.szRule, e.what()); } + } else if (r.szRule == "renderunfocused") { + m_sWindowData.renderUnfocused = CWindowOverridableVar(true, priority); + g_pHyprRenderer->addWindowToRenderUnfocused(m_pSelf.lock()); } } @@ -774,6 +777,8 @@ void CWindow::updateDynamicRules() { m_sWindowData.activeBorderColor.unset(PRIORITY_WINDOW_RULE); m_sWindowData.inactiveBorderColor.unset(PRIORITY_WINDOW_RULE); + m_sWindowData.renderUnfocused.unset(PRIORITY_WINDOW_RULE); + m_eIdleInhibitMode = IDLEINHIBIT_NONE; m_tags.removeDynamicTags(); diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 7197ba26..d14248c5 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -174,6 +174,7 @@ struct SWindowData { CWindowOverridableVar<bool> syncFullscreen = true; CWindowOverridableVar<bool> tearing = false; CWindowOverridableVar<bool> xray = false; + CWindowOverridableVar<bool> renderUnfocused = false; CWindowOverridableVar<int> rounding; CWindowOverridableVar<int> borderSize; diff --git a/src/managers/eventLoop/EventLoopTimer.cpp b/src/managers/eventLoop/EventLoopTimer.cpp index d3cfdf8d..b8943b7c 100644 --- a/src/managers/eventLoop/EventLoopTimer.cpp +++ b/src/managers/eventLoop/EventLoopTimer.cpp @@ -49,3 +49,7 @@ float CEventLoopTimer::leftUs() { return std::chrono::duration_cast<std::chrono::microseconds>(*expires - std::chrono::steady_clock::now()).count(); } + +bool CEventLoopTimer::armed() { + return expires.has_value(); +} diff --git a/src/managers/eventLoop/EventLoopTimer.hpp b/src/managers/eventLoop/EventLoopTimer.hpp index ad7d3986..e5a8c5e3 100644 --- a/src/managers/eventLoop/EventLoopTimer.hpp +++ b/src/managers/eventLoop/EventLoopTimer.hpp @@ -16,6 +16,7 @@ class CEventLoopTimer { void cancel(); bool passed(); + bool armed(); float leftUs(); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 420f8d4c..c5866e4a 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -97,6 +97,44 @@ CHyprRenderer::CHyprRenderer() { m_pCursorTicker = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, cursorTicker, nullptr); wl_event_source_timer_update(m_pCursorTicker, 500); + + m_tRenderUnfocusedTimer = makeShared<CEventLoopTimer>( + std::nullopt, + [this](SP<CEventLoopTimer> self, void* data) { + static auto PFPS = CConfigValue<Hyprlang::INT>("misc:render_unfocused_fps"); + + if (m_vRenderUnfocused.empty()) + return; + + timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + bool dirty = false; + for (auto& w : m_vRenderUnfocused) { + if (!w) { + dirty = true; + continue; + } + + if (!w->m_pWLSurface || !w->m_pWLSurface->resource() || shouldRenderWindow(w.lock())) + continue; + + w->m_pWLSurface->resource()->frame(&now); + auto FEEDBACK = makeShared<CQueuedPresentationData>(w->m_pWLSurface->resource()); + FEEDBACK->attachMonitor(g_pCompositor->m_pLastMonitor.lock()); + FEEDBACK->discarded(); + PROTO::presentation->queueData(FEEDBACK); + } + + if (dirty) + std::erase_if(m_vRenderUnfocused, [](const auto& e) { return !e || !e->m_sWindowData.renderUnfocused.valueOr(false); }); + + if (!m_vRenderUnfocused.empty()) + m_tRenderUnfocusedTimer->updateTimeout(std::chrono::milliseconds(1000 / *PFPS)); + }, + nullptr); + + g_pEventLoopManager->addTimer(m_tRenderUnfocusedTimer); } CHyprRenderer::~CHyprRenderer() { @@ -2800,3 +2838,15 @@ SExplicitSyncSettings CHyprRenderer::getExplicitSyncSettings() { return settings; } + +void CHyprRenderer::addWindowToRenderUnfocused(PHLWINDOW window) { + static auto PFPS = CConfigValue<Hyprlang::INT>("misc:render_unfocused_fps"); + + if (std::find(m_vRenderUnfocused.begin(), m_vRenderUnfocused.end(), window) != m_vRenderUnfocused.end()) + return; + + m_vRenderUnfocused.emplace_back(window); + + if (!m_tRenderUnfocusedTimer->armed()) + m_tRenderUnfocusedTimer->updateTimeout(std::chrono::milliseconds(1000 / *PFPS)); +} diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index d00c0a17..b730d589 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -13,6 +13,7 @@ class CWorkspace; class CWindow; class CInputPopup; class IHLBuffer; +class CEventLoopTimer; // TODO: add fuller damage tracking for updating only parts of a window enum DAMAGETRACKINGMODES { @@ -78,6 +79,7 @@ class CHyprRenderer { void makeEGLCurrent(); void unsetEGL(); SExplicitSyncSettings getExplicitSyncSettings(); + void addWindowToRenderUnfocused(PHLWINDOW window); // if RENDER_MODE_NORMAL, provided damage will be written to. // otherwise, it will be the one used. @@ -143,6 +145,8 @@ class CHyprRenderer { SP<CRenderbuffer> getOrCreateRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t fmt); std::vector<SP<CRenderbuffer>> m_vRenderbuffers; + std::vector<PHLWINDOWREF> m_vRenderUnfocused; + SP<CEventLoopTimer> m_tRenderUnfocusedTimer; friend class CHyprOpenGLImpl; friend class CToplevelExportFrame; |