diff --git a/src/events/events.cpp b/src/events/events.cpp index 8f9c69c..67802ee 100644 --- a/src/events/events.cpp +++ b/src/events/events.cpp @@ -149,9 +149,17 @@ CWindow* Events::remapFloatingWindow(int windowID, int forcemonitor) { PWINDOWINARR->setIsFloating(true); PWINDOWINARR->setDirty(true); - if (!g_pWindowManager->getMonitorFromCursor()) { - Debug::log(ERR, "Monitor was null! (remapWindow)"); - // rip! we cannot continue. + + auto PMONITOR = g_pWindowManager->getMonitorFromCursor(); + if (!PMONITOR) { + Debug::log(ERR, "Monitor was null! (remapWindow) Using 0."); + PMONITOR = &g_pWindowManager->monitors[0]; + + if (g_pWindowManager->monitors.size() == 0) { + Debug::log(ERR, "Not continuing. Monitors size 0."); + return nullptr; + } + } // Check the monitor rule @@ -175,7 +183,7 @@ CWindow* Events::remapFloatingWindow(int windowID, int forcemonitor) { } } - const auto CURRENTSCREEN = forcemonitor != -1 ? forcemonitor : g_pWindowManager->getMonitorFromCursor()->ID; + const auto CURRENTSCREEN = forcemonitor != -1 ? forcemonitor : PMONITOR->ID; PWINDOWINARR->setWorkspaceID(g_pWindowManager->activeWorkspaces[CURRENTSCREEN]); PWINDOWINARR->setMonitor(CURRENTSCREEN); @@ -384,9 +392,16 @@ CWindow* Events::remapWindow(int windowID, bool wasfloating, int forcemonitor) { PWINDOWINARR->setIsFloating(false); PWINDOWINARR->setDirty(true); - if (!g_pWindowManager->getMonitorFromCursor()) { - Debug::log(ERR, "Monitor was null! (remapWindow)"); - // rip! we cannot continue. + + auto PMONITOR = g_pWindowManager->getMonitorFromCursor(); + if (!PMONITOR) { + Debug::log(ERR, "Monitor was null! (remapWindow) Using 0."); + PMONITOR = &g_pWindowManager->monitors[0]; + + if (g_pWindowManager->monitors.size() == 0) { + Debug::log(ERR, "Not continuing. Monitors size 0."); + return nullptr; + } } // Check the monitor rule @@ -410,7 +425,7 @@ CWindow* Events::remapWindow(int windowID, bool wasfloating, int forcemonitor) { } } - const auto CURRENTSCREEN = forcemonitor != -1 ? forcemonitor : g_pWindowManager->getMonitorFromCursor()->ID; + const auto CURRENTSCREEN = forcemonitor != -1 ? forcemonitor : PMONITOR->ID; PWINDOWINARR->setWorkspaceID(g_pWindowManager->activeWorkspaces[CURRENTSCREEN]); PWINDOWINARR->setMonitor(CURRENTSCREEN); @@ -439,12 +454,12 @@ CWindow* Events::remapWindow(int windowID, bool wasfloating, int forcemonitor) { // Set the parent // check if lastwindow is on our workspace - if (auto PLASTWINDOW = g_pWindowManager->getWindowFromDrawable(g_pWindowManager->LastWindow); (PLASTWINDOW && PLASTWINDOW->getWorkspaceID() == g_pWindowManager->activeWorkspaces[CURRENTSCREEN]) || wasfloating || (forcemonitor != -1 && forcemonitor != g_pWindowManager->getMonitorFromCursor()->ID)) { + if (auto PLASTWINDOW = g_pWindowManager->getWindowFromDrawable(g_pWindowManager->LastWindow); (PLASTWINDOW && PLASTWINDOW->getWorkspaceID() == g_pWindowManager->activeWorkspaces[CURRENTSCREEN]) || wasfloating || (forcemonitor != -1 && forcemonitor != PMONITOR->ID)) { // LastWindow is on our workspace, let's make a new split node - if (wasfloating || (forcemonitor != -1 && forcemonitor != g_pWindowManager->getMonitorFromCursor()->ID) || PLASTWINDOW->getIsFloating()) { + if (wasfloating || (forcemonitor != -1 && forcemonitor != PMONITOR->ID) || PLASTWINDOW->getIsFloating()) { // if it's force monitor, find the first on a workspace. - if (forcemonitor != -1 && forcemonitor != g_pWindowManager->getMonitorFromCursor()->ID) { + if (forcemonitor != -1 && forcemonitor != PMONITOR->ID) { PLASTWINDOW = g_pWindowManager->findFirstWindowOnWorkspace(g_pWindowManager->activeWorkspaces[CURRENTSCREEN]); } else { // find a window manually by the cursor @@ -675,7 +690,7 @@ void Events::eventMotionNotify(xcb_generic_event_t* event) { const auto WORKSPACE = g_pWindowManager->activeWorkspaces[g_pWindowManager->getMonitorFromCursor()->ID]; PACTINGWINDOW->setWorkspaceID(WORKSPACE); } else { - PACTINGWINDOW->setWorkspaceID(-1); + Debug::log(WARN, "Monitor was nullptr! Ignoring workspace change in MouseMoveEvent."); } PACTINGWINDOW->setDirty(true); @@ -787,3 +802,44 @@ void Events::eventClientMessage(xcb_generic_event_t* event) { } } } + +void Events::eventRandRScreenChange(xcb_generic_event_t* event) { + + // redetect screens + g_pWindowManager->monitors.clear(); + g_pWindowManager->setupRandrMonitors(); + + // Detect monitors that are incorrect + // Orphaned workspaces + for (auto& w : g_pWindowManager->workspaces) { + if (w.getMonitor() >= g_pWindowManager->monitors.size()) + w.setMonitor(0); + } + + // Empty monitors + bool fineMonitors[g_pWindowManager->monitors.size()]; + for (int i = 0; i < g_pWindowManager->monitors.size(); ++i) + fineMonitors[i] = false; + + for (auto& w : g_pWindowManager->workspaces) { + fineMonitors[w.getMonitor()] = true; + } + + for (int i = 0; i < g_pWindowManager->monitors.size(); ++i) { + if (!fineMonitors[i]) { + // add a workspace + CWorkspace newWorkspace; + newWorkspace.setMonitor(i); + newWorkspace.setID(g_pWindowManager->getHighestWorkspaceID() + 1); + newWorkspace.setHasFullscreenWindow(false); + newWorkspace.setLastWindow(0); + g_pWindowManager->workspaces.push_back(newWorkspace); + } + } + + // reload the config to update the bar too + ConfigManager::loadConfigLoadVars(); + + // Make all windows dirty and recalc all workspaces + g_pWindowManager->recalcAllWorkspaces(); +} \ No newline at end of file diff --git a/src/events/events.hpp b/src/events/events.hpp index 3bec0ce..bf83aa8 100644 --- a/src/events/events.hpp +++ b/src/events/events.hpp @@ -17,6 +17,8 @@ namespace Events { EVENT(MotionNotify); EVENT(ClientMessage); + EVENT(RandRScreenChange); + // Bypass some events for floating windows CWindow* remapWindow(int, bool floating = false, int forcemonitor = -1); CWindow* remapFloatingWindow(int, int forcemonitor = -1); diff --git a/src/ewmh/ewmh.cpp b/src/ewmh/ewmh.cpp index d868075..6386743 100644 --- a/src/ewmh/ewmh.cpp +++ b/src/ewmh/ewmh.cpp @@ -75,13 +75,19 @@ void EWMH::setFrameExtents(xcb_window_t w) { } void EWMH::updateDesktops() { + + int ACTIVEWORKSPACE = -1; if (!g_pWindowManager->getMonitorFromCursor()) { - Debug::log(ERR, "Monitor was null! (updateDesktops EWMH)"); - return; + Debug::log(ERR, "Monitor was null! (updateDesktops EWMH) Using LastWindow"); + if (const auto PWINDOW = g_pWindowManager->getWindowFromDrawable(g_pWindowManager->LastWindow); PWINDOW) + ACTIVEWORKSPACE = g_pWindowManager->activeWorkspaces[PWINDOW->getWorkspaceID()]; + else + ACTIVEWORKSPACE = 0; + } else { + ACTIVEWORKSPACE = g_pWindowManager->activeWorkspaces[g_pWindowManager->getMonitorFromCursor()->ID]; } - - const auto ACTIVEWORKSPACE = g_pWindowManager->activeWorkspaces[g_pWindowManager->getMonitorFromCursor()->ID]; + if (DesktopInfo::lastid != ACTIVEWORKSPACE) { // Update the current workspace DesktopInfo::lastid = ACTIVEWORKSPACE; diff --git a/src/windowManager.cpp b/src/windowManager.cpp index d52e8a5..a401a71 100644 --- a/src/windowManager.cpp +++ b/src/windowManager.cpp @@ -129,16 +129,25 @@ void CWindowManager::setupRandrMonitors() { else { //listen for screen change events xcb_randr_select_input(DisplayConnection, Screen->root, XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE); + RandREventBase = EXTENSIONREPLY->first_event; } xcb_flush(DisplayConnection); +} + +void CWindowManager::setupManager() { + setupColormapAndStuff(); + EWMH::setupInitEWMH(); + + // ---- RANDR ----- // + setupRandrMonitors(); if (monitors.size() == 0) { // RandR failed! Debug::log(WARN, "RandR failed!"); monitors.clear(); - #define TESTING_MON_AMOUNT 3 +#define TESTING_MON_AMOUNT 3 for (int i = 0; i < TESTING_MON_AMOUNT /* Testing on 3 monitors, RandR shouldnt fail on a real desktop */; ++i) { monitors.push_back(SMonitor()); monitors[i].vecPosition = Vector2D(i * Screen->width_in_pixels / TESTING_MON_AMOUNT, 0); @@ -147,15 +156,12 @@ void CWindowManager::setupRandrMonitors() { monitors[i].szName = "Screen" + std::to_string(i); } } -} - -void CWindowManager::setupManager() { - setupColormapAndStuff(); - EWMH::setupInitEWMH(); - setupRandrMonitors(); Debug::log(LOG, "RandR done."); + // + // + Values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE; xcb_change_window_attributes_checked(DisplayConnection, Screen->root, XCB_CW_EVENT_MASK, Values); @@ -244,6 +250,7 @@ void CWindowManager::recieveEvent() { if (!g_pWindowManager->statusBar) IPCRecieveMessageM(m_sIPCBarPipeOut.szPipeName); + const uint8_t TYPE = XCB_EVENT_RESPONSE_TYPE(ev); const auto EVENTCODE = ev->response_type & ~0x80; switch (EVENTCODE) { @@ -299,6 +306,11 @@ void CWindowManager::recieveEvent() { break; } + if (TYPE - RandREventBase == XCB_RANDR_SCREEN_CHANGE_NOTIFY) { + Events::eventRandRScreenChange(ev); + Debug::log(LOG, "Event dispatched RANDR_SCREEN_CHANGE"); + } + free(ev); } } @@ -777,10 +789,15 @@ void CWindowManager::calculateNewTileSetOldTile(CWindow* pWindow) { // Get the parent and both children, one of which will be pWindow const auto PPARENT = getWindowFromDrawable(pWindow->getParentNodeID()); - const auto PMONITOR = getMonitorFromWindow(pWindow); + auto PMONITOR = getMonitorFromWindow(pWindow); if (!PMONITOR) { - Debug::log(ERR, "Monitor was nullptr! (calculateNewTileSetOldTile)"); - return; + Debug::log(ERR, "Monitor was nullptr! (calculateNewTileSetOldTile) using 0."); + PMONITOR = &monitors[0]; + + if (monitors.size() == 0) { + Debug::log(ERR, "Not continuing. Monitors size 0."); + return; + } } if (!PPARENT) { @@ -929,9 +946,18 @@ void CWindowManager::recalcEntireWorkspace(const int& workspace) { } } - if (!pMasterWindow) { + if (!pMasterWindow) return; - } + + const auto PMONITOR = getMonitorFromWorkspace(workspace); + + if (!PMONITOR) + return; + + Debug::log(LOG, "Recalc for workspace " + std::to_string(workspace)); + + pMasterWindow->setSize(PMONITOR->vecSize); + pMasterWindow->setPosition(PMONITOR->vecPosition); pMasterWindow->recalcSizePosRecursive(); setAllWorkspaceWindowsDirtyByID(workspace); @@ -1355,11 +1381,11 @@ void CWindowManager::moveActiveFocusTo(char dir) { void CWindowManager::changeWorkspaceByID(int ID) { - const auto MONITOR = getMonitorFromCursor(); + auto MONITOR = getMonitorFromCursor(); if (!MONITOR) { - Debug::log(ERR, "Monitor was nullptr! (changeWorkspaceByID)"); - return; + Debug::log(ERR, "Monitor was nullptr! (changeWorkspaceByID) Using monitor 0."); + MONITOR = &monitors[0]; } // mark old workspace dirty @@ -1513,12 +1539,18 @@ void CWindowManager::updateBarInfo() { SIPCMessageMainToBar message; - if (!getMonitorFromCursor()) { - Debug::log(ERR, "Monitor was null! (updateBarInfo)"); - return; + auto PMONITOR = getMonitorFromCursor(); + if (!PMONITOR) { + Debug::log(ERR, "Monitor was null! (updateBarInfo) Using 0."); + PMONITOR = &monitors[0]; + + if (monitors.size() == 0) { + Debug::log(ERR, "Not continuing. Monitors size 0."); + return; + } } - message.activeWorkspace = activeWorkspaces[getMonitorFromCursor()->ID]; + message.activeWorkspace = activeWorkspaces[PMONITOR->ID]; auto winname = getWindowFromDrawable(LastWindow) ? getWindowFromDrawable(LastWindow)->getName() : ""; auto winclassname = getWindowFromDrawable(LastWindow) ? getWindowFromDrawable(LastWindow)->getClassName() : ""; diff --git a/src/windowManager.hpp b/src/windowManager.hpp index 854a6e8..68cc637 100644 --- a/src/windowManager.hpp +++ b/src/windowManager.hpp @@ -26,6 +26,7 @@ public: xcb_ewmh_connection_t* EWMHConnection = nullptr; // Bar uses this xcb_screen_t* Screen = nullptr; xcb_drawable_t Drawable; + int RandREventBase = -1; uint32_t Values[3]; std::vector monitors;