aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorVaxry <[email protected]>2024-08-30 17:37:52 +0200
committerGitHub <[email protected]>2024-08-30 17:37:52 +0200
commitc5fd5771814958ad274ea9abb961fff621a35b9c (patch)
treee955a8465ef0b8680603b8f7860b012b2991a09f
parentfbd63543930417f3cefe36bdb9f2cdd20fc3693a (diff)
downloadHyprland-c5fd5771814958ad274ea9abb961fff621a35b9c.tar.gz
Hyprland-c5fd5771814958ad274ea9abb961fff621a35b9c.zip
config: Add a window rule to render while unfocused (#7582)
-rw-r--r--src/config/ConfigDescriptions.hpp6
-rw-r--r--src/config/ConfigManager.cpp3
-rw-r--r--src/desktop/Window.cpp5
-rw-r--r--src/desktop/Window.hpp1
-rw-r--r--src/managers/eventLoop/EventLoopTimer.cpp4
-rw-r--r--src/managers/eventLoop/EventLoopTimer.hpp1
-rw-r--r--src/render/Renderer.cpp50
-rw-r--r--src/render/Renderer.hpp4
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;