diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 1d1dda08..c0ecb7f1 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1349,6 +1349,8 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni if (w->m_bIsFloating && w->m_bIsMapped && !w->m_bHidden) { w->m_vRealPosition = w->m_vRealPosition.vec() - POLDMON->vecPosition + pMonitor->vecPosition; } + + w->updateToplevel(); } } @@ -1541,3 +1543,16 @@ SLayerSurface* CCompositor::getLayerSurfaceFromWlr(wlr_layer_surface_v1* pLS) { return nullptr; } + +void CCompositor::closeWindow(CWindow* pWindow) { + if (pWindow && windowValidMapped(pWindow)) { + g_pXWaylandManager->sendCloseWindow(pWindow); + + if (pWindow == m_pLastWindow) { + g_pCompositor->m_pLastFocus = nullptr; + g_pCompositor->m_pLastWindow = nullptr; + g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","}); // post an activewindow event to empty, as we are currently unfocused + g_pCompositor->focusWindow(g_pCompositor->windowFromCursor()); + } + } +} \ No newline at end of file diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 0517ac1f..fdbd7319 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -156,6 +156,7 @@ public: CWindow* getWindowByRegex(const std::string&); void warpCursorTo(const Vector2D&); SLayerSurface* getLayerSurfaceFromWlr(wlr_layer_surface_v1*); + void closeWindow(CWindow*); std::string explicitConfigPath; diff --git a/src/Window.cpp b/src/Window.cpp index fb1cebed..176e8bb9 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -112,4 +112,63 @@ IHyprWindowDecoration* CWindow::getDecorationByType(eDecorationType type) { } return nullptr; +} + +void CWindow::createToplevelHandle() { + if (m_bIsX11 && (m_bX11DoesntWantBorders || m_iX11Type == 2)) + return; // don't create a toplevel + + m_phForeignToplevel = wlr_foreign_toplevel_handle_v1_create(g_pCompositor->m_sWLRToplevelMgr); + + wlr_foreign_toplevel_handle_v1_set_app_id(m_phForeignToplevel, g_pXWaylandManager->getAppIDClass(this).c_str()); + wlr_foreign_toplevel_handle_v1_output_enter(m_phForeignToplevel, g_pCompositor->getMonitorFromID(m_iMonitorID)->output); + wlr_foreign_toplevel_handle_v1_set_title(m_phForeignToplevel, m_szTitle.c_str()); + wlr_foreign_toplevel_handle_v1_set_maximized(m_phForeignToplevel, false); + wlr_foreign_toplevel_handle_v1_set_minimized(m_phForeignToplevel, false); + wlr_foreign_toplevel_handle_v1_set_fullscreen(m_phForeignToplevel, false); + + // handle events + hyprListener_toplevelActivate.initCallback(&m_phForeignToplevel->events.request_activate, [&](void* owner, void* data) { + + g_pCompositor->focusWindow(this); + + }, this, "Toplevel"); + + hyprListener_toplevelFullscreen.initCallback(&m_phForeignToplevel->events.request_fullscreen, [&](void* owner, void* data) { + + const auto EV = (wlr_foreign_toplevel_handle_v1_fullscreen_event*)data; + + g_pCompositor->setWindowFullscreen(this, EV->fullscreen, FULLSCREEN_FULL); + + }, this, "Toplevel"); + + hyprListener_toplevelClose.initCallback(&m_phForeignToplevel->events.request_close, [&](void* owner, void* data) { + + g_pCompositor->closeWindow(this); + + }, this, "Toplevel"); + + m_iLastToplevelMonitorID = m_iMonitorID; +} + +void CWindow::destroyToplevelHandle() { + hyprListener_toplevelActivate.removeCallback(); + hyprListener_toplevelClose.removeCallback(); + hyprListener_toplevelFullscreen.removeCallback(); + + wlr_foreign_toplevel_handle_v1_destroy(m_phForeignToplevel); + m_phForeignToplevel = nullptr; +} + +void CWindow::updateToplevel() { + wlr_foreign_toplevel_handle_v1_set_app_id(m_phForeignToplevel, g_pXWaylandManager->getAppIDClass(this).c_str()); + wlr_foreign_toplevel_handle_v1_set_title(m_phForeignToplevel, m_szTitle.c_str()); + wlr_foreign_toplevel_handle_v1_set_fullscreen(m_phForeignToplevel, m_bIsFullscreen); + + if (m_iLastToplevelMonitorID != m_iMonitorID) { + wlr_foreign_toplevel_handle_v1_output_leave(m_phForeignToplevel, g_pCompositor->getMonitorFromID(m_iLastToplevelMonitorID)->output); + wlr_foreign_toplevel_handle_v1_output_enter(m_phForeignToplevel, g_pCompositor->getMonitorFromID(m_iMonitorID)->output); + + m_iLastToplevelMonitorID = m_iMonitorID; + } } \ No newline at end of file diff --git a/src/Window.hpp b/src/Window.hpp index ab684432..dab1e88b 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -39,6 +39,11 @@ public: DYNLISTENER(requestMinimize); DYNLISTENER(requestMaximize); DYNLISTENER(requestResize); + DYNLISTENER(activateX11); + DYNLISTENER(configureX11); + DYNLISTENER(toplevelClose); + DYNLISTENER(toplevelActivate); + DYNLISTENER(toplevelFullscreen); // DYNLISTENER(newSubsurfaceWindow); union { @@ -87,8 +92,6 @@ public: uint64_t m_iX11Type = 0; bool m_bIsModal = false; bool m_bX11DoesntWantBorders = false; - DYNLISTENER(activateX11); - DYNLISTENER(configureX11); // // For nofocus @@ -127,6 +130,9 @@ public: // animated shadow color CAnimatedVariable m_cRealShadowColor; + // for toplevel monitor events + int m_iLastToplevelMonitorID = -1; + // For the list lookup bool operator==(const CWindow& rhs) { return m_uSurface.xdg == rhs.m_uSurface.xdg && m_uSurface.xwayland == rhs.m_uSurface.xwayland && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize && m_bFadingOut == rhs.m_bFadingOut; @@ -138,5 +144,8 @@ public: void updateWindowDecos(); pid_t getPID(); IHyprWindowDecoration* getDecorationByType(eDecorationType); + void createToplevelHandle(); + void destroyToplevelHandle(); + void updateToplevel(); }; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 116470c8..dcd2f97d 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -68,9 +68,7 @@ void Events::listener_mapWindow(void* owner, void* data) { g_pXWaylandManager->setWindowStyleTiled(PWINDOW, WLR_EDGE_LEFT | WLR_EDGE_RIGHT | WLR_EDGE_TOP | WLR_EDGE_BOTTOM); // Foreign Toplevel - PWINDOW->m_phForeignToplevel = wlr_foreign_toplevel_handle_v1_create(g_pCompositor->m_sWLRToplevelMgr); - // TODO: handle foreign events (requests) - wlr_foreign_toplevel_handle_v1_set_app_id(PWINDOW->m_phForeignToplevel, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str()); + PWINDOW->createToplevelHandle(); // checks if the window wants borders and sets the appriopriate flag g_pXWaylandManager->checkBorders(PWINDOW); @@ -327,6 +325,8 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->m_pSurfaceTree = SubsurfaceTree::createTreeRoot(g_pXWaylandManager->getWindowSurface(PWINDOW), addViewCoords, PWINDOW, PWINDOW); + PWINDOW->updateToplevel(); + Debug::log(LOG, "Map request dispatched, monitor %s, xywh: %f %f %f %f", PMONITOR->szName.c_str(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y, PWINDOW->m_vRealSize.goalv().x, PWINDOW->m_vRealSize.goalv().y); } @@ -412,8 +412,7 @@ void Events::listener_unmapWindow(void* owner, void* data) { PWINDOW->m_fAlpha = 0.f; // Destroy Foreign Toplevel - wlr_foreign_toplevel_handle_v1_destroy(PWINDOW->m_phForeignToplevel); - PWINDOW->m_phForeignToplevel = nullptr; + PWINDOW->destroyToplevelHandle(); // recheck idle inhibitors g_pInputManager->recheckIdleInhibitorStatus(); @@ -469,8 +468,7 @@ void Events::listener_setTitleWindow(void* owner, void* data) { if (PWINDOW == g_pCompositor->m_pLastWindow) // if it's the active, let's post an event to update others g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", g_pXWaylandManager->getAppIDClass(PWINDOW) + "," + PWINDOW->m_szTitle}); - if (PWINDOW->m_phForeignToplevel) - wlr_foreign_toplevel_handle_v1_set_title(PWINDOW->m_phForeignToplevel, PWINDOW->m_szTitle.c_str()); + PWINDOW->updateToplevel(); Debug::log(LOG, "Window %x set title to %s", PWINDOW, PWINDOW->m_szTitle.c_str()); } @@ -489,6 +487,8 @@ void Events::listener_fullscreenWindow(void* owner, void* data) { g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, !PWINDOW->m_bIsFullscreen); } + PWINDOW->updateToplevel(); + Debug::log(LOG, "Window %x fullscreen to %i", PWINDOW, PWINDOW->m_bIsFullscreen); g_pXWaylandManager->setWindowFullscreen(PWINDOW, PWINDOW->m_bIsFullscreen); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index c07ca6d9..bbdc97ca 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -202,6 +202,8 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { if (PMONITOR) { DRAGGINGWINDOW->m_iMonitorID = PMONITOR->ID; DRAGGINGWINDOW->m_iWorkspaceID = PMONITOR->activeWorkspace; + + DRAGGINGWINDOW->updateToplevel(); } DRAGGINGWINDOW->updateWindowDecos(); @@ -257,6 +259,8 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) { pWindow->m_sSpecialRenderData.rounding = true; } + + pWindow->updateToplevel(); } void IHyprLayout::moveActiveWindow(const Vector2D& delta, CWindow* pWindow) { diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 00cfad3f..bc6bab77 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -408,14 +408,7 @@ void CKeybindManager::spawn(std::string args) { } void CKeybindManager::killActive(std::string args) { - 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_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","}); // post an activewindow event to empty, as we are currently unfocused - } - - g_pCompositor->focusWindow(g_pCompositor->windowFromCursor()); + g_pCompositor->closeWindow(g_pCompositor->m_pLastWindow); } void CKeybindManager::clearKeybinds() { @@ -671,6 +664,8 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) { } g_pInputManager->refocus(); + + PWINDOW->updateToplevel(); } void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) { diff --git a/subprojects/wlroots b/subprojects/wlroots index b24b50ec..7b5e890e 160000 --- a/subprojects/wlroots +++ b/subprojects/wlroots @@ -1 +1 @@ -Subproject commit b24b50ec0c1c54a14acf34df2c95b37043d15b49 +Subproject commit 7b5e890e61a27375725068a7d1884b26851b3102