From c04563734e0482bd10045c70d9d85177e5448143 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Mon, 24 Oct 2022 12:25:36 +0100 Subject: [PATCH] Rework candidate finding on close window --- src/Compositor.cpp | 4 +++ src/Compositor.hpp | 18 ++++++------- src/events/Windows.cpp | 8 +----- src/layout/IHyprLayout.cpp | 53 ++++++++++++++++++++++++++++++++++++++ src/layout/IHyprLayout.hpp | 12 +++++++++ 5 files changed, 79 insertions(+), 16 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 8e3ec390..8441e1bc 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -723,6 +723,8 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) { g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","}); + g_pLayoutManager->getCurrentLayout()->onWindowFocusChange(nullptr); + m_pLastFocus = nullptr; return; } @@ -774,6 +776,8 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) { // Send an event g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", g_pXWaylandManager->getAppIDClass(pWindow) + "," + pWindow->m_szTitle}); + g_pLayoutManager->getCurrentLayout()->onWindowFocusChange(pWindow); + if (pWindow->m_phForeignToplevel) wlr_foreign_toplevel_handle_v1_set_activated(pWindow->m_phForeignToplevel, true); } diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 284eb464..68178246 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -75,7 +75,7 @@ public: const char* m_szWLDisplaySocket; std::string m_szInstanceSignature = ""; - std::string m_szCurrentSplash = "error"; + std::string m_szCurrentSplash = "error"; std::vector> m_vMonitors; std::vector> m_vRealMonitors; // for all monitors, even those turned off @@ -90,17 +90,17 @@ public: void startCompositor(); void cleanup(); - wlr_surface* m_pLastFocus = nullptr; - CWindow* m_pLastWindow = nullptr; - CMonitor* m_pLastMonitor = nullptr; + wlr_surface* m_pLastFocus = nullptr; + CWindow* m_pLastWindow = nullptr; + CMonitor* m_pLastMonitor = nullptr; SSeat m_sSeat; - bool m_bReadyToProcess = false; - bool m_bSessionActive = true; - bool m_bDPMSStateON = true; - bool m_bUnsafeState = false; // unsafe state is when there is no monitors. - bool m_bIsShuttingDown = false; + bool m_bReadyToProcess = false; + bool m_bSessionActive = true; + bool m_bDPMSStateON = true; + bool m_bUnsafeState = false; // unsafe state is when there is no monitors. + bool m_bIsShuttingDown = false; std::deque m_dProcessPIDsOnShutdown; // stores PIDs of apps to kill later when shutting down // ------------------------------------------------- // diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 1235176a..e2946d73 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -548,13 +548,7 @@ void Events::listener_unmapWindow(void* owner, void* data) { // refocus on a new window if needed if (wasLastWindow) { - auto PWINDOWCANDIDATE = g_pCompositor->vectorToWindowIdeal(PWINDOW->m_vRealPosition.goalv() + PWINDOW->m_vRealSize.goalv() / 2.f); - - if (PWORKSPACE->m_bHasFullscreenWindow && ((!PWINDOWCANDIDATE || !PWINDOWCANDIDATE->m_bCreatedOverFullscreen) || !PWINDOW->m_bIsFloating)) - PWINDOWCANDIDATE = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); - - if (!PWINDOWCANDIDATE || PWINDOW == PWINDOWCANDIDATE || !PWINDOWCANDIDATE->m_bIsMapped || PWINDOWCANDIDATE->isHidden() || PWINDOWCANDIDATE->m_bX11ShouldntFocus || PWINDOWCANDIDATE->m_iX11Type == 2 || PWINDOWCANDIDATE->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID) - PWINDOWCANDIDATE = nullptr; + const auto PWINDOWCANDIDATE = g_pLayoutManager->getCurrentLayout()->getNextWindowCandidate(PWINDOW); Debug::log(LOG, "On closed window, new focused candidate is %x", PWINDOWCANDIDATE); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 565e8b0d..bef56f78 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -26,6 +26,9 @@ void IHyprLayout::onWindowRemoved(CWindow* pWindow) { } else { onWindowRemovedTiling(pWindow); } + + if (pWindow == m_pLastTiledWindow) + m_pLastTiledWindow = nullptr; } void IHyprLayout::onWindowRemovedFloating(CWindow* pWindow) { @@ -311,6 +314,9 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) { // fix pseudo leaving artifacts g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID)); + + if (pWindow == g_pCompositor->m_pLastWindow) + m_pLastTiledWindow = pWindow; } else { pWindow->m_vSize = pWindow->m_vRealSize.vec(); pWindow->m_vPosition = pWindow->m_vRealPosition.vec(); @@ -325,6 +331,9 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) { g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID)); pWindow->m_sSpecialRenderData.rounding = true; + + if (pWindow == m_pLastTiledWindow) + m_pLastTiledWindow = nullptr; } g_pCompositor->updateWindowAnimatedDecorationValues(pWindow); @@ -347,3 +356,47 @@ void IHyprLayout::moveActiveWindow(const Vector2D& delta, CWindow* pWindow) { g_pHyprRenderer->damageWindow(PWINDOW); } + +void IHyprLayout::onWindowFocusChange(CWindow* pNewFocus) { + m_pLastTiledWindow = pNewFocus && !pNewFocus->m_bIsFloating ? pNewFocus : m_pLastTiledWindow; +} + +CWindow* IHyprLayout::getNextWindowCandidate(CWindow* pWindow) { + // although we don't expect nullptrs here, let's verify jic + if (!pWindow) + return nullptr; + + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); + + // first of all, if this is a fullscreen workspace, + if (PWORKSPACE->m_bHasFullscreenWindow) + return g_pCompositor->getFullscreenWindowOnWorkspace(pWindow->m_iWorkspaceID); + + if (pWindow->m_bIsFloating) { + // the window was floating, let's try the last tiled window. + + if (m_pLastTiledWindow && m_pLastTiledWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID) + return m_pLastTiledWindow; + + // if we don't, let's try to find any window that is in the middle + if (const auto PWINDOWCANDIDATE = g_pCompositor->vectorToWindowIdeal(pWindow->m_vRealPosition.goalv() + pWindow->m_vRealSize.goalv() / 2.f); PWINDOWCANDIDATE) + return PWINDOWCANDIDATE; + + // if not, floating window + for (auto& w : g_pCompositor->m_vWindows) { + if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && !w->m_bX11ShouldntFocus) + return w.get(); + } + + // if there is no candidate, too bad + return nullptr; + } + + // if it was a tiled window, we first try to find the window that will replace it. + const auto PWINDOWCANDIDATE = g_pCompositor->vectorToWindowIdeal(pWindow->m_vRealPosition.goalv() + pWindow->m_vRealSize.goalv() / 2.f); + + if (!PWINDOWCANDIDATE || pWindow == PWINDOWCANDIDATE || !PWINDOWCANDIDATE->m_bIsMapped || PWINDOWCANDIDATE->isHidden() || PWINDOWCANDIDATE->m_bX11ShouldntFocus || PWINDOWCANDIDATE->m_iX11Type == 2 || PWINDOWCANDIDATE->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID) + return nullptr; + + return PWINDOWCANDIDATE; +} diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index b084e05f..9116212c 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -123,10 +123,22 @@ public: */ virtual std::string getLayoutName() = 0; + /* + Called for getting the next candidate for a focus + */ + virtual CWindow* getNextWindowCandidate(CWindow*); + + /* + Internal: called when window focus changes + */ + virtual void onWindowFocusChange(CWindow*); + private: Vector2D m_vBeginDragXY; Vector2D m_vLastDragXY; Vector2D m_vBeginDragPositionXY; Vector2D m_vBeginDragSizeXY; int m_iGrabbedCorner = 0; + + CWindow* m_pLastTiledWindow = nullptr; };