12
12
13
13
namespace waybar ::modules::hyprland {
14
14
15
+ constexpr int INVALID_WORKSPACE_ID = -100 ;
16
+
15
17
Workspaces::Workspaces (const std::string &id, const Bar &bar, const Json::Value &config)
16
18
: AModule(config, " workspaces" , id, false , false ), m_bar(bar), m_box(bar.orientation, 0 ) {
17
19
modulesReady = true ;
@@ -50,13 +52,12 @@ Json::Value Workspaces::createMonitorWorkspaceData(std::string const &name,
50
52
std::string const &monitor) {
51
53
spdlog::trace (" Creating persistent workspace: {} on monitor {}" , name, monitor);
52
54
Json::Value workspaceData;
53
- try {
54
- // numbered persistent workspaces get the name as ID
55
- workspaceData[" id" ] = name == " special" ? -99 : std::stoi (name);
56
- } catch (const std::exception &e) {
57
- // named persistent workspaces start with ID=0
58
- workspaceData[" id" ] = 0 ;
55
+
56
+ auto workspaceId = getWorkspaceId (name);
57
+ if (workspaceId == INVALID_WORKSPACE_ID) {
58
+ workspaceId = 0
59
59
}
60
+ workspaceData[" id" ] = workspaceId
60
61
workspaceData[" name" ] = name;
61
62
workspaceData[" monitor" ] = monitor;
62
63
workspaceData[" windows" ] = 0 ;
@@ -67,6 +68,7 @@ void Workspaces::createWorkspace(Json::Value const &workspace_data,
67
68
Json::Value const &clients_data) {
68
69
auto workspaceName = workspace_data[" name" ].asString ();
69
70
spdlog::debug (" Creating workspace {}" , workspaceName);
71
+
70
72
71
73
// avoid recreating existing workspaces
72
74
auto workspace = std::find_if (
@@ -325,21 +327,21 @@ void Workspaces::onEvent(const std::string &ev) {
325
327
onWorkspaceDestroyed (payload);
326
328
} else if (eventName == " createworkspacev2" ) {
327
329
onWorkspaceCreated (payload);
328
- } else if (eventName == " focusedmon " ) {
330
+ } else if (eventName == " focusedmonv2 " ) {
329
331
onMonitorFocused (payload);
330
- } else if (eventName == " moveworkspace " ) {
332
+ } else if (eventName == " moveworkspacev2 " ) {
331
333
onWorkspaceMoved (payload);
332
334
} else if (eventName == " openwindow" ) {
333
335
onWindowOpened (payload);
334
336
} else if (eventName == " closewindow" ) {
335
337
onWindowClosed (payload);
336
- } else if (eventName == " movewindow " ) {
338
+ } else if (eventName == " movewindowv2 " ) {
337
339
onWindowMoved (payload);
338
340
} else if (eventName == " urgent" ) {
339
341
setUrgentWorkspace (payload);
340
342
} else if (eventName == " renameworkspace" ) {
341
343
onWorkspaceRenamed (payload);
342
- } else if (eventName == " windowtitle " ) {
344
+ } else if (eventName == " windowtitlev2 " ) {
343
345
onWindowTitleEvent (payload);
344
346
} else if (eventName == " configreloaded" ) {
345
347
onConfigReloaded ();
@@ -349,8 +351,11 @@ void Workspaces::onEvent(const std::string &ev) {
349
351
}
350
352
351
353
void Workspaces::onWorkspaceActivated (std::string const &payload) {
352
- std::string workspaceIdStr = payload.substr (0 , payload.find (' ,' ));
353
- 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
+ }
354
359
}
355
360
356
361
void Workspaces::onSpecialWorkspaceActivated (std::string const &payload) {
@@ -359,18 +364,22 @@ void Workspaces::onSpecialWorkspaceActivated(std::string const &payload) {
359
364
}
360
365
361
366
void Workspaces::onWorkspaceDestroyed (std::string const &payload) {
362
- std::string workspaceIdStr = payload.substr (0 , payload.find (' ,' ));
363
- std::string workspaceName = payload.substr (workspaceIdStr.size () + 1 );
367
+ auto [workspaceId, workspaceName] = splitDoublePayload (payload);
364
368
if (!isDoubleSpecial (workspaceName)) {
365
- m_workspacesToRemove.push_back (workspaceIdStr );
369
+ m_workspacesToRemove.push_back (workspaceId );
366
370
}
367
371
}
368
372
369
373
void Workspaces::onWorkspaceCreated (std::string const &payload,
370
374
Json::Value const &clientsData) {
371
375
spdlog::debug (" Workspace created: {}" , payload);
372
- std::string workspaceIdStr = payload.substr (0 , payload.find (' ,' ));
373
- 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
+ }
374
383
375
384
auto const workspaceRules = gIPC ->getSocket1JsonReply (" workspacerules" );
376
385
auto const workspacesJson = gIPC ->getSocket1JsonReply (" workspaces" );
@@ -412,23 +421,26 @@ void Workspaces::onWorkspaceMoved(std::string const &payload) {
412
421
413
422
if (allOutputs ()) return ;
414
423
415
- std::string workspaceName = payload.substr (0 , payload.find (' ,' ));
416
- std::string monitorName = payload.substr (payload.find (' ,' ) + 1 );
424
+ auto [workspaceIdStr, workspaceName, monitorName] = splitTriplePayload (payload);
425
+
426
+ auto subPayload = joinDoublePayload (workspaceIdStr, workspaceName);
417
427
418
428
if (m_bar.output ->name == monitorName) {
419
429
Json::Value clientsData = gIPC ->getSocket1JsonReply (" clients" );
420
- onWorkspaceCreated (workspaceName , clientsData);
430
+ onWorkspaceCreated (subPayload , clientsData);
421
431
} else {
422
- spdlog::debug (" Removing workspace because it was moved to another monitor: {}" );
423
- onWorkspaceDestroyed (workspaceName );
432
+ spdlog::debug (" Removing workspace because it was moved to another monitor: {}" , subPayload );
433
+ onWorkspaceDestroyed (subPayload );
424
434
}
425
435
}
426
436
427
437
void Workspaces::onWorkspaceRenamed (std::string const &payload) {
428
438
spdlog::debug (" Workspace renamed: {}" , payload);
429
- std::string workspaceIdStr = payload.substr (0 , payload.find (' ,' ));
430
- int workspaceId = workspaceIdStr == " special" ? -99 : std::stoi (workspaceIdStr);
431
- std::string newName = payload.substr (payload.find (' ,' ) + 1 );
439
+ auto [workspaceIdStr, newName] = splitDoublePayload (payload);
440
+
441
+ auto workspaceId = getWorkspaceId (workspaceIdStr);
442
+ if (workspaceId == INVALID_WORKSPACE_ID) return ;
443
+
432
444
for (auto &workspace : m_workspaces) {
433
445
if (workspace->id () == workspaceId) {
434
446
workspace->setName (newName);
@@ -441,18 +453,15 @@ void Workspaces::onWorkspaceRenamed(std::string const &payload) {
441
453
void Workspaces::onMonitorFocused (std::string const &payload) {
442
454
spdlog::trace (" Monitor focused: {}" , payload);
443
455
444
- std::string workspaceName = payload. substr (payload. find ( ' , ' ) + 1 );
456
+ auto [monitorName, workspaceIdStr] = splitDoublePayload (payload);
445
457
446
- // TODO this will be in the payload when we upgrade to focusedmonv2
447
- for (auto &workspace : m_workspaces) {
448
- if (workspace->name () == workspaceName) {
449
- m_activeWorkspaceId = workspace->id ();
450
- break ;
451
- }
452
- }
458
+ auto workspaceId = getWorkspaceId (workspaceIdStr);
459
+ if (workspaceId == INVALID_WORKSPACE_ID) return ;
460
+
461
+ m_activeWorkspaceId = workspaceId;
453
462
454
463
for (Json::Value &monitor : gIPC ->getSocket1JsonReply (" monitors" )) {
455
- if (monitor[" name" ].asString () == payload. substr ( 0 , payload. find ( ' , ' )) ) {
464
+ if (monitor[" name" ].asString () == monitorName ) {
456
465
auto name = monitor[" specialWorkspace" ][" name" ].asString ();
457
466
m_activeSpecialWorkspaceName = !name.starts_with (" special:" ) ? name : name.substr (8 );
458
467
}
@@ -492,13 +501,7 @@ void Workspaces::onWindowClosed(std::string const &addr) {
492
501
void Workspaces::onWindowMoved (std::string const &payload) {
493
502
spdlog::trace (" Window moved: {}" , payload);
494
503
updateWindowCount ();
495
- size_t lastCommaIdx = 0 ;
496
- size_t nextCommaIdx = payload.find (' ,' );
497
- std::string windowAddress = payload.substr (lastCommaIdx, nextCommaIdx - lastCommaIdx);
498
-
499
- std::string workspaceName = payload.substr (nextCommaIdx + 1 , payload.length () - nextCommaIdx);
500
-
501
- std::string windowRepr;
504
+ auto [windowAddress, _, workspaceName] = splitTriplePayload (payload);
502
505
503
506
// If the window was still queued to be created, just change its destination
504
507
// and exit
@@ -532,13 +535,15 @@ void Workspaces::onWindowTitleEvent(std::string const &payload) {
532
535
spdlog::trace (" Window title changed: {}" , payload);
533
536
std::optional<std::function<void (WindowCreationPayload)>> inserter;
534
537
538
+ auto [windowAddress, _] = splitDoublePayload (payload);
539
+
535
540
// If the window was an orphan, rename it at the orphan's vector
536
- if (m_orphanWindowMap.contains (payload )) {
541
+ if (m_orphanWindowMap.contains (windowAddress )) {
537
542
inserter = [this ](WindowCreationPayload wcp) { this ->registerOrphanWindow (std::move (wcp)); };
538
543
} else {
539
544
auto windowWorkspace =
540
545
std::find_if (m_workspaces.begin (), m_workspaces.end (),
541
- [payload ](auto &workspace) { return workspace->containsWindow (payload ); });
546
+ [windowAddress ](auto &workspace) { return workspace->containsWindow (windowAddress ); });
542
547
543
548
// If the window exists on a workspace, rename it at the workspace's window
544
549
// map
@@ -681,20 +686,20 @@ auto Workspaces::registerIpc() -> void {
681
686
gIPC ->registerForIPC (" activespecial" , this );
682
687
gIPC ->registerForIPC (" createworkspacev2" , this );
683
688
gIPC ->registerForIPC (" destroyworkspacev2" , this );
684
- gIPC ->registerForIPC (" focusedmon " , this );
685
- gIPC ->registerForIPC (" moveworkspace " , this );
689
+ gIPC ->registerForIPC (" focusedmonv2 " , this );
690
+ gIPC ->registerForIPC (" moveworkspacev2 " , this );
686
691
gIPC ->registerForIPC (" renameworkspace" , this );
687
692
gIPC ->registerForIPC (" openwindow" , this );
688
693
gIPC ->registerForIPC (" closewindow" , this );
689
- gIPC ->registerForIPC (" movewindow " , this );
694
+ gIPC ->registerForIPC (" movewindowv2 " , this );
690
695
gIPC ->registerForIPC (" urgent" , this );
691
696
gIPC ->registerForIPC (" configreloaded" , this );
692
697
693
698
if (windowRewriteConfigUsesTitle ()) {
694
699
spdlog::info (
695
- " Registering for Hyprland's 'windowtitle ' events because a user-defined window "
700
+ " Registering for Hyprland's 'windowtitlev2 ' events because a user-defined window "
696
701
" rewrite rule uses the 'title' field." );
697
- gIPC ->registerForIPC (" windowtitle " , this );
702
+ gIPC ->registerForIPC (" windowtitlev2 " , this );
698
703
}
699
704
}
700
705
@@ -708,31 +713,29 @@ void Workspaces::removeWorkspacesToRemove() {
708
713
void Workspaces::removeWorkspace (std::string const &workspaceString) {
709
714
spdlog::debug (" Removing workspace {}" , workspaceString);
710
715
711
- int id;
712
- std::string name;
713
716
714
- try {
715
- // If this succeeds, we have a workspace ID.
716
- id = std::stoi (workspaceString) ;
717
- } catch ( const std:: exception &e) {
718
- // TODO: At some point we want to support all workspace selectors
719
- // This is just a subset.
720
- // https://wiki.hyprland.org/Configuring/Workspace-Rules/#workspace-selectors
721
- if (workspaceString. starts_with ( " special: " )) {
722
- name = workspaceString.substr ( 8 );
723
- } else if ( workspaceString.starts_with ( " name: " )) {
724
- name = workspaceString.substr ( 5 );
725
- } else {
726
- name = workspaceString;
727
- }
717
+ // If this succeeds, we have a workspace ID.
718
+ int id = getWorkspaceId (workspaceString);
719
+ auto matchByName = id == INVALID_WORKSPACE_ID ;
720
+
721
+ std::string name;
722
+ // TODO: At some point we want to support all workspace selectors
723
+ // This is just a subset.
724
+ // https://wiki.hyprland.org/Configuring/Workspace-Rules/#workspace-selectors
725
+ if ( workspaceString.starts_with ( " special: " )) {
726
+ name = workspaceString.substr ( 8 );
727
+ } else if ( workspaceString.starts_with ( " name: " )) {
728
+ name = workspaceString. substr ( 5 );
729
+ } else {
730
+ name = workspaceString;
728
731
}
729
732
730
733
auto workspace =
731
734
std::find_if (m_workspaces.begin (), m_workspaces.end (), [&](std::unique_ptr<Workspace> &x) {
732
- if (name. empty () ) {
733
- return id == x->id ();
735
+ if (matchByName ) {
736
+ return name == x->name ();
734
737
}
735
- return name == x->name ();
738
+ return id == x->id ();
736
739
});
737
740
738
741
if (workspace == m_workspaces.end ()) {
@@ -945,4 +948,34 @@ int Workspaces::windowRewritePriorityFunction(std::string const &window_rule) {
945
948
return 0 ;
946
949
}
947
950
951
+ std::string Workspaces::joinDoublePayload (std::string const &part1, std::string const &part2) {
952
+ return part1 + " ," + part2;
953
+ }
954
+
955
+ std::pair<std::string, std::string> Workspaces::splitDoublePayload (std::string const &payload) {
956
+ std::string part1 = payload.substr (0 , payload.find (' ,' ));
957
+ std::string part2 = payload.substr (part1.size () + 1 );
958
+ return {part1, part2};
959
+ }
960
+
961
+ std::tuple<std::string, std::string, std::string> Workspaces::splitTriplePayload (std::string const &payload) {
962
+ size_t firstComma = payload.find (' ,' );
963
+ size_t secondComma = payload.find (' ,' , firstComma + 1 );
964
+
965
+ std::string part1 = payload.substr (0 , firstComma);
966
+ std::string part2 = payload.substr (firstComma + 1 , secondComma - (firstComma + 1 ));
967
+ std::string part3 = payload.substr (secondComma + 1 );
968
+
969
+ return {part1, part2, part3};
970
+ }
971
+
972
+ std::int Workspaces::getWorkspaceId (std::string const &workspaceIdStr) {
973
+ try {
974
+ return workspaceIdStr == " special" ? -99 : std::stoi (workspaceIdStr);
975
+ } catch (std::exception const &e) {
976
+ spdlog::error (" Failed to parse workspace ID: {}" , e.what ());
977
+ return INVALID_WORKSPACE_ID;
978
+ }
979
+ }
980
+
948
981
} // namespace waybar::modules::hyprland
0 commit comments