1212
1313namespace waybar ::modules::hyprland {
1414
15+ constexpr int INVALID_WORKSPACE_ID = -100 ;
16+
1517Workspaces::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
4143void 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
357353void 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
362361void Workspaces::onSpecialWorkspaceActivated (std::string const &payload) {
@@ -365,18 +364,22 @@ void Workspaces::onSpecialWorkspaceActivated(std::string const &payload) {
365364}
366365
367366void 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
375373void 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
442440void 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) {
456456void 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) {
507504void 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
694687auto 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() {
751716void 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