@@ -470,6 +470,8 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) {
470470
471471 const auto OLDWORKSPACE = m_workspace;
472472
473+ bool previouslyEmpty = !pWorkspace->hasWindow ();
474+
473475 if (OLDWORKSPACE->isVisible ()) {
474476 m_movingToWorkspaceAlpha->setValueAndWarp (1 .F );
475477 *m_movingToWorkspaceAlpha = 0 .F ;
@@ -495,6 +497,16 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) {
495497 g_pEventManager->postEvent (SHyprIPCEvent{.event = " movewindow" , .data = std::format (" {:x},{}" , rc<uintptr_t >(this ), pWorkspace->m_name )});
496498 g_pEventManager->postEvent (SHyprIPCEvent{.event = " movewindowv2" , .data = std::format (" {:x},{},{}" , rc<uintptr_t >(this ), pWorkspace->m_id , pWorkspace->m_name )});
497499 EMIT_HOOK_EVENT (" moveWindow" , (std::vector<std::any>{m_self.lock (), pWorkspace}));
500+
501+ if (!OLDWORKSPACE->hasWindow ()) {
502+ g_pEventManager->postEvent (SHyprIPCEvent{.event = " depopulateworkspace" , .data = std::format (" {},{}" , OLDWORKSPACE->m_id , OLDWORKSPACE->m_name )});
503+ EMIT_HOOK_EVENT (" depopulateWorkspace" , OLDWORKSPACE);
504+ }
505+
506+ if (previouslyEmpty) {
507+ g_pEventManager->postEvent (SHyprIPCEvent{.event = " populateworkspace" , .data = std::format (" {},{}" , pWorkspace->m_id , pWorkspace->m_name )});
508+ EMIT_HOOK_EVENT (" populateWorkspace" , pWorkspace);
509+ }
498510 }
499511
500512 if (const auto SWALLOWED = m_swallowed.lock ()) {
@@ -1936,7 +1948,9 @@ void CWindow::mapWindow() {
19361948 Desktop::focusState ()->rawMonitorFocus (g_pCompositor->getMonitorFromVector ({}));
19371949 PMONITOR = Desktop::focusState ()->monitor ();
19381950 }
1939- auto PWORKSPACE = PMONITOR->m_activeSpecialWorkspace ? PMONITOR->m_activeSpecialWorkspace : PMONITOR->m_activeWorkspace ;
1951+ auto PWORKSPACE = PMONITOR->m_activeSpecialWorkspace ? PMONITOR->m_activeSpecialWorkspace : PMONITOR->m_activeWorkspace ;
1952+ bool workspacePreviouslyEmpty = !PWORKSPACE->hasWindow ();
1953+
19401954 m_monitor = PMONITOR;
19411955 m_workspace = PWORKSPACE;
19421956 m_isMapped = true ;
@@ -2233,6 +2247,9 @@ void CWindow::mapWindow() {
22332247 // emit the IPC event before the layout might focus the window to avoid a focus event first
22342248 g_pEventManager->postEvent (SHyprIPCEvent{" openwindow" , std::format (" {:x},{},{},{}" , m_self.lock (), PWORKSPACE->m_name , m_class, m_title)});
22352249 EMIT_HOOK_EVENT (" openWindowEarly" , m_self.lock ());
2250+ if (workspacePreviouslyEmpty) {
2251+ g_pEventManager->postEvent (SHyprIPCEvent{" populateworkspace" , std::format (" {},{}" , PWORKSPACE->m_id , PWORKSPACE->m_name )});
2252+ }
22362253
22372254 if (m_isFloating) {
22382255 g_pLayoutManager->getCurrentLayout ()->onWindowCreated (m_self.lock ());
@@ -2373,6 +2390,10 @@ void CWindow::mapWindow() {
23732390
23742391 // emit the hook event here after basic stuff has been initialized
23752392 EMIT_HOOK_EVENT (" openWindow" , m_self.lock ());
2393+ if (workspacePreviouslyEmpty) {
2394+ EMIT_HOOK_EVENT (" populateWorkspace" , m_self.lock ());
2395+ }
2396+
23762397
23772398 // apply data from default decos. Borders, shadows.
23782399 g_pDecorationPositioner->forceRecalcFor (m_self.lock ());
@@ -2485,6 +2506,11 @@ void CWindow::unmapWindow() {
24852506 // do this after onWindowRemoved because otherwise it'll think the window is invalid
24862507 m_isMapped = false ;
24872508
2509+ if (!m_workspace->hasWindow ()) {
2510+ g_pEventManager->postEvent (SHyprIPCEvent{" depopulateworkspace" , std::format (" {},{}" , m_workspace->m_id , m_workspace->m_name )});
2511+ EMIT_HOOK_EVENT (" depopulateWorkspace" , m_workspace);
2512+ }
2513+
24882514 // refocus on a new window if needed
24892515 if (wasLastWindow) {
24902516 static auto FOCUSONCLOSE = CConfigValue<Hyprlang::INT>(" input:focus_on_close" );
0 commit comments