Merge pull request #3088 from VAWVAW/hyprland-bar-scroll

hyprland/workspaces: Add `enable-bar-scroll` option
This commit is contained in:
Alexis Rouillard
2026-02-13 23:43:12 +01:00
committed by GitHub
3 changed files with 44 additions and 0 deletions

View File

@ -43,6 +43,7 @@ class Workspaces : public AModule, public EventHandler {
auto moveToMonitor() const -> bool { return m_moveToMonitor; }
auto enableTaskbar() const -> bool { return m_enableTaskbar; }
auto taskbarWithIcon() const -> bool { return m_taskbarWithIcon; }
auto barScroll() const -> bool { return m_barScroll; }
auto getBarOutput() const -> std::string { return m_bar.output->name; }
auto formatBefore() const -> std::string { return m_formatBefore; }
@ -122,6 +123,8 @@ class Workspaces : public AModule, public EventHandler {
static std::pair<std::string, std::string> splitDoublePayload(std::string const& payload);
static std::tuple<std::string, std::string, std::string> splitTriplePayload(
std::string const& payload);
// scroll events
bool handleScroll(GdkEventScroll* e) override;
// Update methods
void doUpdate();
@ -145,6 +148,7 @@ class Workspaces : public AModule, public EventHandler {
bool m_specialVisibleOnly = false;
bool m_persistentOnly = false;
bool m_moveToMonitor = false;
bool m_barScroll = false;
Json::Value m_persistentWorkspaceConfig;
// Map for windows stored in workspaces not present in the current bar.

View File

@ -130,6 +130,11 @@ This setting is ignored if *workspace-taskbar.enable* is set to true.
Otherwise, the workspace will open on the monitor where it was previously assigned.
Analog to using `focusworkspaceoncurrentmonitor` dispatcher instead of `workspace` in Hyprland.
*enable-bar-scroll*: ++
typeof: bool ++
default: false ++
If set to false, you can't scroll to cycle throughout workspaces from the entire bar. If set to true this behaviour is enabled.
*ignore-workspaces*: ++
typeof: array ++
default: [] ++

View File

@ -43,6 +43,13 @@ void Workspaces::init() {
m_activeWorkspaceId = m_ipc.getSocket1JsonReply("activeworkspace")["id"].asInt();
initializeWorkspaces();
if (barScroll()) {
auto &window = const_cast<Bar &>(m_bar).window;
window.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
window.signal_scroll_event().connect(sigc::mem_fun(*this, &Workspaces::handleScroll));
}
dp.emit();
}
@ -636,6 +643,7 @@ auto Workspaces::parseConfig(const Json::Value& config) -> void {
populateBoolConfig(config, "persistent-only", m_persistentOnly);
populateBoolConfig(config, "active-only", m_activeOnly);
populateBoolConfig(config, "move-to-monitor", m_moveToMonitor);
populateBoolConfig(config, "enable-bar-scroll", m_barScroll);
m_persistentWorkspaceConfig = config.get("persistent-workspaces", Json::Value());
populateSortByConfig(config);
@ -1151,4 +1159,31 @@ std::optional<int> Workspaces::parseWorkspaceId(std::string const& workspaceIdSt
}
}
bool Workspaces::handleScroll(GdkEventScroll *e) {
// Ignore emulated scroll events on window
if (gdk_event_get_pointer_emulated((GdkEvent *)e)) {
return false;
}
auto dir = AModule::getScrollDir(e);
if (dir == SCROLL_DIR::NONE) {
return true;
}
if (dir == SCROLL_DIR::DOWN || dir == SCROLL_DIR::RIGHT) {
if (allOutputs()) {
m_ipc.getSocket1Reply("dispatch workspace e+1");
} else {
m_ipc.getSocket1Reply("dispatch workspace m+1");
}
} else if (dir == SCROLL_DIR::UP || dir == SCROLL_DIR::LEFT) {
if (allOutputs()) {
m_ipc.getSocket1Reply("dispatch workspace e-1");
} else {
m_ipc.getSocket1Reply("dispatch workspace m-1");
}
}
return true;
}
} // namespace waybar::modules::hyprland