From 223beb8a826773e2e3ea4c6d7e7d40fde9247d9a Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Sat, 2 Apr 2022 18:57:09 +0200 Subject: [PATCH] Multiple focus handling changes --- src/Compositor.cpp | 31 ++++++++---------- src/Compositor.hpp | 4 +-- src/Window.cpp | 4 ++- src/debug/HyprCtl.cpp | 2 +- src/events/Windows.cpp | 11 +++++-- src/helpers/SubsurfaceTree.cpp | 4 +++ src/managers/InputManager.cpp | 55 ++++++++++++++++++-------------- src/managers/KeybindManager.cpp | 15 +++++---- src/managers/XWaylandManager.cpp | 13 ++++++++ src/managers/XWaylandManager.hpp | 1 + 10 files changed, 85 insertions(+), 55 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index dd0e200a..5fc00142 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -335,8 +335,6 @@ wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, CWindow* pW if (PFOUND) { sl.x = subx; sl.y = suby; - if (PFOUND != PSURFACE->surface) - Debug::log(LOG, "found non-base on window XDG %x", pWindow); return PFOUND; } @@ -356,16 +354,20 @@ SMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) { return nullptr; } -void CCompositor::focusWindow(CWindow* pWindow) { +void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) { if (!pWindow || !windowValidMapped(pWindow)) { wlr_seat_keyboard_notify_clear_focus(m_sSeat.seat); return; } - const auto PWINDOWSURFACE = g_pXWaylandManager->getWindowSurface(pWindow); + const auto PWINDOWSURFACE = pSurface ? pSurface : g_pXWaylandManager->getWindowSurface(pWindow); - focusSurface(PWINDOWSURFACE); + focusSurface(PWINDOWSURFACE, pWindow); + + g_pXWaylandManager->activateWindow(pWindow, true); + + m_pLastWindow = pWindow; } void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) { @@ -376,8 +378,8 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) { return; // Unfocus last surface if should - if (m_pLastFocus && !wlr_surface_is_xwayland_surface(pSurface) && !m_pLastFocusWindow) - g_pXWaylandManager->activateSurface(m_pLastFocus, false); + if (m_pLastFocus && m_sSeat.seat->keyboard_state.focused_surface && wlr_surface_is_xdg_surface(m_pLastFocus)) + wlr_xdg_toplevel_set_activated(wlr_xdg_surface_from_wlr_surface(m_pLastFocus)->toplevel, false); const auto KEYBOARD = wlr_seat_get_keyboard(m_sSeat.seat); @@ -386,16 +388,6 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) { wlr_seat_keyboard_notify_enter(m_sSeat.seat, pSurface, KEYBOARD->keycodes, KEYBOARD->num_keycodes, &KEYBOARD->modifiers); - m_pLastFocus = pSurface; - m_pLastFocusWindow = nullptr; - - if (pWindowOwner) { - g_pXWaylandManager->activateSurface(g_pXWaylandManager->getWindowSurface(pWindowOwner), true); - m_pLastFocusWindow = pSurface; - } - else - g_pXWaylandManager->activateSurface(pSurface, true); - if (const auto PWINDOW = getWindowFromSurface(pSurface); PWINDOW) Debug::log(LOG, "Set keyboard focus to surface %x, with window name: %s", pSurface, PWINDOW->m_szTitle.c_str()); else @@ -527,7 +519,10 @@ bool CCompositor::doesSeatAcceptInput(wlr_surface* surface) { } bool CCompositor::isWindowActive(CWindow* pWindow) { + if (!windowValidMapped(pWindow)) + return false; + const auto PSURFACE = g_pXWaylandManager->getWindowSurface(pWindow); - return PSURFACE == m_pLastFocus || PSURFACE == m_pLastFocusWindow; + return PSURFACE == m_pLastFocus || pWindow == m_pLastWindow; } \ No newline at end of file diff --git a/src/Compositor.hpp b/src/Compositor.hpp index bca0e3c5..4bf5d85b 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -60,7 +60,7 @@ public: void startCompositor(); wlr_surface* m_pLastFocus = nullptr; - wlr_surface* m_pLastFocusWindow = nullptr; + CWindow* m_pLastWindow = nullptr; SMonitor* m_pLastMonitor = nullptr; SSeat m_sSeat; @@ -71,7 +71,7 @@ public: SMonitor* getMonitorFromCursor(); SMonitor* getMonitorFromVector(const Vector2D&); void removeWindowFromVectorSafe(CWindow*); - void focusWindow(CWindow*); + void focusWindow(CWindow*, wlr_surface* pSurface = nullptr); void focusSurface(wlr_surface*, CWindow* pWindowOwner = nullptr); bool windowExists(CWindow*); bool windowValidMapped(CWindow*); diff --git a/src/Window.cpp b/src/Window.cpp index 0e5573bb..ff8ba299 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -2,6 +2,8 @@ #include "Compositor.hpp" CWindow::~CWindow() { - if ((this->m_uSurface.xdg || this->m_uSurface.xwayland) && g_pCompositor->m_pLastFocus == g_pXWaylandManager->getWindowSurface(this)) + if (g_pCompositor->isWindowActive(this)) { g_pCompositor->m_pLastFocus = nullptr; + g_pCompositor->m_pLastWindow = nullptr; + } } \ No newline at end of file diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 7b5b8a3f..3a19fd19 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -54,7 +54,7 @@ std::string workspacesRequest() { } std::string activeWindowRequest() { - const auto PWINDOW = g_pCompositor->getWindowFromSurface(g_pCompositor->m_pLastFocus); + const auto PWINDOW = g_pCompositor->m_pLastWindow; if (!g_pCompositor->windowValidMapped(PWINDOW)) return "Invalid"; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 43a3a962..3d50f1f4 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -156,8 +156,10 @@ void Events::listener_unmapWindow(void* owner, void* data) { PWINDOW->hyprListener_setTitleWindow.removeCallback(); } - if (g_pXWaylandManager->getWindowSurface(PWINDOW) == g_pCompositor->m_pLastFocus) + if (PWINDOW == g_pCompositor->m_pLastWindow) { + g_pCompositor->m_pLastWindow = nullptr; g_pCompositor->m_pLastFocus = nullptr; + } PWINDOW->m_bMappedX11 = false; @@ -175,7 +177,7 @@ void Events::listener_unmapWindow(void* owner, void* data) { // refocus on a new window g_pInputManager->refocus(); - + Debug::log(LOG, "Destroying the SubSurface tree of unmapped window %x", PWINDOW); SubsurfaceTree::destroySurfaceTree(PWINDOW->m_pSurfaceTree); PWINDOW->m_pSurfaceTree = nullptr; @@ -192,8 +194,10 @@ void Events::listener_destroyWindow(void* owner, void* data) { Debug::log(LOG, "Window %x destroyed", PWINDOW); - if (g_pXWaylandManager->getWindowSurface(PWINDOW) == g_pCompositor->m_pLastFocus) + if (PWINDOW == g_pCompositor->m_pLastWindow) { + g_pCompositor->m_pLastWindow = nullptr; g_pCompositor->m_pLastFocus = nullptr; + } PWINDOW->hyprListener_mapWindow.removeCallback(); PWINDOW->hyprListener_unmapWindow.removeCallback(); @@ -202,6 +206,7 @@ void Events::listener_destroyWindow(void* owner, void* data) { g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW); if (PWINDOW->m_pSurfaceTree) { + Debug::log(LOG, "Destroying Subsurface tree of %x in destroyWindow", PWINDOW); SubsurfaceTree::destroySurfaceTree(PWINDOW->m_pSurfaceTree); PWINDOW->m_pSurfaceTree = nullptr; } diff --git a/src/helpers/SubsurfaceTree.cpp b/src/helpers/SubsurfaceTree.cpp index b0b62939..19c99eae 100644 --- a/src/helpers/SubsurfaceTree.cpp +++ b/src/helpers/SubsurfaceTree.cpp @@ -154,6 +154,10 @@ void Events::listener_destroySubsurface(void* owner, void* data) { Debug::log(LOG, "Subsurface %x destroyed", subsurface); + subsurface->hyprListener_destroy.removeCallback(); + subsurface->hyprListener_map.removeCallback(); + subsurface->hyprListener_unmap.removeCallback(); + subsurface->pParent->childSubsurfaces.remove(*subsurface); } diff --git a/src/managers/InputManager.cpp b/src/managers/InputManager.cpp index 4c66c7bf..2483832a 100644 --- a/src/managers/InputManager.cpp +++ b/src/managers/InputManager.cpp @@ -34,28 +34,32 @@ void CInputManager::mouseMoveUnified(uint32_t time) { Vector2D surfaceCoords; Vector2D surfacePos = Vector2D(-1337, -1337); + CWindow* pFoundWindow = nullptr; // first, we check if the workspace doesnt have a fullscreen window const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); if (PWORKSPACE->hasFullscreenWindow) { - const auto PFULLSCREENWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->ID); + pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->ID); - // should never ever happen but who knows - if (PFULLSCREENWINDOW) { - foundSurface = g_pXWaylandManager->getWindowSurface(PFULLSCREENWINDOW); - if (foundSurface) - surfacePos = PFULLSCREENWINDOW->m_vRealPosition; - - for (auto& w : g_pCompositor->m_lWindows) { - wlr_box box = {w.m_vRealPosition.x, w.m_vRealPosition.y, w.m_vRealSize.x, w.m_vRealSize.y}; - if (w.m_iWorkspaceID == PFULLSCREENWINDOW->m_iWorkspaceID && w.m_bIsMapped && w.m_bCreatedOverFullscreen && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y)) { - foundSurface = g_pXWaylandManager->getWindowSurface(&w); - if (foundSurface) - surfacePos = w.m_vRealPosition; - break; - } + for (auto w = g_pCompositor->m_lWindows.rbegin(); w != g_pCompositor->m_lWindows.rend(); ++w) { + wlr_box box = {w->m_vRealPosition.x, w->m_vRealPosition.y, w->m_vRealSize.x, w->m_vRealSize.y}; + if (w->m_iWorkspaceID == pFoundWindow->m_iWorkspaceID && w->m_bIsMapped && w->m_bCreatedOverFullscreen && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y)) { + foundSurface = g_pXWaylandManager->getWindowSurface(&(*w)); + if (foundSurface) + surfacePos = w->m_vRealPosition; + break; } - } + } + + if (pFoundWindow && !foundSurface) { + if (pFoundWindow->m_bIsX11) { + foundSurface = g_pXWaylandManager->getWindowSurface(pFoundWindow); + if (foundSurface) + surfacePos = pFoundWindow->m_vRealPosition; + } else { + foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords); + } + } } // then surfaces on top @@ -66,16 +70,16 @@ void CInputManager::mouseMoveUnified(uint32_t time) { foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords); // then windows - const auto PWINDOWIDEAL = g_pCompositor->vectorToWindowIdeal(mouseCoords); - if (!foundSurface && PWINDOWIDEAL) { - if (!PWINDOWIDEAL->m_bIsX11) { - foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, PWINDOWIDEAL, surfaceCoords); + pFoundWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords); + if (!foundSurface && pFoundWindow) { + if (!pFoundWindow->m_bIsX11) { + foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords); } else { - foundSurface = g_pXWaylandManager->getWindowSurface(PWINDOWIDEAL); - surfacePos = PWINDOWIDEAL->m_vRealPosition; + foundSurface = g_pXWaylandManager->getWindowSurface(pFoundWindow); + surfacePos = pFoundWindow->m_vRealPosition; } } - + // then surfaces below if (!foundSurface) foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &surfaceCoords); @@ -100,7 +104,10 @@ void CInputManager::mouseMoveUnified(uint32_t time) { wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y); wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, time, surfaceLocal.x, surfaceLocal.y); - g_pCompositor->focusSurface(foundSurface, PWINDOWIDEAL ? PWINDOWIDEAL : nullptr); + if (pFoundWindow) + g_pCompositor->focusWindow(pFoundWindow, foundSurface); + else + g_pCompositor->focusSurface(foundSurface); g_pLayoutManager->getCurrentLayout()->onMouseMove(getMouseCoordsInternal()); } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 22c880b4..d9d2fa72 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -88,9 +88,12 @@ void CKeybindManager::spawn(std::string args) { } void CKeybindManager::killActive(std::string args) { - if (g_pCompositor->m_pLastFocus && g_pCompositor->windowValidMapped(g_pCompositor->getWindowFromSurface(g_pCompositor->m_pLastFocus))) - g_pXWaylandManager->sendCloseWindow(g_pCompositor->getWindowFromSurface(g_pCompositor->m_pLastFocus)); - + if (g_pCompositor->m_pLastWindow && g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow)) { + g_pXWaylandManager->sendCloseWindow(g_pCompositor->m_pLastWindow); + g_pCompositor->m_pLastFocus = nullptr; + g_pCompositor->m_pLastWindow = nullptr; + } + g_pCompositor->focusWindow(g_pCompositor->windowFromCursor()); } @@ -99,7 +102,7 @@ void CKeybindManager::clearKeybinds() { } void CKeybindManager::toggleActiveFloating(std::string args) { - const auto ACTIVEWINDOW = g_pCompositor->getWindowFromSurface(g_pCompositor->m_pLastFocus); + const auto ACTIVEWINDOW = g_pCompositor->m_pLastWindow; if (g_pCompositor->windowValidMapped(ACTIVEWINDOW)) { ACTIVEWINDOW->m_bIsFloating = !ACTIVEWINDOW->m_bIsFloating; @@ -170,7 +173,7 @@ void CKeybindManager::changeworkspace(std::string args) { } void CKeybindManager::fullscreenActive(std::string args) { - const auto PWINDOW = g_pCompositor->getWindowFromSurface(g_pCompositor->m_pLastFocus); + const auto PWINDOW = g_pCompositor->m_pLastWindow; if (!g_pCompositor->windowValidMapped(PWINDOW)) return; @@ -187,7 +190,7 @@ void CKeybindManager::fullscreenActive(std::string args) { } void CKeybindManager::moveActiveToWorkspace(std::string args) { - const auto PWINDOW = g_pCompositor->getWindowFromSurface(g_pCompositor->m_pLastFocus); + const auto PWINDOW = g_pCompositor->m_pLastWindow; if (!g_pCompositor->windowValidMapped(PWINDOW)) return; diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 6fd37f94..0e419c0f 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -37,6 +37,19 @@ void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate) wlr_xwayland_surface_activate(wlr_xwayland_surface_from_wlr_surface(pSurface), activate); } +void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) { + if (pWindow == g_pCompositor->m_pLastWindow) + return; + + if (pWindow->m_bIsX11) + wlr_xwayland_surface_activate(pWindow->m_uSurface.xwayland, activate); + else + wlr_xdg_toplevel_set_activated(pWindow->m_uSurface.xdg->toplevel, activate); + + g_pCompositor->m_pLastFocus = getWindowSurface(pWindow); + g_pCompositor->m_pLastWindow = pWindow; +} + void CHyprXWaylandManager::getGeometryForWindow(CWindow* pWindow, wlr_box* pbox) { if (pWindow->m_bIsX11) { pbox->x = pWindow->m_uSurface.xwayland->x; diff --git a/src/managers/XWaylandManager.hpp b/src/managers/XWaylandManager.hpp index 143d60da..7008d0e8 100644 --- a/src/managers/XWaylandManager.hpp +++ b/src/managers/XWaylandManager.hpp @@ -12,6 +12,7 @@ public: wlr_surface* getWindowSurface(CWindow*); void activateSurface(wlr_surface*, bool); + void activateWindow(CWindow*, bool); void getGeometryForWindow(CWindow*, wlr_box*); std::string getTitle(CWindow*); std::string getAppIDClass(CWindow*);