From 2e111c8cf97d391c25fc6263660271fab605ece1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 29 Feb 2024 14:26:02 +0000 Subject: [PATCH] xdg: rewrite entire popup implementation --- src/Compositor.cpp | 9 -- src/Compositor.hpp | 2 - src/Window.cpp | 8 ++ src/Window.hpp | 5 +- src/desktop/Popup.cpp | 225 +++++++++++++++++++++++++++++++ src/desktop/Popup.hpp | 69 ++++++++++ src/desktop/Subsurface.cpp | 51 ++++--- src/desktop/Subsurface.hpp | 8 +- src/events/Events.hpp | 11 -- src/events/Layers.cpp | 6 +- src/events/Popups.cpp | 269 ------------------------------------- src/events/Windows.cpp | 7 +- src/helpers/WLClasses.hpp | 32 +---- 13 files changed, 358 insertions(+), 344 deletions(-) create mode 100644 src/desktop/Popup.cpp create mode 100644 src/desktop/Popup.hpp delete mode 100644 src/events/Popups.cpp diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 48ac0e1c..150dbfaa 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1120,15 +1120,6 @@ bool CCompositor::windowValidMapped(CWindow* pWindow) { return true; } -CWindow* CCompositor::getWindowForPopup(wlr_xdg_popup* popup) { - for (auto& p : m_vXDGPopups) { - if (p->popup == popup) - return p->parentWindow; - } - - return nullptr; -} - wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector>* layerSurfaces, Vector2D* sCoords, SLayerSurface** ppLayerSurfaceFound) { for (auto& ls : *layerSurfaces | std::views::reverse) { diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 92573669..e9edae04 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -93,7 +93,6 @@ class CCompositor { std::vector> m_vMonitors; std::vector> m_vRealMonitors; // for all monitors, even those turned off std::vector> m_vWindows; - std::vector> m_vXDGPopups; std::vector> m_vWorkspaces; std::vector m_vWindowsFadingOut; std::vector m_vSurfacesFadingOut; @@ -142,7 +141,6 @@ class CCompositor { Vector2D vectorToSurfaceLocal(const Vector2D&, CWindow*, wlr_surface*); CMonitor* getMonitorFromOutput(wlr_output*); CMonitor* getRealMonitorFromOutput(wlr_output*); - CWindow* getWindowForPopup(wlr_xdg_popup*); CWindow* getWindowFromSurface(wlr_surface*); CWindow* getWindowFromHandle(uint32_t); CWindow* getWindowFromZWLRHandle(wl_resource*); diff --git a/src/Window.cpp b/src/Window.cpp index f1484cb0..6742be60 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -472,7 +472,11 @@ void CWindow::onUnmap() { g_pCompositor->updateWorkspaceWindows(m_iWorkspaceID); + if (m_bIsX11) + return; + m_pSubsurfaceHead.reset(); + m_pPopupHead.reset(); } void CWindow::onMap() { @@ -519,7 +523,11 @@ void CWindow::onMap() { break; } + if (m_bIsX11) + return; + m_pSubsurfaceHead = std::make_unique(this); + m_pPopupHead = std::make_unique(this); } void CWindow::onBorderAngleAnimEnd(void* ptr) { diff --git a/src/Window.hpp b/src/Window.hpp index 476cb1c5..f4809d11 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -8,6 +8,7 @@ #include "config/ConfigDataValues.hpp" #include "helpers/Vector2D.hpp" #include "desktop/WLSurface.hpp" +#include "desktop/Popup.hpp" #include "macros.hpp" #include "managers/XWaylandManager.hpp" @@ -193,7 +194,6 @@ class CWindow { DYNLISTENER(setTitleWindow); DYNLISTENER(setGeometryX11U); DYNLISTENER(fullscreenWindow); - DYNLISTENER(newPopupXDG); DYNLISTENER(requestMove); DYNLISTENER(requestMinimize); DYNLISTENER(requestMaximize); @@ -278,8 +278,9 @@ class CWindow { // bitfield eSuppressEvents uint64_t m_eSuppressedEvents = SUPPRESS_NONE; - // for the subsurface tree + // desktop components std::unique_ptr m_pSubsurfaceHead; + std::unique_ptr m_pPopupHead; // Animated border CGradientValueData m_cRealBorderColor = {0}; diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp new file mode 100644 index 00000000..a4b63826 --- /dev/null +++ b/src/desktop/Popup.cpp @@ -0,0 +1,225 @@ +#include "Popup.hpp" + +CPopup::CPopup(CWindow* pOwner) : m_pWindowOwner(pOwner) { + initAllSignals(); +} + +CPopup::CPopup(SLayerSurface* pOwner) : m_pLayerOwner(pOwner) { + initAllSignals(); +} + +CPopup::CPopup(wlr_xdg_popup* popup, CPopup* pOwner) : m_pParent(pOwner), m_pWLR(popup) { + m_pWLR->base->data = this; + m_sWLSurface.assign(popup->base->surface); + + m_pLayerOwner = pOwner->m_pLayerOwner; + m_pWindowOwner = pOwner->m_pWindowOwner; + + m_vLastSize = {m_pWLR->current.geometry.width, m_pWLR->current.geometry.height}; + unconstrain(); + + initAllSignals(); +} + +CPopup::~CPopup() { + m_sWLSurface.unassign(); + if (m_pWLR) + m_pWLR->base->data = nullptr; + + hyprListener_commitPopup.removeCallback(); + hyprListener_repositionPopup.removeCallback(); + hyprListener_mapPopup.removeCallback(); + hyprListener_unmapPopup.removeCallback(); + hyprListener_newPopup.removeCallback(); + hyprListener_destroyPopup.removeCallback(); +} + +static void onNewPopup(void* owner, void* data) { + const auto POPUP = (CPopup*)owner; + POPUP->onNewPopup((wlr_xdg_popup*)data); +} + +static void onMapPopup(void* owner, void* data) { + const auto POPUP = (CPopup*)owner; + POPUP->onMap(); +} + +static void onDestroyPopup(void* owner, void* data) { + const auto POPUP = (CPopup*)owner; + POPUP->onDestroy(); +} + +static void onUnmapPopup(void* owner, void* data) { + const auto POPUP = (CPopup*)owner; + POPUP->onUnmap(); +} + +static void onCommitPopup(void* owner, void* data) { + const auto POPUP = (CPopup*)owner; + POPUP->onCommit(); +} + +static void onRepositionPopup(void* owner, void* data) { + const auto POPUP = (CPopup*)owner; + POPUP->onReposition(); +} + +void CPopup::initAllSignals() { + + if (!m_pWLR) { + if (m_pWindowOwner) + hyprListener_newPopup.initCallback(&m_pWindowOwner->m_uSurface.xdg->events.new_popup, ::onNewPopup, this, "CPopup Head"); + else if (m_pLayerOwner) + hyprListener_newPopup.initCallback(&m_pLayerOwner->layerSurface->events.new_popup, ::onNewPopup, this, "CPopup Head"); + else + ASSERT(false); + + return; + } + + hyprListener_repositionPopup.initCallback(&m_pWLR->events.reposition, ::onRepositionPopup, this, "CPopup"); + hyprListener_destroyPopup.initCallback(&m_pWLR->events.destroy, ::onDestroyPopup, this, "CPopup"); + hyprListener_mapPopup.initCallback(&m_sWLSurface.wlr()->events.map, ::onMapPopup, this, "CPopup"); + hyprListener_unmapPopup.initCallback(&m_sWLSurface.wlr()->events.unmap, ::onUnmapPopup, this, "CPopup"); + hyprListener_commitPopup.initCallback(&m_sWLSurface.wlr()->events.commit, ::onCommitPopup, this, "CPopup"); + hyprListener_newPopup.initCallback(&m_pWLR->base->events.new_popup, ::onNewPopup, this, "CPopup"); +} + +void CPopup::onNewPopup(wlr_xdg_popup* popup) { + const auto POPUP = m_vChildren.emplace_back(std::make_unique(popup, this)).get(); + Debug::log(LOG, "New popup at wlr {:x} and hl {:x}", (uintptr_t)popup, (uintptr_t)POPUP); +} + +void CPopup::onDestroy() { + m_bInert = true; + + if (!m_pParent) + return; // head node + + std::erase_if(m_pParent->m_vChildren, [this](const auto& other) { return other.get() == this; }); +} + +void CPopup::onMap() { + m_vLastSize = {m_pWLR->current.geometry.width, m_pWLR->current.geometry.height}; + const auto COORDS = coordsGlobal(); + + CBox box = {COORDS, m_vLastSize}; + g_pHyprRenderer->damageBox(&box); + + m_vLastPos = coordsRelativeToParent(); + + g_pInputManager->simulateMouseMovement(); + + m_pSubsurfaceHead = std::make_unique(this); + + unconstrain(); +} + +void CPopup::onUnmap() { + m_vLastSize = {m_pWLR->current.geometry.width, m_pWLR->current.geometry.height}; + const auto COORDS = coordsGlobal(); + + CBox box = {COORDS, m_vLastSize}; + g_pHyprRenderer->damageBox(&box); + + m_pSubsurfaceHead.reset(); + + g_pInputManager->simulateMouseMovement(); +} + +void CPopup::onCommit() { + if (m_pWLR->base->initial_commit) { + wlr_xdg_surface_schedule_configure(m_pWLR->base); + return; + } + + const auto COORDS = coordsGlobal(); + const auto COORDSLOCAL = coordsRelativeToParent(); + + if (m_vLastSize != Vector2D{m_pWLR->current.geometry.width, m_pWLR->current.geometry.height} || m_bRequestedReposition || m_vLastPos != COORDSLOCAL) { + CBox box = {localToGlobal(m_vLastPos), m_vLastSize}; + g_pHyprRenderer->damageBox(&box); + m_vLastSize = {m_pWLR->current.geometry.width, m_pWLR->current.geometry.height}; + box = {COORDS, m_vLastSize}; + g_pHyprRenderer->damageBox(&box); + + m_vLastPos = COORDSLOCAL; + } + + m_pSubsurfaceHead->recheckDamageForSubsurfaces(); + + g_pHyprRenderer->damageSurface(m_sWLSurface.wlr(), COORDS.x, COORDS.y); + + m_bRequestedReposition = false; +} + +void CPopup::onReposition() { + Debug::log(LOG, "Popup {:x} requests reposition", (uintptr_t)this); + + m_bRequestedReposition = true; + + m_vLastPos = coordsRelativeToParent(); + + unconstrain(); +} + +void CPopup::unconstrain() { + const auto COORDS = t1ParentCoords(); + const auto PMONITOR = g_pCompositor->getMonitorFromVector(COORDS); + + if (!PMONITOR) + return; + + CBox box = {PMONITOR->vecPosition.x - COORDS.x, PMONITOR->vecPosition.y - COORDS.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; + wlr_xdg_popup_unconstrain_from_box(m_pWLR, box.pWlr()); +} + +Vector2D CPopup::coordsRelativeToParent() { + Vector2D offset; + + CPopup* current = this; + + while (current->m_pParent) { + + offset += {current->m_sWLSurface.wlr()->current.dx, current->m_sWLSurface.wlr()->current.dy}; + offset += {current->m_pWLR->current.geometry.x, current->m_pWLR->current.geometry.y}; + + current = current->m_pParent; + } + + return offset; +} + +Vector2D CPopup::coordsGlobal() { + return localToGlobal(coordsRelativeToParent()); +} + +Vector2D CPopup::localToGlobal(const Vector2D& rel) { + return t1ParentCoords() + rel; +} + +Vector2D CPopup::t1ParentCoords() { + if (m_pWindowOwner) + return m_pWindowOwner->m_vRealPosition.vec(); + if (m_pLayerOwner) + return m_pLayerOwner->realPosition.vec(); + + ASSERT(false); + return {}; +} + +void CPopup::recheckTree() { + CPopup* curr = this; + while (curr->m_pParent) { + curr = curr->m_pParent; + } + + curr->recheckChildrenRecursive(); +} + +void CPopup::recheckChildrenRecursive() { + for (auto& c : m_vChildren) { + c->onCommit(); + c->recheckChildrenRecursive(); + } +} \ No newline at end of file diff --git a/src/desktop/Popup.hpp b/src/desktop/Popup.hpp new file mode 100644 index 00000000..8279f7ed --- /dev/null +++ b/src/desktop/Popup.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include +#include +#include "Subsurface.hpp" + +struct SLayerSurface; + +class CPopup { + public: + // dummy head nodes + CPopup(CWindow* pOwner); + CPopup(SLayerSurface* pOwner); + + // real nodes + CPopup(wlr_xdg_popup* popup, CPopup* pOwner); + + ~CPopup(); + + Vector2D coordsRelativeToParent(); + Vector2D coordsGlobal(); + + void onNewPopup(wlr_xdg_popup* popup); + void onDestroy(); + void onMap(); + void onUnmap(); + void onCommit(); + void onReposition(); + + void recheckTree(); + + CWLSurface m_sWLSurface; + + private: + // T1 owners, each popup has to have one of these + CWindow* m_pWindowOwner = nullptr; + SLayerSurface* m_pLayerOwner = nullptr; + + // T2 owners + CPopup* m_pParent = nullptr; + + wlr_xdg_popup* m_pWLR = nullptr; + + Vector2D m_vLastSize = {}; + Vector2D m_vLastPos = {}; + + bool m_bRequestedReposition = false; + + bool m_bInert = false; + + // + std::vector> m_vChildren; + std::unique_ptr m_pSubsurfaceHead; + + // signals + DYNLISTENER(newPopup); + DYNLISTENER(destroyPopup); + DYNLISTENER(mapPopup); + DYNLISTENER(unmapPopup); + DYNLISTENER(commitPopup); + DYNLISTENER(repositionPopup); + + void initAllSignals(); + void unconstrain(); + void recheckChildrenRecursive(); + + Vector2D localToGlobal(const Vector2D& rel); + Vector2D t1ParentCoords(); +}; \ No newline at end of file diff --git a/src/desktop/Subsurface.cpp b/src/desktop/Subsurface.cpp index 0923e9cc..dde8d532 100644 --- a/src/desktop/Subsurface.cpp +++ b/src/desktop/Subsurface.cpp @@ -16,12 +16,30 @@ CSubsurface::CSubsurface(CWindow* pOwner) : m_pWindowParent(pOwner) { } } +CSubsurface::CSubsurface(CPopup* pOwner) : m_pPopupParent(pOwner) { + initSignals(); + + wlr_subsurface* wlrSubsurface; + wl_list_for_each(wlrSubsurface, &pOwner->m_sWLSurface.wlr()->current.subsurfaces_below, current.link) { + ::onNewSubsurface(this, wlrSubsurface); + } + wl_list_for_each(wlrSubsurface, &pOwner->m_sWLSurface.wlr()->current.subsurfaces_above, current.link) { + ::onNewSubsurface(this, wlrSubsurface); + } +} + CSubsurface::CSubsurface(wlr_subsurface* pSubsurface, CWindow* pOwner) : m_pSubsurface(pSubsurface), m_pWindowParent(pOwner) { m_sWLSurface.assign(pSubsurface->surface); initSignals(); initExistingSubsurfaces(); } +CSubsurface::CSubsurface(wlr_subsurface* pSubsurface, CPopup* pOwner) : m_pSubsurface(pSubsurface), m_pPopupParent(pOwner) { + m_sWLSurface.assign(pSubsurface->surface); + initSignals(); + initExistingSubsurfaces(); +} + CSubsurface::~CSubsurface() { hyprListener_newSubsurface.removeCallback(); @@ -30,11 +48,6 @@ CSubsurface::~CSubsurface() { hyprListener_commitSubsurface.removeCallback(); hyprListener_destroySubsurface.removeCallback(); - - const auto COORDS = coordsGlobal(); - - CBox box = {COORDS, m_vLastSize}; - g_pHyprRenderer->damageBox(&box); } static void onNewSubsurface(void* owner, void* data) { @@ -68,10 +81,12 @@ void CSubsurface::initSignals() { hyprListener_destroySubsurface.initCallback(&m_pSubsurface->events.destroy, &onDestroySubsurface, this, "CSubsurface"); hyprListener_newSubsurface.initCallback(&m_pSubsurface->surface->events.new_subsurface, &::onNewSubsurface, this, "CSubsurface"); hyprListener_mapSubsurface.initCallback(&m_pSubsurface->surface->events.map, &onMapSubsurface, this, "CSubsurface"); - hyprListener_newSubsurface.initCallback(&m_pSubsurface->surface->events.unmap, &onUnmapSubsurface, this, "CSubsurface"); + hyprListener_unmapSubsurface.initCallback(&m_pSubsurface->surface->events.unmap, &onUnmapSubsurface, this, "CSubsurface"); } else { if (m_pWindowParent) - hyprListener_newSubsurface.initCallback(&m_pWindowParent->m_pWLSurface.wlr()->events.new_subsurface, &::onNewSubsurface, this, "CSubsurface"); + hyprListener_newSubsurface.initCallback(&m_pWindowParent->m_pWLSurface.wlr()->events.new_subsurface, &::onNewSubsurface, this, "CSubsurface Head"); + else if (m_pPopupParent) + hyprListener_newSubsurface.initCallback(&m_pPopupParent->m_sWLSurface.wlr()->events.new_subsurface, &::onNewSubsurface, this, "CSubsurface Head"); else RASSERT(false, "CSubsurface::initSignals empty subsurface"); } @@ -93,11 +108,9 @@ void CSubsurface::checkSiblingDamage() { } void CSubsurface::recheckDamageForSubsurfaces() { - const double SCALE = m_pWindowParent && m_pWindowParent->m_bIsX11 ? 1.0 / m_pWindowParent->m_fX11SurfaceScaledBy : 1.0; - for (auto& n : m_vChildren) { const auto COORDS = n->coordsGlobal(); - g_pHyprRenderer->damageSurface(n->m_sWLSurface.wlr(), COORDS.x, COORDS.y, SCALE); + g_pHyprRenderer->damageSurface(n->m_sWLSurface.wlr(), COORDS.x, COORDS.y); } } @@ -112,11 +125,14 @@ void CSubsurface::onCommit() { return; } - const auto COORDS = coordsGlobal(); + const auto COORDS = coordsGlobal(); - const double SCALE = m_pWindowParent && m_pWindowParent->m_bIsX11 ? 1.0 / m_pWindowParent->m_fX11SurfaceScaledBy : 1.0; + g_pHyprRenderer->damageSurface(m_sWLSurface.wlr(), COORDS.x, COORDS.y); - g_pHyprRenderer->damageSurface(m_sWLSurface.wlr(), COORDS.x, COORDS.y, SCALE); + if (m_pPopupParent) + m_pPopupParent->recheckTree(); + if (m_pWindowParent) // I hate you firefox why are you doing this + m_pWindowParent->m_pPopupHead->recheckTree(); // I do not think this is correct, but it solves a lot of issues with some apps (e.g. firefox) checkSiblingDamage(); @@ -130,9 +146,6 @@ void CSubsurface::onCommit() { } if (m_pWindowParent) { - if (m_pWindowParent->m_bIsX11) - m_pWindowParent->m_vReportedSize = m_pWindowParent->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged. - // tearing: if solitary, redraw it. This still might be a single surface window const auto PMONITOR = g_pCompositor->getMonitorFromID(m_pWindowParent->m_iMonitorID); if (PMONITOR && PMONITOR->solitaryClient == m_pWindowParent && m_pWindowParent->canBeTorn() && PMONITOR->tearingState.canTear && @@ -155,6 +168,8 @@ void CSubsurface::onDestroy() { // destroy children m_vChildren.clear(); + m_bInert = true; + if (!m_pSubsurface) return; // dummy node, nothing to do, it's the parent dying @@ -167,6 +182,8 @@ void CSubsurface::onNewSubsurface(wlr_subsurface* pSubsurface) { if (m_pWindowParent) PSUBSURFACE = m_vChildren.emplace_back(std::make_unique(pSubsurface, m_pWindowParent)).get(); + else if (m_pPopupParent) + PSUBSURFACE = m_vChildren.emplace_back(std::make_unique(pSubsurface, m_pPopupParent)).get(); PSUBSURFACE->m_pParent = this; ASSERT(PSUBSURFACE); @@ -220,6 +237,8 @@ Vector2D CSubsurface::coordsGlobal() { if (m_pWindowParent) coords += m_pWindowParent->m_vRealPosition.vec(); + else if (m_pPopupParent) + coords += m_pPopupParent->coordsGlobal(); return coords; } diff --git a/src/desktop/Subsurface.hpp b/src/desktop/Subsurface.hpp index 22692192..a8babd70 100644 --- a/src/desktop/Subsurface.hpp +++ b/src/desktop/Subsurface.hpp @@ -5,15 +5,17 @@ #include "WLSurface.hpp" class CWindow; -struct SXDGPopup; +class CPopup; class CSubsurface { public: // root dummy nodes CSubsurface(CWindow* pOwner); + CSubsurface(CPopup* pOwner); // real nodes CSubsurface(wlr_subsurface* pSubsurface, CWindow* pOwner); + CSubsurface(wlr_subsurface* pSubsurface, CPopup* pOwner); ~CSubsurface(); @@ -29,7 +31,6 @@ class CSubsurface { void recheckDamageForSubsurfaces(); private: - DYNLISTENER(destroySubsurface); DYNLISTENER(commitSubsurface); DYNLISTENER(newSubsurface); @@ -44,9 +45,12 @@ class CSubsurface { CSubsurface* m_pParent = nullptr; CWindow* m_pWindowParent = nullptr; + CPopup* m_pPopupParent = nullptr; std::vector> m_vChildren; + bool m_bInert = false; + void initSignals(); void initExistingSubsurfaces(); void checkSiblingDamage(); diff --git a/src/events/Events.hpp b/src/events/Events.hpp index 980142a0..69faf6c1 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -22,17 +22,6 @@ namespace Events { DYNLISTENFUNC(unmapLayerSurface); DYNLISTENFUNC(commitLayerSurface); - // Popups - DYNLISTENFUNC(newPopup); // LayerSurface - - DYNLISTENFUNC(newPopupXDG); - DYNLISTENFUNC(mapPopupXDG); - DYNLISTENFUNC(unmapPopupXDG); - DYNLISTENFUNC(destroyPopupXDG); - DYNLISTENFUNC(commitPopupXDG); - DYNLISTENFUNC(newPopupFromPopupXDG); - DYNLISTENFUNC(repositionPopupXDG); - // Surface XDG (window) LISTENER(newXDGToplevel); LISTENER(activateXDG); diff --git a/src/events/Layers.cpp b/src/events/Layers.cpp index 5e9de8b4..7dbcc7b1 100644 --- a/src/events/Layers.cpp +++ b/src/events/Layers.cpp @@ -46,7 +46,6 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) { layerSurface->hyprListener_destroyLayerSurface.initCallback(&WLRLAYERSURFACE->events.destroy, &Events::listener_destroyLayerSurface, layerSurface, "layerSurface"); layerSurface->hyprListener_mapLayerSurface.initCallback(&WLRLAYERSURFACE->surface->events.map, &Events::listener_mapLayerSurface, layerSurface, "layerSurface"); layerSurface->hyprListener_unmapLayerSurface.initCallback(&WLRLAYERSURFACE->surface->events.unmap, &Events::listener_unmapLayerSurface, layerSurface, "layerSurface"); - layerSurface->hyprListener_newPopup.initCallback(&WLRLAYERSURFACE->events.new_popup, &Events::listener_newPopup, layerSurface, "layerSurface"); layerSurface->layerSurface = WLRLAYERSURFACE; layerSurface->layer = WLRLAYERSURFACE->current.layer; @@ -87,7 +86,6 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) { layersurface->hyprListener_destroyLayerSurface.removeCallback(); layersurface->hyprListener_mapLayerSurface.removeCallback(); layersurface->hyprListener_unmapLayerSurface.removeCallback(); - layersurface->hyprListener_newPopup.removeCallback(); // rearrange to fix the reserved areas if (PMONITOR) { @@ -113,6 +111,8 @@ void Events::listener_mapLayerSurface(void* owner, void* data) { layersurface->keyboardExclusive = layersurface->layerSurface->current.keyboard_interactive; layersurface->surface = layersurface->layerSurface->surface; + layersurface->popupHead = std::make_unique(layersurface); + // fix if it changed its mon const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output); @@ -184,6 +184,8 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) { std::erase(g_pInputManager->m_dExclusiveLSes, layersurface); + layersurface->popupHead.reset(); + if (!g_pInputManager->m_dExclusiveLSes.empty()) g_pCompositor->focusSurface(g_pInputManager->m_dExclusiveLSes[0]->layerSurface->surface); diff --git a/src/events/Popups.cpp b/src/events/Popups.cpp deleted file mode 100644 index ca1787f5..00000000 --- a/src/events/Popups.cpp +++ /dev/null @@ -1,269 +0,0 @@ -#include "Events.hpp" - -#include "../Compositor.hpp" -#include "../helpers/WLClasses.hpp" -#include "../managers/input/InputManager.hpp" -#include "../render/Renderer.hpp" - -// --------------------------------------------- // -// _____ ____ _____ _ _ _____ _____ // -// | __ \ / __ \| __ \| | | | __ \ / ____| // -// | |__) | | | | |__) | | | | |__) | (___ // -// | ___/| | | | ___/| | | | ___/ \___ \ // -// | | | |__| | | | |__| | | ____) | // -// |_| \____/|_| \____/|_| |_____/ // -// // -// --------------------------------------------- // - -void addPopupGlobalCoords(void* pPopup, int* x, int* y) { - SXDGPopup* const PPOPUP = (SXDGPopup*)pPopup; - - auto curPopup = PPOPUP; - - int px = 0; - int py = 0; - - while (true) { - px += curPopup->popup->current.geometry.x; - py += curPopup->popup->current.geometry.y; - - if (curPopup == PPOPUP && PPOPUP->parentWindow) { - px -= curPopup->popup->base->current.geometry.x; - py -= curPopup->popup->base->current.geometry.y; - } - - if (curPopup->popup && !curPopup->parentPopup && !curPopup->parentWindow) { - const auto EXTENTSSURFACE = pixman_region32_extents(&curPopup->popup->base->surface->input_region); - px -= EXTENTSSURFACE->x1; - py -= EXTENTSSURFACE->y1; - } - - if (curPopup->parentPopup) { - curPopup = curPopup->parentPopup; - } else { - break; - } - } - - px += PPOPUP->lx; - py += PPOPUP->ly; - - *x += px; - *y += py; -} - -void createNewPopup(wlr_xdg_popup* popup, SXDGPopup* pHyprPopup) { - pHyprPopup->popup = popup; - - pHyprPopup->hyprListener_destroyPopupXDG.initCallback(&popup->events.destroy, &Events::listener_destroyPopupXDG, pHyprPopup, "HyprPopup"); - pHyprPopup->hyprListener_mapPopupXDG.initCallback(&popup->base->surface->events.map, &Events::listener_mapPopupXDG, pHyprPopup, "HyprPopup"); - pHyprPopup->hyprListener_unmapPopupXDG.initCallback(&popup->base->surface->events.unmap, &Events::listener_unmapPopupXDG, pHyprPopup, "HyprPopup"); - pHyprPopup->hyprListener_newPopupFromPopupXDG.initCallback(&popup->base->events.new_popup, &Events::listener_newPopupFromPopupXDG, pHyprPopup, "HyprPopup"); - pHyprPopup->hyprListener_commitPopupXDG.initCallback(&popup->base->surface->events.commit, &Events::listener_commitPopupXDG, pHyprPopup, "HyprPopup"); - pHyprPopup->hyprListener_repositionPopupXDG.initCallback(&popup->events.reposition, &Events::listener_repositionPopupXDG, pHyprPopup, "HyprPopup"); - - const auto PMONITOR = g_pCompositor->m_pLastMonitor; - - CBox box = {PMONITOR->vecPosition.x - pHyprPopup->lx, PMONITOR->vecPosition.y - pHyprPopup->ly, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; - - wlr_xdg_popup_unconstrain_from_box(popup, box.pWlr()); - - pHyprPopup->monitor = PMONITOR; - - Debug::log(LOG, "Popup: Unconstrained from lx ly: {:j5}, pHyprPopup lx ly: {:.5f} {:.5f}", PMONITOR->vecPosition, (float)pHyprPopup->lx, (float)pHyprPopup->ly); -} - -void Events::listener_newPopup(void* owner, void* data) { - SLayerSurface* layersurface = (SLayerSurface*)owner; - - ASSERT(layersurface); - - Debug::log(LOG, "New layer popup created from surface {:x}", (uintptr_t)layersurface); - - const auto WLRPOPUP = (wlr_xdg_popup*)data; - - const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique()).get(); - - const auto PMONITOR = g_pCompositor->getMonitorFromID(layersurface->monitorID); - - PNEWPOPUP->popup = WLRPOPUP; - PNEWPOPUP->lx = layersurface->position.x; - PNEWPOPUP->ly = layersurface->position.y; - PNEWPOPUP->monitor = PMONITOR; - PNEWPOPUP->parentLS = layersurface; - createNewPopup(WLRPOPUP, PNEWPOPUP); -} - -void Events::listener_newPopupXDG(void* owner, void* data) { - CWindow* PWINDOW = (CWindow*)owner; - - ASSERT(PWINDOW); - - if (!PWINDOW->m_bIsMapped) - return; - - Debug::log(LOG, "New layer popup created from XDG window {}", PWINDOW); - - const auto WLRPOPUP = (wlr_xdg_popup*)data; - - const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique()).get(); - - const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); - - PNEWPOPUP->popup = WLRPOPUP; - PNEWPOPUP->lx = PWINDOW->m_vRealPosition.goalv().x; - PNEWPOPUP->ly = PWINDOW->m_vRealPosition.goalv().y; - PNEWPOPUP->parentWindow = PWINDOW; - PNEWPOPUP->monitor = PMONITOR; - createNewPopup(WLRPOPUP, PNEWPOPUP); -} - -void Events::listener_newPopupFromPopupXDG(void* owner, void* data) { - SXDGPopup* PPOPUP = (SXDGPopup*)owner; - - ASSERT(PPOPUP); - - if (PPOPUP->parentWindow) - Debug::log(LOG, "New popup created from XDG Window popup {:x} -> {}", (uintptr_t)PPOPUP, PPOPUP->parentWindow); - else - Debug::log(LOG, "New popup created from Non-Window popup {:x}", (uintptr_t)PPOPUP); - - const auto WLRPOPUP = (wlr_xdg_popup*)data; - - const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique()).get(); - - PNEWPOPUP->popup = WLRPOPUP; - PNEWPOPUP->parentPopup = PPOPUP; - PNEWPOPUP->lx = PPOPUP->lx; - PNEWPOPUP->ly = PPOPUP->ly; - PNEWPOPUP->parentWindow = PPOPUP->parentWindow; - PNEWPOPUP->monitor = PPOPUP->monitor; - - createNewPopup(WLRPOPUP, PNEWPOPUP); -} - -void Events::listener_mapPopupXDG(void* owner, void* data) { - SXDGPopup* PPOPUP = (SXDGPopup*)owner; - - ASSERT(PPOPUP); - - Debug::log(LOG, "New XDG Popup mapped at {} {}", (int)PPOPUP->lx, (int)PPOPUP->ly); - - if (PPOPUP->parentWindow) - PPOPUP->parentWindow->m_lPopupSurfaces.emplace_back(PPOPUP->popup->base->surface); - else if (PPOPUP->parentLS) - PPOPUP->parentLS->popupSurfaces.emplace_back(PPOPUP->popup->base->surface); - - //PPOPUP->pSurfaceTree = SubsurfaceTree::createTreeRoot(PPOPUP->popup->base->surface, addPopupGlobalCoords, PPOPUP, PPOPUP->parentWindow); - - int lx = 0, ly = 0; - addPopupGlobalCoords(PPOPUP, &lx, &ly); - - CBox extents; - wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr()); - extents.applyFromWlr(); - - g_pHyprRenderer->damageBox(lx - extents.x, ly - extents.y, extents.width + 2, extents.height + 2); - - if (PPOPUP->monitor) { - g_pCompositor->setPreferredScaleForSurface(PPOPUP->popup->base->surface, PPOPUP->monitor->scale); - g_pCompositor->setPreferredTransformForSurface(PPOPUP->popup->base->surface, PPOPUP->monitor->transform); - } - - // Debug::log(LOG, "XDG Popup got assigned a surfaceTreeNode {:x}", (uintptr_t)PPOPUP->pSurfaceTree); -} - -void Events::listener_repositionPopupXDG(void* owner, void* data) { - SXDGPopup* PPOPUP = (SXDGPopup*)owner; - - Debug::log(LOG, "XDG Popup {:x} asks for a reposition", (uintptr_t)PPOPUP); - - int lx = 0, ly = 0; - addPopupGlobalCoords(PPOPUP, &lx, &ly); - - CBox extents; - wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr()); - extents.applyFromWlr(); - - PPOPUP->lastPos = {lx - extents.x, ly - extents.y}; - PPOPUP->repositionRequested = true; - - const auto PMONITOR = g_pCompositor->m_pLastMonitor; - - CBox box = {PMONITOR->vecPosition.x - lx + PPOPUP->popup->current.geometry.x, PMONITOR->vecPosition.y - ly + PPOPUP->popup->current.geometry.y, PMONITOR->vecSize.x, - PMONITOR->vecSize.y}; - wlr_xdg_popup_unconstrain_from_box(PPOPUP->popup, box.pWlr()); -} - -void Events::listener_unmapPopupXDG(void* owner, void* data) { - SXDGPopup* PPOPUP = (SXDGPopup*)owner; - Debug::log(LOG, "XDG Popup unmapped"); - - ASSERT(PPOPUP); - - if (PPOPUP->popup->base->surface == g_pCompositor->m_pLastFocus) - g_pInputManager->releaseAllMouseButtons(); - - // SubsurfaceTree::destroySurfaceTree(PPOPUP->pSurfaceTree); - - int lx = 0, ly = 0; - addPopupGlobalCoords(PPOPUP, &lx, &ly); - - CBox extents; - wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr()); - extents.applyFromWlr(); - - g_pHyprRenderer->damageBox(lx - extents.x, ly - extents.y, extents.width + 2, extents.height + 2); - - if (PPOPUP->parentWindow) - std::erase(PPOPUP->parentWindow->m_lPopupSurfaces, PPOPUP->popup->base->surface); - else if (PPOPUP->parentLS) - std::erase(PPOPUP->parentLS->popupSurfaces, PPOPUP->popup->base->surface); - - // PPOPUP->pSurfaceTree = nullptr; - - g_pInputManager->simulateMouseMovement(); // to focus and return back to an appropriate surface -} - -void Events::listener_commitPopupXDG(void* owner, void* data) { - SXDGPopup* PPOPUP = (SXDGPopup*)owner; - - if (PPOPUP->popup->base->initial_commit) { - wlr_xdg_surface_schedule_configure(PPOPUP->popup->base); - return; - } - - if (g_pCompositor->windowValidMapped(PPOPUP->parentWindow)) { - PPOPUP->lx = PPOPUP->parentWindow->m_vRealPosition.vec().x; - PPOPUP->ly = PPOPUP->parentWindow->m_vRealPosition.vec().y; - } - - int lx = 0, ly = 0; - addPopupGlobalCoords(PPOPUP, &lx, &ly); - - CBox extents; - wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr()); - extents.applyFromWlr(); - - if (PPOPUP->repositionRequested) - g_pHyprRenderer->damageBox(PPOPUP->lastPos.x, PPOPUP->lastPos.y, extents.width + 2, extents.height + 2); - - PPOPUP->repositionRequested = false; - - g_pHyprRenderer->damageSurface(PPOPUP->popup->base->surface, lx, ly); -} - -void Events::listener_destroyPopupXDG(void* owner, void* data) { - SXDGPopup* PPOPUP = (SXDGPopup*)owner; - - ASSERT(PPOPUP); - - Debug::log(LOG, "Destroyed popup XDG {:x}", (uintptr_t)PPOPUP); - - // if (PPOPUP->pSurfaceTree) { - // SubsurfaceTree::destroySurfaceTree(PPOPUP->pSurfaceTree); - // PPOPUP->pSurfaceTree = nullptr; - // } - - std::erase_if(g_pCompositor->m_vXDGPopups, [&](std::unique_ptr& el) { return el.get() == PPOPUP; }); -} diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 162415b4..34a34cbd 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -488,7 +488,6 @@ void Events::listener_mapWindow(void* owner, void* data) { if (!PWINDOW->m_bIsX11) { PWINDOW->hyprListener_setTitleWindow.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.set_title, &Events::listener_setTitleWindow, PWINDOW, "XDG Window Late"); - PWINDOW->hyprListener_newPopupXDG.initCallback(&PWINDOW->m_uSurface.xdg->events.new_popup, &Events::listener_newPopupXDG, PWINDOW, "XDG Window Late"); PWINDOW->hyprListener_requestMaximize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_maximize, &Events::listener_requestMaximize, PWINDOW, "XDG Window Late"); PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_minimize, &Events::listener_requestMinimize, PWINDOW, @@ -681,7 +680,6 @@ void Events::listener_unmapWindow(void* owner, void* data) { if (!PWINDOW->m_bIsX11) { Debug::log(LOG, "Unregistered late callbacks XDG"); PWINDOW->hyprListener_setTitleWindow.removeCallback(); - PWINDOW->hyprListener_newPopupXDG.removeCallback(); PWINDOW->hyprListener_requestMaximize.removeCallback(); PWINDOW->hyprListener_requestMinimize.removeCallback(); PWINDOW->hyprListener_requestMove.removeCallback(); @@ -833,7 +831,10 @@ void Events::listener_commitWindow(void* owner, void* data) { g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface.wlr(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y, PWINDOW->m_bIsX11 ? 1.0 / PWINDOW->m_fX11SurfaceScaledBy : 1.0); - PWINDOW->m_pSubsurfaceHead->recheckDamageForSubsurfaces(); + if (!PWINDOW->m_bIsX11) { + PWINDOW->m_pSubsurfaceHead->recheckDamageForSubsurfaces(); + PWINDOW->m_pPopupHead->recheckTree(); + } if (PWINDOW->m_bIsX11 || !PWINDOW->m_bIsFloating || PWINDOW->m_bIsFullscreen) return; diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index e536c3d2..624625af 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -5,6 +5,7 @@ #include "wlr-layer-shell-unstable-v1-protocol.h" #include "../Window.hpp" #include "../desktop/Subsurface.hpp" +#include "../desktop/Popup.hpp" #include "AnimatedVariable.hpp" #include "../desktop/WLSurface.hpp" #include "Region.hpp" @@ -31,13 +32,14 @@ struct SLayerSurface { bool keyboardExclusive = false; CWLSurface surface; - std::list popupSurfaces; + + // desktop components + std::unique_ptr popupHead; DYNLISTENER(destroyLayerSurface); DYNLISTENER(mapLayerSurface); DYNLISTENER(unmapLayerSurface); DYNLISTENER(commitLayerSurface); - DYNLISTENER(newPopup); CBox geometry = {0, 0, 0, 0}; Vector2D position; @@ -199,32 +201,6 @@ struct SConstraint { class CMonitor; -struct SXDGPopup { - CWindow* parentWindow = nullptr; - SLayerSurface* parentLS = nullptr; - SXDGPopup* parentPopup = nullptr; - wlr_xdg_popup* popup = nullptr; - CMonitor* monitor = nullptr; - - DYNLISTENER(newPopupFromPopupXDG); - DYNLISTENER(destroyPopupXDG); - DYNLISTENER(mapPopupXDG); - DYNLISTENER(unmapPopupXDG); - DYNLISTENER(commitPopupXDG); - DYNLISTENER(repositionPopupXDG); - - double lx; - double ly; - - Vector2D lastPos = {}; - bool repositionRequested = false; - - // For the list lookup - bool operator==(const SXDGPopup& rhs) const { - return popup == rhs.popup; - } -}; - struct SSeat { wlr_seat* seat = nullptr; wl_client* exclusiveClient = nullptr;