mirror of
https://github.com/hyprwm/Hyprland.git
synced 2026-08-24 10:04:19 -05:00
config/propRefresher: add capability to execute scheduled prop refresh immediately with lua helper function, add event for prop refresh (#14990)
* Revert https://github.com/hyprwm/Hyprland/pull/14594 * add `executeScheduledRefreshImmediately()`, `refreshProp()` * add exec_scheduled_prop_refresh_immediately helper function * add event add return value for exec_scheduled_prop_refresh_immediately * format * test
This commit is contained in:
@@ -1030,10 +1030,9 @@ TEST_CASE(testScrollingViewBehaviourMoveFocusInGroupFollowFocusTrue) {
|
||||
TEST_CASE(testScrollingViewBehaviourScheduledPropRefresh) {
|
||||
|
||||
/*
|
||||
Scheduled prop refresh must not move scrolling viewport.
|
||||
The reason a prop refresh was queued is not saved, therefore it is not possible to clearly tell when and when not to move scrolling viewport
|
||||
In this test, we test this by setting a workspace rule, which schedules a prop refresh
|
||||
--------------------------------------------------------------------------------------------------------------------------------------
|
||||
Test that hl.exec_scheduled_prop_refresh_immediately() should immediately execute prop refresh. This is tested via inhibiting scrollin during helper functs dispatch; if it works, the viewport
|
||||
should not move when a new workspace rule is created. If it doesn't, dispatch will miss because the refresh will be executed as another event
|
||||
--------------------------------------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
OK(getFromSocket("r/eval hl.config({ general = { layout = 'scrolling' } })"));
|
||||
@@ -1058,7 +1057,8 @@ TEST_CASE(testScrollingViewBehaviourScheduledPropRefresh) {
|
||||
OK(getFromSocket("/dispatch hl.dsp.focus({ window = 'class:a' })"));
|
||||
|
||||
// setting a workspace rule queues a doLater() call in the Event Loop Manager
|
||||
OK(getFromSocket("/eval hl.workspace_rule({workspace = hl.get_active_workspace().id,gaps_in = 0})"));
|
||||
OK(getFromSocket("/eval hl.dispatch(hl.dsp.layout('inhibit_scroll true')); hl.workspace_rule({workspace = hl.get_active_workspace().id,gaps_in = 0}); "
|
||||
"hl.exec_scheduled_prop_refresh_immediately(); hl.dispatch(hl.dsp.layout('inhibit_scroll false'));"));
|
||||
|
||||
// Check that the workspace rule is set
|
||||
ASSERT_CONTAINS(getFromSocket("/workspacerules"), "gapsIn: 0 0 0 0");
|
||||
|
||||
@@ -148,6 +148,9 @@ CLuaEventHandler::CLuaEventHandler(lua_State* L) : m_lua(L) {
|
||||
}));
|
||||
|
||||
m_listeners.push_back(bus()->m_events.config.reloaded.listen([this] { dispatch("config.reloaded", 0, [](lua_State* L) {}); }));
|
||||
m_listeners.push_back(bus()->m_events.config.props_refreshed.listen(
|
||||
[this](const bool execdAsScheduled) { dispatch("config.props_refreshed", 1, [&](lua_State* L) { lua_pushboolean(L, sc<lua_Integer>(execdAsScheduled)); }); }));
|
||||
|
||||
m_listeners.push_back(
|
||||
bus()->m_events.keybinds.submap.listen([this](const std::string& submap) { dispatch("keybinds.submap", 1, [&](lua_State* L) { lua_pushstring(L, submap.c_str()); }); }));
|
||||
m_listeners.push_back(bus()->m_events.screenshare.state.listen([this](bool state, uint8_t type, const std::string& name) {
|
||||
@@ -277,6 +280,7 @@ std::unordered_set<std::string> CLuaEventHandler::knownEvents() {
|
||||
"workspace.removed",
|
||||
"workspace.move_to_monitor",
|
||||
"config.reloaded",
|
||||
"config.props_refreshed",
|
||||
"keybinds.submap",
|
||||
"screenshare.state",
|
||||
"hyprland.start",
|
||||
|
||||
@@ -462,6 +462,11 @@ static int hlTimer(lua_State* L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int hlExecuteScheduledRefreshImmediately(lua_State* L) {
|
||||
|
||||
return Supplementary::refresher()->executeScheduledRefreshImmediately();
|
||||
}
|
||||
|
||||
void Internal::registerToplevelBindings(lua_State* L, CConfigManager* mgr) {
|
||||
Internal::setMgrFn(L, mgr, "on", hlOn);
|
||||
Internal::setMgrFn(L, mgr, "bind", hlBind);
|
||||
@@ -473,5 +478,7 @@ void Internal::registerToplevelBindings(lua_State* L, CConfigManager* mgr) {
|
||||
Internal::setFn(L, "get_loaded_plugins", hlGetPlugins);
|
||||
Internal::setFn(L, "exec_cmd", hlExecCmd);
|
||||
|
||||
Internal::setFn(L, "exec_scheduled_prop_refresh_immediately", hlExecuteScheduledRefreshImmediately);
|
||||
|
||||
Internal::setFn(L, "unbind", hlUnbind);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "../../shared/monitor/MonitorRuleManager.hpp"
|
||||
#include "../../shared/inotify/ConfigWatcher.hpp"
|
||||
#include "../../../event/EventBus.hpp"
|
||||
|
||||
using namespace Config;
|
||||
using namespace Config::Supplementary;
|
||||
@@ -25,111 +26,130 @@ UP<CPropRefresher>& Supplementary::refresher() {
|
||||
}
|
||||
|
||||
void CPropRefresher::scheduleRefresh(PropRefreshBits prop) {
|
||||
static auto PZOOMFACTOR = CConfigValue<Config::FLOAT>("cursor:zoom_factor");
|
||||
|
||||
m_propsTripped |= prop;
|
||||
|
||||
if (!m_scheduled && g_pEventLoopManager) {
|
||||
g_pEventLoopManager->doLater([this, weak = WP<CPropRefresher>{refresher()}] {
|
||||
m_scheduledRefreshSeq = g_pEventLoopManager->doLater([this, weak = WP<CPropRefresher>{refresher()}] {
|
||||
if (!weak)
|
||||
return;
|
||||
|
||||
if (m_propsTripped & REFRESH_INPUT_DEVICES) {
|
||||
g_pInputManager->setKeyboardLayout(); // update kb layout
|
||||
g_pInputManager->setPointerConfigs(); // update mouse cfgs
|
||||
g_pInputManager->setTouchDeviceConfigs(); // update touch device cfgs
|
||||
g_pInputManager->setTabletConfigs(); // update tablets
|
||||
g_pInputManager->setTabletToolConfigs(); // update tablettools
|
||||
}
|
||||
|
||||
if (m_propsTripped & REFRESH_SCREEN_SHADER) {
|
||||
g_pHyprRenderer->m_reloadScreenShader = true;
|
||||
for (auto const& m : State::monitorState()->monitors()) {
|
||||
if (!m)
|
||||
continue;
|
||||
|
||||
m->m_forceFullFrames = 2;
|
||||
m->scheduleFrame();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_propsTripped & REFRESH_BLUR_FB) {
|
||||
for (auto const& m : State::monitorState()->monitors()) {
|
||||
if (!m)
|
||||
continue;
|
||||
|
||||
m->m_blurFBDirty = true;
|
||||
m->m_forceFullFrames = 2;
|
||||
m->scheduleFrame();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_propsTripped & REFRESH_WINDOW_STATES) {
|
||||
Desktop::Rule::ruleEngine()->updateAllRules();
|
||||
|
||||
for (const auto& ws : State::workspaceState()->workspaces()) {
|
||||
if (!ws)
|
||||
continue;
|
||||
|
||||
ws->updateWindows();
|
||||
ws->updateWindowData();
|
||||
ws->updateWindowDecos();
|
||||
}
|
||||
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
for (auto const& m : State::monitorState()->monitors()) {
|
||||
if (!m)
|
||||
continue;
|
||||
|
||||
m->m_forceFullFrames = 2;
|
||||
g_pHyprRenderer->damageMonitor(m);
|
||||
m->scheduleFrame();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_propsTripped & REFRESH_MONITOR_STATES) {
|
||||
Config::monitorRuleMgr()->scheduleReload();
|
||||
Config::monitorRuleMgr()->ensureVRR();
|
||||
|
||||
for (const auto& m : State::monitorState()->monitors()) {
|
||||
if (!m)
|
||||
continue;
|
||||
|
||||
g_layoutManager->recalculateMonitor(m, Layout::CLayoutManager::RECALCULATE_MONITOR_REASON_PROP_REFRESH);
|
||||
}
|
||||
|
||||
State::workspacePlacementController()->ensurePersistentWorkspacesPresent(
|
||||
nullptr, [](PHLWORKSPACE ws, PHLMONITOR mon, bool noWarp) { g_pCompositor->moveWorkspaceToMonitor(ws, mon, noWarp); });
|
||||
}
|
||||
|
||||
if (m_propsTripped & REFRESH_LAYOUTS) {
|
||||
Layout::Supplementary::algoMatcher()->updateWorkspaceLayouts();
|
||||
|
||||
for (auto const& m : State::monitorState()->monitors()) {
|
||||
g_layoutManager->recalculateMonitor(m, Layout::CLayoutManager::RECALCULATE_MONITOR_REASON_PROP_REFRESH);
|
||||
g_pHyprRenderer->damageMonitor(m);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_propsTripped & REFRESH_CURSOR_ZOOMS) {
|
||||
for (auto const& m : State::monitorState()->monitors()) {
|
||||
*(m->m_cursorZoom) = *PZOOMFACTOR;
|
||||
if (m->m_activeWorkspace)
|
||||
m->m_activeWorkspace->m_space->recalculate();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_propsTripped & REFRESH_CONFIG_WATCHER)
|
||||
Config::watcher()->update();
|
||||
|
||||
if (m_propsTripped & REFRESH_GRADIENTS_GROUPBAR)
|
||||
refreshGroupBarGradients();
|
||||
|
||||
m_scheduled = false;
|
||||
m_propsTripped = 0;
|
||||
refreshProp(true);
|
||||
});
|
||||
|
||||
m_scheduled = true;
|
||||
}
|
||||
}
|
||||
|
||||
int CPropRefresher::executeScheduledRefreshImmediately() {
|
||||
|
||||
if (!m_scheduled || m_scheduledRefreshSeq == 0)
|
||||
return 1;
|
||||
|
||||
g_pEventLoopManager->removeDoLater(m_scheduledRefreshSeq);
|
||||
// m_scheduledRefreshSeq must be reset back to 0 during refreshProp() call
|
||||
refreshProp(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CPropRefresher::refreshProp(const bool execdAsScheduled) {
|
||||
|
||||
static auto PZOOMFACTOR = CConfigValue<Config::FLOAT>("cursor:zoom_factor");
|
||||
|
||||
if (m_propsTripped & REFRESH_INPUT_DEVICES) {
|
||||
g_pInputManager->setKeyboardLayout(); // update kb layout
|
||||
g_pInputManager->setPointerConfigs(); // update mouse cfgs
|
||||
g_pInputManager->setTouchDeviceConfigs(); // update touch device cfgs
|
||||
g_pInputManager->setTabletConfigs(); // update tablets
|
||||
g_pInputManager->setTabletToolConfigs(); // update tablettools
|
||||
}
|
||||
|
||||
if (m_propsTripped & REFRESH_SCREEN_SHADER) {
|
||||
g_pHyprRenderer->m_reloadScreenShader = true;
|
||||
for (auto const& m : State::monitorState()->monitors()) {
|
||||
if (!m)
|
||||
continue;
|
||||
|
||||
m->m_forceFullFrames = 2;
|
||||
m->scheduleFrame();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_propsTripped & REFRESH_BLUR_FB) {
|
||||
for (auto const& m : State::monitorState()->monitors()) {
|
||||
if (!m)
|
||||
continue;
|
||||
|
||||
m->m_blurFBDirty = true;
|
||||
m->m_forceFullFrames = 2;
|
||||
m->scheduleFrame();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_propsTripped & REFRESH_WINDOW_STATES) {
|
||||
Desktop::Rule::ruleEngine()->updateAllRules();
|
||||
|
||||
for (const auto& ws : State::workspaceState()->workspaces()) {
|
||||
if (!ws)
|
||||
continue;
|
||||
|
||||
ws->updateWindows();
|
||||
ws->updateWindowData();
|
||||
ws->updateWindowDecos();
|
||||
}
|
||||
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
for (auto const& m : State::monitorState()->monitors()) {
|
||||
if (!m)
|
||||
continue;
|
||||
|
||||
m->m_forceFullFrames = 2;
|
||||
g_pHyprRenderer->damageMonitor(m);
|
||||
m->scheduleFrame();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_propsTripped & REFRESH_MONITOR_STATES) {
|
||||
Config::monitorRuleMgr()->scheduleReload();
|
||||
Config::monitorRuleMgr()->ensureVRR();
|
||||
|
||||
for (const auto& m : State::monitorState()->monitors()) {
|
||||
if (!m)
|
||||
continue;
|
||||
|
||||
g_layoutManager->recalculateMonitor(m);
|
||||
}
|
||||
|
||||
State::workspacePlacementController()->ensurePersistentWorkspacesPresent(
|
||||
nullptr, [](PHLWORKSPACE ws, PHLMONITOR mon, bool noWarp) { g_pCompositor->moveWorkspaceToMonitor(ws, mon, noWarp); });
|
||||
}
|
||||
|
||||
if (m_propsTripped & REFRESH_LAYOUTS) {
|
||||
Layout::Supplementary::algoMatcher()->updateWorkspaceLayouts();
|
||||
|
||||
for (auto const& m : State::monitorState()->monitors()) {
|
||||
g_layoutManager->recalculateMonitor(m);
|
||||
g_pHyprRenderer->damageMonitor(m);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_propsTripped & REFRESH_CURSOR_ZOOMS) {
|
||||
for (auto const& m : State::monitorState()->monitors()) {
|
||||
*(m->m_cursorZoom) = *PZOOMFACTOR;
|
||||
if (m->m_activeWorkspace)
|
||||
m->m_activeWorkspace->m_space->recalculate();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_propsTripped & REFRESH_CONFIG_WATCHER)
|
||||
Config::watcher()->update();
|
||||
|
||||
if (m_propsTripped & REFRESH_GRADIENTS_GROUPBAR)
|
||||
refreshGroupBarGradients();
|
||||
|
||||
m_scheduled = false;
|
||||
m_scheduledRefreshSeq = 0;
|
||||
m_propsTripped = 0;
|
||||
|
||||
Event::bus()->m_events.config.props_refreshed.emit(execdAsScheduled);
|
||||
}
|
||||
@@ -26,10 +26,14 @@ namespace Config::Supplementary {
|
||||
class CPropRefresher {
|
||||
public:
|
||||
void scheduleRefresh(PropRefreshBits reason);
|
||||
int executeScheduledRefreshImmediately();
|
||||
|
||||
private:
|
||||
bool m_scheduled = false;
|
||||
PropRefreshBits m_propsTripped = 0;
|
||||
void refreshProp(const bool execdAsScheduled);
|
||||
|
||||
bool m_scheduled = false;
|
||||
uint64_t m_scheduledRefreshSeq = 0; // 0 if no refresh event scheduled
|
||||
PropRefreshBits m_propsTripped = 0;
|
||||
};
|
||||
|
||||
UP<CPropRefresher>& refresher();
|
||||
|
||||
@@ -165,8 +165,9 @@ namespace Event {
|
||||
} workspace;
|
||||
|
||||
struct {
|
||||
Event<> preReload;
|
||||
Event<> reloaded;
|
||||
Event<> preReload;
|
||||
Event<> reloaded;
|
||||
Event<const bool> props_refreshed;
|
||||
} config;
|
||||
|
||||
struct {
|
||||
|
||||
@@ -52,7 +52,6 @@ namespace Layout {
|
||||
|
||||
enum eRecalculateMonitorReason : uint8_t {
|
||||
RECALCULATE_MONITOR_REASON_UNKNOWN, // when the recalculate monitor reason is unknown or not important to preserve
|
||||
RECALCULATE_MONITOR_REASON_PROP_REFRESH,
|
||||
RECALCULATE_MONITOR_REASON_WORKSPACE_CHANGE,
|
||||
RECALCULATE_MONITOR_REASON_TOGGLE_SPECIAL_WORKSPACE,
|
||||
RECALCULATE_MONITOR_REASON_TOGGLE_FULLSCREEN,
|
||||
|
||||
@@ -32,7 +32,7 @@ CSpace::CSpace(PHLWORKSPACE parent) : m_parent(parent) {
|
||||
recheckWorkArea();
|
||||
|
||||
if (m_algorithm)
|
||||
m_algorithm->recalculate(RECALCULATE_REASON_CREATE_SPACE);
|
||||
m_algorithm->recalculate();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -219,9 +219,9 @@ SP<ITarget> CSpace::getNextCandidate(SP<ITarget> old) {
|
||||
}
|
||||
|
||||
bool Layout::isHardRecalculateReason(eRecalculateReason reason) {
|
||||
return reason != RECALCULATE_REASON_CREATE_SPACE && reason != RECALCULATE_REASON_PROP_REFRESH && reason != RECALCULATE_REASON_WORKSPACE_CHANGE &&
|
||||
reason != RECALCULATE_REASON_SPECIAL_WORKSPACE_TOGGLE && reason != RECALCULATE_REASON_TOGGLE_LAYOUT_HANDLED_FULLSCREEN &&
|
||||
reason != RECALCULATE_REASON_TOGGLE_DEFAULT_HANDLED_FULLSCREEN && reason != RECALCULATE_REASON_INVALIDATE_MONITOR_GEOMETRIES && reason != RECALCULATE_REASON_RENDER_MOINTOR;
|
||||
return reason != RECALCULATE_REASON_WORKSPACE_CHANGE && reason != RECALCULATE_REASON_SPECIAL_WORKSPACE_TOGGLE &&
|
||||
reason != RECALCULATE_REASON_TOGGLE_LAYOUT_HANDLED_FULLSCREEN && reason != RECALCULATE_REASON_TOGGLE_DEFAULT_HANDLED_FULLSCREEN &&
|
||||
reason != RECALCULATE_REASON_INVALIDATE_MONITOR_GEOMETRIES && reason != RECALCULATE_REASON_RENDER_MOINTOR;
|
||||
}
|
||||
|
||||
const std::vector<WP<ITarget>>& CSpace::targets() const {
|
||||
@@ -234,7 +234,6 @@ eRecalculateReason Layout::recalcMonitorReasonToRecalcReason(CLayoutManager::eRe
|
||||
case CLayoutManager::RECALCULATE_MONITOR_REASON_TOGGLE_SPECIAL_WORKSPACE: return RECALCULATE_REASON_SPECIAL_WORKSPACE_TOGGLE;
|
||||
case CLayoutManager::RECALCULATE_MONITOR_REASON_WORKSPACE_CHANGE: return RECALCULATE_REASON_WORKSPACE_CHANGE;
|
||||
case CLayoutManager::RECALCULATE_MONITOR_REASON_TOGGLE_FULLSCREEN: return RECALCULATE_REASON_TOGGLE_DEFAULT_HANDLED_FULLSCREEN;
|
||||
case CLayoutManager::RECALCULATE_MONITOR_REASON_PROP_REFRESH: return RECALCULATE_REASON_PROP_REFRESH;
|
||||
default: return RECALCULATE_REASON_UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -15,8 +15,6 @@ namespace Layout {
|
||||
|
||||
enum eRecalculateReason : uint8_t {
|
||||
RECALCULATE_REASON_UNKNOWN, // when the recalculate reason is unknown or not important to preserve
|
||||
RECALCULATE_REASON_PROP_REFRESH,
|
||||
RECALCULATE_REASON_CREATE_SPACE,
|
||||
RECALCULATE_REASON_WORKSPACE_CHANGE,
|
||||
RECALCULATE_REASON_SPECIAL_WORKSPACE_TOGGLE,
|
||||
RECALCULATE_REASON_TOGGLE_DEFAULT_HANDLED_FULLSCREEN,
|
||||
|
||||
Reference in New Issue
Block a user