feat(hyprland/workspaces): added options `move-to-monitor` and `active-per-monitor`

This commit is contained in:
Tom Benham 2024-03-04 13:17:30 +01:00
parent 26af1066e1
commit df7f1fffcf
3 changed files with 74 additions and 6 deletions

View File

@ -126,6 +126,8 @@ class Workspaces : public AModule, public EventHandler {
auto allOutputs() const -> bool { return m_allOutputs; } auto allOutputs() const -> bool { return m_allOutputs; }
auto showSpecial() const -> bool { return m_showSpecial; } auto showSpecial() const -> bool { return m_showSpecial; }
auto activeOnly() const -> bool { return m_activeOnly; } auto activeOnly() const -> bool { return m_activeOnly; }
auto moveToMonitor() const -> bool { return m_moveToMonitor; }
auto activePerMonitor() const -> bool { return m_activePerMonitor; }
auto getBarOutput() const -> std::string { return m_bar.output->name; } auto getBarOutput() const -> std::string { return m_bar.output->name; }
@ -182,6 +184,8 @@ class Workspaces : public AModule, public EventHandler {
bool m_allOutputs = false; bool m_allOutputs = false;
bool m_showSpecial = false; bool m_showSpecial = false;
bool m_activeOnly = false; bool m_activeOnly = false;
bool m_moveToMonitor = false;
bool m_activePerMonitor = false;
Json::Value m_persistentWorkspaceConfig; Json::Value m_persistentWorkspaceConfig;
// Map for windows stored in workspaces not present in the current bar. // Map for windows stored in workspaces not present in the current bar.

View File

@ -52,6 +52,21 @@ Addressed by *hyprland/workspaces*
default: false ++ default: false ++
If set to true, only the active workspace will be shown. If set to true, only the active workspace will be shown.
*move-to-monitor*: ++
typeof: bool ++
default: false ++
If set to true, open the workspace on the current monitor when clicking on a workspace button.
Otherwise, the workspace will open on the monitor where it was previously assigned.
Analog to using `focusworkspaceoncurrentmonitor` dispatcher instead of `workspace` in Hyprland.
*active-per-monitor*: ++
typeof: bool ++
default: false ++
If set to true, each bar on each monitor will show its separate active
workspace being the currently focused workspace on this monitor.
Otherwise, all bars on all monitors will show the same active workspace
being the currently focused workspace on the currently focused monitor.
*ignore-workspaces*: ++ *ignore-workspaces*: ++
typeof: array ++ typeof: array ++
default: [] ++ default: [] ++

View File

@ -83,6 +83,16 @@ auto Workspaces::parseConfig(const Json::Value &config) -> void {
m_activeOnly = configActiveOnly.asBool(); m_activeOnly = configActiveOnly.asBool();
} }
auto configMoveToMonitor = config_["move-to-monitor"];
if (configMoveToMonitor.isBool()) {
m_moveToMonitor = configMoveToMonitor.asBool();
}
auto configActivePerMonitor = config_["active-per-monitor"];
if (configActivePerMonitor.isBool()) {
m_activePerMonitor = configActivePerMonitor.asBool();
}
auto configSortBy = config_["sort-by"]; auto configSortBy = config_["sort-by"];
if (configSortBy.isString()) { if (configSortBy.isString()) {
auto sortByStr = configSortBy.asString(); auto sortByStr = configSortBy.asString();
@ -321,7 +331,14 @@ void Workspaces::onEvent(const std::string &ev) {
} }
void Workspaces::onWorkspaceActivated(std::string const &payload) { void Workspaces::onWorkspaceActivated(std::string const &payload) {
if (!m_activePerMonitor) {
m_activeWorkspaceName = payload; m_activeWorkspaceName = payload;
return;
}
auto activeWorkspace = gIPC->getSocket1JsonReply("activeworkspace");
if (m_bar.output->name == activeWorkspace["monitor"].asString()) {
m_activeWorkspaceName = payload;
}
} }
void Workspaces::onSpecialWorkspaceActivated(std::string const &payload) { void Workspaces::onSpecialWorkspaceActivated(std::string const &payload) {
@ -374,6 +391,16 @@ void Workspaces::onWorkspaceMoved(std::string const &payload) {
if (m_bar.output->name == monitorName) { if (m_bar.output->name == monitorName) {
Json::Value clientsData = gIPC->getSocket1JsonReply("clients"); Json::Value clientsData = gIPC->getSocket1JsonReply("clients");
onWorkspaceCreated(workspaceName, clientsData); onWorkspaceCreated(workspaceName, clientsData);
if (m_activePerMonitor) {
for (Json::Value &monitor : gIPC->getSocket1JsonReply("monitors")) {
if (m_bar.output->name == monitor["name"].asString()) {
auto ws = monitor["activeWorkspace"];
if (ws.isObject() && (ws["name"].isString())) {
m_activeWorkspaceName = ws["name"].asString();
}
}
}
}
} else { } else {
spdlog::debug("Removing workspace because it was moved to another monitor: {}"); spdlog::debug("Removing workspace because it was moved to another monitor: {}");
onWorkspaceDestroyed(workspaceName); onWorkspaceDestroyed(workspaceName);
@ -399,10 +426,13 @@ void Workspaces::onWorkspaceRenamed(std::string const &payload) {
void Workspaces::onMonitorFocused(std::string const &payload) { void Workspaces::onMonitorFocused(std::string const &payload) {
spdlog::trace("Monitor focused: {}", payload); spdlog::trace("Monitor focused: {}", payload);
auto monitorName = payload.substr(0, payload.find(','));
if (!m_activePerMonitor || m_bar.output->name == monitorName) {
m_activeWorkspaceName = payload.substr(payload.find(',') + 1); m_activeWorkspaceName = payload.substr(payload.find(',') + 1);
}
for (Json::Value &monitor : gIPC->getSocket1JsonReply("monitors")) { for (Json::Value &monitor : gIPC->getSocket1JsonReply("monitors")) {
if (monitor["name"].asString() == payload.substr(0, payload.find(','))) { if (monitor["name"].asString() == monitorName) {
auto name = monitor["specialWorkspace"]["name"].asString(); auto name = monitor["specialWorkspace"]["name"].asString();
m_activeSpecialWorkspaceName = !name.starts_with("special:") ? name : name.substr(8); m_activeSpecialWorkspaceName = !name.starts_with("special:") ? name : name.substr(8);
} }
@ -804,7 +834,18 @@ void Workspaces::extendOrphans(int workspaceId, Json::Value const &clientsJson)
} }
void Workspaces::init() { void Workspaces::init() {
if (!m_activePerMonitor) {
m_activeWorkspaceName = (gIPC->getSocket1JsonReply("activeworkspace"))["name"].asString(); m_activeWorkspaceName = (gIPC->getSocket1JsonReply("activeworkspace"))["name"].asString();
} else {
for (Json::Value &monitor : gIPC->getSocket1JsonReply("monitors")) {
if (m_bar.output->name == monitor["name"].asString()) {
auto ws = monitor["activeWorkspace"];
if (ws.isObject() && (ws["name"].isString())) {
m_activeWorkspaceName = ws["name"].asString();
}
}
}
}
initializeWorkspaces(); initializeWorkspaces();
updateWindowCount(); updateWindowCount();
@ -1019,9 +1060,17 @@ bool Workspace::handleClicked(GdkEventButton *bt) const {
if (bt->type == GDK_BUTTON_PRESS) { if (bt->type == GDK_BUTTON_PRESS) {
try { try {
if (id() > 0) { // normal if (id() > 0) { // normal
if (m_workspaceManager.moveToMonitor()) {
gIPC->getSocket1Reply("dispatch focusworkspaceoncurrentmonitor " + std::to_string(id()));
} else {
gIPC->getSocket1Reply("dispatch workspace " + std::to_string(id())); gIPC->getSocket1Reply("dispatch workspace " + std::to_string(id()));
}
} else if (!isSpecial()) { // named (this includes persistent) } else if (!isSpecial()) { // named (this includes persistent)
if (m_workspaceManager.moveToMonitor()) {
gIPC->getSocket1Reply("dispatch focusworkspaceoncurrentmonitor name:" + name());
} else {
gIPC->getSocket1Reply("dispatch workspace name:" + name()); gIPC->getSocket1Reply("dispatch workspace name:" + name());
}
} else if (id() != -99) { // named special } else if (id() != -99) { // named special
gIPC->getSocket1Reply("dispatch togglespecialworkspace " + name()); gIPC->getSocket1Reply("dispatch togglespecialworkspace " + name());
} else { // special } else { // special