hyprland/workspaces: add debounce timer to prevent workspace button flicker
When switching between workspaces rapidly (especially empty ones), Hyprland sends createworkspace and destroyworkspace events slightly out of order. This causes workspace buttons to render in wrong positions for a split second before snapping to their correct spots. Add a 7ms debounce timer that batches workspace events before calling dp.emit(), preventing the visual glitch. Fixes #4376
This commit is contained in:
@@ -211,6 +211,9 @@ class Workspaces : public AModule, public EventHandler {
|
|||||||
Gtk::Box m_box;
|
Gtk::Box m_box;
|
||||||
sigc::connection m_scrollEventConnection_;
|
sigc::connection m_scrollEventConnection_;
|
||||||
IPC& m_ipc;
|
IPC& m_ipc;
|
||||||
|
|
||||||
|
sigc::connection m_debounceTimer;
|
||||||
|
bool m_updatePending = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::modules::hyprland
|
} // namespace waybar::modules::hyprland
|
||||||
|
|||||||
@@ -338,46 +338,62 @@ void Workspaces::loadPersistentWorkspacesFromWorkspaceRules(const Json::Value& c
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::onEvent(const std::string& ev) {
|
void Workspaces::onEvent(const std::string& ev) {
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
{
|
||||||
const auto separator = ev.find(">>");
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
if (separator == std::string::npos) {
|
const auto separator = ev.find(">>");
|
||||||
spdlog::warn("Malformed Hyprland workspace event: {}", ev);
|
if (separator == std::string::npos) {
|
||||||
return;
|
spdlog::warn("Malformed Hyprland workspace event: {}", ev);
|
||||||
}
|
return;
|
||||||
std::string eventName = ev.substr(0, separator);
|
}
|
||||||
std::string payload = ev.substr(separator + 2);
|
std::string eventName = ev.substr(0, separator);
|
||||||
|
std::string payload = ev.substr(separator + 2);
|
||||||
|
|
||||||
if (eventName == "workspacev2") {
|
if (eventName == "workspacev2") {
|
||||||
onWorkspaceActivated(payload);
|
onWorkspaceActivated(payload);
|
||||||
} else if (eventName == "activespecial") {
|
} else if (eventName == "activespecial") {
|
||||||
onSpecialWorkspaceActivated(payload);
|
onSpecialWorkspaceActivated(payload);
|
||||||
} else if (eventName == "destroyworkspacev2") {
|
} else if (eventName == "destroyworkspacev2") {
|
||||||
onWorkspaceDestroyed(payload);
|
onWorkspaceDestroyed(payload);
|
||||||
} else if (eventName == "createworkspacev2") {
|
} else if (eventName == "createworkspacev2") {
|
||||||
onWorkspaceCreated(payload);
|
onWorkspaceCreated(payload);
|
||||||
} else if (eventName == "focusedmonv2") {
|
} else if (eventName == "focusedmonv2") {
|
||||||
onMonitorFocused(payload);
|
onMonitorFocused(payload);
|
||||||
} else if (eventName == "moveworkspacev2") {
|
} else if (eventName == "moveworkspacev2") {
|
||||||
onWorkspaceMoved(payload);
|
onWorkspaceMoved(payload);
|
||||||
} else if (eventName == "openwindow") {
|
} else if (eventName == "openwindow") {
|
||||||
onWindowOpened(payload);
|
onWindowOpened(payload);
|
||||||
} else if (eventName == "closewindow") {
|
} else if (eventName == "closewindow") {
|
||||||
onWindowClosed(payload);
|
onWindowClosed(payload);
|
||||||
} else if (eventName == "movewindowv2") {
|
} else if (eventName == "movewindowv2") {
|
||||||
onWindowMoved(payload);
|
onWindowMoved(payload);
|
||||||
} else if (eventName == "urgent") {
|
} else if (eventName == "urgent") {
|
||||||
setUrgentWorkspace(payload);
|
setUrgentWorkspace(payload);
|
||||||
} else if (eventName == "renameworkspace") {
|
} else if (eventName == "renameworkspace") {
|
||||||
onWorkspaceRenamed(payload);
|
onWorkspaceRenamed(payload);
|
||||||
} else if (eventName == "windowtitlev2") {
|
} else if (eventName == "windowtitlev2") {
|
||||||
onWindowTitleEvent(payload);
|
onWindowTitleEvent(payload);
|
||||||
} else if (eventName == "activewindowv2") {
|
} else if (eventName == "activewindowv2") {
|
||||||
onActiveWindowChanged(payload);
|
onActiveWindowChanged(payload);
|
||||||
} else if (eventName == "configreloaded") {
|
} else if (eventName == "configreloaded") {
|
||||||
onConfigReloaded();
|
onConfigReloaded();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dp.emit();
|
if (m_debounceTimer.connected()) {
|
||||||
|
m_debounceTimer.disconnect();
|
||||||
|
m_updatePending = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_updatePending = true;
|
||||||
|
m_debounceTimer = Glib::signal_timeout().connect([this]() {
|
||||||
|
if (!m_updatePending) return false;
|
||||||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
if (m_updatePending) {
|
||||||
|
dp.emit();
|
||||||
|
m_updatePending = false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::onWorkspaceActivated(std::string const& payload) {
|
void Workspaces::onWorkspaceActivated(std::string const& payload) {
|
||||||
|
|||||||
Reference in New Issue
Block a user