diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 0b60369d6..4239c7bf0 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -936,4 +936,21 @@ void CCompositor::updateWindowBorderColor(CWindow* pWindow) { pWindow->m_cRealBorderColor = RENDERDATA.borderColor; else pWindow->m_cRealBorderColor = CColor(pWindow == m_pLastWindow ? *ACTIVECOL : *INACTIVECOL); -} \ No newline at end of file +} + +void CCompositor::moveWindowToWorkspace(CWindow* pWindow, const std::string& work) { + m_pLastWindow = pWindow; + g_pKeybindManager->moveActiveToWorkspace(work); + + g_pInputManager->refocus(); +} + +int CCompositor::getNextAvailableMonitorID() { + int64_t topID = -1; + for (auto& m : m_lMonitors) { + if ((int64_t)m.ID > topID) + topID = m.ID; + } + + return topID + 1; +} diff --git a/src/Compositor.hpp b/src/Compositor.hpp index d2839103c..e866cdc2a 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -126,6 +126,8 @@ public: SMonitor* getMonitorInDirection(const char&); void updateAllWindowsBorders(); void updateWindowBorderColor(CWindow*); + void moveWindowToWorkspace(CWindow*, const std::string&); + int getNextAvailableMonitorID(); private: void initAllSignals(); diff --git a/src/events/Layers.cpp b/src/events/Layers.cpp index d5ad22454..7baeda672 100644 --- a/src/events/Layers.cpp +++ b/src/events/Layers.cpp @@ -58,7 +58,12 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) { Debug::log(LOG, "LayerSurface %x destroyed", layersurface->layerSurface); - if (!layersurface->fadingOut) { + const auto PMONITOR = g_pCompositor->getMonitorFromID(layersurface->monitorID); + + if (!g_pCompositor->getMonitorFromID(layersurface->monitorID)) + Debug::log(WARN, "Layersurface destroyed on an invalid monitor (removed?)"); + + if (!layersurface->fadingOut && PMONITOR) { Debug::log(LOG, "Removing LayerSurface that wasn't mapped."); layersurface->alpha.setValueAndWarp(0.f); layersurface->fadingOut = true; @@ -70,8 +75,6 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) { layersurface->hyprListener_unmapLayerSurface.removeCallback(); layersurface->hyprListener_newPopup.removeCallback(); - const auto PMONITOR = g_pCompositor->getMonitorFromID(layersurface->monitorID); - // rearrange to fix the reserved areas if (PMONITOR) { g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID); @@ -131,6 +134,11 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) { Debug::log(LOG, "LayerSurface %x unmapped", layersurface->layerSurface); + if (!g_pCompositor->getMonitorFromID(layersurface->monitorID)) { + Debug::log(WARN, "Layersurface unmapping on invalid monitor (removed?) ignoring."); + return; + } + // make a snapshot and start fade g_pHyprOpenGL->makeLayerSnapshot(layersurface); layersurface->alpha = 0.f; diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 2e05d2785..13f99749a 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -70,7 +70,7 @@ void Events::listener_newOutput(wl_listener* listener, void* data) { SMonitor newMonitor; newMonitor.output = OUTPUT; - newMonitor.ID = g_pCompositor->m_lMonitors.size(); + newMonitor.ID = g_pCompositor->getNextAvailableMonitorID(); newMonitor.szName = OUTPUT->name; wlr_output_init_render(OUTPUT, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer); @@ -296,7 +296,44 @@ void Events::listener_monitorDestroy(void* owner, void* data) { if (!pMonitor) return; + // Cleanup everything. Move windows back, snap cursor, shit. + const auto BACKUPMON = &g_pCompositor->m_lMonitors.front(); + const auto BACKUPWORKSPACE = BACKUPMON->activeWorkspace > 0 ? std::to_string(BACKUPMON->activeWorkspace) : "name:" + g_pCompositor->getWorkspaceByID(BACKUPMON->activeWorkspace)->m_szName; + + if (!BACKUPMON) { + Debug::log(CRIT, "No monitors! Unplugged last! Exiting."); + g_pCompositor->cleanupExit(); + return; + } + + // snap cursor + wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, BACKUPMON->vecPosition.x + BACKUPMON->vecTransformedSize.x / 2.f, BACKUPMON->vecPosition.y + BACKUPMON->vecTransformedSize.y / 2.f); + + // move windows + for (auto& w : g_pCompositor->m_lWindows) { + if (w.m_iMonitorID == pMonitor->ID) { + g_pCompositor->moveWindowToWorkspace(&w, BACKUPWORKSPACE); + } + } + + g_pCompositor->sanityCheckWorkspaces(); + + Debug::log(LOG, "Removed monitor %s!", pMonitor->szName.c_str()); + g_pCompositor->m_lMonitors.remove(*pMonitor); - // TODO: cleanup windows + // update the pMostHzMonitor + if (pMostHzMonitor == pMonitor) { + int mostHz = 0; + SMonitor* pMonitorMostHz = nullptr; + + for (auto& m : g_pCompositor->m_lMonitors) { + if (m.refreshRate > mostHz) { + pMonitorMostHz = &m; + mostHz = m.refreshRate; + } + } + + pMostHzMonitor = pMonitorMostHz; + } } diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index cf9b36d24..849b518c2 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -51,6 +51,8 @@ private: static void moveCursorToCorner(std::string); static void workspaceOpt(std::string); static void exitHyprland(std::string); + + friend class CCompositor; }; inline std::unique_ptr g_pKeybindManager; \ No newline at end of file