Skip to content

Commit 65a97fc

Browse files
committed
fix(hyprland): support additional v2 events
1 parent a9e49c6 commit 65a97fc

File tree

1 file changed

+103
-116
lines changed

1 file changed

+103
-116
lines changed

src/modules/hyprland/workspaces.cpp

+103-116
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
namespace waybar::modules::hyprland {
1414

15+
constexpr int INVALID_WORKSPACE_ID = -100;
16+
1517
Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value &config)
1618
: AModule(config, "workspaces", id, false, false),
1719
m_bar(bar),
@@ -39,13 +41,7 @@ Workspaces::~Workspaces() {
3941
}
4042

4143
void Workspaces::init() {
42-
<<<<<<< HEAD
43-
m_activeWorkspaceName = (m_ipc.getSocket1JsonReply("activeworkspace"))["name"].asString();
44-
||||||| parent of 24d391b9 (feat(hyprland): support workspacev2)
45-
m_activeWorkspaceName = (gIPC->getSocket1JsonReply("activeworkspace"))["name"].asString();
46-
=======
4744
m_activeWorkspaceId = (gIPC->getSocket1JsonReply("activeworkspace"))["id"].asInt();
48-
>>>>>>> 24d391b9 (feat(hyprland): support workspacev2)
4945

5046
initializeWorkspaces();
5147
dp.emit();
@@ -55,13 +51,12 @@ Json::Value Workspaces::createMonitorWorkspaceData(std::string const &name,
5551
std::string const &monitor) {
5652
spdlog::trace("Creating persistent workspace: {} on monitor {}", name, monitor);
5753
Json::Value workspaceData;
58-
try {
59-
// numbered persistent workspaces get the name as ID
60-
workspaceData["id"] = name == "special" ? -99 : std::stoi(name);
61-
} catch (const std::exception &e) {
62-
// named persistent workspaces start with ID=0
63-
workspaceData["id"] = 0;
54+
55+
auto workspaceId = getWorkspaceId(name);
56+
if (workspaceId == INVALID_WORKSPACE_ID) {
57+
workspaceId = 0
6458
}
59+
workspaceData["id"] = workspaceId
6560
workspaceData["name"] = name;
6661
workspaceData["monitor"] = monitor;
6762
workspaceData["windows"] = 0;
@@ -72,6 +67,7 @@ void Workspaces::createWorkspace(Json::Value const &workspace_data,
7267
Json::Value const &clients_data) {
7368
auto workspaceName = workspace_data["name"].asString();
7469
spdlog::debug("Creating workspace {}", workspaceName);
70+
7571

7672
// avoid recreating existing workspaces
7773
auto workspace = std::find_if(
@@ -331,21 +327,21 @@ void Workspaces::onEvent(const std::string &ev) {
331327
onWorkspaceDestroyed(payload);
332328
} else if (eventName == "createworkspacev2") {
333329
onWorkspaceCreated(payload);
334-
} else if (eventName == "focusedmon") {
330+
} else if (eventName == "focusedmonv2") {
335331
onMonitorFocused(payload);
336-
} else if (eventName == "moveworkspace") {
332+
} else if (eventName == "moveworkspacev2") {
337333
onWorkspaceMoved(payload);
338334
} else if (eventName == "openwindow") {
339335
onWindowOpened(payload);
340336
} else if (eventName == "closewindow") {
341337
onWindowClosed(payload);
342-
} else if (eventName == "movewindow") {
338+
} else if (eventName == "movewindowv2") {
343339
onWindowMoved(payload);
344340
} else if (eventName == "urgent") {
345341
setUrgentWorkspace(payload);
346342
} else if (eventName == "renameworkspace") {
347343
onWorkspaceRenamed(payload);
348-
} else if (eventName == "windowtitle") {
344+
} else if (eventName == "windowtitlev2") {
349345
onWindowTitleEvent(payload);
350346
} else if (eventName == "configreloaded") {
351347
onConfigReloaded();
@@ -355,8 +351,11 @@ void Workspaces::onEvent(const std::string &ev) {
355351
}
356352

357353
void Workspaces::onWorkspaceActivated(std::string const &payload) {
358-
std::string workspaceIdStr = payload.substr(0, payload.find(','));
359-
m_activeWorkspaceId = std::stoi(workspaceIdStr);
354+
auto [workspaceIdStr, _] = splitDoublePayload(payload);
355+
auto workspaceId = getWorkspaceId(workspaceIdStr);
356+
if (workspaceId != INVALID_WORKSPACE_ID) {
357+
m_activeWorkspaceId = workspaceId;
358+
}
360359
}
361360

362361
void Workspaces::onSpecialWorkspaceActivated(std::string const &payload) {
@@ -365,18 +364,22 @@ void Workspaces::onSpecialWorkspaceActivated(std::string const &payload) {
365364
}
366365

367366
void Workspaces::onWorkspaceDestroyed(std::string const &payload) {
368-
std::string workspaceIdStr = payload.substr(0, payload.find(','));
369-
std::string workspaceName = payload.substr(workspaceIdStr.size() + 1);
367+
auto [workspaceId, workspaceName] = splitDoublePayload(payload);
370368
if (!isDoubleSpecial(workspaceName)) {
371-
m_workspacesToRemove.push_back(workspaceIdStr);
369+
m_workspacesToRemove.push_back(workspaceId);
372370
}
373371
}
374372

375373
void Workspaces::onWorkspaceCreated(std::string const &payload,
376374
Json::Value const &clientsData) {
377375
spdlog::debug("Workspace created: {}", payload);
378-
std::string workspaceIdStr = payload.substr(0, payload.find(','));
379-
int workspaceId = std::stoi(workspaceIdStr);
376+
377+
auto [workspaceIdStr, _] = splitDoublePayload(payload);
378+
379+
auto workspaceId = getWorkspaceId(workspaceIdStr);
380+
if (workspaceId == INVALID_WORKSPACE_ID) {
381+
return;
382+
}
380383

381384
auto const workspaceRules = gIPC->getSocket1JsonReply("workspacerules");
382385
auto const workspacesJson = gIPC->getSocket1JsonReply("workspaces");
@@ -417,33 +420,30 @@ void Workspaces::onWorkspaceMoved(std::string const &payload) {
417420
spdlog::debug("Workspace moved: {}", payload);
418421

419422
// Update active workspace
420-
<<<<<<< HEAD
421-
m_activeWorkspaceName = (m_ipc.getSocket1JsonReply("activeworkspace"))["name"].asString();
422-
||||||| parent of 24d391b9 (feat(hyprland): support workspacev2)
423-
m_activeWorkspaceName = (gIPC->getSocket1JsonReply("activeworkspace"))["name"].asString();
424-
=======
425-
m_activeWorkspaceId = (gIPC->getSocket1JsonReply("activeworkspace"))["id"].asInt();
426-
>>>>>>> 24d391b9 (feat(hyprland): support workspacev2)
423+
m_activeWorkspaceId = (m_ipc.getSocket1JsonReply("activeworkspace"))["id"].asString();
427424

428425
if (allOutputs()) return;
429426

430-
std::string workspaceName = payload.substr(0, payload.find(','));
431-
std::string monitorName = payload.substr(payload.find(',') + 1);
427+
auto [workspaceIdStr, workspaceName, monitorName] = splitTriplePayload(payload);
428+
429+
auto subPayload = joinDoublePayload(workspaceIdStr, workspaceName);
432430

433431
if (m_bar.output->name == monitorName) {
434432
Json::Value clientsData = m_ipc.getSocket1JsonReply("clients");
435-
onWorkspaceCreated(workspaceName, clientsData);
433+
onWorkspaceCreated(subPayload, clientsData);
436434
} else {
437-
spdlog::debug("Removing workspace because it was moved to another monitor: {}");
438-
onWorkspaceDestroyed(workspaceName);
435+
spdlog::debug("Removing workspace because it was moved to another monitor: {}", subPayload);
436+
onWorkspaceDestroyed(subPayload);
439437
}
440438
}
441439

442440
void Workspaces::onWorkspaceRenamed(std::string const &payload) {
443441
spdlog::debug("Workspace renamed: {}", payload);
444-
std::string workspaceIdStr = payload.substr(0, payload.find(','));
445-
int workspaceId = workspaceIdStr == "special" ? -99 : std::stoi(workspaceIdStr);
446-
std::string newName = payload.substr(payload.find(',') + 1);
442+
auto [workspaceIdStr, newName] = splitDoublePayload(payload);
443+
444+
auto workspaceId = getWorkspaceId(workspaceIdStr);
445+
if (workspaceId == INVALID_WORKSPACE_ID) return;
446+
447447
for (auto &workspace : m_workspaces) {
448448
if (workspace->id() == workspaceId) {
449449
workspace->setName(newName);
@@ -456,18 +456,15 @@ void Workspaces::onWorkspaceRenamed(std::string const &payload) {
456456
void Workspaces::onMonitorFocused(std::string const &payload) {
457457
spdlog::trace("Monitor focused: {}", payload);
458458

459-
std::string workspaceName = payload.substr(payload.find(',') + 1);
459+
auto [monitorName, workspaceIdStr] = splitDoublePayload(payload);
460460

461-
// TODO this will be in the payload when we upgrade to focusedmonv2
462-
for (auto &workspace : m_workspaces) {
463-
if (workspace->name() == workspaceName) {
464-
m_activeWorkspaceId = workspace->id();
465-
break;
466-
}
467-
}
461+
auto workspaceId = getWorkspaceId(workspaceIdStr);
462+
if (workspaceId == INVALID_WORKSPACE_ID) return;
463+
464+
m_activeWorkspaceId = workspaceId;
468465

469466
for (Json::Value &monitor : m_ipc.getSocket1JsonReply("monitors")) {
470-
if (monitor["name"].asString() == payload.substr(0, payload.find(','))) {
467+
if (monitor["name"].asString() == monitorName) {
471468
auto name = monitor["specialWorkspace"]["name"].asString();
472469
m_activeSpecialWorkspaceName = !name.starts_with("special:") ? name : name.substr(8);
473470
}
@@ -507,13 +504,7 @@ void Workspaces::onWindowClosed(std::string const &addr) {
507504
void Workspaces::onWindowMoved(std::string const &payload) {
508505
spdlog::trace("Window moved: {}", payload);
509506
updateWindowCount();
510-
size_t lastCommaIdx = 0;
511-
size_t nextCommaIdx = payload.find(',');
512-
std::string windowAddress = payload.substr(lastCommaIdx, nextCommaIdx - lastCommaIdx);
513-
514-
std::string workspaceName = payload.substr(nextCommaIdx + 1, payload.length() - nextCommaIdx);
515-
516-
std::string windowRepr;
507+
auto [windowAddress, _, workspaceName] = splitTriplePayload(payload);
517508

518509
// If the window was still queued to be created, just change its destination
519510
// and exit
@@ -547,13 +538,15 @@ void Workspaces::onWindowTitleEvent(std::string const &payload) {
547538
spdlog::trace("Window title changed: {}", payload);
548539
std::optional<std::function<void(WindowCreationPayload)>> inserter;
549540

541+
auto [windowAddress, _] = splitDoublePayload(payload);
542+
550543
// If the window was an orphan, rename it at the orphan's vector
551-
if (m_orphanWindowMap.contains(payload)) {
544+
if (m_orphanWindowMap.contains(windowAddress)) {
552545
inserter = [this](WindowCreationPayload wcp) { this->registerOrphanWindow(std::move(wcp)); };
553546
} else {
554547
auto windowWorkspace =
555548
std::find_if(m_workspaces.begin(), m_workspaces.end(),
556-
[payload](auto &workspace) { return workspace->containsWindow(payload); });
549+
[windowAddress](auto &workspace) { return workspace->containsWindow(windowAddress); });
557550

558551
// If the window exists on a workspace, rename it at the workspace's window
559552
// map
@@ -692,52 +685,24 @@ void Workspaces::registerOrphanWindow(WindowCreationPayload create_window_payloa
692685
}
693686

694687
auto Workspaces::registerIpc() -> void {
695-
<<<<<<< HEAD
696688
m_ipc.registerForIPC("workspace", this);
697689
m_ipc.registerForIPC("activespecial", this);
698-
m_ipc.registerForIPC("createworkspace", this);
699-
m_ipc.registerForIPC("destroyworkspace", this);
700-
m_ipc.registerForIPC("focusedmon", this);
701-
m_ipc.registerForIPC("moveworkspace", this);
690+
m_ipc.registerForIPC("createworkspacev2", this);
691+
m_ipc.registerForIPC("destroyworkspacev2", this);
692+
m_ipc.registerForIPC("focusedmonv2", this);
693+
m_ipc.registerForIPC("moveworkspacev2", this);
702694
m_ipc.registerForIPC("renameworkspace", this);
703695
m_ipc.registerForIPC("openwindow", this);
704696
m_ipc.registerForIPC("closewindow", this);
705-
m_ipc.registerForIPC("movewindow", this);
697+
m_ipc.registerForIPC("movewindowv2", this);
706698
m_ipc.registerForIPC("urgent", this);
707699
m_ipc.registerForIPC("configreloaded", this);
708-
||||||| parent of 24d391b9 (feat(hyprland): support workspacev2)
709-
gIPC->registerForIPC("workspace", this);
710-
gIPC->registerForIPC("activespecial", this);
711-
gIPC->registerForIPC("createworkspacev2", this);
712-
gIPC->registerForIPC("destroyworkspacev2", this);
713-
gIPC->registerForIPC("focusedmon", this);
714-
gIPC->registerForIPC("moveworkspace", this);
715-
gIPC->registerForIPC("renameworkspace", this);
716-
gIPC->registerForIPC("openwindow", this);
717-
gIPC->registerForIPC("closewindow", this);
718-
gIPC->registerForIPC("movewindow", this);
719-
gIPC->registerForIPC("urgent", this);
720-
gIPC->registerForIPC("configreloaded", this);
721-
=======
722-
gIPC->registerForIPC("workspacev2", this);
723-
gIPC->registerForIPC("activespecial", this);
724-
gIPC->registerForIPC("createworkspacev2", this);
725-
gIPC->registerForIPC("destroyworkspacev2", this);
726-
gIPC->registerForIPC("focusedmon", this);
727-
gIPC->registerForIPC("moveworkspace", this);
728-
gIPC->registerForIPC("renameworkspace", this);
729-
gIPC->registerForIPC("openwindow", this);
730-
gIPC->registerForIPC("closewindow", this);
731-
gIPC->registerForIPC("movewindow", this);
732-
gIPC->registerForIPC("urgent", this);
733-
gIPC->registerForIPC("configreloaded", this);
734-
>>>>>>> 24d391b9 (feat(hyprland): support workspacev2)
735700

736701
if (windowRewriteConfigUsesTitle()) {
737702
spdlog::info(
738-
"Registering for Hyprland's 'windowtitle' events because a user-defined window "
703+
"Registering for Hyprland's 'windowtitlev2' events because a user-defined window "
739704
"rewrite rule uses the 'title' field.");
740-
m_ipc.registerForIPC("windowtitle", this);
705+
m_ipc.registerForIPC("windowtitlev2", this);
741706
}
742707
}
743708

@@ -751,31 +716,29 @@ void Workspaces::removeWorkspacesToRemove() {
751716
void Workspaces::removeWorkspace(std::string const &workspaceString) {
752717
spdlog::debug("Removing workspace {}", workspaceString);
753718

754-
int id;
755-
std::string name;
756719

757-
try {
758-
// If this succeeds, we have a workspace ID.
759-
id = std::stoi(workspaceString);
760-
} catch (const std::exception &e) {
761-
// TODO: At some point we want to support all workspace selectors
762-
// This is just a subset.
763-
// https://wiki.hyprland.org/Configuring/Workspace-Rules/#workspace-selectors
764-
if (workspaceString.starts_with("special:")) {
765-
name = workspaceString.substr(8);
766-
} else if (workspaceString.starts_with("name:")) {
767-
name = workspaceString.substr(5);
768-
} else {
769-
name = workspaceString;
770-
}
720+
// If this succeeds, we have a workspace ID.
721+
int id = getWorkspaceId(workspaceString);
722+
auto matchByName = id == INVALID_WORKSPACE_ID;
723+
724+
std::string name;
725+
// TODO: At some point we want to support all workspace selectors
726+
// This is just a subset.
727+
// https://wiki.hyprland.org/Configuring/Workspace-Rules/#workspace-selectors
728+
if (workspaceString.starts_with("special:")) {
729+
name = workspaceString.substr(8);
730+
} else if (workspaceString.starts_with("name:")) {
731+
name = workspaceString.substr(5);
732+
} else {
733+
name = workspaceString;
771734
}
772735

773736
auto workspace =
774737
std::find_if(m_workspaces.begin(), m_workspaces.end(), [&](std::unique_ptr<Workspace> &x) {
775-
if (name.empty()) {
776-
return id == x->id();
738+
if (matchByName) {
739+
return name == x->name();
777740
}
778-
return name == x->name();
741+
return id == x->id();
779742
});
780743

781744
if (workspace == m_workspaces.end()) {
@@ -946,13 +909,7 @@ void Workspaces::updateWorkspaceStates() {
946909
for (auto &workspace : m_workspaces) {
947910
workspace->setActive(workspace->id() == m_activeWorkspaceId ||
948911
workspace->name() == m_activeSpecialWorkspaceName);
949-
<<<<<<< HEAD
950912
if (workspace->isActive() && workspace->isUrgent()) {
951-
||||||| parent of 24d391b9 (feat(hyprland): support workspacev2)
952-
if (workspace->name() == m_activeWorkspaceName && workspace->isUrgent()) {
953-
=======
954-
if (workspace->id() == m_activeWorkspaceId && workspace->isUrgent()) {
955-
>>>>>>> 24d391b9 (feat(hyprland): support workspacev2)
956913
workspace->setUrgent(false);
957914
}
958915
workspace->setVisible(std::find(visibleWorkspaces.begin(), visibleWorkspaces.end(),
@@ -994,4 +951,34 @@ int Workspaces::windowRewritePriorityFunction(std::string const &window_rule) {
994951
return 0;
995952
}
996953

954+
std::string Workspaces::joinDoublePayload(std::string const &part1, std::string const &part2) {
955+
return part1 + "," + part2;
956+
}
957+
958+
std::pair<std::string, std::string> Workspaces::splitDoublePayload(std::string const &payload) {
959+
std::string part1 = payload.substr(0, payload.find(','));
960+
std::string part2 = payload.substr(part1.size() + 1);
961+
return {part1, part2};
962+
}
963+
964+
std::tuple<std::string, std::string, std::string> Workspaces::splitTriplePayload(std::string const &payload) {
965+
size_t firstComma = payload.find(',');
966+
size_t secondComma = payload.find(',', firstComma + 1);
967+
968+
std::string part1 = payload.substr(0, firstComma);
969+
std::string part2 = payload.substr(firstComma + 1, secondComma - (firstComma + 1));
970+
std::string part3 = payload.substr(secondComma + 1);
971+
972+
return {part1, part2, part3};
973+
}
974+
975+
std::int Workspaces::getWorkspaceId(std::string const &workspaceIdStr) {
976+
try {
977+
return workspaceIdStr == "special" ? -99 : std::stoi(workspaceIdStr);
978+
} catch (std::exception const &e) {
979+
spdlog::error("Failed to parse workspace ID: {}", e.what());
980+
return INVALID_WORKSPACE_ID;
981+
}
982+
}
983+
997984
} // namespace waybar::modules::hyprland

0 commit comments

Comments
 (0)