From d56e43354b515a885416a3c7f8a9945fcb3bd068 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Mon, 27 May 2024 00:08:35 +0200 Subject: [PATCH] wayland: move to new impl it's the final countdown --- CMakeLists.txt | 1 + protocols/meson.build | 1 + src/Compositor.cpp | 149 ++++++----- src/Compositor.hpp | 164 ++++++------ src/desktop/LayerSurface.cpp | 51 ++-- src/desktop/LayerSurface.hpp | 2 +- src/desktop/Popup.cpp | 39 ++- src/desktop/Popup.hpp | 2 +- src/desktop/Subsurface.cpp | 120 +++------ src/desktop/Subsurface.hpp | 25 +- src/desktop/WLSurface.cpp | 95 ++++--- src/desktop/WLSurface.hpp | 77 +++--- src/desktop/Window.cpp | 75 +++--- src/desktop/Window.hpp | 2 +- src/devices/Tablet.cpp | 26 +- src/devices/Tablet.hpp | 37 +-- src/events/Windows.cpp | 24 +- src/helpers/Monitor.cpp | 12 +- src/helpers/Monitor.hpp | 1 - src/helpers/WLClasses.hpp | 13 +- src/helpers/memory/SharedPtr.hpp | 2 +- src/helpers/memory/WeakPtr.hpp | 2 +- src/layout/IHyprLayout.cpp | 5 +- src/managers/CursorManager.cpp | 4 +- src/managers/CursorManager.hpp | 2 +- src/managers/KeybindManager.cpp | 24 +- src/managers/PointerManager.cpp | 76 +++--- src/managers/PointerManager.hpp | 18 +- src/managers/ProtocolManager.cpp | 24 +- src/managers/SeatManager.cpp | 50 ++-- src/managers/SeatManager.hpp | 41 ++- src/managers/SessionLockManager.cpp | 6 +- src/managers/SessionLockManager.hpp | 6 +- src/managers/XWaylandManager.cpp | 13 +- src/managers/XWaylandManager.hpp | 26 +- src/managers/input/IdleInhibitor.cpp | 4 +- src/managers/input/InputManager.cpp | 60 +++-- src/managers/input/InputManager.hpp | 24 +- src/managers/input/InputMethodPopup.cpp | 22 +- src/managers/input/InputMethodPopup.hpp | 16 +- src/managers/input/InputMethodRelay.cpp | 20 +- src/managers/input/InputMethodRelay.hpp | 10 +- src/managers/input/Tablets.cpp | 6 +- src/managers/input/TextInput.cpp | 71 +++-- src/managers/input/TextInput.hpp | 42 +-- src/managers/input/Touch.cpp | 2 +- src/protocols/AlphaModifier.cpp | 43 +-- src/protocols/AlphaModifier.hpp | 22 +- src/protocols/FocusGrab.cpp | 36 +-- src/protocols/FocusGrab.hpp | 26 +- src/protocols/FractionalScale.cpp | 55 ++-- src/protocols/FractionalScale.hpp | 36 ++- src/protocols/GammaControl.cpp | 11 +- src/protocols/IdleInhibit.cpp | 25 +- src/protocols/IdleInhibit.hpp | 16 +- src/protocols/InputMethodV2.cpp | 65 +++-- src/protocols/InputMethodV2.hpp | 16 +- src/protocols/LayerShell.cpp | 105 ++++---- src/protocols/LayerShell.hpp | 20 +- src/protocols/OutputPower.cpp | 7 +- src/protocols/PointerConstraints.cpp | 25 +- src/protocols/PointerConstraints.hpp | 22 +- src/protocols/PointerGestures.cpp | 7 +- src/protocols/PresentationTime.cpp | 14 +- src/protocols/PresentationTime.hpp | 16 +- src/protocols/Screencopy.cpp | 3 +- src/protocols/ServerDecorationKDE.cpp | 6 +- src/protocols/ServerDecorationKDE.hpp | 2 +- src/protocols/SessionLock.cpp | 89 +++---- src/protocols/SessionLock.hpp | 17 +- src/protocols/ShortcutsInhibit.cpp | 11 +- src/protocols/ShortcutsInhibit.hpp | 8 +- src/protocols/Tablet.cpp | 17 +- src/protocols/Tablet.hpp | 22 +- src/protocols/TearingControl.cpp | 12 +- src/protocols/TearingControl.hpp | 4 +- src/protocols/TextInputV1.cpp | 3 +- src/protocols/TextInputV3.cpp | 9 +- src/protocols/TextInputV3.hpp | 4 +- src/protocols/Viewporter.cpp | 117 ++++++++ src/protocols/Viewporter.hpp | 54 ++++ src/protocols/WaylandProtocol.hpp | 2 +- src/protocols/XDGActivation.cpp | 5 +- src/protocols/XDGOutput.cpp | 5 +- src/protocols/XDGShell.cpp | 108 ++++---- src/protocols/XDGShell.hpp | 10 +- src/protocols/XWaylandShell.cpp | 5 +- src/protocols/XWaylandShell.hpp | 8 +- src/protocols/core/Compositor.cpp | 338 ++++++++++++++++++++++++ src/protocols/core/Compositor.hpp | 167 ++++++++++++ src/protocols/core/DataDevice.cpp | 63 ++--- src/protocols/core/DataDevice.hpp | 12 +- src/protocols/core/Output.cpp | 88 ++++++ src/protocols/core/Output.hpp | 50 ++++ src/protocols/core/Seat.cpp | 52 ++-- src/protocols/core/Seat.hpp | 30 ++- src/protocols/core/Shm.cpp | 209 +++++++++++++++ src/protocols/core/Shm.hpp | 107 ++++++++ src/protocols/core/Subcompositor.cpp | 157 +++++++++++ src/protocols/core/Subcompositor.hpp | 79 ++++++ src/protocols/types/Buffer.cpp | 37 +++ src/protocols/types/Buffer.hpp | 70 +++++ src/protocols/types/SurfaceRole.hpp | 14 + src/protocols/types/WLBuffer.cpp | 29 ++ src/protocols/types/WLBuffer.hpp | 34 +++ src/render/OpenGL.cpp | 43 ++- src/render/OpenGL.hpp | 98 ++++--- src/render/Renderer.cpp | 219 ++++++++------- src/render/Renderer.hpp | 14 +- src/render/Texture.cpp | 48 ++++ src/render/Texture.hpp | 2 + src/xwayland/XSurface.cpp | 66 +++-- src/xwayland/XSurface.hpp | 7 +- src/xwayland/XWM.cpp | 21 +- src/xwayland/XWM.hpp | 7 +- 115 files changed, 3085 insertions(+), 1556 deletions(-) create mode 100644 src/protocols/Viewporter.cpp create mode 100644 src/protocols/Viewporter.hpp create mode 100644 src/protocols/core/Compositor.cpp create mode 100644 src/protocols/core/Compositor.hpp create mode 100644 src/protocols/core/Output.cpp create mode 100644 src/protocols/core/Output.hpp create mode 100644 src/protocols/core/Shm.cpp create mode 100644 src/protocols/core/Shm.hpp create mode 100644 src/protocols/core/Subcompositor.cpp create mode 100644 src/protocols/core/Subcompositor.hpp create mode 100644 src/protocols/types/Buffer.cpp create mode 100644 src/protocols/types/Buffer.hpp create mode 100644 src/protocols/types/SurfaceRole.hpp create mode 100644 src/protocols/types/WLBuffer.cpp create mode 100644 src/protocols/types/WLBuffer.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e780ac0990d..0f82936f4317 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -316,6 +316,7 @@ protocolNew("stable/presentation-time" "presentation-time" false) protocolNew("stable/xdg-shell" "xdg-shell" false) protocolNew("unstable/primary-selection" "primary-selection-unstable-v1" false) protocolNew("staging/xwayland-shell" "xwayland-shell-v1" false) +protocolNew("stable/viewporter" "viewporter" false) protocolWayland() diff --git a/protocols/meson.build b/protocols/meson.build index f491bb09632b..6f8502a622a1 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -64,6 +64,7 @@ new_protocols = [ [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], [wl_protocol_dir, 'unstable/primary-selection/primary-selection-unstable-v1.xml'], [wl_protocol_dir, 'staging/xwayland-shell/xwayland-shell-v1.xml'], + [wl_protocol_dir, 'stable/viewporter/viewporter.xml], ] wl_protos_src = [] diff --git a/src/Compositor.cpp b/src/Compositor.cpp index a14e91fda27e..4b12851a2537 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -19,6 +19,8 @@ #include "protocols/PointerConstraints.hpp" #include "protocols/LayerShell.hpp" #include "protocols/XDGShell.hpp" +#include "protocols/core/Compositor.hpp" +#include "protocols/core/Subcompositor.hpp" #include "desktop/LayerSurface.hpp" #include "xwayland/XWayland.hpp" @@ -184,7 +186,7 @@ void CCompositor::initServer() { &isHeadlessOnly); if (isHeadlessOnly) { - m_sWLRRenderer = wlr_renderer_autocreate(m_sWLRBackend); + m_sWLRRenderer = wlr_renderer_autocreate(m_sWLRBackend); // TODO: remove this, it's barely needed now. } else { m_iDRMFD = wlr_backend_get_drm_fd(m_sWLRBackend); if (m_iDRMFD < 0) { @@ -200,13 +202,13 @@ void CCompositor::initServer() { throwError("wlr_gles2_renderer_create_with_drm_fd() failed!"); } - wlr_renderer_init_wl_shm(m_sWLRRenderer, m_sWLDisplay); + //wlr_renderer_init_wl_shm(m_sWLRRenderer, m_sWLDisplay); if (wlr_renderer_get_dmabuf_texture_formats(m_sWLRRenderer)) { - if (wlr_renderer_get_drm_fd(m_sWLRRenderer) >= 0) - wlr_drm_create(m_sWLDisplay, m_sWLRRenderer); + // if (wlr_renderer_get_drm_fd(m_sWLRRenderer) >= 0) + // wlr_drm_create(m_sWLDisplay, m_sWLRRenderer); - m_sWLRLinuxDMABuf = wlr_linux_dmabuf_v1_create_with_renderer(m_sWLDisplay, 4, m_sWLRRenderer); + // m_sWLRLinuxDMABuf = wlr_linux_dmabuf_v1_create_with_renderer(m_sWLDisplay, 4, m_sWLRRenderer); } m_sWLRAllocator = wlr_allocator_autocreate(m_sWLRBackend, m_sWLRRenderer); @@ -223,13 +225,13 @@ void CCompositor::initServer() { throwError("wlr_gles2_renderer_get_egl() failed!"); } - m_sWLRCompositor = wlr_compositor_create(m_sWLDisplay, 6, m_sWLRRenderer); - m_sWLRSubCompositor = wlr_subcompositor_create(m_sWLDisplay); + // m_sWLRCompositor = wlr_compositor_create(m_sWLDisplay, 6, m_sWLRRenderer); + //m_sWLRSubCompositor = wlr_subcompositor_create(m_sWLDisplay); // m_sWLRDataDevMgr = wlr_data_device_manager_create(m_sWLDisplay); // wlr_data_control_manager_v1_create(m_sWLDisplay); // wlr_primary_selection_v1_device_manager_create(m_sWLDisplay); - wlr_viewporter_create(m_sWLDisplay); + //wlr_viewporter_create(m_sWLDisplay); m_sWRLDRMLeaseMgr = wlr_drm_lease_v1_manager_create(m_sWLDisplay, m_sWLRBackend); if (!m_sWRLDRMLeaseMgr) { @@ -244,7 +246,7 @@ void CCompositor::initServer() { throwError("wlr_headless_backend_create() failed!"); } - wlr_single_pixel_buffer_manager_v1_create(m_sWLDisplay); + // wlr_single_pixel_buffer_manager_v1_create(m_sWLDisplay); wlr_multi_backend_add(m_sWLRBackend, m_sWLRHeadlessBackend); @@ -320,7 +322,7 @@ void CCompositor::cleanup() { // still in a normal working state. g_pPluginSystem->unloadAllPlugins(); - m_pLastFocus = nullptr; + m_pLastFocus.reset(); m_pLastWindow.reset(); m_vWorkspaces.clear(); @@ -786,7 +788,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper return windowForWorkspace(false); } -wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, PHLWINDOW pWindow, Vector2D& sl) { +SP CCompositor::vectorWindowToSurface(const Vector2D& pos, PHLWINDOW pWindow, Vector2D& sl) { if (!validMapped(pWindow)) return nullptr; @@ -798,14 +800,23 @@ wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, PHLWINDOW p CBox geom = pWindow->m_pXDGSurface->current.geometry; // try popups first - const auto PPOPUP = pWindow->m_pPopupHead->at(pos); - - wlr_surface* found = PPOPUP ? PPOPUP->m_sWLSurface.wlr() : nullptr; - - if (!PPOPUP) - found = wlr_surface_surface_at(pWindow->m_pWLSurface.wlr(), pos.x - pWindow->m_vRealPosition.value().x + geom.x, pos.y - pWindow->m_vRealPosition.value().y + geom.y, &subx, - &suby); - else { + const auto PPOPUP = pWindow->m_pPopupHead->at(pos); + + SP found = PPOPUP ? PPOPUP->m_pWLSurface->resource() : nullptr; + + if (!PPOPUP) { + found = pWindow->m_pWLSurface->resource()->at(pos, true); + if (found) { + if (found->role->role() != SURFACE_ROLE_SUBSURFACE) + found.reset(); + else { + auto subsurface = (CWLSubsurfaceResource*)found->role.get(); + const auto OFF = subsurface->posRelativeToParent(); + subx = pos.x - OFF.x + geom.x - pWindow->m_vRealPosition.goal().x; + suby = pos.y - OFF.y + geom.y - pWindow->m_vRealPosition.goal().y; + } + } + } else { const auto OFF = PPOPUP->coordsRelativeToParent(); subx = pos.x - OFF.x + geom.x - pWindow->m_vRealPosition.goal().x; suby = pos.y - OFF.y + geom.y - pWindow->m_vRealPosition.goal().y; @@ -823,10 +834,10 @@ wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, PHLWINDOW p sl.x += geom.x; sl.y += geom.y; - return pWindow->m_pWLSurface.wlr(); + return pWindow->m_pWLSurface->resource(); } -Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindow, wlr_surface* pSurface) { +Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindow, SP pSurface) { if (!validMapped(pWindow)) return {}; @@ -837,25 +848,28 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindo if (PPOPUP) return vec - PPOPUP->coordsGlobal(); - std::tuple iterData = {pSurface, -1337, -1337}; + std::tuple, Vector2D> iterData = {pSurface, {-1337, -1337}}; - wlr_surface_for_each_surface( - pWindow->m_pWLSurface.wlr(), - [](wlr_surface* surf, int x, int y, void* data) { - const auto PDATA = (std::tuple*)data; + pWindow->m_pWLSurface->resource()->breadthfirst( + [](SP surf, void* data) { + const auto PDATA = (std::tuple, Vector2D>*)data; if (surf == std::get<0>(*PDATA)) { - std::get<1>(*PDATA) = x; - std::get<2>(*PDATA) = y; + if (surf->role->role() != SURFACE_ROLE_SUBSURFACE) + std::get<1>(*PDATA) = Vector2D{0, 0}; + else { + auto subsurface = (CWLSubsurfaceResource*)surf->role.get(); + std::get<1>(*PDATA) = subsurface->posRelativeToParent(); + } } }, &iterData); CBox geom = pWindow->m_pXDGSurface->current.geometry; - if (std::get<1>(iterData) == -1337 && std::get<2>(iterData) == -1337) + if (std::get<1>(iterData) == Vector2D{-1337, -1337}) return vec - pWindow->m_vRealPosition.goal(); - return vec - pWindow->m_vRealPosition.goal() - Vector2D{std::get<1>(iterData), std::get<2>(iterData)} + Vector2D{geom.x, geom.y}; + return vec - pWindow->m_vRealPosition.goal() - std::get<1>(iterData) + Vector2D{geom.x, geom.y}; } CMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) { @@ -878,7 +892,7 @@ CMonitor* CCompositor::getRealMonitorFromOutput(wlr_output* out) { return nullptr; } -void CCompositor::focusWindow(PHLWINDOW pWindow, wlr_surface* pSurface) { +void CCompositor::focusWindow(PHLWINDOW pWindow, SP pSurface) { static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); static auto PSPECIALFALLTHROUGH = CConfigValue("input:special_fallthrough"); @@ -921,7 +935,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, wlr_surface* pSurface) { g_pLayoutManager->getCurrentLayout()->onWindowFocusChange(nullptr); - m_pLastFocus = nullptr; + m_pLastFocus.reset(); g_pInputManager->recheckIdleInhibitorStatus(); return; @@ -973,7 +987,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, wlr_surface* pSurface) { m_pLastWindow = PLASTWINDOW; - const auto PWINDOWSURFACE = pSurface ? pSurface : pWindow->m_pWLSurface.wlr(); + const auto PWINDOWSURFACE = pSurface ? pSurface : pWindow->m_pWLSurface->resource(); focusSurface(PWINDOWSURFACE, pWindow); @@ -1008,9 +1022,9 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, wlr_surface* pSurface) { g_pInputManager->sendMotionEventsToFocused(); } -void CCompositor::focusSurface(wlr_surface* pSurface, PHLWINDOW pWindowOwner) { +void CCompositor::focusSurface(SP pSurface, PHLWINDOW pWindowOwner) { - if (g_pSeatManager->state.keyboardFocus == pSurface || (pWindowOwner && g_pSeatManager->state.keyboardFocus == pWindowOwner->m_pWLSurface.wlr())) + if (g_pSeatManager->state.keyboardFocus == pSurface || (pWindowOwner && g_pSeatManager->state.keyboardFocus == pWindowOwner->m_pWLSurface->resource())) return; // Don't focus when already focused on this. if (g_pSessionLockManager->isSessionLocked() && !g_pSessionLockManager->isSurfaceSessionLock(pSurface)) @@ -1021,18 +1035,18 @@ void CCompositor::focusSurface(wlr_surface* pSurface, PHLWINDOW pWindowOwner) { return; } - const auto PLASTSURF = m_pLastFocus; + const auto PLASTSURF = m_pLastFocus.lock(); // Unfocus last surface if should if (m_pLastFocus && !pWindowOwner) - g_pXWaylandManager->activateSurface(m_pLastFocus, false); + g_pXWaylandManager->activateSurface(m_pLastFocus.lock(), false); if (!pSurface) { g_pSeatManager->setKeyboardFocus(nullptr); g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","}); // unfocused g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", ""}); - EMIT_HOOK_EVENT("keyboardFocus", (wlr_surface*)nullptr); - m_pLastFocus = nullptr; + EMIT_HOOK_EVENT("keyboardFocus", (SP)nullptr); + m_pLastFocus.reset(); return; } @@ -1049,8 +1063,8 @@ void CCompositor::focusSurface(wlr_surface* pSurface, PHLWINDOW pWindowOwner) { EMIT_HOOK_EVENT("keyboardFocus", pSurface); - const auto SURF = CWLSurface::surfaceFromWlr(pSurface); - const auto OLDSURF = CWLSurface::surfaceFromWlr(PLASTSURF); + const auto SURF = CWLSurface::fromResource(pSurface); + const auto OLDSURF = CWLSurface::fromResource(PLASTSURF); if (OLDSURF && OLDSURF->constraint()) OLDSURF->constraint()->deactivate(); @@ -1059,7 +1073,7 @@ void CCompositor::focusSurface(wlr_surface* pSurface, PHLWINDOW pWindowOwner) { SURF->constraint()->activate(); } -wlr_surface* CCompositor::vectorToLayerPopupSurface(const Vector2D& pos, CMonitor* monitor, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) { +SP CCompositor::vectorToLayerPopupSurface(const Vector2D& pos, CMonitor* monitor, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) { for (auto& lsl : monitor->m_aLayerSurfaceLayers | std::views::reverse) { for (auto& ls : lsl | std::views::reverse) { if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->mapped) || ls->alpha.value() == 0.f) @@ -1070,7 +1084,7 @@ wlr_surface* CCompositor::vectorToLayerPopupSurface(const Vector2D& pos, CMonito if (SURFACEAT) { *ppLayerSurfaceFound = ls.lock(); *sCoords = pos - SURFACEAT->coordsGlobal(); - return SURFACEAT->m_sWLSurface.wlr(); + return SURFACEAT->m_pWLSurface->resource(); } } } @@ -1078,15 +1092,15 @@ wlr_surface* CCompositor::vectorToLayerPopupSurface(const Vector2D& pos, CMonito return nullptr; } -wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector* layerSurfaces, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) { +SP CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector* layerSurfaces, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) { for (auto& ls : *layerSurfaces | std::views::reverse) { if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha.value() == 0.f) continue; - auto SURFACEAT = wlr_surface_surface_at(ls->layerSurface->surface, pos.x - ls->geometry.x, pos.y - ls->geometry.y, &sCoords->x, &sCoords->y); + auto SURFACEAT = ls->layerSurface->surface->at(pos); if (SURFACEAT) { - if (!pixman_region32_not_empty(&SURFACEAT->input_region)) + if (SURFACEAT->current.input.empty()) continue; *ppLayerSurfaceFound = ls.lock(); @@ -1097,12 +1111,12 @@ wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector< return nullptr; } -PHLWINDOW CCompositor::getWindowFromSurface(wlr_surface* pSurface) { +PHLWINDOW CCompositor::getWindowFromSurface(SP pSurface) { for (auto& w : m_vWindows) { if (!w->m_bIsMapped || w->m_bFadingOut) continue; - if (w->m_pWLSurface.wlr() == pSurface) + if (w->m_pWLSurface->resource() == pSurface) return w; } @@ -1241,7 +1255,7 @@ bool CCompositor::isWindowActive(PHLWINDOW pWindow) { if (!pWindow->m_bIsMapped) return false; - const auto PSURFACE = pWindow->m_pWLSurface.wlr(); + const auto PSURFACE = pWindow->m_pWLSurface->resource(); return PSURFACE == m_pLastFocus || pWindow == m_pLastWindow.lock(); } @@ -1643,11 +1657,6 @@ bool CCompositor::isPointOnReservedArea(const Vector2D& point, const CMonitor* p return !VECINRECT(point, XY1.x, XY1.y, XY2.x, XY2.y); } -void checkFocusSurfaceIter(wlr_surface* pSurface, int x, int y, void* data) { - auto pair = (std::pair*)data; - pair->second = pair->second || pSurface == pair->first; -} - CMonitor* CCompositor::getMonitorInDirection(const char& dir) { return this->getMonitorInDirection(m_pLastMonitor.get(), dir); } @@ -2382,24 +2391,24 @@ void CCompositor::closeWindow(PHLWINDOW pWindow) { } } -PHLLS CCompositor::getLayerSurfaceFromSurface(wlr_surface* pSurface) { - std::pair result = {pSurface, false}; +PHLLS CCompositor::getLayerSurfaceFromSurface(SP pSurface) { + std::pair, bool> result = {pSurface, false}; for (auto& ls : m_vLayers) { if (ls->layerSurface && ls->layerSurface->surface == pSurface) return ls; - static auto iter = [](wlr_surface* surf, int x, int y, void* data) -> void { - if (surf == ((std::pair*)data)->first) { - *(bool*)data = true; - return; - } - }; - if (!ls->layerSurface || !ls->mapped) continue; - wlr_surface_for_each_surface(ls->layerSurface->surface, iter, &result); + ls->layerSurface->surface->breadthfirst( + [](SP surf, void* data) { + if (surf == ((std::pair, bool>*)data)->first) { + *(bool*)data = true; + return; + } + }, + &result); if (result.second) return ls; @@ -2731,11 +2740,11 @@ void CCompositor::leaveUnsafeState() { } } -void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scale) { +void CCompositor::setPreferredScaleForSurface(SP pSurface, double scale) { PROTO::fractional->sendScale(pSurface, scale); - wlr_surface_set_preferred_buffer_scale(pSurface, static_cast(std::ceil(scale))); + pSurface->sendPreferredScale(std::ceil(scale)); - const auto PSURFACE = CWLSurface::surfaceFromWlr(pSurface); + const auto PSURFACE = CWLSurface::fromResource(pSurface); if (!PSURFACE) { Debug::log(WARN, "Orphaned wlr_surface {:x} in setPreferredScaleForSurface", (uintptr_t)pSurface); return; @@ -2745,10 +2754,10 @@ void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scal PSURFACE->m_iLastScale = static_cast(std::ceil(scale)); } -void CCompositor::setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform) { - wlr_surface_set_preferred_buffer_transform(pSurface, transform); +void CCompositor::setPreferredTransformForSurface(SP pSurface, wl_output_transform transform) { + pSurface->sendPreferredTransform(transform); - const auto PSURFACE = CWLSurface::surfaceFromWlr(pSurface); + const auto PSURFACE = CWLSurface::fromResource(pSurface); if (!PSURFACE) { Debug::log(WARN, "Orphaned wlr_surface {:x} in setPreferredTransformForSurface", (uintptr_t)pSurface); return; diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 94d9e4d0719c..8dfd2cd9a442 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -29,6 +29,8 @@ #include "plugins/PluginSystem.hpp" #include "helpers/Watchdog.hpp" +class CWLSurfaceResource; + enum eManagersInitStage { STAGE_PRIORITY = 0, STAGE_LATE @@ -79,7 +81,7 @@ class CCompositor { void createLockFile(); void removeLockFile(); - wlr_surface* m_pLastFocus = nullptr; + WP m_pLastFocus; PHLWINDOWREF m_pLastWindow; WP m_pLastMonitor; @@ -96,86 +98,86 @@ class CCompositor { // ------------------------------------------------- // - CMonitor* getMonitorFromID(const int&); - CMonitor* getMonitorFromName(const std::string&); - CMonitor* getMonitorFromDesc(const std::string&); - CMonitor* getMonitorFromCursor(); - CMonitor* getMonitorFromVector(const Vector2D&); - void removeWindowFromVectorSafe(PHLWINDOW); - void focusWindow(PHLWINDOW, wlr_surface* pSurface = nullptr); - void focusSurface(wlr_surface*, PHLWINDOW pWindowOwner = nullptr); - bool monitorExists(CMonitor*); - PHLWINDOW vectorToWindowUnified(const Vector2D&, uint8_t properties, PHLWINDOW pIgnoreWindow = nullptr); - wlr_surface* vectorToLayerSurface(const Vector2D&, std::vector*, Vector2D*, PHLLS*); - wlr_surface* vectorToLayerPopupSurface(const Vector2D&, CMonitor* monitor, Vector2D*, PHLLS*); - wlr_surface* vectorWindowToSurface(const Vector2D&, PHLWINDOW, Vector2D& sl); - Vector2D vectorToSurfaceLocal(const Vector2D&, PHLWINDOW, wlr_surface*); - CMonitor* getMonitorFromOutput(wlr_output*); - CMonitor* getRealMonitorFromOutput(wlr_output*); - PHLWINDOW getWindowFromSurface(wlr_surface*); - PHLWINDOW getWindowFromHandle(uint32_t); - bool isWorkspaceVisible(PHLWORKSPACE); - PHLWORKSPACE getWorkspaceByID(const int&); - PHLWORKSPACE getWorkspaceByName(const std::string&); - PHLWORKSPACE getWorkspaceByString(const std::string&); - void sanityCheckWorkspaces(); - void updateWorkspaceWindowDecos(const int&); - void updateWorkspaceSpecialRenderData(const int&); - int getWindowsOnWorkspace(const int& id, std::optional onlyTiled = {}, std::optional onlyVisible = {}); - int getGroupsOnWorkspace(const int& id, std::optional onlyTiled = {}, std::optional onlyVisible = {}); - PHLWINDOW getUrgentWindow(); - bool hasUrgentWindowOnWorkspace(const int&); - PHLWINDOW getFirstWindowOnWorkspace(const int&); - PHLWINDOW getTopLeftWindowOnWorkspace(const int&); - PHLWINDOW getFullscreenWindowOnWorkspace(const int&); - bool isWindowActive(PHLWINDOW); - void changeWindowZOrder(PHLWINDOW, bool); - void cleanupFadingOut(const int& monid); - PHLWINDOW getWindowInDirection(PHLWINDOW, char); - PHLWINDOW getNextWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional floating = {}); - PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional floating = {}); - int getNextAvailableNamedWorkspace(); - bool isPointOnAnyMonitor(const Vector2D&); - bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr); - CMonitor* getMonitorInDirection(const char&); - CMonitor* getMonitorInDirection(CMonitor*, const char&); - void updateAllWindowsAnimatedDecorationValues(); - void updateWorkspaceWindows(const int64_t& id); - void updateWindowAnimatedDecorationValues(PHLWINDOW); - int getNextAvailableMonitorID(std::string const& name); - void moveWorkspaceToMonitor(PHLWORKSPACE, CMonitor*, bool noWarpCursor = false); - void swapActiveWorkspaces(CMonitor*, CMonitor*); - CMonitor* getMonitorFromString(const std::string&); - bool workspaceIDOutOfBounds(const int64_t&); - void setWindowFullscreen(PHLWINDOW, bool, eFullscreenMode mode = FULLSCREEN_INVALID); - void updateFullscreenFadeOnWorkspace(PHLWORKSPACE); - PHLWINDOW getX11Parent(PHLWINDOW); - void scheduleFrameForMonitor(CMonitor*); - void addToFadingOutSafe(PHLLS); - void addToFadingOutSafe(PHLWINDOW); - PHLWINDOW getWindowByRegex(const std::string&); - void warpCursorTo(const Vector2D&, bool force = false); - PHLLS getLayerSurfaceFromSurface(wlr_surface*); - void closeWindow(PHLWINDOW); - Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&); - void forceReportSizesToWindowsOnWorkspace(const int&); - PHLWORKSPACE createNewWorkspace(const int&, const int&, const std::string& name = "", bool isEmtpy = true); // will be deleted next frame if left empty and unfocused! - void renameWorkspace(const int&, const std::string& name = ""); - void setActiveMonitor(CMonitor*); - bool isWorkspaceSpecial(const int&); - int getNewSpecialID(); - void performUserChecks(); - void moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWorkspace); - PHLWINDOW getForceFocus(); - void arrangeMonitors(); - void enterUnsafeState(); - void leaveUnsafeState(); - void setPreferredScaleForSurface(wlr_surface* pSurface, double scale); - void setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform); - void updateSuspendedStates(); - PHLWINDOW windowForCPointer(CWindow*); - - std::string explicitConfigPath; + CMonitor* getMonitorFromID(const int&); + CMonitor* getMonitorFromName(const std::string&); + CMonitor* getMonitorFromDesc(const std::string&); + CMonitor* getMonitorFromCursor(); + CMonitor* getMonitorFromVector(const Vector2D&); + void removeWindowFromVectorSafe(PHLWINDOW); + void focusWindow(PHLWINDOW, SP pSurface = nullptr); + void focusSurface(SP, PHLWINDOW pWindowOwner = nullptr); + bool monitorExists(CMonitor*); + PHLWINDOW vectorToWindowUnified(const Vector2D&, uint8_t properties, PHLWINDOW pIgnoreWindow = nullptr); + SP vectorToLayerSurface(const Vector2D&, std::vector*, Vector2D*, PHLLS*); + SP vectorToLayerPopupSurface(const Vector2D&, CMonitor* monitor, Vector2D*, PHLLS*); + SP vectorWindowToSurface(const Vector2D&, PHLWINDOW, Vector2D& sl); + Vector2D vectorToSurfaceLocal(const Vector2D&, PHLWINDOW, SP); + CMonitor* getMonitorFromOutput(wlr_output*); + CMonitor* getRealMonitorFromOutput(wlr_output*); + PHLWINDOW getWindowFromSurface(SP); + PHLWINDOW getWindowFromHandle(uint32_t); + bool isWorkspaceVisible(PHLWORKSPACE); + PHLWORKSPACE getWorkspaceByID(const int&); + PHLWORKSPACE getWorkspaceByName(const std::string&); + PHLWORKSPACE getWorkspaceByString(const std::string&); + void sanityCheckWorkspaces(); + void updateWorkspaceWindowDecos(const int&); + void updateWorkspaceSpecialRenderData(const int&); + int getWindowsOnWorkspace(const int& id, std::optional onlyTiled = {}, std::optional onlyVisible = {}); + int getGroupsOnWorkspace(const int& id, std::optional onlyTiled = {}, std::optional onlyVisible = {}); + PHLWINDOW getUrgentWindow(); + bool hasUrgentWindowOnWorkspace(const int&); + PHLWINDOW getFirstWindowOnWorkspace(const int&); + PHLWINDOW getTopLeftWindowOnWorkspace(const int&); + PHLWINDOW getFullscreenWindowOnWorkspace(const int&); + bool isWindowActive(PHLWINDOW); + void changeWindowZOrder(PHLWINDOW, bool); + void cleanupFadingOut(const int& monid); + PHLWINDOW getWindowInDirection(PHLWINDOW, char); + PHLWINDOW getNextWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional floating = {}); + PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional floating = {}); + int getNextAvailableNamedWorkspace(); + bool isPointOnAnyMonitor(const Vector2D&); + bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr); + CMonitor* getMonitorInDirection(const char&); + CMonitor* getMonitorInDirection(CMonitor*, const char&); + void updateAllWindowsAnimatedDecorationValues(); + void updateWorkspaceWindows(const int64_t& id); + void updateWindowAnimatedDecorationValues(PHLWINDOW); + int getNextAvailableMonitorID(std::string const& name); + void moveWorkspaceToMonitor(PHLWORKSPACE, CMonitor*, bool noWarpCursor = false); + void swapActiveWorkspaces(CMonitor*, CMonitor*); + CMonitor* getMonitorFromString(const std::string&); + bool workspaceIDOutOfBounds(const int64_t&); + void setWindowFullscreen(PHLWINDOW, bool, eFullscreenMode mode = FULLSCREEN_INVALID); + void updateFullscreenFadeOnWorkspace(PHLWORKSPACE); + PHLWINDOW getX11Parent(PHLWINDOW); + void scheduleFrameForMonitor(CMonitor*); + void addToFadingOutSafe(PHLLS); + void addToFadingOutSafe(PHLWINDOW); + PHLWINDOW getWindowByRegex(const std::string&); + void warpCursorTo(const Vector2D&, bool force = false); + PHLLS getLayerSurfaceFromSurface(SP); + void closeWindow(PHLWINDOW); + Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&); + void forceReportSizesToWindowsOnWorkspace(const int&); + PHLWORKSPACE createNewWorkspace(const int&, const int&, const std::string& name = "", bool isEmtpy = true); // will be deleted next frame if left empty and unfocused! + void renameWorkspace(const int&, const std::string& name = ""); + void setActiveMonitor(CMonitor*); + bool isWorkspaceSpecial(const int&); + int getNewSpecialID(); + void performUserChecks(); + void moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWorkspace); + PHLWINDOW getForceFocus(); + void arrangeMonitors(); + void enterUnsafeState(); + void leaveUnsafeState(); + void setPreferredScaleForSurface(SP pSurface, double scale); + void setPreferredTransformForSurface(SP pSurface, wl_output_transform transform); + void updateSuspendedStates(); + PHLWINDOW windowForCPointer(CWindow*); + + std::string explicitConfigPath; private: void initAllSignals(); diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 759eb09f5399..128fad57c3e8 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -2,6 +2,7 @@ #include "../Compositor.hpp" #include "../events/Events.hpp" #include "../protocols/LayerShell.hpp" +#include "../protocols/core/Compositor.hpp" #include "../managers/SeatManager.hpp" PHLLS CLayerSurface::create(SP resource) { @@ -39,7 +40,7 @@ PHLLS CLayerSurface::create(SP resource) { pLS->alpha.setValueAndWarp(0.f); - pLS->surface.assign(resource->surface, pLS); + pLS->surface->assign(resource->surface.lock(), pLS); Debug::log(LOG, "LayerSurface {:x} (namespace {} layer {}) created on monitor {}", (uintptr_t)resource.get(), resource->layerNamespace, (int)pLS->layer, pMonitor->szName); @@ -58,13 +59,15 @@ CLayerSurface::CLayerSurface(SP resource_) : layerSurface(r listeners.map = layerSurface->events.map.registerListener([this](std::any d) { onMap(); }); listeners.unmap = layerSurface->events.unmap.registerListener([this](std::any d) { onUnmap(); }); listeners.destroy = layerSurface->events.destroy.registerListener([this](std::any d) { onDestroy(); }); + + surface = CWLSurface::create(); } CLayerSurface::~CLayerSurface() { if (!g_pHyprOpenGL) return; - surface.unassign(); + surface->unassign(); g_pHyprRenderer->makeEGLCurrent(); std::erase_if(g_pHyprOpenGL->m_mLayerFramebuffers, [&](const auto& other) { return other.first.expired() || other.first.lock() == self.lock(); }); } @@ -105,7 +108,7 @@ void CLayerSurface::onDestroy() { readyToDelete = true; layerSurface.reset(); - surface.unassign(); + surface->unassign(); } void CLayerSurface::onMap() { @@ -126,7 +129,7 @@ void CLayerSurface::onMap() { g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID); - wlr_surface_send_enter(surface.wlr(), PMONITOR->output); + surface->resource()->enter(PMONITOR->self.lock()); if (layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) g_pInputManager->m_dExclusiveLSes.push_back(self); @@ -139,10 +142,10 @@ void CLayerSurface::onMap() { // TODO: use the new superb really very cool grab g_pSeatManager->setGrab(nullptr); g_pInputManager->releaseAllMouseButtons(); - g_pCompositor->focusSurface(surface.wlr()); + g_pCompositor->focusSurface(surface->resource()); const auto LOCAL = g_pInputManager->getMouseCoordsInternal() - Vector2D(geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y); - g_pSeatManager->setPointerFocus(surface.wlr(), LOCAL); + g_pSeatManager->setPointerFocus(surface->resource(), LOCAL); g_pInputManager->m_bEmptyFocusCursorSet = false; } @@ -160,8 +163,8 @@ void CLayerSurface::onMap() { g_pEventManager->postEvent(SHyprIPCEvent{"openlayer", szNamespace}); EMIT_HOOK_EVENT("openLayer", self.lock()); - g_pCompositor->setPreferredScaleForSurface(surface.wlr(), PMONITOR->scale); - g_pCompositor->setPreferredTransformForSurface(surface.wlr(), PMONITOR->transform); + g_pCompositor->setPreferredScaleForSurface(surface->resource(), PMONITOR->scale); + g_pCompositor->setPreferredTransformForSurface(surface->resource(), PMONITOR->transform); } void CLayerSurface::onUnmap() { @@ -173,7 +176,7 @@ void CLayerSurface::onUnmap() { std::erase_if(g_pInputManager->m_dExclusiveLSes, [this](const auto& other) { return !other.lock() || other.lock() == self.lock(); }); if (!g_pInputManager->m_dExclusiveLSes.empty()) - g_pCompositor->focusSurface(g_pInputManager->m_dExclusiveLSes[0]->layerSurface->surface); + g_pCompositor->focusSurface(g_pInputManager->m_dExclusiveLSes[0]->surface->resource()); if (!g_pCompositor->getMonitorFromID(monitorID) || g_pCompositor->m_bUnsafeState) { Debug::log(WARN, "Layersurface unmapping on invalid monitor (removed?) ignoring."); @@ -197,7 +200,7 @@ void CLayerSurface::onUnmap() { const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID); - const bool WASLASTFOCUS = g_pCompositor->m_pLastFocus == layerSurface->surface; + const bool WASLASTFOCUS = g_pCompositor->m_pLastFocus == surface->resource(); surface = nullptr; @@ -208,11 +211,11 @@ void CLayerSurface::onUnmap() { if (WASLASTFOCUS) { g_pInputManager->releaseAllMouseButtons(); - Vector2D surfaceCoords; - PHLLS pFoundLayerSurface; - wlr_surface* foundSurface = nullptr; + Vector2D surfaceCoords; + PHLLS pFoundLayerSurface; + SP foundSurface = nullptr; - g_pCompositor->m_pLastFocus = nullptr; + g_pCompositor->m_pLastFocus.reset(); // find LS-es to focus foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], @@ -236,8 +239,8 @@ void CLayerSurface::onUnmap() { CBox geomFixed = {geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y, geometry.width, geometry.height}; g_pHyprRenderer->damageBox(&geomFixed); - geomFixed = {geometry.x + (int)PMONITOR->vecPosition.x, geometry.y + (int)PMONITOR->vecPosition.y, (int)layerSurface->surface->current.width, - (int)layerSurface->surface->current.height}; + geomFixed = {geometry.x + (int)PMONITOR->vecPosition.x, geometry.y + (int)PMONITOR->vecPosition.y, (int)layerSurface->surface->current.size.x, + (int)layerSurface->surface->current.size.y}; g_pHyprRenderer->damageBox(&geomFixed); g_pInputManager->sendMotionEventsToFocused(); @@ -284,12 +287,12 @@ void CLayerSurface::onCommit() { position = Vector2D(geometry.x, geometry.y); // update geom if it changed - if (layerSurface->surface->current.scale == 1 && PMONITOR->scale != 1.f && layerSurface->surface->current.viewport.has_dst) { + if (layerSurface->surface->current.scale == 1 && PMONITOR->scale != 1.f && layerSurface->surface->current.viewport.hasDestination) { // fractional scaling. Dirty hack. - geometry = {geometry.x, geometry.y, (int)(layerSurface->surface->current.viewport.dst_width), (int)(layerSurface->surface->current.viewport.dst_height)}; + geometry = {geometry.pos(), layerSurface->surface->current.viewport.destination}; } else { // this is because some apps like e.g. rofi-lbonn can't fucking use the protocol correctly. - geometry = {geometry.x, geometry.y, (int)layerSurface->surface->current.width, (int)layerSurface->surface->current.height}; + geometry = {geometry.pos(), layerSurface->surface->current.size}; } } @@ -308,10 +311,10 @@ void CLayerSurface::onCommit() { if (layerSurface->current.interactivity && (g_pSeatManager->mouse.expired() || !g_pInputManager->isConstrained()) // don't focus if constrained && !keyboardExclusive && mapped) { - g_pCompositor->focusSurface(layerSurface->surface); + g_pCompositor->focusSurface(surface->resource()); const auto LOCAL = g_pInputManager->getMouseCoordsInternal() - Vector2D(geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y); - g_pSeatManager->setPointerFocus(layerSurface->surface, LOCAL); + g_pSeatManager->setPointerFocus(surface->resource(), LOCAL); g_pInputManager->m_bEmptyFocusCursorSet = false; } else if (!layerSurface->current.interactivity && (g_pSeatManager->mouse.expired() || !g_pInputManager->isConstrained()) && keyboardExclusive) { g_pInputManager->refocus(); @@ -319,10 +322,10 @@ void CLayerSurface::onCommit() { keyboardExclusive = layerSurface->current.interactivity; - g_pHyprRenderer->damageSurface(layerSurface->surface, position.x, position.y); + g_pHyprRenderer->damageSurface(surface->resource(), position.x, position.y); - g_pCompositor->setPreferredScaleForSurface(layerSurface->surface, PMONITOR->scale); - g_pCompositor->setPreferredTransformForSurface(layerSurface->surface, PMONITOR->transform); + g_pCompositor->setPreferredScaleForSurface(surface->resource(), PMONITOR->scale); + g_pCompositor->setPreferredTransformForSurface(surface->resource(), PMONITOR->transform); } void CLayerSurface::applyRules() { diff --git a/src/desktop/LayerSurface.hpp b/src/desktop/LayerSurface.hpp index d60a6dd0d926..9fa96d2d4a2c 100644 --- a/src/desktop/LayerSurface.hpp +++ b/src/desktop/LayerSurface.hpp @@ -36,7 +36,7 @@ class CLayerSurface { bool keyboardExclusive = false; - CWLSurface surface; + SP surface; bool mapped = false; uint32_t layer = 0; diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index 03acfff916d0..ed67a7b59bc2 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -3,6 +3,7 @@ #include "../Compositor.hpp" #include "../protocols/LayerShell.hpp" #include "../protocols/XDGShell.hpp" +#include "../protocols/core/Compositor.hpp" #include CPopup::CPopup(PHLWINDOW pOwner) : m_pWindowOwner(pOwner) { @@ -14,7 +15,8 @@ CPopup::CPopup(PHLLS pOwner) : m_pLayerOwner(pOwner) { } CPopup::CPopup(SP popup, CPopup* pOwner) : m_pParent(pOwner), m_pResource(popup) { - m_sWLSurface.assign(popup->surface->surface, this); + m_pWLSurface = CWLSurface::create(); + m_pWLSurface->assign(popup->surface->surface.lock(), this); m_pLayerOwner = pOwner->m_pLayerOwner; m_pWindowOwner = pOwner->m_pWindowOwner; @@ -26,7 +28,8 @@ CPopup::CPopup(SP popup, CPopup* pOwner) : m_pParent(pOwner), } CPopup::~CPopup() { - m_sWLSurface.unassign(); + if (m_pWLSurface) + m_pWLSurface->unassign(); } void CPopup::initAllSignals() { @@ -66,12 +69,11 @@ void CPopup::onDestroy() { } void CPopup::onMap() { - m_vLastSize = {m_pResource->surface->surface->current.width, m_pResource->surface->surface->current.height}; + m_vLastSize = m_pResource->surface->surface->current.size; const auto COORDS = coordsGlobal(); const auto PMONITOR = g_pCompositor->getMonitorFromVector(COORDS); - CBox box; - wlr_surface_get_extends(m_sWLSurface.wlr(), box.pWlr()); + CBox box = m_pWLSurface->resource()->extends(); box.applyFromWlr().translate(COORDS).expand(4); g_pHyprRenderer->damageBox(&box); @@ -83,7 +85,7 @@ void CPopup::onMap() { //unconstrain(); sendScale(); - wlr_surface_send_enter(m_pResource->surface->surface, PMONITOR->output); + m_pResource->surface->surface->enter(PMONITOR->self.lock()); if (!m_pLayerOwner.expired() && m_pLayerOwner->layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP) g_pHyprOpenGL->markBlurDirtyForMonitor(g_pCompositor->getMonitorFromID(m_pLayerOwner->layer)); @@ -92,11 +94,10 @@ void CPopup::onMap() { void CPopup::onUnmap() { if (!m_pResource || !m_pResource->surface) return; - m_vLastSize = {m_pResource->surface->surface->current.width, m_pResource->surface->surface->current.height}; + m_vLastSize = m_pResource->surface->surface->current.size; const auto COORDS = coordsGlobal(); - CBox box; - wlr_surface_get_extends(m_sWLSurface.wlr(), box.pWlr()); + CBox box = m_pWLSurface->resource()->extends(); box.applyFromWlr().translate(COORDS).expand(4); g_pHyprRenderer->damageBox(&box); @@ -126,7 +127,7 @@ void CPopup::onCommit(bool ignoreSiblings) { } if (!m_pWindowOwner.expired() && (!m_pWindowOwner->m_bIsMapped || !m_pWindowOwner->m_pWorkspace->m_bVisible)) { - m_vLastSize = {m_pResource->surface->surface->current.width, m_pResource->surface->surface->current.height}; + m_vLastSize = m_pResource->surface->surface->current.size; static auto PLOGDAMAGE = CConfigValue("debug:log_damage"); if (*PLOGDAMAGE) @@ -140,11 +141,10 @@ void CPopup::onCommit(bool ignoreSiblings) { const auto COORDS = coordsGlobal(); const auto COORDSLOCAL = coordsRelativeToParent(); - if (m_vLastSize != Vector2D{m_pResource->surface->surface->current.width, m_pResource->surface->surface->current.height} || m_bRequestedReposition || - m_vLastPos != COORDSLOCAL) { + if (m_vLastSize != m_pResource->surface->surface->current.size || m_bRequestedReposition || m_vLastPos != COORDSLOCAL) { CBox box = {localToGlobal(m_vLastPos), m_vLastSize}; g_pHyprRenderer->damageBox(&box); - m_vLastSize = {m_pResource->surface->surface->current.width, m_pResource->surface->surface->current.height}; + m_vLastSize = m_pResource->surface->surface->current.size; box = {COORDS, m_vLastSize}; g_pHyprRenderer->damageBox(&box); @@ -154,7 +154,7 @@ void CPopup::onCommit(bool ignoreSiblings) { if (!ignoreSiblings && m_pSubsurfaceHead) m_pSubsurfaceHead->recheckDamageForSubsurfaces(); - g_pHyprRenderer->damageSurface(m_sWLSurface.wlr(), COORDS.x, COORDS.y); + g_pHyprRenderer->damageSurface(m_pWLSurface->resource(), COORDS.x, COORDS.y); m_bRequestedReposition = false; @@ -194,7 +194,7 @@ Vector2D CPopup::coordsRelativeToParent() { while (current->m_pParent && current->m_pResource) { - offset += {current->m_sWLSurface.wlr()->current.dx, current->m_sWLSurface.wlr()->current.dy}; + offset += current->m_pWLSurface->resource()->current.offset; offset += current->m_pResource->geometry.pos(); current = current->m_pParent; @@ -243,9 +243,9 @@ Vector2D CPopup::size() { void CPopup::sendScale() { if (!m_pWindowOwner.expired()) - g_pCompositor->setPreferredScaleForSurface(m_sWLSurface.wlr(), m_pWindowOwner->m_pWLSurface.m_fLastScale); + g_pCompositor->setPreferredScaleForSurface(m_pWLSurface->resource(), m_pWindowOwner->m_pWLSurface->m_fLastScale); else if (!m_pLayerOwner.expired()) - g_pCompositor->setPreferredScaleForSurface(m_sWLSurface.wlr(), m_pLayerOwner->surface.m_fLastScale); + g_pCompositor->setPreferredScaleForSurface(m_pWLSurface->resource(), m_pLayerOwner->surface->m_fLastScale); else UNREACHABLE(); } @@ -301,9 +301,8 @@ CPopup* CPopup::at(const Vector2D& globalCoords, bool allowsInput) { return p; } else { const Vector2D offset = p->m_pResource ? (p->size() - p->m_pResource->geometry.size()) / 2.F : Vector2D{}; - const auto REGION = CRegion{&p->m_sWLSurface.wlr()->current.input} - .intersect(CBox{{}, {p->m_sWLSurface.wlr()->current.width, p->m_sWLSurface.wlr()->current.height}}) - .translate(p->coordsGlobal() + offset); + const auto REGION = + CRegion{p->m_pWLSurface->resource()->current.input}.intersect(CBox{{}, p->m_pWLSurface->resource()->current.size}).translate(p->coordsGlobal() + offset); if (REGION.containsPoint(globalCoords)) return p; } diff --git a/src/desktop/Popup.hpp b/src/desktop/Popup.hpp index ba6da55a5ffd..71a019fc7532 100644 --- a/src/desktop/Popup.hpp +++ b/src/desktop/Popup.hpp @@ -39,7 +39,7 @@ class CPopup { CPopup* at(const Vector2D& globalCoords, bool allowsInput = false); // - CWLSurface m_sWLSurface; + SP m_pWLSurface; private: // T1 owners, each popup has to have one of these diff --git a/src/desktop/Subsurface.cpp b/src/desktop/Subsurface.cpp index 21482ff7c208..ab287a461f51 100644 --- a/src/desktop/Subsurface.cpp +++ b/src/desktop/Subsurface.cpp @@ -2,29 +2,31 @@ #include "../events/Events.hpp" #include "../Compositor.hpp" #include "../config/ConfigValue.hpp" - -static void onNewSubsurface(void* owner, void* data); +#include "../protocols/core/Compositor.hpp" +#include "../protocols/core/Subcompositor.hpp" CSubsurface::CSubsurface(PHLWINDOW pOwner) : m_pWindowParent(pOwner) { initSignals(); - initExistingSubsurfaces(pOwner->m_pWLSurface.wlr()); + initExistingSubsurfaces(pOwner->m_pWLSurface->resource()); } CSubsurface::CSubsurface(CPopup* pOwner) : m_pPopupParent(pOwner) { initSignals(); - initExistingSubsurfaces(pOwner->m_sWLSurface.wlr()); + initExistingSubsurfaces(pOwner->m_pWLSurface->resource()); } -CSubsurface::CSubsurface(wlr_subsurface* pSubsurface, PHLWINDOW pOwner) : m_pSubsurface(pSubsurface), m_pWindowParent(pOwner) { - m_sWLSurface.assign(pSubsurface->surface, this); +CSubsurface::CSubsurface(SP pSubsurface, PHLWINDOW pOwner) : m_pSubsurface(pSubsurface), m_pWindowParent(pOwner) { + m_pWLSurface = CWLSurface::create(); + m_pWLSurface->assign(pSubsurface->surface.lock(), this); initSignals(); - initExistingSubsurfaces(pSubsurface->surface); + initExistingSubsurfaces(pSubsurface->surface.lock()); } -CSubsurface::CSubsurface(wlr_subsurface* pSubsurface, CPopup* pOwner) : m_pSubsurface(pSubsurface), m_pPopupParent(pOwner) { - m_sWLSurface.assign(pSubsurface->surface, this); +CSubsurface::CSubsurface(SP pSubsurface, CPopup* pOwner) : m_pSubsurface(pSubsurface), m_pPopupParent(pOwner) { + m_pWLSurface = CWLSurface::create(); + m_pWLSurface->assign(pSubsurface->surface.lock(), this); initSignals(); - initExistingSubsurfaces(pSubsurface->surface); + initExistingSubsurfaces(pSubsurface->surface.lock()); } CSubsurface::~CSubsurface() { @@ -33,52 +35,28 @@ CSubsurface::~CSubsurface() { if (!m_pSubsurface) return; - m_pSubsurface->data = nullptr; - hyprListener_commitSubsurface.removeCallback(); hyprListener_destroySubsurface.removeCallback(); } -static void onNewSubsurface(void* owner, void* data) { - const auto PSUBSURFACE = (CSubsurface*)owner; - PSUBSURFACE->onNewSubsurface((wlr_subsurface*)data); -} - -static void onDestroySubsurface(void* owner, void* data) { - const auto PSUBSURFACE = (CSubsurface*)owner; - PSUBSURFACE->onDestroy(); -} - -static void onCommitSubsurface(void* owner, void* data) { - const auto PSUBSURFACE = (CSubsurface*)owner; - PSUBSURFACE->onCommit(); -} - -static void onMapSubsurface(void* owner, void* data) { - const auto PSUBSURFACE = (CSubsurface*)owner; - PSUBSURFACE->onMap(); -} - -static void onUnmapSubsurface(void* owner, void* data) { - const auto PSUBSURFACE = (CSubsurface*)owner; - PSUBSURFACE->onUnmap(); -} - void CSubsurface::initSignals() { + if (m_pSubsurface) { - m_pSubsurface->data = this; - hyprListener_commitSubsurface.initCallback(&m_pSubsurface->surface->events.commit, &onCommitSubsurface, this, "CSubsurface"); - 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_unmapSubsurface.initCallback(&m_pSubsurface->surface->events.unmap, &onUnmapSubsurface, this, "CSubsurface"); + listeners.commitSubsurface = m_pSubsurface->surface->events.commit.registerListener([this](std::any d) { onCommit(); }); + listeners.destroySubsurface = m_pSubsurface->events.destroy.registerListener([this](std::any d) { onDestroy(); }); + listeners.mapSubsurface = m_pSubsurface->surface->events.map.registerListener([this](std::any d) { onMap(); }); + listeners.unmapSubsurface = m_pSubsurface->surface->events.unmap.registerListener([this](std::any d) { onUnmap(); }); + listeners.newSubsurface = + m_pSubsurface->surface->events.newSubsurface.registerListener([this](std::any d) { onNewSubsurface(std::any_cast>(d)); }); } else { - if (!m_pWindowParent.expired()) - hyprListener_newSubsurface.initCallback(&m_pWindowParent->m_pWLSurface.wlr()->events.new_subsurface, &::onNewSubsurface, this, "CSubsurface Head"); + if (m_pWindowParent) + listeners.newSubsurface = m_pWindowParent->m_pWLSurface->resource()->events.newSubsurface.registerListener( + [this](std::any d) { onNewSubsurface(std::any_cast>(d)); }); else if (m_pPopupParent) - hyprListener_newSubsurface.initCallback(&m_pPopupParent->m_sWLSurface.wlr()->events.new_subsurface, &::onNewSubsurface, this, "CSubsurface Head"); + listeners.newSubsurface = m_pPopupParent->m_pWLSurface->resource()->events.newSubsurface.registerListener( + [this](std::any d) { onNewSubsurface(std::any_cast>(d)); }); else - RASSERT(false, "CSubsurface::initSignals empty subsurface"); + ASSERT(false); } } @@ -93,21 +71,21 @@ void CSubsurface::checkSiblingDamage() { continue; const auto COORDS = n->coordsGlobal(); - g_pHyprRenderer->damageSurface(n->m_sWLSurface.wlr(), COORDS.x, COORDS.y, SCALE); + g_pHyprRenderer->damageSurface(n->m_pWLSurface->resource(), COORDS.x, COORDS.y, SCALE); } } void CSubsurface::recheckDamageForSubsurfaces() { for (auto& n : m_vChildren) { const auto COORDS = n->coordsGlobal(); - g_pHyprRenderer->damageSurface(n->m_sWLSurface.wlr(), COORDS.x, COORDS.y); + g_pHyprRenderer->damageSurface(n->m_pWLSurface->resource(), COORDS.x, COORDS.y); } } void CSubsurface::onCommit() { // no damaging if it's not visible if (!m_pWindowParent.expired() && (!m_pWindowParent->m_bIsMapped || !m_pWindowParent->m_pWorkspace->m_bVisible)) { - m_vLastSize = Vector2D{m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height}; + m_vLastSize = m_pWLSurface->resource()->current.size; static auto PLOGDAMAGE = CConfigValue("debug:log_damage"); if (*PLOGDAMAGE) @@ -117,7 +95,7 @@ void CSubsurface::onCommit() { const auto COORDS = coordsGlobal(); - g_pHyprRenderer->damageSurface(m_sWLSurface.wlr(), COORDS.x, COORDS.y); + g_pHyprRenderer->damageSurface(m_pWLSurface->resource(), COORDS.x, COORDS.y); if (m_pPopupParent) m_pPopupParent->recheckTree(); @@ -127,10 +105,10 @@ void CSubsurface::onCommit() { // I do not think this is correct, but it solves a lot of issues with some apps (e.g. firefox) checkSiblingDamage(); - if (m_vLastSize != Vector2D{m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height}) { + if (m_vLastSize != m_pWLSurface->resource()->current.size) { CBox box{COORDS, m_vLastSize}; g_pHyprRenderer->damageBox(&box); - m_vLastSize = Vector2D{m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height}; + m_vLastSize = m_pWLSurface->resource()->current.size; box = {COORDS, m_vLastSize}; g_pHyprRenderer->damageBox(&box); } @@ -149,7 +127,7 @@ void CSubsurface::onDestroy() { std::erase_if(m_pParent->m_vChildren, [this](const auto& other) { return other.get() == this; }); } -void CSubsurface::onNewSubsurface(wlr_subsurface* pSubsurface) { +void CSubsurface::onNewSubsurface(SP pSubsurface) { CSubsurface* PSUBSURFACE = nullptr; if (!m_pWindowParent.expired()) @@ -162,7 +140,7 @@ void CSubsurface::onNewSubsurface(wlr_subsurface* pSubsurface) { } void CSubsurface::onMap() { - m_vLastSize = {m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height}; + m_vLastSize = m_pWLSurface->resource()->current.size; const auto COORDS = coordsGlobal(); CBox box{COORDS, m_vLastSize}; @@ -179,7 +157,7 @@ void CSubsurface::onUnmap() { box.expand(4); g_pHyprRenderer->damageBox(&box); - if (m_sWLSurface.wlr() == g_pCompositor->m_pLastFocus) + if (m_pWLSurface->resource() == g_pCompositor->m_pLastFocus) g_pInputManager->releaseAllMouseButtons(); g_pInputManager->simulateMouseMovement(); @@ -188,19 +166,9 @@ void CSubsurface::onUnmap() { } Vector2D CSubsurface::coordsRelativeToParent() { - Vector2D offset; - - CSubsurface* current = this; - - while (current->m_pParent) { - - offset += {current->m_sWLSurface.wlr()->current.dx, current->m_sWLSurface.wlr()->current.dy}; - offset += {current->m_pSubsurface->current.x, current->m_pSubsurface->current.y}; - - current = current->m_pParent; - } - - return offset; + if (!m_pSubsurface) + return {}; + return m_pSubsurface->posRelativeToParent(); } Vector2D CSubsurface::coordsGlobal() { @@ -214,18 +182,16 @@ Vector2D CSubsurface::coordsGlobal() { return coords; } -void CSubsurface::initExistingSubsurfaces(wlr_surface* pSurface) { - wlr_subsurface* wlrSubsurface; - wl_list_for_each(wlrSubsurface, &pSurface->current.subsurfaces_below, current.link) { - ::onNewSubsurface(this, wlrSubsurface); - } - wl_list_for_each(wlrSubsurface, &pSurface->current.subsurfaces_above, current.link) { - ::onNewSubsurface(this, wlrSubsurface); +void CSubsurface::initExistingSubsurfaces(SP pSurface) { + for (auto& s : pSurface->subsurfaces) { + if (!s) + continue; + onNewSubsurface(s.lock()); } } Vector2D CSubsurface::size() { - return {m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height}; + return m_pWLSurface->resource()->current.size; } bool CSubsurface::visible() { diff --git a/src/desktop/Subsurface.hpp b/src/desktop/Subsurface.hpp index f3a5ea4b8e45..101f4f195743 100644 --- a/src/desktop/Subsurface.hpp +++ b/src/desktop/Subsurface.hpp @@ -5,6 +5,7 @@ #include "WLSurface.hpp" class CPopup; +class CWLSubsurfaceResource; class CSubsurface { public: @@ -13,8 +14,8 @@ class CSubsurface { CSubsurface(CPopup* pOwner); // real nodes - CSubsurface(wlr_subsurface* pSubsurface, PHLWINDOW pOwner); - CSubsurface(wlr_subsurface* pSubsurface, CPopup* pOwner); + CSubsurface(SP pSubsurface, PHLWINDOW pOwner); + CSubsurface(SP pSubsurface, CPopup* pOwner); ~CSubsurface(); @@ -25,7 +26,7 @@ class CSubsurface { void onCommit(); void onDestroy(); - void onNewSubsurface(wlr_subsurface* pSubsurface); + void onNewSubsurface(SP pSubsurface); void onMap(); void onUnmap(); @@ -37,12 +38,18 @@ class CSubsurface { DYNLISTENER(destroySubsurface); DYNLISTENER(commitSubsurface); DYNLISTENER(newSubsurface); - DYNLISTENER(mapSubsurface); - DYNLISTENER(unmapSubsurface); - wlr_subsurface* m_pSubsurface = nullptr; - CWLSurface m_sWLSurface; - Vector2D m_vLastSize = {}; + struct { + CHyprSignalListener destroySubsurface; + CHyprSignalListener commitSubsurface; + CHyprSignalListener mapSubsurface; + CHyprSignalListener unmapSubsurface; + CHyprSignalListener newSubsurface; + } listeners; + + WP m_pSubsurface; + SP m_pWLSurface; + Vector2D m_vLastSize = {}; // if nullptr, means it's a dummy node CSubsurface* m_pParent = nullptr; @@ -55,6 +62,6 @@ class CSubsurface { bool m_bInert = false; void initSignals(); - void initExistingSubsurfaces(wlr_surface* pSurface); + void initExistingSubsurfaces(SP pSurface); void checkSiblingDamage(); }; \ No newline at end of file diff --git a/src/desktop/WLSurface.cpp b/src/desktop/WLSurface.cpp index 78b50d4510f5..cf315c7351b2 100644 --- a/src/desktop/WLSurface.cpp +++ b/src/desktop/WLSurface.cpp @@ -1,36 +1,37 @@ #include "WLSurface.hpp" #include "../Compositor.hpp" +#include "../protocols/core/Compositor.hpp" -void CWLSurface::assign(wlr_surface* pSurface) { - m_pWLRSurface = pSurface; +void CWLSurface::assign(SP pSurface) { + m_pResource = pSurface; init(); m_bInert = false; } -void CWLSurface::assign(wlr_surface* pSurface, PHLWINDOW pOwner) { +void CWLSurface::assign(SP pSurface, PHLWINDOW pOwner) { m_pWindowOwner = pOwner; - m_pWLRSurface = pSurface; + m_pResource = pSurface; init(); m_bInert = false; } -void CWLSurface::assign(wlr_surface* pSurface, PHLLS pOwner) { +void CWLSurface::assign(SP pSurface, PHLLS pOwner) { m_pLayerOwner = pOwner; - m_pWLRSurface = pSurface; + m_pResource = pSurface; init(); m_bInert = false; } -void CWLSurface::assign(wlr_surface* pSurface, CSubsurface* pOwner) { +void CWLSurface::assign(SP pSurface, CSubsurface* pOwner) { m_pSubsurfaceOwner = pOwner; - m_pWLRSurface = pSurface; + m_pResource = pSurface; init(); m_bInert = false; } -void CWLSurface::assign(wlr_surface* pSurface, CPopup* pOwner) { +void CWLSurface::assign(SP pSurface, CPopup* pOwner) { m_pPopupOwner = pOwner; - m_pWLRSurface = pSurface; + m_pResource = pSurface; init(); m_bInert = false; } @@ -44,20 +45,23 @@ CWLSurface::~CWLSurface() { } bool CWLSurface::exists() const { - return m_pWLRSurface; + return m_pResource; } -wlr_surface* CWLSurface::wlr() const { - return m_pWLRSurface; +SP CWLSurface::resource() const { + return m_pResource.lock(); } bool CWLSurface::small() const { if (!validMapped(m_pWindowOwner) || !exists()) return false; + if (!m_pResource->current.buffer) + return false; + const auto O = m_pWindowOwner.lock(); - return O->m_vReportedSize.x > m_pWLRSurface->current.buffer_width + 1 || O->m_vReportedSize.y > m_pWLRSurface->current.buffer_height + 1; + return O->m_vReportedSize.x > m_pResource->current.buffer->size.x + 1 || O->m_vReportedSize.y > m_pResource->current.buffer->size.y + 1; } Vector2D CWLSurface::correctSmallVec() const { @@ -71,29 +75,28 @@ Vector2D CWLSurface::correctSmallVec() const { } Vector2D CWLSurface::getViewporterCorrectedSize() const { - if (!exists()) + if (!exists() || !m_pResource->current.buffer) return {}; - return m_pWLRSurface->current.viewport.has_dst ? Vector2D{m_pWLRSurface->current.viewport.dst_width, m_pWLRSurface->current.viewport.dst_height} : - Vector2D{m_pWLRSurface->current.buffer_width, m_pWLRSurface->current.buffer_height}; + return m_pResource->current.viewport.hasDestination ? m_pResource->current.viewport.destination : m_pResource->current.buffer->size; } CRegion CWLSurface::logicalDamage() const { - CRegion damage{&m_pWLRSurface->buffer_damage}; - damage.transform(m_pWLRSurface->current.transform, m_pWLRSurface->current.buffer_width, m_pWLRSurface->current.buffer_height); - damage.scale(1.0 / m_pWLRSurface->current.scale); + if (!m_pResource->current.buffer) + return {}; + + CRegion damage{m_pResource->current.bufferDamage}; + damage.transform(m_pResource->current.transform, m_pResource->current.buffer->size.x, m_pResource->current.buffer->size.y); + damage.scale(1.0 / m_pResource->current.scale); const auto VPSIZE = getViewporterCorrectedSize(); const auto CORRECTVEC = correctSmallVec(); - if (m_pWLRSurface->current.viewport.has_src) { - damage.intersect(CBox{std::floor(m_pWLRSurface->current.viewport.src.x), std::floor(m_pWLRSurface->current.viewport.src.y), - std::ceil(m_pWLRSurface->current.viewport.src.width), std::ceil(m_pWLRSurface->current.viewport.src.height)}); - } + if (m_pResource->current.viewport.hasSource) + damage.intersect(m_pResource->current.viewport.source); - const auto SCALEDSRCSIZE = m_pWLRSurface->current.viewport.has_src ? - Vector2D{m_pWLRSurface->current.viewport.src.width, m_pWLRSurface->current.viewport.src.height} * m_pWLRSurface->current.scale : - Vector2D{m_pWLRSurface->current.buffer_width, m_pWLRSurface->current.buffer_height}; + const auto SCALEDSRCSIZE = + m_pResource->current.viewport.hasSource ? m_pResource->current.viewport.source.pos() * m_pResource->current.scale : m_pResource->current.buffer->size; damage.scale({VPSIZE.x / SCALEDSRCSIZE.x, VPSIZE.y / SCALEDSRCSIZE.y}); damage.translate(CORRECTVEC); @@ -102,48 +105,38 @@ CRegion CWLSurface::logicalDamage() const { } void CWLSurface::destroy() { - if (!m_pWLRSurface) + if (!m_pResource) return; events.destroy.emit(); m_pConstraint.reset(); - hyprListener_destroy.removeCallback(); - hyprListener_commit.removeCallback(); - m_pWLRSurface->data = nullptr; + listeners.destroy.reset(); + m_pResource->hlSurface.reset(); m_pWindowOwner.reset(); m_pLayerOwner.reset(); m_pPopupOwner = nullptr; m_pSubsurfaceOwner = nullptr; m_bInert = true; - if (g_pCompositor && g_pCompositor->m_pLastFocus == m_pWLRSurface) - g_pCompositor->m_pLastFocus = nullptr; - if (g_pHyprRenderer && g_pHyprRenderer->m_sLastCursorData.surf == this) + if (g_pHyprRenderer && g_pHyprRenderer->m_sLastCursorData.surf && g_pHyprRenderer->m_sLastCursorData.surf->get() == this) g_pHyprRenderer->m_sLastCursorData.surf.reset(); - m_pWLRSurface = nullptr; + m_pResource.reset(); Debug::log(LOG, "CWLSurface {:x} called destroy()", (uintptr_t)this); } -static void onCommit(void* owner, void* data) { - const auto SURF = (CWLSurface*)owner; - SURF->onCommit(); -} - void CWLSurface::init() { - if (!m_pWLRSurface) + if (!m_pResource) return; - RASSERT(!m_pWLRSurface->data, "Attempted to duplicate CWLSurface ownership!"); + RASSERT(!m_pResource->hlSurface, "Attempted to duplicate CWLSurface ownership!"); - m_pWLRSurface->data = this; + m_pResource->hlSurface = self.lock(); - hyprListener_destroy.initCallback( - &m_pWLRSurface->events.destroy, [&](void* owner, void* data) { destroy(); }, this, "CWLSurface"); - hyprListener_commit.initCallback(&m_pWLRSurface->events.commit, ::onCommit, this, "CWLSurface"); + listeners.destroy = m_pResource->events.destroy.registerListener([this](std::any d) { destroy(); }); Debug::log(LOG, "CWLSurface {:x} called init()", (uintptr_t)this); } @@ -188,10 +181,6 @@ void CWLSurface::appendConstraint(WP constraint) { m_pConstraint = constraint; } -void CWLSurface::onCommit() { - ; -} - SP CWLSurface::constraint() { return m_pConstraint.lock(); } @@ -207,3 +196,9 @@ bool CWLSurface::visible() { return m_pSubsurfaceOwner->visible(); return true; // non-desktop, we don't know much. } + +SP CWLSurface::fromResource(SP pSurface) { + if (!pSurface) + return nullptr; + return pSurface->hlSurface.lock(); +} diff --git a/src/desktop/WLSurface.hpp b/src/desktop/WLSurface.hpp index 03e81b45d6df..4ba381a9a984 100644 --- a/src/desktop/WLSurface.hpp +++ b/src/desktop/WLSurface.hpp @@ -7,33 +7,37 @@ class CSubsurface; class CPopup; class CPointerConstraint; +class CWLSurfaceResource; class CWLSurface { public: - CWLSurface() = default; + static SP create() { + auto p = SP(new CWLSurface); + p->self = p; + return p; + } ~CWLSurface(); // anonymous surfaces are non-desktop components, e.g. a cursor surface or a DnD - void assign(wlr_surface* pSurface); - void assign(wlr_surface* pSurface, PHLWINDOW pOwner); - void assign(wlr_surface* pSurface, PHLLS pOwner); - void assign(wlr_surface* pSurface, CSubsurface* pOwner); - void assign(wlr_surface* pSurface, CPopup* pOwner); + void assign(SP pSurface); + void assign(SP pSurface, PHLWINDOW pOwner); + void assign(SP pSurface, PHLLS pOwner); + void assign(SP pSurface, CSubsurface* pOwner); + void assign(SP pSurface, CPopup* pOwner); void unassign(); - CWLSurface(const CWLSurface&) = delete; - CWLSurface(CWLSurface&&) = delete; - CWLSurface& operator=(const CWLSurface&) = delete; - CWLSurface& operator=(CWLSurface&&) = delete; + CWLSurface(const CWLSurface&) = delete; + CWLSurface(CWLSurface&&) = delete; + CWLSurface& operator=(const CWLSurface&) = delete; + CWLSurface& operator=(CWLSurface&&) = delete; - wlr_surface* wlr() const; - bool exists() const; - bool small() const; // means surface is smaller than the requested size - Vector2D correctSmallVec() const; // returns a corrective vector for small() surfaces - Vector2D getViewporterCorrectedSize() const; - CRegion logicalDamage() const; - void onCommit(); - bool visible(); + SP resource() const; + bool exists() const; + bool small() const; // means surface is smaller than the requested size + Vector2D correctSmallVec() const; // returns a corrective vector for small() surfaces + Vector2D getViewporterCorrectedSize() const; + CRegion logicalDamage() const; + bool visible(); // getters for owners. PHLWINDOW getWindow(); @@ -55,31 +59,27 @@ class CWLSurface { wl_output_transform m_eLastTransform = (wl_output_transform)-1; // - CWLSurface& operator=(wlr_surface* pSurface) { + CWLSurface& operator=(SP pSurface) { destroy(); - m_pWLRSurface = pSurface; + m_pResource = pSurface; init(); return *this; } bool operator==(const CWLSurface& other) const { - return other.wlr() == wlr(); + return other.resource() == resource(); } - bool operator==(const wlr_surface* other) const { - return other == wlr(); + bool operator==(const SP other) const { + return other == resource(); } explicit operator bool() const { return exists(); } - static CWLSurface* surfaceFromWlr(wlr_surface* pSurface) { - if (!pSurface) - return nullptr; - return (CWLSurface*)pSurface->data; - } + static SP fromResource(SP pSurface); // used by the alpha-modifier protocol float m_pAlphaModifier = 1.F; @@ -88,15 +88,19 @@ class CWLSurface { CSignal destroy; } events; + WP self; + private: - bool m_bInert = true; + CWLSurface() = default; + + bool m_bInert = true; - wlr_surface* m_pWLRSurface = nullptr; + WP m_pResource; - PHLWINDOWREF m_pWindowOwner; - PHLLSREF m_pLayerOwner; - CPopup* m_pPopupOwner = nullptr; - CSubsurface* m_pSubsurfaceOwner = nullptr; + PHLWINDOWREF m_pWindowOwner; + PHLLSREF m_pLayerOwner; + CPopup* m_pPopupOwner = nullptr; + CSubsurface* m_pSubsurfaceOwner = nullptr; // WP m_pConstraint; @@ -105,8 +109,9 @@ class CWLSurface { void init(); bool desktopComponent(); - DYNLISTENER(destroy); - DYNLISTENER(commit); + struct { + CHyprSignalListener destroy; + } listeners; friend class CPointerConstraint; }; \ No newline at end of file diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 093cab5e6d9a..505dc4d28088 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -7,6 +7,7 @@ #include #include "../managers/TokenManager.hpp" #include "../protocols/XDGShell.hpp" +#include "../protocols/core/Compositor.hpp" #include "../xwayland/XWayland.hpp" PHLWINDOW CWindow::create(SP surface) { @@ -49,12 +50,14 @@ PHLWINDOW CWindow::create(SP resource) { pWindow->addWindowDeco(std::make_unique(pWindow)); pWindow->addWindowDeco(std::make_unique(pWindow)); - pWindow->m_pWLSurface.assign(pWindow->m_pXDGSurface->surface, pWindow); + pWindow->m_pWLSurface->assign(pWindow->m_pXDGSurface->surface.lock(), pWindow); return pWindow; } CWindow::CWindow(SP resource) : m_pXDGSurface(resource) { + m_pWLSurface = CWLSurface::create(); + listeners.map = m_pXDGSurface->events.map.registerListener([this](std::any d) { Events::listener_mapWindow(this, nullptr); }); listeners.ack = m_pXDGSurface->events.ack.registerListener([this](std::any d) { onAck(std::any_cast(d)); }); listeners.unmap = m_pXDGSurface->events.unmap.registerListener([this](std::any d) { Events::listener_unmapWindow(this, nullptr); }); @@ -65,6 +68,8 @@ CWindow::CWindow(SP resource) : m_pXDGSurface(resource) { } CWindow::CWindow(SP surface) : m_pXWaylandSurface(surface) { + m_pWLSurface = CWLSurface::create(); + listeners.map = m_pXWaylandSurface->events.map.registerListener([this](std::any d) { Events::listener_mapWindow(this, nullptr); }); listeners.unmap = m_pXWaylandSurface->events.unmap.registerListener([this](std::any d) { Events::listener_unmapWindow(this, nullptr); }); listeners.destroy = m_pXWaylandSurface->events.destroy.registerListener([this](std::any d) { Events::listener_destroyWindow(this, nullptr); }); @@ -81,7 +86,7 @@ CWindow::CWindow(SP surface) : m_pXWaylandSurface(surface) { CWindow::~CWindow() { if (g_pCompositor->m_pLastWindow.lock().get() == this) { - g_pCompositor->m_pLastFocus = nullptr; + g_pCompositor->m_pLastFocus.reset(); g_pCompositor->m_pLastWindow.reset(); } @@ -122,12 +127,12 @@ SWindowDecorationExtents CWindow::getFullWindowExtents() { if (EXTENTS.bottomRight.y > maxExtents.bottomRight.y) maxExtents.bottomRight.y = EXTENTS.bottomRight.y; - if (m_pWLSurface.exists() && !m_bIsX11 && m_pPopupHead) { + if (m_pWLSurface->exists() && !m_bIsX11 && m_pPopupHead) { CBox surfaceExtents = {0, 0, 0, 0}; // TODO: this could be better, perhaps make a getFullWindowRegion? m_pPopupHead->breadthfirst( [](CPopup* popup, void* data) { - if (!popup->m_sWLSurface.wlr()) + if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource()) return; CBox* pSurfaceExtents = (CBox*)data; @@ -149,11 +154,11 @@ SWindowDecorationExtents CWindow::getFullWindowExtents() { if (-surfaceExtents.y > maxExtents.topLeft.y) maxExtents.topLeft.y = -surfaceExtents.y; - if (surfaceExtents.x + surfaceExtents.width > m_pWLSurface.wlr()->current.width + maxExtents.bottomRight.x) - maxExtents.bottomRight.x = surfaceExtents.x + surfaceExtents.width - m_pWLSurface.wlr()->current.width; + if (surfaceExtents.x + surfaceExtents.width > m_pWLSurface->resource()->current.size.x + maxExtents.bottomRight.x) + maxExtents.bottomRight.x = surfaceExtents.x + surfaceExtents.width - m_pWLSurface->resource()->current.size.x; - if (surfaceExtents.y + surfaceExtents.height > m_pWLSurface.wlr()->current.height + maxExtents.bottomRight.y) - maxExtents.bottomRight.y = surfaceExtents.y + surfaceExtents.height - m_pWLSurface.wlr()->current.height; + if (surfaceExtents.y + surfaceExtents.height > m_pWLSurface->resource()->current.size.y + maxExtents.bottomRight.y) + maxExtents.bottomRight.y = surfaceExtents.y + surfaceExtents.height - m_pWLSurface->resource()->current.size.y; } return maxExtents; @@ -336,16 +341,6 @@ void CWindow::updateToplevel() { updateSurfaceScaleTransformDetails(); } -void sendEnterIter(wlr_surface* pSurface, int x, int y, void* data) { - const auto OUTPUT = (wlr_output*)data; - wlr_surface_send_enter(pSurface, OUTPUT); -} - -void sendLeaveIter(wlr_surface* pSurface, int x, int y, void* data) { - const auto OUTPUT = (wlr_output*)data; - wlr_surface_send_leave(pSurface, OUTPUT); -} - void CWindow::updateSurfaceScaleTransformDetails() { if (!m_bIsMapped || m_bHidden || g_pCompositor->m_bUnsafeState) return; @@ -361,24 +356,23 @@ void CWindow::updateSurfaceScaleTransformDetails() { if (PNEWMONITOR != PLASTMONITOR) { if (PLASTMONITOR && PLASTMONITOR->m_bEnabled) - wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendLeaveIter, PLASTMONITOR->output); + m_pWLSurface->resource()->breadthfirst([PLASTMONITOR](SP s, void* d) { s->leave(PLASTMONITOR->self.lock()); }, nullptr); - wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendEnterIter, PNEWMONITOR->output); + m_pWLSurface->resource()->breadthfirst([PNEWMONITOR](SP s, void* d) { s->enter(PNEWMONITOR->self.lock()); }, nullptr); } - wlr_surface_for_each_surface( - m_pWLSurface.wlr(), - [](wlr_surface* surf, int x, int y, void* data) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(((CWindow*)data)->m_iMonitorID); + m_pWLSurface->resource()->breadthfirst( + [this](SP s, void* d) { + const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); - const auto PSURFACE = CWLSurface::surfaceFromWlr(surf); + const auto PSURFACE = CWLSurface::fromResource(s); if (PSURFACE && PSURFACE->m_fLastScale == PMONITOR->scale) return; - g_pCompositor->setPreferredScaleForSurface(surf, PMONITOR->scale); - g_pCompositor->setPreferredTransformForSurface(surf, PMONITOR->transform); + g_pCompositor->setPreferredScaleForSurface(s, PMONITOR->scale); + g_pCompositor->setPreferredTransformForSurface(s, PMONITOR->transform); }, - this); + nullptr); } void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { @@ -847,7 +841,7 @@ bool CWindow::hasPopupAt(const Vector2D& pos) { CPopup* popup = m_pPopupHead->at(pos); - return popup && popup->m_sWLSurface.wlr(); + return popup && popup->m_pWLSurface->resource(); } void CWindow::applyGroupRules() { @@ -1122,7 +1116,7 @@ bool CWindow::opaque() { const auto PWORKSPACE = m_pWorkspace; - if (m_pWLSurface.small() && !m_pWLSurface.m_bFillIgnoreSmall) + if (m_pWLSurface->small() && !m_pWLSurface->m_bFillIgnoreSmall) return false; if (PWORKSPACE->m_fAlpha.value() != 1.f) @@ -1131,11 +1125,9 @@ bool CWindow::opaque() { if (m_bIsX11) return false; - if (m_pXDGSurface && m_pXDGSurface->surface->opaque) - return true; - - const auto EXTENTS = pixman_region32_extents(&m_pXDGSurface->surface->opaque_region); - if (EXTENTS->x2 - EXTENTS->x1 >= m_pXDGSurface->surface->current.buffer_width && EXTENTS->y2 - EXTENTS->y1 >= m_pXDGSurface->surface->current.buffer_height) + // TODO: this is wrong + const auto EXTENTS = m_pXDGSurface->surface->current.opaque.getExtents(); + if (EXTENTS.w >= m_pXDGSurface->surface->current.buffer->size.x && EXTENTS.h >= m_pXDGSurface->surface->current.buffer->size.y) return true; return false; @@ -1269,8 +1261,7 @@ int CWindow::surfacesCount() { return 1; int no = 0; - wlr_surface_for_each_surface( - m_pWLSurface.wlr(), [](wlr_surface* surf, int x, int y, void* data) { *((int*)data) += 1; }, &no); + m_pWLSurface->resource()->breadthfirst([](SP r, void* d) { *((int*)d) += 1; }, &no); return no; } @@ -1442,16 +1433,16 @@ void CWindow::onAck(uint32_t serial) { } void CWindow::onResourceChangeX11() { - if (m_pXWaylandSurface->surface && !m_pWLSurface.wlr()) - m_pWLSurface.assign(m_pXWaylandSurface->surface, m_pSelf.lock()); - else if (!m_pXWaylandSurface->surface && m_pWLSurface.wlr()) - m_pWLSurface.unassign(); + if (m_pXWaylandSurface->surface && !m_pWLSurface->resource()) + m_pWLSurface->assign(m_pXWaylandSurface->surface.lock(), m_pSelf.lock()); + else if (!m_pXWaylandSurface->surface && m_pWLSurface->resource()) + m_pWLSurface->unassign(); // update metadata as well, // could be first assoc and we need to catch the class onUpdateMeta(); - Debug::log(LOG, "xwayland window {:x} -> association to {:x}", (uintptr_t)m_pXWaylandSurface.get(), (uintptr_t)m_pWLSurface.wlr()); + Debug::log(LOG, "xwayland window {:x} -> association to {:x}", (uintptr_t)m_pXWaylandSurface.get(), (uintptr_t)m_pWLSurface->resource().get()); } void CWindow::onX11Configure(CBox box) { diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 473ce361c950..9be6e25b3611 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -209,7 +209,7 @@ class CWindow { public: ~CWindow(); - CWLSurface m_pWLSurface; + SP m_pWLSurface; struct { CSignal destroy; diff --git a/src/devices/Tablet.cpp b/src/devices/Tablet.cpp index f5b610a9f6ab..b5ab16c11cc0 100644 --- a/src/devices/Tablet.cpp +++ b/src/devices/Tablet.cpp @@ -1,6 +1,7 @@ #include "Tablet.hpp" #include "../defines.hpp" #include "../protocols/Tablet.hpp" +#include "../protocols/core/Compositor.hpp" SP CTablet::create(wlr_tablet* tablet) { SP pTab = SP(new CTablet(tablet)); @@ -295,32 +296,29 @@ CTabletTool::~CTabletTool() { void CTabletTool::disconnectCallbacks() { hyprListener_destroy.removeCallback(); - hyprListener_destroySurface.removeCallback(); + listeners.destroySurface.reset(); } -wlr_surface* CTabletTool::getSurface() { - return pSurface; +SP CTabletTool::getSurface() { + return pSurface.lock(); } -void CTabletTool::setSurface(wlr_surface* surf) { +void CTabletTool::setSurface(SP surf) { if (surf == pSurface) return; if (pSurface) { - hyprListener_destroySurface.removeCallback(); - pSurface = nullptr; + listeners.destroySurface.reset(); + pSurface.reset(); } pSurface = surf; if (surf) { - hyprListener_destroySurface.initCallback( - &surf->events.destroy, - [this](void* owner, void* data) { - PROTO::tablet->proximityOut(self.lock()); - pSurface = nullptr; - hyprListener_destroySurface.removeCallback(); - }, - this, "CTabletTool"); + listeners.destroySurface = surf->events.destroy.registerListener([this](std::any d) { + PROTO::tablet->proximityOut(self.lock()); + pSurface.reset(); + listeners.destroySurface.reset(); + }); } } diff --git a/src/devices/Tablet.hpp b/src/devices/Tablet.hpp index f2444972efb3..3fd81ad18e4a 100644 --- a/src/devices/Tablet.hpp +++ b/src/devices/Tablet.hpp @@ -197,32 +197,35 @@ class CTabletTool : public IHID { HID_TABLET_TOOL_CAPABILITY_WHEEL = (1 << 5), }; - virtual uint32_t getCapabilities(); - wlr_tablet_tool* wlr(); - virtual eHIDType getType(); - wlr_surface* getSurface(); - void setSurface(wlr_surface*); + virtual uint32_t getCapabilities(); + wlr_tablet_tool* wlr(); + virtual eHIDType getType(); + SP getSurface(); + void setSurface(SP); - WP self; - Vector2D tilt; - bool active = false; // true if in proximity - uint32_t toolCapabilities = 0; + WP self; + Vector2D tilt; + bool active = false; // true if in proximity + uint32_t toolCapabilities = 0; - bool isDown = false; - std::vector buttonsDown; - Vector2D absolutePos; // last known absolute position. + bool isDown = false; + std::vector buttonsDown; + Vector2D absolutePos; // last known absolute position. - std::string hlName; + std::string hlName; private: CTabletTool(wlr_tablet_tool* tool); - void disconnectCallbacks(); + void disconnectCallbacks(); - wlr_surface* pSurface = nullptr; + WP pSurface; - wlr_tablet_tool* tool = nullptr; + wlr_tablet_tool* tool = nullptr; DYNLISTENER(destroy); - DYNLISTENER(destroySurface); + + struct { + CHyprSignalListener destroySurface; + } listeners; }; \ No newline at end of file diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 9044bc61ad53..c2567c13c52c 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -9,6 +9,7 @@ #include "../config/ConfigValue.hpp" #include "../protocols/LayerShell.hpp" #include "../protocols/XDGShell.hpp" +#include "../protocols/core/Compositor.hpp" #include "../xwayland/XSurface.hpp" // ------------------------------------------------------------ // @@ -104,7 +105,7 @@ void Events::listener_mapWindow(void* owner, void* data) { // registers the animated vars and stuff PWINDOW->onMap(); - const auto PWINDOWSURFACE = PWINDOW->m_pWLSurface.wlr(); + const auto PWINDOWSURFACE = PWINDOW->m_pWLSurface->resource(); if (!PWINDOWSURFACE) { g_pCompositor->removeWindowFromVectorSafe(PWINDOW); @@ -463,7 +464,7 @@ void Events::listener_mapWindow(void* owner, void* data) { // check LS focus grab const auto PFORCEFOCUS = g_pCompositor->getForceFocus(); - const auto PLSFROMFOCUS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus); + const auto PLSFROMFOCUS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus.lock()); if (PLSFROMFOCUS && PLSFROMFOCUS->layerSurface->current.interactivity != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE) PWINDOW->m_bNoInitialFocus = true; if (PWORKSPACE->m_bHasFullscreenWindow && !requestsFullscreen && !PWINDOW->m_bIsFloating) { @@ -618,8 +619,8 @@ void Events::listener_mapWindow(void* owner, void* data) { if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->m_bIsFullscreen && !PWINDOW->m_bIsFloating) PWINDOW->m_fAlpha.setValueAndWarp(0.f); - g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->scale); - g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->transform); + g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface->resource(), PMONITOR->scale); + g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface->resource(), PMONITOR->transform); if (g_pSeatManager->mouse.expired() || !g_pInputManager->isConstrained()) g_pInputManager->sendMotionEventsToFocused(); @@ -638,7 +639,7 @@ void Events::listener_unmapWindow(void* owner, void* data) { Debug::log(LOG, "{:c} unmapped", PWINDOW); - if (!PWINDOW->m_pWLSurface.exists() || !PWINDOW->m_bIsMapped) { + if (!PWINDOW->m_pWLSurface->exists() || !PWINDOW->m_bIsMapped) { Debug::log(WARN, "{} unmapped without being mapped??", PWINDOW); PWINDOW->m_bFadingOut = false; return; @@ -674,7 +675,7 @@ void Events::listener_unmapWindow(void* owner, void* data) { if (PWINDOW == g_pCompositor->m_pLastWindow.lock()) { wasLastWindow = true; g_pCompositor->m_pLastWindow.reset(); - g_pCompositor->m_pLastFocus = nullptr; + g_pCompositor->m_pLastFocus.reset(); g_pInputManager->releaseAllMouseButtons(); } @@ -788,7 +789,7 @@ void Events::listener_commitWindow(void* owner, void* data) { if (!PWINDOW->m_pWorkspace->m_bVisible) return; - g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface.wlr(), PWINDOW->m_vRealPosition.goal().x, PWINDOW->m_vRealPosition.goal().y, + g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface->resource(), PWINDOW->m_vRealPosition.goal().x, PWINDOW->m_vRealPosition.goal().y, PWINDOW->m_bIsX11 ? 1.0 / PWINDOW->m_fX11SurfaceScaledBy : 1.0); if (!PWINDOW->m_bIsX11) { @@ -798,9 +799,8 @@ void Events::listener_commitWindow(void* owner, void* data) { // tearing: if solitary, redraw it. This still might be a single surface window const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); - if (PMONITOR && PMONITOR->solitaryClient.lock() == PWINDOW && PWINDOW->canBeTorn() && PMONITOR->tearingState.canTear && - PWINDOW->m_pWLSurface.wlr()->current.committed & WLR_SURFACE_STATE_BUFFER) { - CRegion damageBox{&PWINDOW->m_pWLSurface.wlr()->buffer_damage}; + if (PMONITOR && PMONITOR->solitaryClient.lock() == PWINDOW && PWINDOW->canBeTorn() && PMONITOR->tearingState.canTear && PWINDOW->m_pWLSurface->resource()->current.newBuffer) { + CRegion damageBox{PWINDOW->m_pWLSurface->resource()->current.bufferDamage}; if (!damageBox.empty()) { if (PMONITOR->tearingState.busy) { @@ -820,10 +820,10 @@ void Events::listener_destroyWindow(void* owner, void* data) { if (PWINDOW == g_pCompositor->m_pLastWindow.lock()) { g_pCompositor->m_pLastWindow.reset(); - g_pCompositor->m_pLastFocus = nullptr; + g_pCompositor->m_pLastFocus.reset(); } - PWINDOW->m_pWLSurface.unassign(); + PWINDOW->m_pWLSurface->unassign(); PWINDOW->listeners = {}; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index d13acf0ca75d..5962b73dcbbf 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -216,7 +216,6 @@ void CMonitor::onConnect(bool noRule) { PROTO::gamma->applyGammaToState(this); events.connect.emit(); - updateGlobal(); } void CMonitor::onDisconnect(bool destroy) { @@ -284,8 +283,6 @@ void CMonitor::onDisconnect(bool destroy) { m_bEnabled = false; m_bRenderingInitPassed = false; - updateGlobal(); - if (BACKUPMON) { // snap cursor g_pCompositor->warpCursorTo(BACKUPMON->vecPosition + BACKUPMON->vecTransformedSize / 2.F, true); @@ -304,7 +301,7 @@ void CMonitor::onDisconnect(bool destroy) { w->startAnim(true, true, true); } } else { - g_pCompositor->m_pLastFocus = nullptr; + g_pCompositor->m_pLastFocus.reset(); g_pCompositor->m_pLastWindow.reset(); g_pCompositor->m_pLastMonitor.reset(); } @@ -750,13 +747,6 @@ CBox CMonitor::logicalBox() { return {vecPosition, vecSize}; } -void CMonitor::updateGlobal() { - if (output->width > 0 && output->height > 0 && m_bEnabled) - wlr_output_create_global(output, g_pCompositor->m_sWLDisplay); - else - wlr_output_destroy_global(output); -} - CMonitorState::CMonitorState(CMonitor* owner) { m_pOwner = owner; wlr_output_state_init(&m_state); diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index e4456084d024..4bfbf53c33d6 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -172,7 +172,6 @@ class CMonitor { int64_t activeWorkspaceID(); int64_t activeSpecialWorkspaceID(); CBox logicalBox(); - void updateGlobal(); bool m_bEnabled = false; bool m_bRenderingInitPassed = false; diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index 30f5aebf39f6..d5be9f40ea30 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -13,6 +13,7 @@ class CMonitor; class IPointer; class IKeyboard; +class CWLSurfaceResource; struct SRenderData { CMonitor* pMonitor; @@ -20,9 +21,9 @@ struct SRenderData { double x, y; // for iters - void* data = nullptr; - wlr_surface* surface = nullptr; - double w, h; + void* data = nullptr; + SP surface = nullptr; + double w, h; // for rounding bool dontRound = true; @@ -52,12 +53,6 @@ struct SRenderData { bool popup = false; }; -struct SExtensionFindingData { - Vector2D origin; - Vector2D vec; - wlr_surface** found; -}; - struct SSwipeGesture { PHLWORKSPACE pWorkspaceBegin = nullptr; diff --git a/src/helpers/memory/SharedPtr.hpp b/src/helpers/memory/SharedPtr.hpp index 77f5164a751a..1de2aea1e0dc 100644 --- a/src/helpers/memory/SharedPtr.hpp +++ b/src/helpers/memory/SharedPtr.hpp @@ -297,6 +297,6 @@ static CSharedPointer makeShared(Args&&... args) { template struct std::hash> { std::size_t operator()(const CSharedPointer& p) const noexcept { - return std::hash{}(p->impl_); + return std::hash{}(p.impl_); } }; diff --git a/src/helpers/memory/WeakPtr.hpp b/src/helpers/memory/WeakPtr.hpp index f0e721466cb3..872f8e55a9c2 100644 --- a/src/helpers/memory/WeakPtr.hpp +++ b/src/helpers/memory/WeakPtr.hpp @@ -185,6 +185,6 @@ class CWeakPointer { template struct std::hash> { std::size_t operator()(const CWeakPointer& p) const noexcept { - return std::hash{}(p->impl_); + return std::hash{}(p.impl_); } }; diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 108f90391f2b..28f7d454318f 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -5,6 +5,7 @@ #include "../config/ConfigValue.hpp" #include "../desktop/Window.hpp" #include "../protocols/XDGShell.hpp" +#include "../protocols/core/Compositor.hpp" #include "../xwayland/XSurface.hpp" void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) { @@ -99,8 +100,8 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { } if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) { - const auto PWINDOWSURFACE = pWindow->m_pWLSurface.wlr(); - pWindow->m_vRealSize = Vector2D(PWINDOWSURFACE->current.width, PWINDOWSURFACE->current.height); + const auto PWINDOWSURFACE = pWindow->m_pWLSurface->resource(); + pWindow->m_vRealSize = PWINDOWSURFACE->current.size; if ((desiredGeometry.width <= 1 || desiredGeometry.height <= 1) && pWindow->m_bIsX11 && pWindow->m_iX11Type == 2) { // XDG windows should be fine. TODO: check for weird atoms? diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index c9783844983d..0975dc3df465 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -114,8 +114,8 @@ wlr_buffer* CCursorManager::getCursorBuffer() { return !m_vCursorBuffers.empty() ? &m_vCursorBuffers.back()->wlrBuffer.base : nullptr; } -void CCursorManager::setCursorSurface(CWLSurface* surf, const Vector2D& hotspot) { - if (!surf || !surf->wlr()) +void CCursorManager::setCursorSurface(SP surf, const Vector2D& hotspot) { + if (!surf || !surf->resource()) g_pPointerManager->resetCursorImage(); else g_pPointerManager->setCursorSurface(surf, hotspot); diff --git a/src/managers/CursorManager.hpp b/src/managers/CursorManager.hpp index 4ff9adeb69c0..1b7a065d2c0a 100644 --- a/src/managers/CursorManager.hpp +++ b/src/managers/CursorManager.hpp @@ -18,7 +18,7 @@ class CCursorManager { wlr_buffer* getCursorBuffer(); void setCursorFromName(const std::string& name); - void setCursorSurface(CWLSurface* surf, const Vector2D& hotspot); + void setCursorSurface(SP surf, const Vector2D& hotspot); void setXCursor(const std::string& name); void changeTheme(const std::string& name, const int size); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 41b82d1092c5..d2fac885050c 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1966,14 +1966,14 @@ void CKeybindManager::pass(std::string regexp) { } const auto XWTOXW = PWINDOW->m_bIsX11 && g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bIsX11; - const auto LASTSRF = g_pCompositor->m_pLastFocus; + const auto LASTSRF = g_pCompositor->m_pLastFocus.lock(); // pass all mf shit if (!XWTOXW) { if (g_pKeybindManager->m_uLastCode != 0) - g_pSeatManager->setKeyboardFocus(PWINDOW->m_pWLSurface.wlr()); + g_pSeatManager->setKeyboardFocus(PWINDOW->m_pWLSurface->resource()); else - g_pSeatManager->setPointerFocus(PWINDOW->m_pWLSurface.wlr(), {1, 1}); + g_pSeatManager->setPointerFocus(PWINDOW->m_pWLSurface->resource(), {1, 1}); } g_pSeatManager->sendKeyboardMods(g_pInputManager->accumulateModsFromAllKBs(), 0, 0, 0); @@ -2007,10 +2007,10 @@ void CKeybindManager::pass(std::string regexp) { // please kill me if (PWINDOW->m_bIsX11) { if (g_pKeybindManager->m_uLastCode != 0) { - g_pSeatManager->state.keyboardFocus = nullptr; + g_pSeatManager->state.keyboardFocus.reset(); g_pSeatManager->state.keyboardFocusResource.reset(); } else { - g_pSeatManager->state.pointerFocus = nullptr; + g_pSeatManager->state.pointerFocus.reset(); g_pSeatManager->state.pointerFocusResource.reset(); } } @@ -2020,7 +2020,7 @@ void CKeybindManager::pass(std::string regexp) { if (g_pKeybindManager->m_uLastCode != 0) g_pSeatManager->setKeyboardFocus(LASTSRF); else - g_pSeatManager->setPointerFocus(PWINDOW->m_pWLSurface.wlr(), SL); + g_pSeatManager->setPointerFocus(PWINDOW->m_pWLSurface->resource(), SL); } void CKeybindManager::sendshortcut(std::string args) { @@ -2099,7 +2099,7 @@ void CKeybindManager::sendshortcut(std::string args) { const std::string regexp = ARGS[2]; PHLWINDOW PWINDOW = nullptr; - const auto LASTSURFACE = g_pCompositor->m_pLastFocus; + const auto LASTSURFACE = g_pCompositor->m_pLastFocus.lock(); //if regexp is not empty, send shortcut to current window //else, dont change focus @@ -2117,15 +2117,15 @@ void CKeybindManager::sendshortcut(std::string args) { } if (!isMouse) - g_pSeatManager->setKeyboardFocus(PWINDOW->m_pWLSurface.wlr()); + g_pSeatManager->setKeyboardFocus(PWINDOW->m_pWLSurface->resource()); else - g_pSeatManager->setPointerFocus(PWINDOW->m_pWLSurface.wlr(), {1, 1}); + g_pSeatManager->setPointerFocus(PWINDOW->m_pWLSurface->resource(), {1, 1}); } //copied the rest from pass and modified it // if wl -> xwl, activate destination if (PWINDOW && PWINDOW->m_bIsX11 && g_pCompositor->m_pLastWindow && !g_pCompositor->m_pLastWindow->m_bIsX11) - g_pXWaylandManager->activateSurface(PWINDOW->m_pWLSurface.wlr(), true); + g_pXWaylandManager->activateSurface(PWINDOW->m_pWLSurface->resource(), true); // if xwl -> xwl, send to current. Timing issues make this not work. if (PWINDOW && PWINDOW->m_bIsX11 && g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow->m_bIsX11) PWINDOW = nullptr; @@ -2158,10 +2158,10 @@ void CKeybindManager::sendshortcut(std::string args) { if (PWINDOW->m_bIsX11) { //xwayland hack, see pass if (!isMouse) { - g_pSeatManager->state.keyboardFocus = nullptr; + g_pSeatManager->state.keyboardFocus.reset(); g_pSeatManager->state.keyboardFocusResource.reset(); } else { - g_pSeatManager->state.pointerFocus = nullptr; + g_pSeatManager->state.pointerFocus.reset(); g_pSeatManager->state.pointerFocusResource.reset(); } } diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 7df2d6f429ca..3c716cb5b269 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -3,6 +3,7 @@ #include "../config/ConfigValue.hpp" #include "../protocols/PointerGestures.hpp" #include "../protocols/FractionalScale.hpp" +#include "../protocols/core/Compositor.hpp" #include "SeatManager.hpp" #include #include @@ -212,13 +213,13 @@ void CPointerManager::setCursorBuffer(wlr_buffer* buf, const Vector2D& hotspot, damageIfSoftware(); } -void CPointerManager::setCursorSurface(CWLSurface* surf, const Vector2D& hotspot) { +void CPointerManager::setCursorSurface(SP surf, const Vector2D& hotspot) { damageIfSoftware(); if (surf == currentCursorImage.surface) { - if (hotspot != currentCursorImage.hotspot || (surf && surf->wlr() ? surf->wlr()->current.scale : 1.F) != currentCursorImage.scale) { + if (hotspot != currentCursorImage.hotspot || (surf && surf->resource() ? surf->resource()->current.scale : 1.F) != currentCursorImage.scale) { currentCursorImage.hotspot = hotspot; - currentCursorImage.scale = surf && surf->wlr() ? surf->wlr()->current.scale : 1.F; + currentCursorImage.scale = surf && surf->resource() ? surf->resource()->current.scale : 1.F; updateCursorBackend(); damageIfSoftware(); } @@ -229,27 +230,24 @@ void CPointerManager::setCursorSurface(CWLSurface* surf, const Vector2D& hotspot resetCursorImage(false); if (surf) { - currentCursorImage.size = {surf->wlr()->current.buffer_width, surf->wlr()->current.buffer_height}; currentCursorImage.surface = surf; - currentCursorImage.scale = surf->wlr()->current.scale; + currentCursorImage.scale = surf->resource()->current.scale; currentCursorImage.destroySurface = surf->events.destroy.registerListener([this](std::any data) { resetCursorImage(); }); - currentCursorImage.hyprListener_commitSurface.initCallback( - &surf->wlr()->events.commit, - [this](void* owner, void* data) { - damageIfSoftware(); - currentCursorImage.size = {currentCursorImage.surface->wlr()->current.buffer_width, currentCursorImage.surface->wlr()->current.buffer_height}; - currentCursorImage.scale = currentCursorImage.surface && currentCursorImage.surface->wlr() ? currentCursorImage.surface->wlr()->current.scale : 1.F; - recheckEnteredOutputs(); - updateCursorBackend(); - damageIfSoftware(); - }, - nullptr, "CPointerManager"); + currentCursorImage.commitSurface = surf->resource()->events.commit.registerListener([this](std::any data) { + damageIfSoftware(); + currentCursorImage.size = currentCursorImage.surface->resource()->current.buffer ? currentCursorImage.surface->resource()->current.buffer->size : Vector2D{}; + currentCursorImage.scale = currentCursorImage.surface ? currentCursorImage.surface->resource()->current.scale : 1.F; + recheckEnteredOutputs(); + updateCursorBackend(); + damageIfSoftware(); + }); - if (wlr_surface_has_buffer(surf->wlr())) { + if (surf->resource()->current.buffer) { + currentCursorImage.size = surf->resource()->current.buffer->size; timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - wlr_surface_send_frame_done(surf->wlr(), &now); + surf->resource()->frame(&now); } } @@ -278,9 +276,9 @@ void CPointerManager::recheckEnteredOutputs() { if (!currentCursorImage.surface) continue; - wlr_surface_send_enter(currentCursorImage.surface->wlr(), s->monitor->output); - PROTO::fractional->sendScale(currentCursorImage.surface->wlr(), s->monitor->scale); - g_pCompositor->setPreferredScaleForSurface(currentCursorImage.surface->wlr(), s->monitor->scale); + currentCursorImage.surface->resource()->enter(s->monitor.lock()); + PROTO::fractional->sendScale(currentCursorImage.surface->resource(), s->monitor->scale); + g_pCompositor->setPreferredScaleForSurface(currentCursorImage.surface->resource(), s->monitor->scale); } else if (s->entered && !overlaps) { s->entered = false; @@ -293,7 +291,7 @@ void CPointerManager::recheckEnteredOutputs() { if (!currentCursorImage.surface) continue; - wlr_surface_send_leave(currentCursorImage.surface->wlr(), s->monitor->output); + currentCursorImage.surface->resource()->leave(s->monitor.lock()); } } } @@ -303,12 +301,12 @@ void CPointerManager::resetCursorImage(bool apply) { if (currentCursorImage.surface) { for (auto& m : g_pCompositor->m_vMonitors) { - wlr_surface_send_leave(currentCursorImage.surface->wlr(), m->output); + currentCursorImage.surface->resource()->leave(m); } currentCursorImage.destroySurface.reset(); - currentCursorImage.hyprListener_commitSurface.removeCallback(); - currentCursorImage.surface = nullptr; + currentCursorImage.commitSurface.reset(); + currentCursorImage.surface.reset(); } else if (currentCursorImage.pBuffer) { wlr_buffer_unlock(currentCursorImage.pBuffer); currentCursorImage.hyprListener_destroyBuffer.removeCallback(); @@ -403,13 +401,13 @@ bool CPointerManager::attemptHardwareCursor(SP hiding"); setHWCursorBuffer(state, nullptr); return true; } - auto buffer = renderHWCursorBuffer(state, texture); + auto buffer = renderHWCursorBuffer(state, **texture); if (!buffer) { Debug::log(TRACE, "[pointer] hw cursor failed rendering"); @@ -451,7 +449,7 @@ bool CPointerManager::setHWCursorBuffer(SP state, wlr_buff return true; } -wlr_buffer* CPointerManager::renderHWCursorBuffer(SP state, wlr_texture* texture) { +wlr_buffer* CPointerManager::renderHWCursorBuffer(SP state, const CTexture& texture) { auto output = state->monitor->output; int w = currentCursorImage.size.x, h = currentCursorImage.size.y; @@ -528,7 +526,7 @@ void CPointerManager::renderSoftwareCursorsFor(SP pMonitor, timespec* if ((!state->hardwareFailed && state->softwareLocks == 0)) { if (currentCursorImage.surface) - wlr_surface_send_frame_done(currentCursorImage.surface->wlr(), now); + currentCursorImage.surface->resource()->frame(now); return; } @@ -542,15 +540,15 @@ void CPointerManager::renderSoftwareCursorsFor(SP pMonitor, timespec* return; auto texture = getCurrentCursorTexture(); - if (!texture) + if (!texture.has_value()) return; box.scale(pMonitor->scale); - g_pHyprOpenGL->renderTextureWithDamage(texture, &box, &damage, 1.F); + g_pHyprOpenGL->renderTextureWithDamage(**texture, &box, &damage, 1.F); if (currentCursorImage.surface) - wlr_surface_send_frame_done(currentCursorImage.surface->wlr(), now); + currentCursorImage.surface->resource()->frame(now); } Vector2D CPointerManager::getCursorPosForMonitor(SP pMonitor) { @@ -762,17 +760,19 @@ void CPointerManager::onMonitorLayoutChange() { damageIfSoftware(); } -wlr_texture* CPointerManager::getCurrentCursorTexture() { - if (!currentCursorImage.pBuffer && (!currentCursorImage.surface || !wlr_surface_get_texture(currentCursorImage.surface->wlr()))) - return nullptr; +std::optional CPointerManager::getCurrentCursorTexture() { + if (!currentCursorImage.pBuffer && (!currentCursorImage.surface || !currentCursorImage.surface->resource()->current.buffer)) + return {}; if (currentCursorImage.pBuffer) { - if (!currentCursorImage.pBufferTexture) + if (!currentCursorImage.pBufferTexture) { currentCursorImage.pBufferTexture = wlr_texture_from_buffer(g_pCompositor->m_sWLRRenderer, currentCursorImage.pBuffer); - return currentCursorImage.pBufferTexture; + currentCursorImage.bufferTex = currentCursorImage.pBufferTexture; + } + return {¤tCursorImage.bufferTex}; } - return wlr_surface_get_texture(currentCursorImage.surface->wlr()); + return {¤tCursorImage.surface->resource()->current.buffer->texture}; } void CPointerManager::attachPointer(SP pointer) { diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp index b6cb0c7a5e76..5404b9c6d3b7 100644 --- a/src/managers/PointerManager.hpp +++ b/src/managers/PointerManager.hpp @@ -11,6 +11,7 @@ class CMonitor; struct wlr_input_device; class IHID; +class CTexture; /* The naming here is a bit confusing. @@ -37,7 +38,7 @@ class CPointerManager { void warpAbsolute(Vector2D abs, SP dev); void setCursorBuffer(wlr_buffer* buf, const Vector2D& hotspot, const float& scale); - void setCursorSurface(CWLSurface* buf, const Vector2D& hotspot); + void setCursorSurface(SP buf, const Vector2D& hotspot); void resetCursorImage(bool apply = true); void lockSoftwareForMonitor(SP pMonitor); @@ -72,11 +73,11 @@ class CPointerManager { // returns the thing in logical coordinates of the monitor CBox getCursorBoxLogicalForMonitor(SP pMonitor); // returns the thing in global coords - CBox getCursorBoxGlobal(); + CBox getCursorBoxGlobal(); - Vector2D transformedHotspot(SP pMonitor); + Vector2D transformedHotspot(SP pMonitor); - wlr_texture* getCurrentCursorTexture(); + std::optional getCurrentCursorTexture(); struct SPointerListener { CHyprSignalListener destroy; @@ -129,8 +130,9 @@ class CPointerManager { } currentMonitorLayout; struct { - wlr_buffer* pBuffer = nullptr; - CWLSurface* surface = nullptr; + wlr_buffer* pBuffer = nullptr; + CTexture bufferTex; + WP surface; wlr_texture* pBufferTexture = nullptr; Vector2D hotspot; @@ -138,7 +140,7 @@ class CPointerManager { float scale = 1.F; CHyprSignalListener destroySurface; - DYNLISTENER(commitSurface); + CHyprSignalListener commitSurface; DYNLISTENER(destroyBuffer); } currentCursorImage; // TODO: support various sizes per-output so we can have pixel-perfect cursors @@ -160,7 +162,7 @@ class CPointerManager { std::vector> monitorStates; SP stateFor(SP mon); bool attemptHardwareCursor(SP state); - wlr_buffer* renderHWCursorBuffer(SP state, wlr_texture* texture); + wlr_buffer* renderHWCursorBuffer(SP state, const CTexture& texture); bool setHWCursorBuffer(SP state, wlr_buffer* buf); struct { diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index feff69e0f41f..411c53f30b35 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -32,17 +32,37 @@ #include "../protocols/DataDeviceWlr.hpp" #include "../protocols/PrimarySelection.hpp" #include "../protocols/XWaylandShell.hpp" +#include "../protocols/Viewporter.hpp" #include "../protocols/core/Seat.hpp" #include "../protocols/core/DataDevice.hpp" +#include "../protocols/core/Compositor.hpp" +#include "../protocols/core/Subcompositor.hpp" +#include "../protocols/core/Output.hpp" +#include "../protocols/core/Shm.hpp" CProtocolManager::CProtocolManager() { + // Outputs are a bit dumb, we have to agree. + static auto P = g_pHookSystem->hookDynamic("monitorAdded", [](void* self, SCallbackInfo& info, std::any param) { + auto M = std::any_cast(param); + PROTO::outputs.emplace(M->szName, std::make_unique(&wl_output_interface, 4, std::format("WLOutput ({})", M->szName), M->self.lock())); + }); + + static auto P2 = g_pHookSystem->hookDynamic("monitorRemoved", [](void* self, SCallbackInfo& info, std::any param) { + auto M = std::any_cast(param); + PROTO::outputs.erase(M->szName); + }); + // Core - PROTO::seat = std::make_unique(&wl_seat_interface, 9, "WLSeat"); - PROTO::data = std::make_unique(&wl_data_device_manager_interface, 3, "WLDataDevice"); + PROTO::seat = std::make_unique(&wl_seat_interface, 9, "WLSeat"); + PROTO::data = std::make_unique(&wl_data_device_manager_interface, 3, "WLDataDevice"); + PROTO::compositor = std::make_unique(&wl_compositor_interface, 6, "WLCompositor"); + PROTO::subcompositor = std::make_unique(&wl_subcompositor_interface, 1, "WLSubcompositor"); + PROTO::shm = std::make_unique(&wl_shm_interface, 1, "WLSHM"); // Extensions + PROTO::viewport = std::make_unique(&wp_viewporter_interface, 1, "Viewporter"); PROTO::tearing = std::make_unique(&wp_tearing_control_manager_v1_interface, 1, "TearingControl"); PROTO::fractional = std::make_unique(&wp_fractional_scale_manager_v1_interface, 1, "FractionalScale"); PROTO::xdgOutput = std::make_unique(&zxdg_output_manager_v1_interface, 3, "XDGOutput"); diff --git a/src/managers/SeatManager.cpp b/src/managers/SeatManager.cpp index ce40650d8fb2..78a22501c1d5 100644 --- a/src/managers/SeatManager.cpp +++ b/src/managers/SeatManager.cpp @@ -3,6 +3,7 @@ #include "../protocols/core/DataDevice.hpp" #include "../protocols/DataDeviceWlr.hpp" #include "../protocols/PrimarySelection.hpp" +#include "../protocols/core/Compositor.hpp" #include "../Compositor.hpp" #include "../devices/IKeyboard.hpp" #include @@ -98,7 +99,7 @@ void CSeatManager::updateActiveKeyboardData() { PROTO::seat->updateKeymap(); } -void CSeatManager::setKeyboardFocus(wlr_surface* surf) { +void CSeatManager::setKeyboardFocus(SP surf) { if (state.keyboardFocus == surf) return; @@ -107,7 +108,7 @@ void CSeatManager::setKeyboardFocus(wlr_surface* surf) { return; } - hyprListener_keyboardSurfaceDestroy.removeCallback(); + listeners.keyboardSurfaceDestroy.reset(); if (state.keyboardFocusResource) { // we will iterate over all bound wl_seat @@ -138,7 +139,7 @@ void CSeatManager::setKeyboardFocus(wlr_surface* surf) { return; } - auto client = wl_resource_get_client(surf->resource); + auto client = surf->client(); for (auto& r : seatResources | std::views::reverse) { if (r->resource->client() != client) continue; @@ -153,8 +154,7 @@ void CSeatManager::setKeyboardFocus(wlr_surface* surf) { } } - hyprListener_keyboardSurfaceDestroy.initCallback( - &surf->events.destroy, [this](void* owner, void* data) { setKeyboardFocus(nullptr); }, nullptr, "CSeatManager"); + listeners.keyboardSurfaceDestroy = surf->events.destroy.registerListener([this](std::any d) { setKeyboardFocus(nullptr); }); events.keyboardFocusChange.emit(); } @@ -183,7 +183,7 @@ void CSeatManager::sendKeyboardMods(uint32_t depressed, uint32_t latched, uint32 } } -void CSeatManager::setPointerFocus(wlr_surface* surf, const Vector2D& local) { +void CSeatManager::setPointerFocus(SP surf, const Vector2D& local) { if (state.pointerFocus == surf) return; @@ -192,7 +192,7 @@ void CSeatManager::setPointerFocus(wlr_surface* surf, const Vector2D& local) { return; } - hyprListener_pointerSurfaceDestroy.removeCallback(); + listeners.pointerSurfaceDestroy.reset(); if (state.pointerFocusResource) { auto client = state.pointerFocusResource->client(); @@ -220,7 +220,7 @@ void CSeatManager::setPointerFocus(wlr_surface* surf, const Vector2D& local) { return; } - auto client = wl_resource_get_client(surf->resource); + auto client = surf->client(); for (auto& r : seatResources | std::views::reverse) { if (r->resource->client() != client) continue; @@ -239,8 +239,7 @@ void CSeatManager::setPointerFocus(wlr_surface* surf, const Vector2D& local) { sendPointerFrame(); - hyprListener_pointerSurfaceDestroy.initCallback( - &surf->events.destroy, [this](void* owner, void* data) { setPointerFocus(nullptr, {}); }, nullptr, "CSeatManager"); + listeners.pointerSurfaceDestroy = surf->events.destroy.registerListener([this](std::any d) { setPointerFocus(nullptr, {}); }); events.pointerFocusChange.emit(); } @@ -311,11 +310,11 @@ void CSeatManager::sendPointerAxis(uint32_t timeMs, wl_pointer_axis axis, double } } -void CSeatManager::sendTouchDown(wlr_surface* surf, uint32_t timeMs, int32_t id, const Vector2D& local) { +void CSeatManager::sendTouchDown(SP surf, uint32_t timeMs, int32_t id, const Vector2D& local) { if (state.touchFocus == surf) return; - hyprListener_touchSurfaceDestroy.removeCallback(); + listeners.touchSurfaceDestroy.reset(); if (state.touchFocusResource) { auto client = state.touchFocusResource->client(); @@ -340,7 +339,7 @@ void CSeatManager::sendTouchDown(wlr_surface* surf, uint32_t timeMs, int32_t id, return; } - auto client = wl_resource_get_client(surf->resource); + auto client = surf->client(); for (auto& r : seatResources | std::views::reverse) { if (r->resource->client() != client) continue; @@ -354,8 +353,7 @@ void CSeatManager::sendTouchDown(wlr_surface* surf, uint32_t timeMs, int32_t id, } } - hyprListener_touchSurfaceDestroy.initCallback( - &surf->events.destroy, [this, timeMs, id](void* owner, void* data) { sendTouchUp(timeMs + 10, id); }, nullptr, "CSeatManager"); + listeners.touchSurfaceDestroy = surf->events.destroy.registerListener([this, timeMs, id](std::any d) { sendTouchUp(timeMs + 10, id); }); events.touchFocusChange.emit(); } @@ -432,7 +430,7 @@ void CSeatManager::refocusGrab() { // try to find a surf in focus first const auto MOUSE = g_pInputManager->getMouseCoordsInternal(); for (auto& s : seatGrab->surfs) { - auto hlSurf = CWLSurface::surfaceFromWlr(s); + auto hlSurf = CWLSurface::fromResource(s.lock()); if (!hlSurf) continue; @@ -444,13 +442,13 @@ void CSeatManager::refocusGrab() { continue; if (seatGrab->keyboard) - setKeyboardFocus(s); + setKeyboardFocus(s.lock()); if (seatGrab->pointer) - setPointerFocus(s, MOUSE - b->pos()); + setPointerFocus(s.lock(), MOUSE - b->pos()); return; } - wlr_surface* surf = seatGrab->surfs.at(0); + SP surf = seatGrab->surfs.at(0).lock(); if (seatGrab->keyboard) setKeyboardFocus(surf); if (seatGrab->pointer) @@ -458,7 +456,7 @@ void CSeatManager::refocusGrab() { } } -void CSeatManager::onSetCursor(SP seatResource, uint32_t serial, wlr_surface* surf, const Vector2D& hotspot) { +void CSeatManager::onSetCursor(SP seatResource, uint32_t serial, SP surf, const Vector2D& hotspot) { if (!state.pointerFocusResource || !seatResource || seatResource->client() != state.pointerFocusResource->client()) { Debug::log(LOG, "[seatmgr] Rejecting a setCursor because the client ain't in focus"); return; @@ -545,10 +543,10 @@ void CSeatManager::setGrab(SP grab) { } void CSeatManager::resendEnterEvents() { - wlr_surface* kb = state.keyboardFocus; - wlr_surface* pt = state.pointerFocus; + SP kb = state.keyboardFocus.lock(); + SP pt = state.pointerFocus.lock(); - auto last = lastLocalCoords; + auto last = lastLocalCoords; setKeyboardFocus(nullptr); setPointerFocus(nullptr, {}); @@ -557,15 +555,15 @@ void CSeatManager::resendEnterEvents() { setPointerFocus(pt, last); } -bool CSeatGrab::accepts(wlr_surface* surf) { +bool CSeatGrab::accepts(SP surf) { return std::find(surfs.begin(), surfs.end(), surf) != surfs.end(); } -void CSeatGrab::add(wlr_surface* surf) { +void CSeatGrab::add(SP surf) { surfs.push_back(surf); } -void CSeatGrab::remove(wlr_surface* surf) { +void CSeatGrab::remove(SP surf) { std::erase(surfs, surf); if ((keyboard && g_pSeatManager->state.keyboardFocus == surf) || (pointer && g_pSeatManager->state.pointerFocus == surf)) g_pSeatManager->refocusGrab(); diff --git a/src/managers/SeatManager.hpp b/src/managers/SeatManager.hpp index b88058a8fc7a..347627c8dac5 100644 --- a/src/managers/SeatManager.hpp +++ b/src/managers/SeatManager.hpp @@ -28,9 +28,9 @@ class IKeyboard; */ class CSeatGrab { public: - bool accepts(wlr_surface* surf); - void add(wlr_surface* surf); - void remove(wlr_surface* surf); + bool accepts(SP surf); + void add(SP surf); + void remove(SP surf); void setCallback(std::function onEnd_); void clear(); @@ -41,8 +41,8 @@ class CSeatGrab { bool removeOnInput = true; // on hard input e.g. click outside, remove private: - std::vector surfs; // read-only - std::function onEnd; + std::vector> surfs; + std::function onEnd; friend class CSeatManager; }; @@ -56,18 +56,18 @@ class CSeatManager { void setKeyboard(SP keeb); void updateActiveKeyboardData(); // updates the clients with the keymap and repeat info - void setKeyboardFocus(wlr_surface* surf); + void setKeyboardFocus(SP surf); void sendKeyboardKey(uint32_t timeMs, uint32_t key, wl_keyboard_key_state state); void sendKeyboardMods(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); - void setPointerFocus(wlr_surface* surf, const Vector2D& local); + void setPointerFocus(SP surf, const Vector2D& local); void sendPointerMotion(uint32_t timeMs, const Vector2D& local); void sendPointerButton(uint32_t timeMs, uint32_t key, wl_pointer_button_state state); void sendPointerFrame(); void sendPointerFrame(WP pResource); void sendPointerAxis(uint32_t timeMs, wl_pointer_axis axis, double value, int32_t discrete, wl_pointer_axis_source source, wl_pointer_axis_relative_direction relative); - void sendTouchDown(wlr_surface* surf, uint32_t timeMs, int32_t id, const Vector2D& local); + void sendTouchDown(SP surf, uint32_t timeMs, int32_t id, const Vector2D& local); void sendTouchUp(uint32_t timeMs, int32_t id); void sendTouchMotion(uint32_t timeMs, int32_t id, const Vector2D& local); void sendTouchFrame(); @@ -81,24 +81,24 @@ class CSeatManager { // pops the serial if it was valid, meaning it is consumed. bool serialValid(SP seatResource, uint32_t serial); - void onSetCursor(SP seatResource, uint32_t serial, wlr_surface* surf, const Vector2D& hotspot); + void onSetCursor(SP seatResource, uint32_t serial, SP surf, const Vector2D& hotspot); SP seatResourceForClient(wl_client* client); struct { - wlr_surface* keyboardFocus = nullptr; - WP keyboardFocusResource; + WP keyboardFocus; + WP keyboardFocusResource; - wlr_surface* pointerFocus = nullptr; - WP pointerFocusResource; + WP pointerFocus; + WP pointerFocusResource; - wlr_surface* touchFocus = nullptr; - WP touchFocusResource; + WP touchFocus; + WP touchFocusResource; } state; struct SSetCursorEvent { - wlr_surface* surf = nullptr; - Vector2D hotspot; + SP surf = nullptr; + Vector2D hotspot; }; struct { @@ -147,14 +147,13 @@ class CSeatManager { struct { CHyprSignalListener newSeatResource; + CHyprSignalListener keyboardSurfaceDestroy; + CHyprSignalListener pointerSurfaceDestroy; + CHyprSignalListener touchSurfaceDestroy; } listeners; Vector2D lastLocalCoords; - DYNLISTENER(keyboardSurfaceDestroy); - DYNLISTENER(pointerSurfaceDestroy); - DYNLISTENER(touchSurfaceDestroy); - friend struct SSeatResourceContainer; friend class CSeatGrab; }; diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index fd4841f4046d..3bec1c4b23d7 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -20,7 +20,7 @@ SSessionLockSurface::SSessionLockSurface(SP surface_) : sur listeners.destroy = surface_->events.destroy.registerListener([this](std::any data) { if (pWlrSurface == g_pCompositor->m_pLastFocus) - g_pCompositor->m_pLastFocus = nullptr; + g_pCompositor->m_pLastFocus.reset(); g_pSessionLockManager->removeSessionLockSurface(this); }); @@ -70,7 +70,7 @@ void CSessionLockManager::onNewSessionLock(SP pLock) { g_pHyprRenderer->damageMonitor(m.get()); }); - m_pSessionLock->listeners.destroy = pLock->events.destroyed.registerListener([this](std::any data) { + m_pSessionLock->listeners.destroy = pLock->events.destroyed.registerListener([](std::any data) { g_pCompositor->focusSurface(nullptr); for (auto& m : g_pCompositor->m_vMonitors) @@ -117,7 +117,7 @@ float CSessionLockManager::getRedScreenAlphaForMonitor(uint64_t id) { return std::clamp(NOMAPPEDSURFACETIMER->second.getSeconds() - /* delay for screencopy */ 0.5f, 0.f, 1.f); } -bool CSessionLockManager::isSurfaceSessionLock(wlr_surface* pSurface) { +bool CSessionLockManager::isSurfaceSessionLock(SP pSurface) { // TODO: this has some edge cases when it's wrong (e.g. destroyed lock but not yet surfaces) // but can be easily fixed when I rewrite wlr_surface diff --git a/src/managers/SessionLockManager.hpp b/src/managers/SessionLockManager.hpp index d655a2bcc91f..49cfa1fda1ed 100644 --- a/src/managers/SessionLockManager.hpp +++ b/src/managers/SessionLockManager.hpp @@ -13,8 +13,8 @@ struct SSessionLockSurface { SSessionLockSurface(SP surface_); WP surface; - wlr_surface* pWlrSurface = nullptr; - uint64_t iMonitorID = -1; + WP pWlrSurface; + uint64_t iMonitorID = -1; bool mapped = false; @@ -49,7 +49,7 @@ class CSessionLockManager { bool isSessionLocked(); bool isSessionLockPresent(); - bool isSurfaceSessionLock(wlr_surface*); + bool isSurfaceSessionLock(SP); void removeSessionLockSurface(SSessionLockSurface*); diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 4aebefcb44b1..4641c6f89ff6 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -3,6 +3,7 @@ #include "../events/Events.hpp" #include "../config/ConfigValue.hpp" #include "../protocols/XDGShell.hpp" +#include "../protocols/core/Compositor.hpp" #include "../xwayland/XWayland.hpp" #define OUTPUT_MANAGER_VERSION 3 @@ -19,11 +20,11 @@ CHyprXWaylandManager::~CHyprXWaylandManager() { #endif } -wlr_surface* CHyprXWaylandManager::getWindowSurface(PHLWINDOW pWindow) { - return pWindow->m_pWLSurface.wlr(); +SP CHyprXWaylandManager::getWindowSurface(PHLWINDOW pWindow) { + return pWindow->m_pWLSurface->resource(); } -void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate) { +void CHyprXWaylandManager::activateSurface(SP pSurface, bool activate) { if (!pSurface) return; @@ -33,7 +34,7 @@ void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate) if (!w->m_bIsMapped) continue; - if (w->m_pWLSurface.wlr() != pSurface) + if (w->m_pWLSurface->resource() != pSurface) continue; if (w->m_bIsX11) { @@ -131,8 +132,8 @@ void CHyprXWaylandManager::setWindowSize(PHLWINDOW pWindow, Vector2D size, bool pWindow->m_vPendingSizeAcks.push_back(std::make_pair<>(pWindow->m_pXDGSurface->toplevel->setSize(size), size.floor())); } -wlr_surface* CHyprXWaylandManager::surfaceAt(PHLWINDOW pWindow, const Vector2D& client, Vector2D& surface) { - return wlr_surface_surface_at(pWindow->m_pWLSurface.wlr(), client.x, client.y, &surface.x, &surface.y); +SP CHyprXWaylandManager::surfaceAt(PHLWINDOW pWindow, const Vector2D& client, Vector2D& surface) { + return pWindow->m_pWLSurface->resource()->at(client + surface); } bool CHyprXWaylandManager::shouldBeFloated(PHLWINDOW pWindow, bool pending) { diff --git a/src/managers/XWaylandManager.hpp b/src/managers/XWaylandManager.hpp index 5bbab802a7c8..ebe819f9e0a9 100644 --- a/src/managers/XWaylandManager.hpp +++ b/src/managers/XWaylandManager.hpp @@ -11,19 +11,19 @@ class CHyprXWaylandManager { CHyprXWaylandManager(); ~CHyprXWaylandManager(); - wlr_surface* getWindowSurface(PHLWINDOW); - void activateSurface(wlr_surface*, bool); - void activateWindow(PHLWINDOW, bool); - void getGeometryForWindow(PHLWINDOW, CBox*); - void sendCloseWindow(PHLWINDOW); - void setWindowSize(PHLWINDOW, Vector2D, bool force = false); - void setWindowFullscreen(PHLWINDOW, bool); - wlr_surface* surfaceAt(PHLWINDOW, const Vector2D&, Vector2D&); - bool shouldBeFloated(PHLWINDOW, bool pending = false); - void checkBorders(PHLWINDOW); - Vector2D getMaxSizeForWindow(PHLWINDOW); - Vector2D getMinSizeForWindow(PHLWINDOW); - Vector2D xwaylandToWaylandCoords(const Vector2D&); + SP getWindowSurface(PHLWINDOW); + void activateSurface(SP, bool); + void activateWindow(PHLWINDOW, bool); + void getGeometryForWindow(PHLWINDOW, CBox*); + void sendCloseWindow(PHLWINDOW); + void setWindowSize(PHLWINDOW, Vector2D, bool force = false); + void setWindowFullscreen(PHLWINDOW, bool); + SP surfaceAt(PHLWINDOW, const Vector2D&, Vector2D&); + bool shouldBeFloated(PHLWINDOW, bool pending = false); + void checkBorders(PHLWINDOW); + Vector2D getMaxSizeForWindow(PHLWINDOW); + Vector2D getMinSizeForWindow(PHLWINDOW); + Vector2D xwaylandToWaylandCoords(const Vector2D&); }; inline std::unique_ptr g_pXWaylandManager; \ No newline at end of file diff --git a/src/managers/input/IdleInhibitor.cpp b/src/managers/input/IdleInhibitor.cpp index a71059e45ad4..a38acdbfa372 100644 --- a/src/managers/input/IdleInhibitor.cpp +++ b/src/managers/input/IdleInhibitor.cpp @@ -14,7 +14,7 @@ void CInputManager::newIdleInhibitor(std::any inhibitor) { recheckIdleInhibitorStatus(); }); - auto WLSurface = CWLSurface::surfaceFromWlr(PINHIBIT->inhibitor->surface); + auto WLSurface = CWLSurface::fromResource(PINHIBIT->inhibitor->surface.lock()); if (!WLSurface) { Debug::log(LOG, "Inhibitor has no HL Surface attached to it, likely meaning it's a non-desktop element. Assuming it's visible."); @@ -37,7 +37,7 @@ void CInputManager::recheckIdleInhibitorStatus() { return; } - auto WLSurface = CWLSurface::surfaceFromWlr(ii->inhibitor->surface); + auto WLSurface = CWLSurface::fromResource(ii->inhibitor->surface.lock()); if (!WLSurface) continue; diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 5a7688cddd37..8f9187ed14fc 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -42,7 +42,7 @@ CInputManager::CInputManager() { Debug::log(LOG, "cursorImage request: shape {} -> {}", (uint32_t)event.shape, event.shapeName); - m_sCursorSurfaceInfo.wlSurface.unassign(); + m_sCursorSurfaceInfo.wlSurface->unassign(); m_sCursorSurfaceInfo.vHotspot = {}; m_sCursorSurfaceInfo.name = event.shapeName; m_sCursorSurfaceInfo.hidden = false; @@ -57,6 +57,8 @@ CInputManager::CInputManager() { m_sListeners.newVirtualMouse = PROTO::virtualPointer->events.newPointer.registerListener([this](std::any data) { this->newVirtualMouse(std::any_cast>(data)); }); m_sListeners.setCursor = g_pSeatManager->events.setCursor.registerListener([this](std::any d) { this->processMouseRequest(d); }); + + m_sCursorSurfaceInfo.wlSurface = CWLSurface::create(); } CInputManager::~CInputManager() { @@ -114,8 +116,8 @@ void CInputManager::sendMotionEventsToFocused() { return; // todo: this sucks ass - const auto PWINDOW = g_pCompositor->getWindowFromSurface(g_pCompositor->m_pLastFocus); - const auto PLS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus); + const auto PWINDOW = g_pCompositor->getWindowFromSurface(g_pCompositor->m_pLastFocus.lock()); + const auto PLS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus.lock()); timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -124,7 +126,7 @@ void CInputManager::sendMotionEventsToFocused() { m_bEmptyFocusCursorSet = false; - g_pSeatManager->setPointerFocus(g_pCompositor->m_pLastFocus, LOCAL); + g_pSeatManager->setPointerFocus(g_pCompositor->m_pLastFocus.lock(), LOCAL); } void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { @@ -140,14 +142,14 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { const auto FOLLOWMOUSE = *PFOLLOWONDND && PROTO::data->dndActive() ? 1 : *PFOLLOWMOUSE; - m_pFoundSurfaceToFocus = nullptr; + m_pFoundSurfaceToFocus.reset(); m_pFoundLSToFocus.reset(); m_pFoundWindowToFocus.reset(); - wlr_surface* foundSurface = nullptr; - Vector2D surfaceCoords; - Vector2D surfacePos = Vector2D(-1337, -1337); - PHLWINDOW pFoundWindow; - PHLLS pFoundLayerSurface; + SP foundSurface; + Vector2D surfaceCoords; + Vector2D surfacePos = Vector2D(-1337, -1337); + PHLWINDOW pFoundWindow; + PHLLS pFoundLayerSurface; if (!g_pCompositor->m_bReadyToProcess || g_pCompositor->m_bIsShuttingDown || g_pCompositor->m_bUnsafeState) return; @@ -190,12 +192,12 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (forcedFocus) { pFoundWindow = forcedFocus; surfacePos = pFoundWindow->m_vRealPosition.value(); - foundSurface = pFoundWindow->m_pWLSurface.wlr(); + foundSurface = pFoundWindow->m_pWLSurface->resource(); } // constraints if (!g_pSeatManager->mouse.expired() && isConstrained()) { - const auto SURF = CWLSurface::surfaceFromWlr(g_pCompositor->m_pLastFocus); + const auto SURF = CWLSurface::fromResource(g_pCompositor->m_pLastFocus.lock()); const auto CONSTRAINT = SURF->constraint(); if (SURF && CONSTRAINT) { @@ -222,7 +224,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { // if we are holding a pointer button, // and we're not dnd-ing, don't refocus. Keep focus on last surface. if (!PROTO::data->dndActive() && !m_lCurrentlyHeldButtons.empty() && g_pCompositor->m_pLastFocus && g_pSeatManager->state.pointerFocus && !m_bHardInput) { - foundSurface = g_pSeatManager->state.pointerFocus; + foundSurface = g_pSeatManager->state.pointerFocus.lock(); // IME popups aren't desktop-like elements // TODO: make them. @@ -232,7 +234,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { m_bFocusHeldByButtons = true; m_bRefocusHeldByButtons = refocus; } else { - auto HLSurface = CWLSurface::surfaceFromWlr(foundSurface); + auto HLSurface = CWLSurface::fromResource(foundSurface); if (HLSurface) { const auto BOX = HLSurface->getSurfaceBoxGlobal(); @@ -274,7 +276,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (!foundSurface) { auto popup = g_pInputManager->m_sIMERelay.popupFromCoords(mouseCoords); if (popup) { - foundSurface = popup->getWlrSurface(); + foundSurface = popup->getSurface(); surfacePos = popup->globalBox().pos(); } } @@ -305,7 +307,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords); surfacePos = Vector2D(-1337, -1337); } else { - foundSurface = pFoundWindow->m_pWLSurface.wlr(); + foundSurface = pFoundWindow->m_pWLSurface->resource(); surfacePos = pFoundWindow->m_vRealPosition.value(); } } @@ -344,7 +346,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (!pFoundWindow->m_bIsX11) { foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords); } else { - foundSurface = pFoundWindow->m_pWLSurface.wlr(); + foundSurface = pFoundWindow->m_pWLSurface->resource(); surfacePos = pFoundWindow->m_vRealPosition.value(); } } @@ -368,9 +370,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { return; // setGrab will refocus } else { // we need to grab the last surface. - foundSurface = g_pSeatManager->state.pointerFocus; + foundSurface = g_pSeatManager->state.pointerFocus.lock(); - auto HLSurface = CWLSurface::surfaceFromWlr(foundSurface); + auto HLSurface = CWLSurface::fromResource(foundSurface); if (HLSurface) { const auto BOX = HLSurface->getSurfaceBoxGlobal(); @@ -422,7 +424,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { bool allowKeyboardRefocus = true; if (!refocus && g_pCompositor->m_pLastFocus) { - const auto PLS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus); + const auto PLS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus.lock()); if (PLS && PLS->layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) allowKeyboardRefocus = false; @@ -440,7 +442,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { return; } - if (pFoundWindow && foundSurface == pFoundWindow->m_pWLSurface.wlr() && !m_bCursorImageOverridden) { + if (pFoundWindow && foundSurface == pFoundWindow->m_pWLSurface->resource() && !m_bCursorImageOverridden) { const auto BOX = pFoundWindow->getWindowMainSurfaceBox(); if (!VECINRECT(mouseCoords, BOX.x, BOX.y, BOX.x + BOX.width, BOX.y + BOX.height)) setCursorImageOverride("left_ptr"); @@ -554,11 +556,11 @@ void CInputManager::processMouseRequest(std::any E) { Debug::log(LOG, "cursorImage request: surface {:x}", (uintptr_t)e.surf); - if (e.surf != m_sCursorSurfaceInfo.wlSurface.wlr()) { - m_sCursorSurfaceInfo.wlSurface.unassign(); + if (e.surf != m_sCursorSurfaceInfo.wlSurface->resource()) { + m_sCursorSurfaceInfo.wlSurface->unassign(); if (e.surf) - m_sCursorSurfaceInfo.wlSurface.assign(e.surf); + m_sCursorSurfaceInfo.wlSurface->assign(e.surf); } if (e.surf) { @@ -572,7 +574,7 @@ void CInputManager::processMouseRequest(std::any E) { m_sCursorSurfaceInfo.name = ""; m_sCursorSurfaceInfo.inUse = true; - g_pHyprRenderer->setCursorSurface(&m_sCursorSurfaceInfo.wlSurface, e.hotspot.x, e.hotspot.y); + g_pHyprRenderer->setCursorSurface(m_sCursorSurfaceInfo.wlSurface, e.hotspot.x, e.hotspot.y); } void CInputManager::restoreCursorIconToApp() { @@ -585,8 +587,8 @@ void CInputManager::restoreCursorIconToApp() { } if (m_sCursorSurfaceInfo.name.empty()) { - if (m_sCursorSurfaceInfo.wlSurface.exists()) - g_pHyprRenderer->setCursorSurface(&m_sCursorSurfaceInfo.wlSurface, m_sCursorSurfaceInfo.vHotspot.x, m_sCursorSurfaceInfo.vHotspot.y); + if (m_sCursorSurfaceInfo.wlSurface->exists()) + g_pHyprRenderer->setCursorSurface(m_sCursorSurfaceInfo.wlSurface, m_sCursorSurfaceInfo.vHotspot.x, m_sCursorSurfaceInfo.vHotspot.y); } else { g_pHyprRenderer->setCursorFromName(m_sCursorSurfaceInfo.name); } @@ -695,7 +697,7 @@ void CInputManager::processMouseDownNormal(const IPointer::SButtonEvent& e) { if (!g_pSeatManager->state.pointerFocus) break; - auto HLSurf = CWLSurface::surfaceFromWlr(g_pSeatManager->state.pointerFocus); + auto HLSurf = CWLSurface::fromResource(g_pSeatManager->state.pointerFocus.lock()); if (HLSurf && HLSurf->getWindow()) g_pCompositor->changeWindowZOrder(HLSurf->getWindow(), true); @@ -1397,7 +1399,7 @@ bool CInputManager::isConstrained() { if (!C) continue; - if (!C->isActive() || C->owner()->wlr() != g_pCompositor->m_pLastFocus) + if (!C->isActive() || C->owner()->resource() != g_pCompositor->m_pLastFocus) continue; return true; diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index f7d9ae576242..9fdf061c288b 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -44,10 +44,10 @@ enum eBorderIconDirection { }; struct STouchData { - PHLWINDOWREF touchFocusWindow; - PHLLSREF touchFocusLS; - wlr_surface* touchFocusSurface = nullptr; - Vector2D touchSurfaceOrigin; + PHLWINDOWREF touchFocusWindow; + PHLLSREF touchFocusLS; + WP touchFocusSurface; + Vector2D touchSurfaceOrigin; }; // The third row is always 0 0 1 and is not expected by `libinput_device_config_calibration_set_matrix` @@ -236,9 +236,9 @@ class CInputManager { void applyConfigToKeyboard(SP); // this will be set after a refocus() - wlr_surface* m_pFoundSurfaceToFocus = nullptr; - PHLLSREF m_pFoundLSToFocus; - PHLWINDOWREF m_pFoundWindowToFocus; + WP m_pFoundSurfaceToFocus; + PHLLSREF m_pFoundLSToFocus; + PHLWINDOWREF m_pFoundWindowToFocus; // for holding focus on buttons held bool m_bFocusHeldByButtons = false; @@ -268,11 +268,11 @@ class CInputManager { // cursor surface struct cursorSI { - bool hidden = false; // null surface = hidden - CWLSurface wlSurface; - Vector2D vHotspot; - std::string name; // if not empty, means set by name. - bool inUse = false; + bool hidden = false; // null surface = hidden + SP wlSurface; + Vector2D vHotspot; + std::string name; // if not empty, means set by name. + bool inUse = false; } m_sCursorSurfaceInfo; void restoreCursorIconToApp(); // no-op if restored diff --git a/src/managers/input/InputMethodPopup.cpp b/src/managers/input/InputMethodPopup.cpp index 9ff584e64da7..a8757030de25 100644 --- a/src/managers/input/InputMethodPopup.cpp +++ b/src/managers/input/InputMethodPopup.cpp @@ -3,22 +3,24 @@ #include "../../Compositor.hpp" #include "../../protocols/FractionalScale.hpp" #include "../../protocols/InputMethodV2.hpp" +#include "../../protocols/core/Compositor.hpp" CInputPopup::CInputPopup(SP popup_) : popup(popup_) { listeners.commit = popup_->events.commit.registerListener([this](std::any d) { onCommit(); }); listeners.map = popup_->events.map.registerListener([this](std::any d) { onMap(); }); listeners.unmap = popup_->events.unmap.registerListener([this](std::any d) { onUnmap(); }); listeners.destroy = popup_->events.destroy.registerListener([this](std::any d) { onDestroy(); }); - surface.assign(popup_->surface()); + surface = CWLSurface::create(); + surface->assign(popup_->surface()); } -CWLSurface* CInputPopup::queryOwner() { +SP CInputPopup::queryOwner() { const auto FOCUSED = g_pInputManager->m_sIMERelay.getFocusedTextInput(); if (!FOCUSED) return nullptr; - return CWLSurface::surfaceFromWlr(FOCUSED->focusedSurface()); + return CWLSurface::fromResource(FOCUSED->focusedSurface()); } void CInputPopup::onDestroy() { @@ -36,7 +38,7 @@ void CInputPopup::onMap() { if (!PMONITOR) return; - PROTO::fractional->sendScale(surface.wlr(), PMONITOR->scale); + PROTO::fractional->sendScale(surface->resource(), PMONITOR->scale); } void CInputPopup::onUnmap() { @@ -69,7 +71,7 @@ void CInputPopup::damageSurface() { } Vector2D pos = globalBox().pos(); - g_pHyprRenderer->damageSurface(surface.wlr(), pos.x, pos.y); + g_pHyprRenderer->damageSurface(surface->resource(), pos.x, pos.y); } void CInputPopup::updateBox() { @@ -98,7 +100,7 @@ void CInputPopup::updateBox() { cursorBoxParent = {0, 0, (int)parentBox.w, (int)parentBox.h}; } - Vector2D currentPopupSize = surface.getViewporterCorrectedSize(); + Vector2D currentPopupSize = surface->getViewporterCorrectedSize(); CMonitor* pMonitor = g_pCompositor->getMonitorFromVector(parentBox.middle()); @@ -127,9 +129,9 @@ void CInputPopup::updateBox() { const auto PML = g_pCompositor->getMonitorFromID(lastMonitor); if (PML) - wlr_surface_send_leave(surface.wlr(), PML->output); + surface->resource()->leave(PML->self.lock()); - wlr_surface_send_enter(surface.wlr(), PM->output); + surface->resource()->enter(PM->self.lock()); lastMonitor = PM->ID; } @@ -151,6 +153,6 @@ bool CInputPopup::isVecInPopup(const Vector2D& point) { return globalBox().containsPoint(point); } -wlr_surface* CInputPopup::getWlrSurface() { - return surface.wlr(); +SP CInputPopup::getSurface() { + return surface->resource(); } diff --git a/src/managers/input/InputMethodPopup.hpp b/src/managers/input/InputMethodPopup.hpp index 61b45d7483da..9c5491bf54e8 100644 --- a/src/managers/input/InputMethodPopup.hpp +++ b/src/managers/input/InputMethodPopup.hpp @@ -12,18 +12,18 @@ class CInputPopup { public: CInputPopup(SP popup); - void damageEntire(); - void damageSurface(); + void damageEntire(); + void damageSurface(); - bool isVecInPopup(const Vector2D& point); + bool isVecInPopup(const Vector2D& point); - CBox globalBox(); - wlr_surface* getWlrSurface(); + CBox globalBox(); + SP getSurface(); - void onCommit(); + void onCommit(); private: - CWLSurface* queryOwner(); + SP queryOwner(); void updateBox(); void onDestroy(); @@ -31,7 +31,7 @@ class CInputPopup { void onUnmap(); WP popup; - CWLSurface surface; + SP surface; CBox lastBoxLocal; uint64_t lastMonitor = -1; diff --git a/src/managers/input/InputMethodRelay.cpp b/src/managers/input/InputMethodRelay.cpp index abf18fba4559..92ab14d8cbba 100644 --- a/src/managers/input/InputMethodRelay.cpp +++ b/src/managers/input/InputMethodRelay.cpp @@ -3,9 +3,11 @@ #include "../../Compositor.hpp" #include "../../protocols/TextInputV3.hpp" #include "../../protocols/InputMethodV2.hpp" +#include "../../protocols/core/Compositor.hpp" CInputMethodRelay::CInputMethodRelay() { - static auto P = g_pHookSystem->hookDynamic("keyboardFocus", [&](void* self, SCallbackInfo& info, std::any param) { onKeyboardFocus(std::any_cast(param)); }); + static auto P = + g_pHookSystem->hookDynamic("keyboardFocus", [&](void* self, SCallbackInfo& info, std::any param) { onKeyboardFocus(std::any_cast>(param)); }); listeners.newTIV3 = PROTO::textInputV3->events.newTextInput.registerListener([this](std::any ti) { onNewTextInput(ti); }); listeners.newIME = PROTO::ime->events.newIME.registerListener([this](std::any ime) { onNewIME(std::any_cast>(ime)); }); @@ -54,17 +56,17 @@ void CInputMethodRelay::onNewIME(SP pIME) { return; for (auto& ti : m_vTextInputs) { - if (ti->client() != wl_resource_get_client(g_pCompositor->m_pLastFocus->resource)) + if (ti->client() != g_pCompositor->m_pLastFocus->client()) continue; if (ti->isV3()) - ti->enter(g_pCompositor->m_pLastFocus); + ti->enter(g_pCompositor->m_pLastFocus.lock()); else - ti->onEnabled(g_pCompositor->m_pLastFocus); + ti->onEnabled(g_pCompositor->m_pLastFocus.lock()); } } -void CInputMethodRelay::setIMEPopupFocus(CInputPopup* pPopup, wlr_surface* pSurface) { +void CInputMethodRelay::setIMEPopupFocus(CInputPopup* pPopup, SP pSurface) { pPopup->onCommit(); } @@ -125,7 +127,7 @@ void CInputMethodRelay::commitIMEState(CTextInput* pInput) { pInput->commitStateToIME(m_pIME.lock()); } -void CInputMethodRelay::onKeyboardFocus(wlr_surface* pSurface) { +void CInputMethodRelay::onKeyboardFocus(SP pSurface) { if (m_pIME.expired()) return; @@ -145,7 +147,7 @@ void CInputMethodRelay::onKeyboardFocus(wlr_surface* pSurface) { if (!ti->isV3()) continue; - if (ti->client() != wl_resource_get_client(pSurface->resource)) + if (ti->client() != pSurface->client()) continue; ti->enter(pSurface); @@ -161,9 +163,9 @@ CInputPopup* CInputMethodRelay::popupFromCoords(const Vector2D& point) { return nullptr; } -CInputPopup* CInputMethodRelay::popupFromSurface(const wlr_surface* surface) { +CInputPopup* CInputMethodRelay::popupFromSurface(const SP surface) { for (auto& p : m_vIMEPopups) { - if (p->getWlrSurface() == surface) + if (p->getSurface() == surface) return p.get(); } diff --git a/src/managers/input/InputMethodRelay.hpp b/src/managers/input/InputMethodRelay.hpp index 2896e8e8ee59..e942add89e7d 100644 --- a/src/managers/input/InputMethodRelay.hpp +++ b/src/managers/input/InputMethodRelay.hpp @@ -26,15 +26,15 @@ class CInputMethodRelay { void commitIMEState(CTextInput* pInput); void removeTextInput(CTextInput* pInput); - void onKeyboardFocus(wlr_surface*); + void onKeyboardFocus(SP); CTextInput* getFocusedTextInput(); - void setIMEPopupFocus(CInputPopup*, wlr_surface*); + void setIMEPopupFocus(CInputPopup*, SP); void removePopup(CInputPopup*); CInputPopup* popupFromCoords(const Vector2D& point); - CInputPopup* popupFromSurface(const wlr_surface* surface); + CInputPopup* popupFromSurface(const SP surface); void updateAllPopups(); @@ -44,7 +44,7 @@ class CInputMethodRelay { std::vector> m_vTextInputs; std::vector> m_vIMEPopups; - wlr_surface* m_pLastKbFocus = nullptr; + WP m_pLastKbFocus; struct { CHyprSignalListener newTIV3; @@ -57,6 +57,6 @@ class CInputMethodRelay { friend class CHyprRenderer; friend class CInputManager; friend class CTextInputV1ProtocolManager; - friend struct CTextInput; + friend class CTextInput; friend class CHyprRenderer; }; diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index 56e817ec9a6a..f1157e4b642f 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -20,7 +20,7 @@ static void unfocusTool(SP tool) { PROTO::tablet->proximityOut(tool); } -static void focusTool(SP tool, SP tablet, wlr_surface* surf) { +static void focusTool(SP tool, SP tablet, SP surf) { if (tool->getSurface() == surf || !surf) return; @@ -37,7 +37,7 @@ static void focusTool(SP tool, SP tablet, wlr_surface* sur } static void refocusTablet(SP tab, SP tool, bool motion = false) { - const auto LASTHLSURFACE = CWLSurface::surfaceFromWlr(g_pSeatManager->state.pointerFocus); + const auto LASTHLSURFACE = CWLSurface::fromResource(g_pSeatManager->state.pointerFocus.lock()); if (!LASTHLSURFACE || !tool->active) { if (tool->getSurface()) @@ -57,7 +57,7 @@ static void refocusTablet(SP tab, SP tool, bool motion = f const auto CURSORPOS = g_pInputManager->getMouseCoordsInternal(); - focusTool(tool, tab, g_pSeatManager->state.pointerFocus); + focusTool(tool, tab, g_pSeatManager->state.pointerFocus.lock()); if (!motion) return; diff --git a/src/managers/input/TextInput.cpp b/src/managers/input/TextInput.cpp index b3f0b0cbb8f3..4c7ffe6e3005 100644 --- a/src/managers/input/TextInput.cpp +++ b/src/managers/input/TextInput.cpp @@ -5,6 +5,7 @@ #include "../../Compositor.hpp" #include "../../protocols/TextInputV3.hpp" #include "../../protocols/InputMethodV2.hpp" +#include "../../protocols/core/Compositor.hpp" CTextInput::CTextInput(STextInputV1* ti) : pV1Input(ti) { ti->pTextInput = this; @@ -56,8 +57,8 @@ void CTextInput::initCallbacks() { hyprListener_textInputDestroy.removeCallback(); hyprListener_textInputDisable.removeCallback(); hyprListener_textInputEnable.removeCallback(); - hyprListener_surfaceDestroyed.removeCallback(); - hyprListener_surfaceUnmapped.removeCallback(); + listeners.surfaceUnmap.reset(); + listeners.surfaceDestroy.reset(); g_pInputManager->m_sIMERelay.removeTextInput(this); }, @@ -65,7 +66,7 @@ void CTextInput::initCallbacks() { } } -void CTextInput::onEnabled(wlr_surface* surfV1) { +void CTextInput::onEnabled(SP surfV1) { Debug::log(LOG, "TI ENABLE"); if (g_pInputManager->m_sIMERelay.m_pIME.expired()) { @@ -75,7 +76,7 @@ void CTextInput::onEnabled(wlr_surface* surfV1) { // v1 only, map surface to PTI if (!isV3()) { - wlr_surface* pSurface = surfV1; + SP pSurface = surfV1; if (g_pCompositor->m_pLastFocus != pSurface || !pV1Input->active) return; @@ -97,8 +98,8 @@ void CTextInput::onDisabled() { if (!isV3()) leave(); - hyprListener_surfaceDestroyed.removeCallback(); - hyprListener_surfaceUnmapped.removeCallback(); + listeners.surfaceUnmap.reset(); + listeners.surfaceDestroy.reset(); g_pInputManager->m_sIMERelay.deactivateIME(this); } @@ -117,50 +118,44 @@ void CTextInput::onCommit() { g_pInputManager->m_sIMERelay.commitIMEState(this); } -void CTextInput::setFocusedSurface(wlr_surface* pSurface) { +void CTextInput::setFocusedSurface(SP pSurface) { if (pSurface == pFocusedSurface) return; pFocusedSurface = pSurface; - hyprListener_surfaceUnmapped.removeCallback(); - hyprListener_surfaceDestroyed.removeCallback(); + listeners.surfaceUnmap.reset(); + listeners.surfaceDestroy.reset(); if (!pSurface) return; - hyprListener_surfaceUnmapped.initCallback( - &pSurface->events.unmap, - [this](void* owner, void* data) { - Debug::log(LOG, "Unmap TI owner1"); - - if (enterLocks) - enterLocks--; - pFocusedSurface = nullptr; - hyprListener_surfaceUnmapped.removeCallback(); - hyprListener_surfaceDestroyed.removeCallback(); - }, - this, "CTextInput"); - - hyprListener_surfaceDestroyed.initCallback( - &pSurface->events.destroy, - [this](void* owner, void* data) { - Debug::log(LOG, "destroy TI owner1"); - - if (enterLocks) - enterLocks--; - pFocusedSurface = nullptr; - hyprListener_surfaceUnmapped.removeCallback(); - hyprListener_surfaceDestroyed.removeCallback(); - }, - this, "CTextInput"); + listeners.surfaceUnmap = pSurface->events.unmap.registerListener([this](std::any d) { + Debug::log(LOG, "Unmap TI owner1"); + + if (enterLocks) + enterLocks--; + pFocusedSurface.reset(); + listeners.surfaceUnmap.reset(); + listeners.surfaceDestroy.reset(); + }); + + listeners.surfaceDestroy = pSurface->events.destroy.registerListener([this](std::any d) { + Debug::log(LOG, "Destroy TI owner1"); + + if (enterLocks) + enterLocks--; + pFocusedSurface.reset(); + listeners.surfaceUnmap.reset(); + listeners.surfaceDestroy.reset(); + }); } bool CTextInput::isV3() { return !pV1Input; } -void CTextInput::enter(wlr_surface* pSurface) { +void CTextInput::enter(SP pSurface) { if (!pSurface || !pSurface->mapped) return; @@ -182,7 +177,7 @@ void CTextInput::enter(wlr_surface* pSurface) { if (isV3()) pV3Input->enter(pSurface); else { - zwp_text_input_v1_send_enter(pV1Input->resourceImpl, pSurface->resource); + zwp_text_input_v1_send_enter(pV1Input->resourceImpl, pSurface->getResource()->resource()); pV1Input->active = true; } @@ -211,8 +206,8 @@ void CTextInput::leave() { g_pInputManager->m_sIMERelay.deactivateIME(this); } -wlr_surface* CTextInput::focusedSurface() { - return pFocusedSurface; +SP CTextInput::focusedSurface() { + return pFocusedSurface.lock(); } wl_client* CTextInput::client() { diff --git a/src/managers/input/TextInput.hpp b/src/managers/input/TextInput.hpp index ff21da9505ec..28555dad2309 100644 --- a/src/managers/input/TextInput.hpp +++ b/src/managers/input/TextInput.hpp @@ -19,43 +19,43 @@ class CTextInput { CTextInput(STextInputV1* ti); ~CTextInput(); - bool isV3(); - void enter(wlr_surface* pSurface); - void leave(); - void tiV1Destroyed(); - wl_client* client(); - void commitStateToIME(SP ime); - void updateIMEState(SP ime); + bool isV3(); + void enter(SP pSurface); + void leave(); + void tiV1Destroyed(); + wl_client* client(); + void commitStateToIME(SP ime); + void updateIMEState(SP ime); - void onEnabled(wlr_surface* surfV1 = nullptr); - void onDisabled(); - void onCommit(); + void onEnabled(SP surfV1 = nullptr); + void onDisabled(); + void onCommit(); - bool hasCursorRectangle(); - CBox cursorBox(); + bool hasCursorRectangle(); + CBox cursorBox(); - wlr_surface* focusedSurface(); + SP focusedSurface(); private: - void setFocusedSurface(wlr_surface* pSurface); - void initCallbacks(); + void setFocusedSurface(SP pSurface); + void initCallbacks(); - wlr_surface* pFocusedSurface = nullptr; - int enterLocks = 0; - WP pV3Input; - STextInputV1* pV1Input = nullptr; + WP pFocusedSurface; + int enterLocks = 0; + WP pV3Input; + STextInputV1* pV1Input = nullptr; DYNLISTENER(textInputEnable); DYNLISTENER(textInputDisable); DYNLISTENER(textInputCommit); DYNLISTENER(textInputDestroy); - DYNLISTENER(surfaceUnmapped); - DYNLISTENER(surfaceDestroyed); struct { CHyprSignalListener enable; CHyprSignalListener disable; CHyprSignalListener commit; CHyprSignalListener destroy; + CHyprSignalListener surfaceUnmap; + CHyprSignalListener surfaceDestroy; } listeners; }; \ No newline at end of file diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index 7748813b7bc1..a1f949c2c465 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -77,7 +77,7 @@ void CInputManager::onTouchDown(ITouch::SDownEvent e) { } else return; // oops, nothing found. - g_pSeatManager->sendTouchDown(m_sTouchData.touchFocusSurface, e.timeMs, e.touchID, local); + g_pSeatManager->sendTouchDown(m_sTouchData.touchFocusSurface.lock(), e.timeMs, e.touchID, local); PROTO::idle->onActivity(); } diff --git a/src/protocols/AlphaModifier.cpp b/src/protocols/AlphaModifier.cpp index b9b99f6971d1..04dcd0a8672a 100644 --- a/src/protocols/AlphaModifier.cpp +++ b/src/protocols/AlphaModifier.cpp @@ -2,10 +2,11 @@ #include #include "../desktop/WLSurface.hpp" #include "../render/Renderer.hpp" +#include "core/Compositor.hpp" #define LOGM PROTO::alphaModifier->protoLog -CAlphaModifier::CAlphaModifier(SP resource_, wlr_surface* surface_) : resource(resource_), pSurface(surface_) { +CAlphaModifier::CAlphaModifier(SP resource_, SP surface_) : resource(resource_), pSurface(surface_) { if (!resource->resource()) return; @@ -18,8 +19,7 @@ CAlphaModifier::CAlphaModifier(SP resource_, wlr_surf setSurfaceAlpha(1.F); }); - hyprListener_surfaceDestroy.initCallback( - &surface_->events.destroy, [this](void* owner, void* data) { onSurfaceDestroy(); }, this, "CAlphaModifier"); + listeners.destroySurface = pSurface->events.destroy.registerListener([this](std::any d) { onSurfaceDestroy(); }); resource->setSetMultiplier([this](CWpAlphaModifierSurfaceV1* mod, uint32_t alpha) { if (!pSurface) { @@ -35,19 +35,19 @@ CAlphaModifier::CAlphaModifier(SP resource_, wlr_surf } CAlphaModifier::~CAlphaModifier() { - hyprListener_surfaceDestroy.removeCallback(); + ; } bool CAlphaModifier::good() { return resource->resource(); } -wlr_surface* CAlphaModifier::getSurface() { - return pSurface; +SP CAlphaModifier::getSurface() { + return pSurface.lock(); } void CAlphaModifier::setSurfaceAlpha(float a) { - CWLSurface* surf = CWLSurface::surfaceFromWlr(pSurface); + auto surf = CWLSurface::fromResource(pSurface.lock()); if (!surf) { LOGM(ERR, "CAlphaModifier::setSurfaceAlpha: No CWLSurface for given surface??"); @@ -62,8 +62,7 @@ void CAlphaModifier::setSurfaceAlpha(float a) { } void CAlphaModifier::onSurfaceDestroy() { - hyprListener_surfaceDestroy.removeCallback(); - pSurface = nullptr; + pSurface.reset(); } CAlphaModifierProtocol::CAlphaModifierProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { @@ -75,7 +74,7 @@ void CAlphaModifierProtocol::bindManager(wl_client* client, void* data, uint32_t RESOURCE->setOnDestroy([this](CWpAlphaModifierV1* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CWpAlphaModifierV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); - RESOURCE->setGetSurface([this](CWpAlphaModifierV1* pMgr, uint32_t id, wl_resource* surface) { this->onGetSurface(pMgr, id, wlr_surface_from_resource(surface)); }); + RESOURCE->setGetSurface([this](CWpAlphaModifierV1* pMgr, uint32_t id, wl_resource* surface) { this->onGetSurface(pMgr, id, CWLSurfaceResource::fromResource(surface)); }); } void CAlphaModifierProtocol::onManagerResourceDestroy(wl_resource* res) { @@ -83,29 +82,11 @@ void CAlphaModifierProtocol::onManagerResourceDestroy(wl_resource* res) { } void CAlphaModifierProtocol::destroyModifier(CAlphaModifier* modifier) { - if (modifier->getSurface()) - m_mAlphaModifiers.erase(modifier->getSurface()); - else { - // find it first - wlr_surface* deadptr = nullptr; - for (auto& [k, v] : m_mAlphaModifiers) { - if (v.get() == modifier) { - deadptr = k; - break; - } - } - - if (!deadptr) { - LOGM(ERR, "CAlphaModifierProtocol::destroyModifier: dead resource but no deadptr???"); - return; - } - - m_mAlphaModifiers.erase(deadptr); - } + std::erase_if(m_mAlphaModifiers, [](const auto& e) { return e.first.expired(); }); } -void CAlphaModifierProtocol::onGetSurface(CWpAlphaModifierV1* pMgr, uint32_t id, wlr_surface* surface) { - if (m_mAlphaModifiers.contains(surface)) { +void CAlphaModifierProtocol::onGetSurface(CWpAlphaModifierV1* pMgr, uint32_t id, SP surface) { + if (std::find_if(m_mAlphaModifiers.begin(), m_mAlphaModifiers.end(), [surface](const auto& e) { return e.first == surface; }) != m_mAlphaModifiers.end()) { LOGM(ERR, "AlphaModifier already present for surface {:x}", (uintptr_t)surface); pMgr->error(WP_ALPHA_MODIFIER_V1_ERROR_ALREADY_CONSTRUCTED, "AlphaModifier already present"); return; diff --git a/src/protocols/AlphaModifier.hpp b/src/protocols/AlphaModifier.hpp index 457d1b4c525e..38ed582fd1bb 100644 --- a/src/protocols/AlphaModifier.hpp +++ b/src/protocols/AlphaModifier.hpp @@ -8,20 +8,22 @@ class CAlphaModifier { public: - CAlphaModifier(SP resource_, wlr_surface* surface); + CAlphaModifier(SP resource_, SP surface); ~CAlphaModifier(); - bool good(); - wlr_surface* getSurface(); - void onSurfaceDestroy(); + bool good(); + SP getSurface(); + void onSurfaceDestroy(); private: SP resource; - wlr_surface* pSurface = nullptr; + WP pSurface; void setSurfaceAlpha(float a); - DYNLISTENER(surfaceDestroy); + struct { + CHyprSignalListener destroySurface; + } listeners; }; class CAlphaModifierProtocol : public IWaylandProtocol { @@ -33,15 +35,15 @@ class CAlphaModifierProtocol : public IWaylandProtocol { private: void onManagerResourceDestroy(wl_resource* res); void destroyModifier(CAlphaModifier* decoration); - void onGetSurface(CWpAlphaModifierV1* pMgr, uint32_t id, wlr_surface* surface); + void onGetSurface(CWpAlphaModifierV1* pMgr, uint32_t id, SP surface); // - std::vector> m_vManagers; - std::unordered_map> m_mAlphaModifiers; // xdg_toplevel -> deco + std::vector> m_vManagers; + std::unordered_map, UP> m_mAlphaModifiers; // xdg_toplevel -> deco friend class CAlphaModifier; }; namespace PROTO { inline UP alphaModifier; -}; \ No newline at end of file +}; diff --git a/src/protocols/FocusGrab.cpp b/src/protocols/FocusGrab.cpp index 5f0771e03026..40f9af44b629 100644 --- a/src/protocols/FocusGrab.cpp +++ b/src/protocols/FocusGrab.cpp @@ -1,21 +1,21 @@ #include "FocusGrab.hpp" -#include "Compositor.hpp" +#include "../Compositor.hpp" #include #include "../managers/input/InputManager.hpp" #include "../managers/SeatManager.hpp" +#include "core/Compositor.hpp" #include #include #include #define LOGM PROTO::focusGrab->protoLog -CFocusGrabSurfaceState::CFocusGrabSurfaceState(CFocusGrab* grab, wlr_surface* surface) { - hyprListener_surfaceDestroy.initCallback( - &surface->events.destroy, [=](void*, void*) { grab->eraseSurface(surface); }, this, "CFocusGrab"); +CFocusGrabSurfaceState::CFocusGrabSurfaceState(CFocusGrab* grab, SP surface) { + listeners.destroy = surface->events.destroy.registerListener([=](std::any d) { grab->eraseSurface(surface); }); } CFocusGrabSurfaceState::~CFocusGrabSurfaceState() { - hyprListener_surfaceDestroy.removeCallback(); + ; } CFocusGrab::CFocusGrab(SP resource_) : resource(resource_) { @@ -29,8 +29,8 @@ CFocusGrab::CFocusGrab(SP resource_) : resource(resource_) resource->setDestroy([this](CHyprlandFocusGrabV1* pMgr) { PROTO::focusGrab->destroyGrab(this); }); resource->setOnDestroy([this](CHyprlandFocusGrabV1* pMgr) { PROTO::focusGrab->destroyGrab(this); }); - resource->setAddSurface([this](CHyprlandFocusGrabV1* pMgr, wl_resource* surface) { addSurface(wlr_surface_from_resource(surface)); }); - resource->setRemoveSurface([this](CHyprlandFocusGrabV1* pMgr, wl_resource* surface) { removeSurface(wlr_surface_from_resource(surface)); }); + resource->setAddSurface([this](CHyprlandFocusGrabV1* pMgr, wl_resource* surface) { addSurface(CWLSurfaceResource::fromResource(surface)); }); + resource->setRemoveSurface([this](CHyprlandFocusGrabV1* pMgr, wl_resource* surface) { removeSurface(CWLSurfaceResource::fromResource(surface)); }); resource->setCommit([this](CHyprlandFocusGrabV1* pMgr) { commit(); }); } @@ -42,8 +42,8 @@ bool CFocusGrab::good() { return resource->resource(); } -bool CFocusGrab::isSurfaceComitted(wlr_surface* surface) { - auto iter = m_mSurfaces.find(surface); +bool CFocusGrab::isSurfaceComitted(SP surface) { + auto iter = std::find_if(m_mSurfaces.begin(), m_mSurfaces.end(), [surface](const auto& o) { return o.first == surface; }); if (iter == m_mSurfaces.end()) return false; @@ -77,14 +77,14 @@ void CFocusGrab::finish(bool sendCleared) { } } -void CFocusGrab::addSurface(wlr_surface* surface) { - auto iter = m_mSurfaces.find(surface); +void CFocusGrab::addSurface(SP surface) { + auto iter = std::find_if(m_mSurfaces.begin(), m_mSurfaces.end(), [surface](const auto& e) { return e.first == surface; }); if (iter == m_mSurfaces.end()) { m_mSurfaces.emplace(surface, std::make_unique(this, surface)); } } -void CFocusGrab::removeSurface(wlr_surface* surface) { +void CFocusGrab::removeSurface(SP surface) { auto iter = m_mSurfaces.find(surface); if (iter != m_mSurfaces.end()) { if (iter->second->state == CFocusGrabSurfaceState::PendingAddition) { @@ -94,20 +94,20 @@ void CFocusGrab::removeSurface(wlr_surface* surface) { } } -void CFocusGrab::eraseSurface(wlr_surface* surface) { +void CFocusGrab::eraseSurface(SP surface) { removeSurface(surface); commit(true); } void CFocusGrab::refocusKeyboard() { auto keyboardSurface = g_pSeatManager->state.keyboardFocus; - if (keyboardSurface != nullptr && isSurfaceComitted(keyboardSurface)) + if (keyboardSurface && isSurfaceComitted(keyboardSurface.lock())) return; - wlr_surface* surface = nullptr; + SP surface = nullptr; for (auto& [surf, state] : m_mSurfaces) { if (state->state == CFocusGrabSurfaceState::Comitted) { - surface = surf; + surface = surf.lock(); break; } } @@ -124,14 +124,14 @@ void CFocusGrab::commit(bool removeOnly) { for (auto iter = m_mSurfaces.begin(); iter != m_mSurfaces.end();) { switch (iter->second->state) { case CFocusGrabSurfaceState::PendingRemoval: - grab->remove(iter->first); + grab->remove(iter->first.lock()); iter = m_mSurfaces.erase(iter); surfacesChanged = true; continue; case CFocusGrabSurfaceState::PendingAddition: if (!removeOnly) { iter->second->state = CFocusGrabSurfaceState::Comitted; - grab->add(iter->first); + grab->add(iter->first.lock()); surfacesChanged = true; anyComitted = true; } diff --git a/src/protocols/FocusGrab.hpp b/src/protocols/FocusGrab.hpp index 40922c2221fd..3d264574b445 100644 --- a/src/protocols/FocusGrab.hpp +++ b/src/protocols/FocusGrab.hpp @@ -12,7 +12,7 @@ class CSeatGrab; class CFocusGrabSurfaceState { public: - CFocusGrabSurfaceState(CFocusGrab* grab, wlr_surface* surface); + CFocusGrabSurfaceState(CFocusGrab* grab, SP surface); ~CFocusGrabSurfaceState(); enum State { @@ -22,7 +22,9 @@ class CFocusGrabSurfaceState { } state = PendingAddition; private: - DYNLISTENER(surfaceDestroy); + struct { + CHyprSignalListener destroy; + } listeners; }; class CFocusGrab { @@ -31,23 +33,23 @@ class CFocusGrab { ~CFocusGrab(); bool good(); - bool isSurfaceComitted(wlr_surface* surface); + bool isSurfaceComitted(SP surface); void start(); void finish(bool sendCleared); private: - void addSurface(wlr_surface* surface); - void removeSurface(wlr_surface* surface); - void eraseSurface(wlr_surface* surface); - void refocusKeyboard(); - void commit(bool removeOnly = false); + void addSurface(SP surface); + void removeSurface(SP surface); + void eraseSurface(SP surface); + void refocusKeyboard(); + void commit(bool removeOnly = false); - SP resource; - std::unordered_map> m_mSurfaces; - SP grab; + SP resource; + std::unordered_map, UP> m_mSurfaces; + SP grab; - bool m_bGrabActive = false; + bool m_bGrabActive = false; DYNLISTENER(pointerGrabStarted); DYNLISTENER(keyboardGrabStarted); diff --git a/src/protocols/FractionalScale.cpp b/src/protocols/FractionalScale.cpp index 691ab6970c61..6d225e991473 100644 --- a/src/protocols/FractionalScale.cpp +++ b/src/protocols/FractionalScale.cpp @@ -1,13 +1,9 @@ #include "FractionalScale.hpp" +#include +#include "core/Compositor.hpp" #define LOGM PROTO::fractional->protoLog -static void onWlrSurfaceDestroy(void* owner, void* data) { - const auto SURF = (wlr_surface*)owner; - - PROTO::fractional->onSurfaceDestroy(SURF); -} - CFractionalScaleProtocol::CFractionalScaleProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { ; } @@ -18,7 +14,7 @@ void CFractionalScaleProtocol::bindManager(wl_client* client, void* data, uint32 RESOURCE->setDestroy([this](CWpFractionalScaleManagerV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); RESOURCE->setGetFractionalScale( - [this](CWpFractionalScaleManagerV1* pMgr, uint32_t id, wl_resource* surface) { this->onGetFractionalScale(pMgr, id, wlr_surface_from_resource(surface)); }); + [this](CWpFractionalScaleManagerV1* pMgr, uint32_t id, wl_resource* surface) { this->onGetFractionalScale(pMgr, id, CWLSurfaceResource::fromResource(surface)); }); } void CFractionalScaleProtocol::removeAddon(CFractionalScaleAddon* addon) { @@ -29,11 +25,13 @@ void CFractionalScaleProtocol::onManagerResourceDestroy(wl_resource* res) { std::erase_if(m_vManagers, [res](const auto& other) { return other->resource() == res; }); } -void CFractionalScaleProtocol::onGetFractionalScale(CWpFractionalScaleManagerV1* pMgr, uint32_t id, wlr_surface* surface) { - if (m_mAddons.contains(surface)) { - LOGM(ERR, "Surface {:x} already has a fractionalScale addon", (uintptr_t)surface); - pMgr->error(WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_FRACTIONAL_SCALE_EXISTS, "Fractional scale already exists"); - return; +void CFractionalScaleProtocol::onGetFractionalScale(CWpFractionalScaleManagerV1* pMgr, uint32_t id, SP surface) { + for (auto& [k, v] : m_mAddons) { + if (k == surface) { + LOGM(ERR, "Surface {:x} already has a fractionalScale addon", (uintptr_t)surface); + pMgr->error(WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_FRACTIONAL_SCALE_EXISTS, "Fractional scale already exists"); + return; + } } const auto PADDON = @@ -48,35 +46,22 @@ void CFractionalScaleProtocol::onGetFractionalScale(CWpFractionalScaleManagerV1* PADDON->resource->setOnDestroy([this, PADDON](CWpFractionalScaleV1* self) { this->removeAddon(PADDON); }); PADDON->resource->setDestroy([this, PADDON](CWpFractionalScaleV1* self) { this->removeAddon(PADDON); }); - if (!m_mSurfaceScales.contains(surface)) - m_mSurfaceScales[surface] = 1.F; + if (std::find_if(m_mSurfaceScales.begin(), m_mSurfaceScales.end(), [surface](const auto& e) { return e.first == surface; }) == m_mSurfaceScales.end()) + m_mSurfaceScales.emplace(surface, 1.F); + + PADDON->setScale(m_mSurfaceScales.at(surface)); - PADDON->setScale(m_mSurfaceScales[surface]); - registerSurface(surface); + // clean old + std::erase_if(m_mSurfaceScales, [](const auto& e) { return e.first.expired(); }); } -void CFractionalScaleProtocol::sendScale(wlr_surface* surf, const float& scale) { +void CFractionalScaleProtocol::sendScale(SP surf, const float& scale) { m_mSurfaceScales[surf] = scale; if (m_mAddons.contains(surf)) m_mAddons[surf]->setScale(scale); - registerSurface(surf); -} - -void CFractionalScaleProtocol::registerSurface(wlr_surface* surf) { - if (m_mSurfaceDestroyListeners.contains(surf)) - return; - - m_mSurfaceDestroyListeners[surf].hyprListener_surfaceDestroy.initCallback(&surf->events.destroy, ::onWlrSurfaceDestroy, surf, "FractionalScale"); -} - -void CFractionalScaleProtocol::onSurfaceDestroy(wlr_surface* surf) { - m_mSurfaceDestroyListeners.erase(surf); - m_mSurfaceScales.erase(surf); - if (m_mAddons.contains(surf)) - m_mAddons[surf]->onSurfaceDestroy(); } -CFractionalScaleAddon::CFractionalScaleAddon(SP resource_, wlr_surface* surf_) : resource(resource_), surface(surf_) { +CFractionalScaleAddon::CFractionalScaleAddon(SP resource_, SP surf_) : resource(resource_), surface(surf_) { resource->setDestroy([this](CWpFractionalScaleV1* self) { PROTO::fractional->removeAddon(this); }); resource->setOnDestroy([this](CWpFractionalScaleV1* self) { PROTO::fractional->removeAddon(this); }); } @@ -93,6 +78,6 @@ bool CFractionalScaleAddon::good() { return resource->resource(); } -wlr_surface* CFractionalScaleAddon::surf() { - return surface; +SP CFractionalScaleAddon::surf() { + return surface.lock(); } \ No newline at end of file diff --git a/src/protocols/FractionalScale.hpp b/src/protocols/FractionalScale.hpp index 10ebf49a9602..38b1d32c049d 100644 --- a/src/protocols/FractionalScale.hpp +++ b/src/protocols/FractionalScale.hpp @@ -9,16 +9,16 @@ class CFractionalScaleProtocol; class CFractionalScaleAddon { public: - CFractionalScaleAddon(SP resource_, wlr_surface* surf_); + CFractionalScaleAddon(SP resource_, SP surf_); - void setScale(const float& scale); - void onSurfaceDestroy(); + void setScale(const float& scale); + void onSurfaceDestroy(); - bool good(); + bool good(); - wlr_surface* surf(); + SP surf(); - bool operator==(const wl_resource* other) const { + bool operator==(const wl_resource* other) const { return other == resource->resource(); } @@ -28,42 +28,36 @@ class CFractionalScaleAddon { private: SP resource; - float scale = 1.F; - wlr_surface* surface = nullptr; + float scale = 1.F; + WP surface; bool surfaceGone = false; friend class CFractionalScaleProtocol; }; -struct SSurfaceListener { - DYNLISTENER(surfaceDestroy); -}; - class CFractionalScaleProtocol : public IWaylandProtocol { public: CFractionalScaleProtocol(const wl_interface* iface, const int& ver, const std::string& name); virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); - void onSurfaceDestroy(wlr_surface* surf); - void sendScale(wlr_surface* surf, const float& scale); + void onSurfaceDestroy(SP surf); + void sendScale(SP surf, const float& scale); private: void removeAddon(CFractionalScaleAddon*); - void registerSurface(wlr_surface*); void onManagerResourceDestroy(wl_resource* res); - void onGetFractionalScale(CWpFractionalScaleManagerV1* pMgr, uint32_t id, wlr_surface* surface); + void onGetFractionalScale(CWpFractionalScaleManagerV1* pMgr, uint32_t id, SP surface); // - std::unordered_map m_mSurfaceDestroyListeners; - std::unordered_map m_mSurfaceScales; - std::unordered_map> m_mAddons; - std::vector> m_vManagers; + std::unordered_map, float> m_mSurfaceScales; + std::unordered_map, UP> m_mAddons; + std::vector> m_vManagers; friend class CFractionalScaleAddon; }; namespace PROTO { inline UP fractional; -}; \ No newline at end of file +}; diff --git a/src/protocols/GammaControl.cpp b/src/protocols/GammaControl.cpp index c8db7100bb94..7c3b39ceafaf 100644 --- a/src/protocols/GammaControl.cpp +++ b/src/protocols/GammaControl.cpp @@ -3,6 +3,7 @@ #include #include "../helpers/Monitor.hpp" #include "../Compositor.hpp" +#include "../protocols/core/Output.hpp" #define LOGM PROTO::gamma->protoLog @@ -10,15 +11,15 @@ CGammaControl::CGammaControl(SP resource_, wl_resource* out if (!resource_->resource()) return; - wlr_output* wlrOutput = wlr_output_from_resource(output); + auto OUTPUTRES = CWLOutputResource::fromResource(output); - if (!wlrOutput) { - LOGM(ERR, "No wlr_output in CGammaControl"); + if (!OUTPUTRES) { + LOGM(ERR, "No output in CGammaControl"); resource->sendFailed(); return; } - pMonitor = g_pCompositor->getRealMonitorFromOutput(wlrOutput); + pMonitor = OUTPUTRES->monitor.get(); if (!pMonitor) { LOGM(ERR, "No CMonitor"); @@ -33,7 +34,7 @@ CGammaControl::CGammaControl(SP resource_, wl_resource* out } } - gammaSize = wlr_output_get_gamma_size(wlrOutput); + gammaSize = wlr_output_get_gamma_size(pMonitor->output); if (gammaSize <= 0) { LOGM(ERR, "Output {} doesn't support gamma", pMonitor->szName); diff --git a/src/protocols/IdleInhibit.cpp b/src/protocols/IdleInhibit.cpp index 0ff11a56fc03..89eb31085331 100644 --- a/src/protocols/IdleInhibit.cpp +++ b/src/protocols/IdleInhibit.cpp @@ -1,26 +1,23 @@ #include "IdleInhibit.hpp" +#include "core/Compositor.hpp" -CIdleInhibitor::CIdleInhibitor(SP resource_, wlr_surface* surf_) : resource(resource_), surface(surf_) { +CIdleInhibitor::CIdleInhibitor(SP resource_, SP surf_) : resource(resource_), surface(surf_) { ; } -CIdleInhibitorResource::CIdleInhibitorResource(SP resource_, wlr_surface* surface_) : resource(resource_), surface(surface_) { - hyprListener_surfaceDestroy.initCallback( - &surface->events.destroy, - [this](void* owner, void* data) { - surface = nullptr; - hyprListener_surfaceDestroy.removeCallback(); - destroySent = true; - events.destroy.emit(); - }, - this, "CIdleInhibitorResource"); +CIdleInhibitorResource::CIdleInhibitorResource(SP resource_, SP surface_) : resource(resource_), surface(surface_) { + listeners.destroySurface = surface->events.destroy.registerListener([this](std::any d) { + surface.reset(); + listeners.destroySurface.reset(); + destroySent = true; + events.destroy.emit(); + }); resource->setOnDestroy([this](CZwpIdleInhibitorV1* p) { PROTO::idleInhibit->removeInhibitor(this); }); resource->setDestroy([this](CZwpIdleInhibitorV1* p) { PROTO::idleInhibit->removeInhibitor(this); }); } CIdleInhibitorResource::~CIdleInhibitorResource() { - hyprListener_surfaceDestroy.removeCallback(); if (!destroySent) events.destroy.emit(); } @@ -39,14 +36,14 @@ void CIdleInhibitProtocol::bindManager(wl_client* client, void* data, uint32_t v RESOURCE->setDestroy([this](CZwpIdleInhibitManagerV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); RESOURCE->setCreateInhibitor( - [this](CZwpIdleInhibitManagerV1* pMgr, uint32_t id, wl_resource* surface) { this->onCreateInhibitor(pMgr, id, wlr_surface_from_resource(surface)); }); + [this](CZwpIdleInhibitManagerV1* pMgr, uint32_t id, wl_resource* surface) { this->onCreateInhibitor(pMgr, id, CWLSurfaceResource::fromResource(surface)); }); } void CIdleInhibitProtocol::removeInhibitor(CIdleInhibitorResource* resource) { std::erase_if(m_vInhibitors, [resource](const auto& el) { return el.get() == resource; }); } -void CIdleInhibitProtocol::onCreateInhibitor(CZwpIdleInhibitManagerV1* pMgr, uint32_t id, wlr_surface* surface) { +void CIdleInhibitProtocol::onCreateInhibitor(CZwpIdleInhibitManagerV1* pMgr, uint32_t id, SP surface) { const auto CLIENT = pMgr->client(); const auto RESOURCE = m_vInhibitors.emplace_back(makeShared(makeShared(CLIENT, pMgr->version(), id), surface)); diff --git a/src/protocols/IdleInhibit.hpp b/src/protocols/IdleInhibit.hpp index b59e8789e088..ee01f0293ce8 100644 --- a/src/protocols/IdleInhibit.hpp +++ b/src/protocols/IdleInhibit.hpp @@ -10,19 +10,19 @@ class CIdleInhibitorResource; class CIdleInhibitor { public: - CIdleInhibitor(SP resource_, wlr_surface* surf_); + CIdleInhibitor(SP resource_, SP surf_); struct { CHyprSignalListener destroy; } listeners; WP resource; - wlr_surface* surface = nullptr; + WP surface; }; class CIdleInhibitorResource { public: - CIdleInhibitorResource(SP resource_, wlr_surface* surface_); + CIdleInhibitorResource(SP resource_, SP surface_); ~CIdleInhibitorResource(); SP inhibitor; @@ -33,10 +33,12 @@ class CIdleInhibitorResource { private: SP resource; - wlr_surface* surface = nullptr; + WP surface; bool destroySent = false; - DYNLISTENER(surfaceDestroy); + struct { + CHyprSignalListener destroySurface; + } listeners; }; class CIdleInhibitProtocol : public IWaylandProtocol { @@ -51,7 +53,7 @@ class CIdleInhibitProtocol : public IWaylandProtocol { private: void onManagerResourceDestroy(wl_resource* res); - void onCreateInhibitor(CZwpIdleInhibitManagerV1* pMgr, uint32_t id, wlr_surface* surface); + void onCreateInhibitor(CZwpIdleInhibitManagerV1* pMgr, uint32_t id, SP surface); void removeInhibitor(CIdleInhibitorResource*); @@ -64,4 +66,4 @@ class CIdleInhibitProtocol : public IWaylandProtocol { namespace PROTO { inline UP idleInhibit; -} \ No newline at end of file +} diff --git a/src/protocols/InputMethodV2.cpp b/src/protocols/InputMethodV2.cpp index 93ca38c0740e..5d0bd417e923 100644 --- a/src/protocols/InputMethodV2.cpp +++ b/src/protocols/InputMethodV2.cpp @@ -3,6 +3,7 @@ #include "../managers/SeatManager.hpp" #include "../devices/IKeyboard.hpp" #include +#include "core/Compositor.hpp" #define LOGM PROTO::ime->protoLog @@ -83,51 +84,45 @@ wl_client* CInputMethodKeyboardGrabV2::client() { return resource->client(); } -CInputMethodPopupV2::CInputMethodPopupV2(SP resource_, SP owner_, wlr_surface* wlrSurface) : resource(resource_), owner(owner_) { +CInputMethodPopupV2::CInputMethodPopupV2(SP resource_, SP owner_, SP surface) : resource(resource_), owner(owner_) { if (!resource->resource()) return; resource->setDestroy([this](CZwpInputPopupSurfaceV2* r) { PROTO::ime->destroyResource(this); }); resource->setOnDestroy([this](CZwpInputPopupSurfaceV2* r) { PROTO::ime->destroyResource(this); }); - pSurface = wlrSurface; + pSurface = surface; - hyprListener_destroySurface.initCallback( - &wlrSurface->events.destroy, - [this](void* owner, void* data) { - if (mapped) - events.unmap.emit(); + listeners.destroySurface = surface->events.destroy.registerListener([this](std::any d) { + if (mapped) + events.unmap.emit(); - hyprListener_commitSurface.removeCallback(); - hyprListener_destroySurface.removeCallback(); + listeners.destroySurface.reset(); + listeners.commitSurface.reset(); - if (g_pCompositor->m_pLastFocus == pSurface) - g_pCompositor->m_pLastFocus = nullptr; + if (g_pCompositor->m_pLastFocus == pSurface) + g_pCompositor->m_pLastFocus.reset(); - pSurface = nullptr; - }, - this, "IMEPopup"); + pSurface.reset(); + }); - hyprListener_commitSurface.initCallback( - &wlrSurface->events.commit, - [this](void* owner, void* data) { - if (pSurface->pending.buffer_width > 0 && pSurface->pending.buffer_height > 0 && !mapped) { - mapped = true; - wlr_surface_map(pSurface); - events.map.emit(); - return; - } + listeners.commitSurface = surface->events.commit.registerListener([this](std::any d) { + if (pSurface->current.buffer && !mapped) { + mapped = true; + pSurface->map(); + events.map.emit(); + return; + } - if (pSurface->pending.buffer_width <= 0 && pSurface->pending.buffer_height <= 0 && mapped) { - mapped = false; - wlr_surface_unmap(pSurface); - events.unmap.emit(); - return; - } + if (!pSurface->current.buffer && mapped) { + mapped = false; + pSurface->unmap(); + events.unmap.emit(); + return; + } - events.commit.emit(); - }, - this, "IMEPopup"); + events.commit.emit(); + }); } CInputMethodPopupV2::~CInputMethodPopupV2() { @@ -145,8 +140,8 @@ void CInputMethodPopupV2::sendInputRectangle(const CBox& box) { resource->sendTextInputRectangle(box.x, box.y, box.w, box.h); } -wlr_surface* CInputMethodPopupV2::surface() { - return pSurface; +SP CInputMethodPopupV2::surface() { + return pSurface.lock(); } void CInputMethodV2::SState::reset() { @@ -194,7 +189,7 @@ CInputMethodV2::CInputMethodV2(SP resource_) : resource(resou resource->setGetInputPopupSurface([this](CZwpInputMethodV2* r, uint32_t id, wl_resource* surface) { const auto RESOURCE = PROTO::ime->m_vPopups.emplace_back( - makeShared(makeShared(r->client(), r->version(), id), self.lock(), wlr_surface_from_resource(surface))); + makeShared(makeShared(r->client(), r->version(), id), self.lock(), CWLSurfaceResource::fromResource(surface))); if (!RESOURCE->good()) { r->noMemory(); diff --git a/src/protocols/InputMethodV2.hpp b/src/protocols/InputMethodV2.hpp index 1f5d25981d2d..bc21270c471c 100644 --- a/src/protocols/InputMethodV2.hpp +++ b/src/protocols/InputMethodV2.hpp @@ -101,12 +101,12 @@ class CInputMethodKeyboardGrabV2 { class CInputMethodPopupV2 { public: - CInputMethodPopupV2(SP resource_, SP owner_, wlr_surface* surface); + CInputMethodPopupV2(SP resource_, SP owner_, SP surface); ~CInputMethodPopupV2(); - bool good(); - void sendInputRectangle(const CBox& box); - wlr_surface* surface(); + bool good(); + void sendInputRectangle(const CBox& box); + SP surface(); struct { CSignal map; @@ -120,10 +120,12 @@ class CInputMethodPopupV2 { private: SP resource; WP owner; - wlr_surface* pSurface = nullptr; + WP pSurface; - DYNLISTENER(commitSurface); - DYNLISTENER(destroySurface); + struct { + CHyprSignalListener destroySurface; + CHyprSignalListener commitSurface; + } listeners; }; class CInputMethodV2Protocol : public IWaylandProtocol { diff --git a/src/protocols/LayerShell.cpp b/src/protocols/LayerShell.cpp index 962b89a34d0c..8fa6dd27fb2d 100644 --- a/src/protocols/LayerShell.cpp +++ b/src/protocols/LayerShell.cpp @@ -1,6 +1,8 @@ #include "LayerShell.hpp" #include "../Compositor.hpp" #include "XDGShell.hpp" +#include "core/Compositor.hpp" +#include "core/Output.hpp" #define LOGM PROTO::layerShell->protoLog @@ -14,7 +16,7 @@ void CLayerShellResource::SState::reset() { margin = {0, 0, 0, 0}; } -CLayerShellResource::CLayerShellResource(SP resource_, wlr_surface* surf_, std::string namespace_, CMonitor* pMonitor, zwlrLayerShellV1Layer layer) : +CLayerShellResource::CLayerShellResource(SP resource_, SP surf_, std::string namespace_, CMonitor* pMonitor, zwlrLayerShellV1Layer layer) : layerNamespace(namespace_), surface(surf_), resource(resource_) { if (!good()) return; @@ -31,57 +33,52 @@ CLayerShellResource::CLayerShellResource(SP resource_, wlr_ PROTO::layerShell->destroyResource(this); }); - hyprListener_destroySurface.initCallback( - &surf_->events.destroy, - [this](void* owner, void* data) { - events.destroy.emit(); - PROTO::layerShell->destroyResource(this); - }, - this, "CLayerShellResource"); - - hyprListener_commitSurface.initCallback( - &surf_->events.commit, - [this](void* owner, void* data) { - current = pending; - pending.committed = 0; - - bool attachedBuffer = surface->pending.buffer_width > 0 && surface->pending.buffer_height > 0; - - if (attachedBuffer && !configured) { - wlr_surface_reject_pending(surface, resource->resource(), -1, "layerSurface was not configured, but a buffer was attached"); - return; - } - - constexpr uint32_t horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; - constexpr uint32_t vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; - - if (current.desiredSize.x <= 0 && (current.anchor & horiz) != horiz) { - wlr_surface_reject_pending(surface, resource->resource(), -1, "x == 0 but anchor doesn't have left and right"); - return; - } - - if (current.desiredSize.y <= 0 && (current.anchor & vert) != vert) { - wlr_surface_reject_pending(surface, resource->resource(), -1, "y == 0 but anchor doesn't have top and bottom"); - return; - } - - if (attachedBuffer && !mapped) { - mapped = true; - wlr_surface_map(surface); - events.map.emit(); - return; - } - - if (!attachedBuffer && mapped) { - mapped = false; - wlr_surface_unmap(surface); - events.unmap.emit(); - return; - } - - events.commit.emit(); - }, - this, "CLayerShellResource"); + listeners.destroySurface = surf_->events.destroy.registerListener([this](std::any d) { + events.destroy.emit(); + PROTO::layerShell->destroyResource(this); + }); + + listeners.commitSurface = surf_->events.commit.registerListener([this](std::any d) { + current = pending; + pending.committed = 0; + + bool attachedBuffer = surface->current.buffer; + + if (attachedBuffer && !configured) { + surface->error(-1, "layerSurface was not configured, but a buffer was attached"); + return; + } + + constexpr uint32_t horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; + constexpr uint32_t vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; + + if (current.desiredSize.x <= 0 && (current.anchor & horiz) != horiz) { + surface->error(-1, "x == 0 but anchor doesn't have left and right"); + return; + } + + if (current.desiredSize.y <= 0 && (current.anchor & vert) != vert) { + surface->error(-1, "y == 0 but anchor doesn't have top and bottom"); + return; + } + + if (attachedBuffer && !mapped) { + mapped = true; + surface->map(); + events.map.emit(); + return; + } + + if (!attachedBuffer && mapped) { + mapped = false; + surface->unmap(); + events.unmap.emit(); + configured = false; + return; + } + + events.commit.emit(); + }); resource->setSetSize([this](CZwlrLayerSurfaceV1* r, uint32_t x, uint32_t y) { pending.committed |= STATE_SIZE; @@ -209,9 +206,9 @@ void CLayerShellProtocol::destroyResource(CLayerShellResource* surf) { void CLayerShellProtocol::onGetLayerSurface(CZwlrLayerShellV1* pMgr, uint32_t id, wl_resource* surface, wl_resource* output, zwlrLayerShellV1Layer layer, std::string namespace_) { const auto CLIENT = pMgr->client(); - const auto PMONITOR = output ? g_pCompositor->getMonitorFromOutput(wlr_output_from_resource(output)) : nullptr; + const auto PMONITOR = output ? CWLOutputResource::fromResource(output)->monitor.get() : nullptr; const auto RESOURCE = m_vLayers.emplace_back( - makeShared(makeShared(CLIENT, pMgr->version(), id), wlr_surface_from_resource(surface), namespace_, PMONITOR, layer)); + makeShared(makeShared(CLIENT, pMgr->version(), id), CWLSurfaceResource::fromResource(surface), namespace_, PMONITOR, layer)); if (!RESOURCE->good()) { pMgr->noMemory(); diff --git a/src/protocols/LayerShell.hpp b/src/protocols/LayerShell.hpp index 9ed6bc66fbe2..e8b613dd3847 100644 --- a/src/protocols/LayerShell.hpp +++ b/src/protocols/LayerShell.hpp @@ -13,7 +13,7 @@ class CMonitor; class CLayerShellResource { public: - CLayerShellResource(SP resource_, wlr_surface* surf_, std::string namespace_, CMonitor* pMonitor, zwlrLayerShellV1Layer layer); + CLayerShellResource(SP resource_, SP surf_, std::string namespace_, CMonitor* pMonitor, zwlrLayerShellV1Layer layer); ~CLayerShellResource(); bool good(); @@ -54,18 +54,20 @@ class CLayerShellResource { void reset(); } current, pending; - Vector2D size; - std::string layerNamespace; - std::string monitor = ""; - wlr_surface* surface = nullptr; - bool mapped = false; - bool configured = false; + Vector2D size; + std::string layerNamespace; + std::string monitor = ""; + WP surface; + bool mapped = false; + bool configured = false; private: SP resource; - DYNLISTENER(destroySurface); - DYNLISTENER(commitSurface); + struct { + CHyprSignalListener commitSurface; + CHyprSignalListener destroySurface; + } listeners; bool closed = false; diff --git a/src/protocols/OutputPower.cpp b/src/protocols/OutputPower.cpp index db241048763d..ef287cfaa195 100644 --- a/src/protocols/OutputPower.cpp +++ b/src/protocols/OutputPower.cpp @@ -1,5 +1,6 @@ #include "OutputPower.hpp" #include "../Compositor.hpp" +#include "core/Output.hpp" #define LOGM PROTO::outputPower->protoLog @@ -61,15 +62,15 @@ void COutputPowerProtocol::destroyOutputPower(COutputPower* power) { void COutputPowerProtocol::onGetOutputPower(CZwlrOutputPowerManagerV1* pMgr, uint32_t id, wl_resource* output) { - const auto PMONITOR = g_pCompositor->getMonitorFromOutput(wlr_output_from_resource(output)); + const auto OUTPUT = CWLOutputResource::fromResource(output); - if (!PMONITOR) { + if (!OUTPUT) { pMgr->error(0, "Invalid output resource"); return; } const auto CLIENT = pMgr->client(); - const auto RESOURCE = m_vOutputPowers.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id), PMONITOR)).get(); + const auto RESOURCE = m_vOutputPowers.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id), OUTPUT->monitor.get())).get(); if (!RESOURCE->good()) { pMgr->noMemory(); diff --git a/src/protocols/PointerConstraints.cpp b/src/protocols/PointerConstraints.cpp index 87abdcdd6aee..ad84ae0d50d9 100644 --- a/src/protocols/PointerConstraints.cpp +++ b/src/protocols/PointerConstraints.cpp @@ -3,10 +3,11 @@ #include "../Compositor.hpp" #include "../config/ConfigValue.hpp" #include "../managers/SeatManager.hpp" +#include "core/Compositor.hpp" #define LOGM PROTO::constraints->protoLog -CPointerConstraint::CPointerConstraint(SP resource_, wlr_surface* surf, wl_resource* region_, zwpPointerConstraintsV1Lifetime lifetime) : +CPointerConstraint::CPointerConstraint(SP resource_, SP surf, wl_resource* region_, zwpPointerConstraintsV1Lifetime lifetime) : resourceL(resource_), locked(true) { if (!resource_->resource()) return; @@ -14,7 +15,7 @@ CPointerConstraint::CPointerConstraint(SP resource_, wlr_su resource_->setOnDestroy([this](CZwpLockedPointerV1* p) { PROTO::constraints->destroyPointerConstraint(this); }); resource_->setDestroy([this](CZwpLockedPointerV1* p) { PROTO::constraints->destroyPointerConstraint(this); }); - pHLSurface = CWLSurface::surfaceFromWlr(surf); + pHLSurface = CWLSurface::fromResource(surf); if (!pHLSurface) return; @@ -45,7 +46,7 @@ CPointerConstraint::CPointerConstraint(SP resource_, wlr_su sharedConstructions(); } -CPointerConstraint::CPointerConstraint(SP resource_, wlr_surface* surf, wl_resource* region_, zwpPointerConstraintsV1Lifetime lifetime) : +CPointerConstraint::CPointerConstraint(SP resource_, SP surf, wl_resource* region_, zwpPointerConstraintsV1Lifetime lifetime) : resourceC(resource_), locked(false) { if (!resource_->resource()) return; @@ -53,7 +54,7 @@ CPointerConstraint::CPointerConstraint(SP resource_, wlr_ resource_->setOnDestroy([this](CZwpConfinedPointerV1* p) { PROTO::constraints->destroyPointerConstraint(this); }); resource_->setDestroy([this](CZwpConfinedPointerV1* p) { PROTO::constraints->destroyPointerConstraint(this); }); - pHLSurface = CWLSurface::surfaceFromWlr(surf); + pHLSurface = CWLSurface::fromResource(surf); if (!pHLSurface) return; @@ -79,7 +80,7 @@ CPointerConstraint::~CPointerConstraint() { void CPointerConstraint::sharedConstructions() { if (pHLSurface) { listeners.destroySurface = pHLSurface->events.destroy.registerListener([this](std::any d) { - pHLSurface = nullptr; + pHLSurface.reset(); if (active) deactivate(); @@ -92,7 +93,7 @@ void CPointerConstraint::sharedConstructions() { cursorPosOnActivate = g_pInputManager->getMouseCoordsInternal(); - if (g_pCompositor->m_pLastFocus == pHLSurface->wlr()) + if (g_pCompositor->m_pLastFocus == pHLSurface->resource()) activate(); } @@ -126,10 +127,10 @@ void CPointerConstraint::activate() { return; // TODO: hack, probably not a super duper great idea - if (g_pSeatManager->state.pointerFocus != pHLSurface->wlr()) { + if (g_pSeatManager->state.pointerFocus != pHLSurface->resource()) { const auto SURFBOX = pHLSurface->getSurfaceBoxGlobal(); const auto LOCAL = SURFBOX.has_value() ? logicPositionHint() - SURFBOX->pos() : Vector2D{}; - g_pSeatManager->setPointerFocus(pHLSurface->wlr(), LOCAL); + g_pSeatManager->setPointerFocus(pHLSurface->resource(), LOCAL); } if (locked) @@ -159,8 +160,8 @@ void CPointerConstraint::onSetRegion(wl_resource* wlRegion) { g_pInputManager->simulateMouseMovement(); // to warp the cursor if anything's amiss } -CWLSurface* CPointerConstraint::owner() { - return pHLSurface; +SP CPointerConstraint::owner() { + return pHLSurface.lock(); } CRegion CPointerConstraint::logicConstraintRegion() { @@ -241,7 +242,7 @@ void CPointerConstraintsProtocol::onLockPointer(CZwpPointerConstraintsV1* pMgr, zwpPointerConstraintsV1Lifetime lifetime) { const auto CLIENT = pMgr->client(); const auto RESOURCE = m_vConstraints.emplace_back( - makeShared(makeShared(CLIENT, pMgr->version(), id), wlr_surface_from_resource(surface), region, lifetime)); + makeShared(makeShared(CLIENT, pMgr->version(), id), CWLSurfaceResource::fromResource(surface), region, lifetime)); onNewConstraint(RESOURCE, pMgr); } @@ -250,7 +251,7 @@ void CPointerConstraintsProtocol::onConfinePointer(CZwpPointerConstraintsV1* pMg zwpPointerConstraintsV1Lifetime lifetime) { const auto CLIENT = pMgr->client(); const auto RESOURCE = m_vConstraints.emplace_back( - makeShared(makeShared(CLIENT, pMgr->version(), id), wlr_surface_from_resource(surface), region, lifetime)); + makeShared(makeShared(CLIENT, pMgr->version(), id), CWLSurfaceResource::fromResource(surface), region, lifetime)); onNewConstraint(RESOURCE, pMgr); } diff --git a/src/protocols/PointerConstraints.hpp b/src/protocols/PointerConstraints.hpp index 93e57c46163f..fb71789f1a81 100644 --- a/src/protocols/PointerConstraints.hpp +++ b/src/protocols/PointerConstraints.hpp @@ -15,28 +15,28 @@ class CWLSurface; class CPointerConstraint { public: - CPointerConstraint(SP resource_, wlr_surface* surf, wl_resource* region, zwpPointerConstraintsV1Lifetime lifetime); - CPointerConstraint(SP resource_, wlr_surface* surf, wl_resource* region, zwpPointerConstraintsV1Lifetime lifetime); + CPointerConstraint(SP resource_, SP surf, wl_resource* region, zwpPointerConstraintsV1Lifetime lifetime); + CPointerConstraint(SP resource_, SP surf, wl_resource* region, zwpPointerConstraintsV1Lifetime lifetime); ~CPointerConstraint(); - bool good(); + bool good(); - void deactivate(); - void activate(); - bool isActive(); + void deactivate(); + void activate(); + bool isActive(); - CWLSurface* owner(); + SP owner(); - CRegion logicConstraintRegion(); - bool isLocked(); - Vector2D logicPositionHint(); + CRegion logicConstraintRegion(); + bool isLocked(); + Vector2D logicPositionHint(); private: SP resourceL; SP resourceC; wl_client* pClient = nullptr; - CWLSurface* pHLSurface = nullptr; + WP pHLSurface; CRegion region; bool hintSet = false; diff --git a/src/protocols/PointerGestures.cpp b/src/protocols/PointerGestures.cpp index 2bfd74da710b..865107790af4 100644 --- a/src/protocols/PointerGestures.cpp +++ b/src/protocols/PointerGestures.cpp @@ -2,6 +2,7 @@ #include "../Compositor.hpp" #include "../managers/SeatManager.hpp" #include "core/Seat.hpp" +#include "core/Compositor.hpp" #define LOGM PROTO::pointerGestures->protoLog @@ -116,7 +117,7 @@ void CPointerGesturesProtocol::swipeBegin(uint32_t timeMs, uint32_t fingers) { if (sw->resource->client() != FOCUSEDCLIENT) continue; - sw->resource->sendBegin(SERIAL, timeMs, g_pSeatManager->state.pointerFocus->resource, fingers); + sw->resource->sendBegin(SERIAL, timeMs, g_pSeatManager->state.pointerFocus->getResource()->resource(), fingers); } } @@ -162,7 +163,7 @@ void CPointerGesturesProtocol::pinchBegin(uint32_t timeMs, uint32_t fingers) { if (sw->resource->client() != FOCUSEDCLIENT) continue; - sw->resource->sendBegin(SERIAL, timeMs, g_pSeatManager->state.pointerFocus->resource, fingers); + sw->resource->sendBegin(SERIAL, timeMs, g_pSeatManager->state.pointerFocus->getResource()->resource(), fingers); } } @@ -208,7 +209,7 @@ void CPointerGesturesProtocol::holdBegin(uint32_t timeMs, uint32_t fingers) { if (sw->resource->client() != FOCUSEDCLIENT) continue; - sw->resource->sendBegin(SERIAL, timeMs, g_pSeatManager->state.pointerFocus->resource, fingers); + sw->resource->sendBegin(SERIAL, timeMs, g_pSeatManager->state.pointerFocus->getResource()->resource(), fingers); } } diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp index e21c84031135..0275b53ff9b7 100644 --- a/src/protocols/PresentationTime.cpp +++ b/src/protocols/PresentationTime.cpp @@ -2,10 +2,11 @@ #include #include "../helpers/Monitor.hpp" #include "../managers/HookSystemManager.hpp" +#include "core/Compositor.hpp" #define LOGM PROTO::presentation->protoLog -CQueuedPresentationData::CQueuedPresentationData(wlr_surface* surf) : surface(surf) { +CQueuedPresentationData::CQueuedPresentationData(SP surf) : surface(surf) { ; } @@ -25,7 +26,7 @@ void CQueuedPresentationData::discarded() { wasPresented = false; } -CPresentationFeedback::CPresentationFeedback(SP resource_, wlr_surface* surf) : resource(resource_), surface(surf) { +CPresentationFeedback::CPresentationFeedback(SP resource_, SP surf) : resource(resource_), surface(surf) { if (!good()) return; @@ -69,7 +70,7 @@ void CPresentationFeedback::sendQueued(SP data, timespe CPresentationProtocol::CPresentationProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { static auto P = g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) { const auto PMONITOR = std::any_cast(param); - std::erase_if(m_vQueue, [PMONITOR, this](const auto& other) { return !other->surface || other->pMonitor == PMONITOR; }); + std::erase_if(m_vQueue, [PMONITOR](const auto& other) { return !other->surface || other->pMonitor == PMONITOR; }); }); } @@ -92,7 +93,8 @@ void CPresentationProtocol::destroyResource(CPresentationFeedback* feedback) { void CPresentationProtocol::onGetFeedback(CWpPresentation* pMgr, wl_resource* surf, uint32_t id) { const auto CLIENT = pMgr->client(); const auto RESOURCE = - m_vFeedbacks.emplace_back(makeShared(makeShared(CLIENT, pMgr->version(), id), wlr_surface_from_resource(surf))).get(); + m_vFeedbacks.emplace_back(makeShared(makeShared(CLIENT, pMgr->version(), id), CWLSurfaceResource::fromResource(surf))) + .get(); if (!RESOURCE->good()) { pMgr->noMemory(); @@ -116,8 +118,8 @@ void CPresentationProtocol::onPresented(CMonitor* pMonitor, timespec* when, uint } } - std::erase_if(m_vFeedbacks, [pMonitor, this](const auto& other) { return !other->surface || other->done; }); - std::erase_if(m_vQueue, [pMonitor, this](const auto& other) { return !other->surface || other->pMonitor == pMonitor || !other->pMonitor; }); + std::erase_if(m_vFeedbacks, [](const auto& other) { return !other->surface || other->done; }); + std::erase_if(m_vQueue, [pMonitor](const auto& other) { return !other->surface || other->pMonitor == pMonitor || !other->pMonitor; }); } void CPresentationProtocol::queueData(SP data) { diff --git a/src/protocols/PresentationTime.hpp b/src/protocols/PresentationTime.hpp index 2df1c78166f8..b905cc7a2770 100644 --- a/src/protocols/PresentationTime.hpp +++ b/src/protocols/PresentationTime.hpp @@ -10,7 +10,7 @@ class CMonitor; class CQueuedPresentationData { public: - CQueuedPresentationData(wlr_surface* surf); + CQueuedPresentationData(SP surf); void setPresentationType(bool zeroCopy); void attachMonitor(CMonitor* pMonitor); @@ -19,10 +19,10 @@ class CQueuedPresentationData { void discarded(); private: - bool wasPresented = false; - bool zeroCopy = false; - CMonitor* pMonitor = nullptr; - wlr_surface* surface = nullptr; // READ-ONLY + bool wasPresented = false; + bool zeroCopy = false; + CMonitor* pMonitor = nullptr; + WP surface; DYNLISTENER(destroySurface); @@ -32,7 +32,7 @@ class CQueuedPresentationData { class CPresentationFeedback { public: - CPresentationFeedback(SP resource_, wlr_surface* surf); + CPresentationFeedback(SP resource_, SP surf); bool good(); @@ -40,8 +40,8 @@ class CPresentationFeedback { private: SP resource; - wlr_surface* surface = nullptr; // READ-ONLY - bool done = false; + WP surface; + bool done = false; friend class CPresentationProtocol; }; diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 622d9d68fec9..88b395d10e1c 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -2,6 +2,7 @@ #include "../Compositor.hpp" #include "../managers/eventLoop/EventLoopManager.hpp" #include "../managers/PointerManager.hpp" +#include "core/Output.hpp" #include @@ -214,7 +215,7 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r const auto PFRAME = &m_lFrames.emplace_back(); PFRAME->overlayCursor = !!overlay_cursor; PFRAME->resource = wl_resource_create(client, &zwlr_screencopy_frame_v1_interface, wl_resource_get_version(resource), frame); - PFRAME->pMonitor = g_pCompositor->getMonitorFromOutput(wlr_output_from_resource(output)); + PFRAME->pMonitor = CWLOutputResource::fromResource(output)->monitor.get(); if (!PFRAME->pMonitor) { Debug::log(ERR, "client requested sharing of a monitor that doesnt exist"); diff --git a/src/protocols/ServerDecorationKDE.cpp b/src/protocols/ServerDecorationKDE.cpp index d47467b3ab11..42da52a9e238 100644 --- a/src/protocols/ServerDecorationKDE.cpp +++ b/src/protocols/ServerDecorationKDE.cpp @@ -1,8 +1,9 @@ #include "ServerDecorationKDE.hpp" +#include "core/Compositor.hpp" #define LOGM PROTO::serverDecorationKDE->protoLog -CServerDecorationKDE::CServerDecorationKDE(SP resource_, wlr_surface* surf) : resource(resource_) { +CServerDecorationKDE::CServerDecorationKDE(SP resource_, SP surf) : resource(resource_) { if (!good()) return; @@ -42,7 +43,8 @@ void CServerDecorationKDEProtocol::destroyResource(CServerDecorationKDE* hayperl void CServerDecorationKDEProtocol::createDecoration(COrgKdeKwinServerDecorationManager* pMgr, uint32_t id, wl_resource* surf) { const auto CLIENT = pMgr->client(); const auto RESOURCE = - m_vDecos.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id), wlr_surface_from_resource(surf))).get(); + m_vDecos.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id), CWLSurfaceResource::fromResource(surf))) + .get(); if (!RESOURCE->good()) { pMgr->noMemory(); diff --git a/src/protocols/ServerDecorationKDE.hpp b/src/protocols/ServerDecorationKDE.hpp index ec7a852f7a63..0604be249b8f 100644 --- a/src/protocols/ServerDecorationKDE.hpp +++ b/src/protocols/ServerDecorationKDE.hpp @@ -8,7 +8,7 @@ class CServerDecorationKDE { public: - CServerDecorationKDE(SP resource_, wlr_surface* surf); + CServerDecorationKDE(SP resource_, SP surf); bool good(); diff --git a/src/protocols/SessionLock.cpp b/src/protocols/SessionLock.cpp index fd803eda04cd..ae45b0f1eecf 100644 --- a/src/protocols/SessionLock.cpp +++ b/src/protocols/SessionLock.cpp @@ -2,10 +2,12 @@ #include "../Compositor.hpp" #include "../managers/SeatManager.hpp" #include "FractionalScale.hpp" +#include "core/Compositor.hpp" +#include "core/Output.hpp" #define LOGM PROTO::sessionLock->protoLog -CSessionLockSurface::CSessionLockSurface(SP resource_, wlr_surface* surface_, CMonitor* pMonitor_, WP owner_) : +CSessionLockSurface::CSessionLockSurface(SP resource_, SP surface_, CMonitor* pMonitor_, WP owner_) : resource(resource_), sessionLock(owner_), pSurface(surface_), pMonitor(pMonitor_) { if (!resource->resource()) return; @@ -21,45 +23,38 @@ CSessionLockSurface::CSessionLockSurface(SP resource_, resource->setAckConfigure([this](CExtSessionLockSurfaceV1* r, uint32_t serial) { ackdConfigure = true; }); - hyprListener_surfaceCommit.initCallback( - &pSurface->events.commit, - [this](void* owner, void* data) { - if (pSurface->pending.buffer_width <= 0 || pSurface->pending.buffer_height <= 0) { - LOGM(ERR, "SessionLock attached a null buffer"); - resource->error(EXT_SESSION_LOCK_SURFACE_V1_ERROR_NULL_BUFFER, "Null buffer attached"); - return; - } - - if (!ackdConfigure) { - LOGM(ERR, "SessionLock committed without an ack"); - resource->error(EXT_SESSION_LOCK_SURFACE_V1_ERROR_COMMIT_BEFORE_FIRST_ACK, "Committed surface before first ack"); - return; - } - - if (committed) - events.commit.emit(); - else { - wlr_surface_map(pSurface); - events.map.emit(); - } - committed = true; - }, - this, "SessionLockSurface"); - - hyprListener_surfaceDestroy.initCallback( - &pSurface->events.destroy, - [this](void* owner, void* data) { - LOGM(WARN, "SessionLockSurface object remains but surface is being destroyed???"); - wlr_surface_unmap(pSurface); - hyprListener_surfaceCommit.removeCallback(); - hyprListener_surfaceDestroy.removeCallback(); - - if (g_pCompositor->m_pLastFocus == pSurface) - g_pCompositor->m_pLastFocus = nullptr; - - pSurface = nullptr; - }, - this, "SessionLockSurface"); + listeners.surfaceCommit = pSurface->events.commit.registerListener([this](std::any d) { + if (!pSurface->current.buffer) { + LOGM(ERR, "SessionLock attached a null buffer"); + resource->error(EXT_SESSION_LOCK_SURFACE_V1_ERROR_NULL_BUFFER, "Null buffer attached"); + return; + } + + if (!ackdConfigure) { + LOGM(ERR, "SessionLock committed without an ack"); + resource->error(EXT_SESSION_LOCK_SURFACE_V1_ERROR_COMMIT_BEFORE_FIRST_ACK, "Committed surface before first ack"); + return; + } + + if (committed) + events.commit.emit(); + else { + pSurface->map(); + events.map.emit(); + } + committed = true; + }); + + listeners.surfaceDestroy = pSurface->events.destroy.registerListener([this](std::any d) { + LOGM(WARN, "SessionLockSurface object remains but surface is being destroyed???"); + pSurface->unmap(); + listeners.surfaceCommit.reset(); + listeners.surfaceDestroy.reset(); + if (g_pCompositor->m_pLastFocus == pSurface) + g_pCompositor->m_pLastFocus.reset(); + + pSurface.reset(); + }); PROTO::fractional->sendScale(surface_, pMonitor_->scale); @@ -70,9 +65,9 @@ CSessionLockSurface::CSessionLockSurface(SP resource_, CSessionLockSurface::~CSessionLockSurface() { if (pSurface && pSurface->mapped) - wlr_surface_unmap(pSurface); - hyprListener_surfaceCommit.removeCallback(); - hyprListener_surfaceDestroy.removeCallback(); + pSurface->unmap(); + listeners.surfaceCommit.reset(); + listeners.surfaceDestroy.reset(); events.destroy.emit(); // just in case. } @@ -93,8 +88,8 @@ CMonitor* CSessionLockSurface::monitor() { return pMonitor; } -wlr_surface* CSessionLockSurface::surface() { - return pSurface; +SP CSessionLockSurface::surface() { + return pSurface.lock(); } CSessionLock::CSessionLock(SP resource_) : resource(resource_) { @@ -195,8 +190,8 @@ void CSessionLockProtocol::onLock(CExtSessionLockManagerV1* pMgr, uint32_t id) { void CSessionLockProtocol::onGetLockSurface(CExtSessionLockV1* lock, uint32_t id, wl_resource* surface, wl_resource* output) { LOGM(LOG, "New sessionLockSurface with id {}", id); - auto PSURFACE = wlr_surface_from_resource(surface); - auto PMONITOR = g_pCompositor->getMonitorFromOutput(wlr_output_from_resource(output)); + auto PSURFACE = CWLSurfaceResource::fromResource(surface); + auto PMONITOR = CWLOutputResource::fromResource(output)->monitor.get(); SP sessionLock; for (auto& l : m_vLocks) { diff --git a/src/protocols/SessionLock.hpp b/src/protocols/SessionLock.hpp index 6b0c4e088312..0d935db900cb 100644 --- a/src/protocols/SessionLock.hpp +++ b/src/protocols/SessionLock.hpp @@ -12,13 +12,13 @@ class CSessionLock; class CSessionLockSurface { public: - CSessionLockSurface(SP resource_, wlr_surface* surface_, CMonitor* pMonitor_, WP owner_); + CSessionLockSurface(SP resource_, SP surface_, CMonitor* pMonitor_, WP owner_); ~CSessionLockSurface(); - bool good(); - bool inert(); - CMonitor* monitor(); - wlr_surface* surface(); + bool good(); + bool inert(); + CMonitor* monitor(); + SP surface(); struct { CSignal map; @@ -29,7 +29,7 @@ class CSessionLockSurface { private: SP resource; WP sessionLock; - wlr_surface* pSurface = nullptr; + WP pSurface; CMonitor* pMonitor = nullptr; bool ackdConfigure = false; @@ -37,11 +37,10 @@ class CSessionLockSurface { void sendConfigure(); - DYNLISTENER(surfaceCommit); - DYNLISTENER(surfaceDestroy); - struct { CHyprSignalListener monitorMode; + CHyprSignalListener surfaceCommit; + CHyprSignalListener surfaceDestroy; } listeners; }; diff --git a/src/protocols/ShortcutsInhibit.cpp b/src/protocols/ShortcutsInhibit.cpp index af9724b53679..211a7a013fe3 100644 --- a/src/protocols/ShortcutsInhibit.cpp +++ b/src/protocols/ShortcutsInhibit.cpp @@ -1,10 +1,11 @@ #include "ShortcutsInhibit.hpp" #include #include "../Compositor.hpp" +#include "core/Compositor.hpp" #define LOGM PROTO::shortcutsInhibit->protoLog -CKeyboardShortcutsInhibitor::CKeyboardShortcutsInhibitor(SP resource_, wlr_surface* surf) : resource(resource_), pSurface(surf) { +CKeyboardShortcutsInhibitor::CKeyboardShortcutsInhibitor(SP resource_, SP surf) : resource(resource_), pSurface(surf) { if (!resource->resource()) return; @@ -16,8 +17,8 @@ CKeyboardShortcutsInhibitor::CKeyboardShortcutsInhibitor(SPsendActive(); } -wlr_surface* CKeyboardShortcutsInhibitor::surface() { - return pSurface; +SP CKeyboardShortcutsInhibitor::surface() { + return pSurface.lock(); } bool CKeyboardShortcutsInhibitor::good() { @@ -46,8 +47,8 @@ void CKeyboardShortcutsInhibitProtocol::destroyInhibitor(CKeyboardShortcutsInhib } void CKeyboardShortcutsInhibitProtocol::onInhibit(CZwpKeyboardShortcutsInhibitManagerV1* pMgr, uint32_t id, wl_resource* surface, wl_resource* seat) { - wlr_surface* surf = wlr_surface_from_resource(surface); - const auto CLIENT = pMgr->client(); + SP surf = CWLSurfaceResource::fromResource(surface); + const auto CLIENT = pMgr->client(); for (auto& in : m_vInhibitors) { if (in->surface() != surf) diff --git a/src/protocols/ShortcutsInhibit.hpp b/src/protocols/ShortcutsInhibit.hpp index 4e06938f3e1d..77b5f800de07 100644 --- a/src/protocols/ShortcutsInhibit.hpp +++ b/src/protocols/ShortcutsInhibit.hpp @@ -8,15 +8,15 @@ class CKeyboardShortcutsInhibitor { public: - CKeyboardShortcutsInhibitor(SP resource_, wlr_surface* surf); + CKeyboardShortcutsInhibitor(SP resource_, SP surf); // read-only pointer, may be invalid - wlr_surface* surface(); - bool good(); + SP surface(); + bool good(); private: SP resource; - wlr_surface* pSurface = nullptr; + WP pSurface; }; class CKeyboardShortcutsInhibitProtocol : public IWaylandProtocol { diff --git a/src/protocols/Tablet.cpp b/src/protocols/Tablet.cpp index 54c551760586..393dfd38f150 100644 --- a/src/protocols/Tablet.cpp +++ b/src/protocols/Tablet.cpp @@ -3,6 +3,7 @@ #include "../Compositor.hpp" #include "../managers/SeatManager.hpp" #include "core/Seat.hpp" +#include "core/Compositor.hpp" #include #define LOGM PROTO::tablet->protoLog @@ -160,11 +161,11 @@ CTabletToolV2Resource::CTabletToolV2Resource(SP resource_, SP< resource->setDestroy([this](CZwpTabletToolV2* r) { PROTO::tablet->destroyResource(this); }); resource->setOnDestroy([this](CZwpTabletToolV2* r) { PROTO::tablet->destroyResource(this); }); - resource->setSetCursor([this](CZwpTabletToolV2* r, uint32_t serial, wl_resource* surf, int32_t hot_x, int32_t hot_y) { + resource->setSetCursor([](CZwpTabletToolV2* r, uint32_t serial, wl_resource* surf, int32_t hot_x, int32_t hot_y) { if (!g_pSeatManager->state.pointerFocusResource || g_pSeatManager->state.pointerFocusResource->client() != r->client()) return; - g_pInputManager->processMouseRequest(CSeatManager::SSetCursorEvent{surf ? wlr_surface_from_resource(surf) : nullptr, {hot_x, hot_y}}); + g_pInputManager->processMouseRequest(CSeatManager::SSetCursorEvent{surf ? CWLSurfaceResource::fromResource(surf) : nullptr, {hot_x, hot_y}}); }); } @@ -448,7 +449,7 @@ void CTabletV2Protocol::recheckRegisteredDevices() { if (t->current) { t->resource->sendProximityOut(); t->sendFrame(); - t->lastSurf = nullptr; + t->lastSurf.reset(); } t->resource->sendRemoved(); @@ -545,9 +546,9 @@ void CTabletV2Protocol::down(SP tool) { } } -void CTabletV2Protocol::proximityIn(SP tool, SP tablet, wlr_surface* surf) { +void CTabletV2Protocol::proximityIn(SP tool, SP tablet, SP surf) { proximityOut(tool); - const auto CLIENT = wl_resource_get_client(surf->resource); + const auto CLIENT = surf->client(); SP toolResource; SP tabletResource; @@ -587,7 +588,7 @@ void CTabletV2Protocol::proximityIn(SP tool, SP tablet, wl toolResource->lastSurf = surf; auto serial = g_pSeatManager->nextSerial(g_pSeatManager->seatResourceForClient(toolResource->resource->client())); - toolResource->resource->sendProximityIn(serial, tabletResource->resource.get(), surf->resource); + toolResource->resource->sendProximityIn(serial, tabletResource->resource.get(), surf->getResource()->resource()); toolResource->queueFrame(); LOGM(ERR, "proximityIn: found no resource to send enter"); @@ -598,8 +599,8 @@ void CTabletV2Protocol::proximityOut(SP tool) { if (t->tool != tool || !t->current) continue; - t->current = false; - t->lastSurf = nullptr; + t->current = false; + t->lastSurf.reset(); t->resource->sendProximityOut(); t->sendFrame(); } diff --git a/src/protocols/Tablet.hpp b/src/protocols/Tablet.hpp index 74a45c6343db..e643f59b0f9c 100644 --- a/src/protocols/Tablet.hpp +++ b/src/protocols/Tablet.hpp @@ -112,19 +112,19 @@ class CTabletToolV2Resource { CTabletToolV2Resource(SP resource_, SP tool_, SP seat_); ~CTabletToolV2Resource(); - bool good(); - void sendData(); - void queueFrame(); - void sendFrame(bool removeSource = true); + bool good(); + void sendData(); + void queueFrame(); + void sendFrame(bool removeSource = true); - bool current = false; - wlr_surface* lastSurf = nullptr; // READ-ONLY + bool current = false; + WP lastSurf; - WP tool; - WP seat; - wl_event_source* frameSource = nullptr; + WP tool; + WP seat; + wl_event_source* frameSource = nullptr; - bool inert = false; // removed was sent + bool inert = false; // removed was sent private: SP resource; @@ -180,7 +180,7 @@ class CTabletV2Protocol : public IWaylandProtocol { void tilt(SP tool, const Vector2D& value); void up(SP tool); void down(SP tool); - void proximityIn(SP tool, SP tablet, wlr_surface* surf); + void proximityIn(SP tool, SP tablet, SP surf); void proximityOut(SP tool); void buttonTool(SP tool, uint32_t button, uint32_t state); void motion(SP tool, const Vector2D& value); diff --git a/src/protocols/TearingControl.cpp b/src/protocols/TearingControl.cpp index df3126fe53aa..7f3c0a18ce17 100644 --- a/src/protocols/TearingControl.cpp +++ b/src/protocols/TearingControl.cpp @@ -2,6 +2,7 @@ #include "../managers/ProtocolManager.hpp" #include "../desktop/Window.hpp" #include "../Compositor.hpp" +#include "core/Compositor.hpp" CTearingControlProtocol::CTearingControlProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { static auto P = @@ -13,15 +14,16 @@ void CTearingControlProtocol::bindManager(wl_client* client, void* data, uint32_ RESOURCE->setOnDestroy([this](CWpTearingControlManagerV1* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CWpTearingControlManagerV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); - RESOURCE->setGetTearingControl( - [this](CWpTearingControlManagerV1* pMgr, uint32_t id, wl_resource* surface) { this->onGetController(pMgr->client(), pMgr, id, wlr_surface_from_resource(surface)); }); + RESOURCE->setGetTearingControl([this](CWpTearingControlManagerV1* pMgr, uint32_t id, wl_resource* surface) { + this->onGetController(pMgr->client(), pMgr, id, CWLSurfaceResource::fromResource(surface)); + }); } void CTearingControlProtocol::onManagerResourceDestroy(wl_resource* res) { std::erase_if(m_vManagers, [&](const auto& other) { return other->resource() == res; }); } -void CTearingControlProtocol::onGetController(wl_client* client, CWpTearingControlManagerV1* pMgr, uint32_t id, wlr_surface* surf) { +void CTearingControlProtocol::onGetController(wl_client* client, CWpTearingControlManagerV1* pMgr, uint32_t id, SP surf) { const auto CONTROLLER = m_vTearingControllers.emplace_back(std::make_unique(makeShared(client, pMgr->version(), id), surf)).get(); if (!CONTROLLER->good()) { @@ -44,14 +46,14 @@ void CTearingControlProtocol::onWindowDestroy(PHLWINDOW pWindow) { // -CTearingControl::CTearingControl(SP resource_, wlr_surface* surf_) : resource(resource_) { +CTearingControl::CTearingControl(SP resource_, SP surf_) : resource(resource_) { resource->setData(this); resource->setOnDestroy([this](CWpTearingControlV1* res) { PROTO::tearing->onControllerDestroy(this); }); resource->setDestroy([this](CWpTearingControlV1* res) { PROTO::tearing->onControllerDestroy(this); }); resource->setSetPresentationHint([this](CWpTearingControlV1* res, wpTearingControlV1PresentationHint hint) { this->onHint(hint); }); for (auto& w : g_pCompositor->m_vWindows) { - if (w->m_pWLSurface.wlr() == surf_) { + if (w->m_pWLSurface->resource() == surf_) { pWindow = w; break; } diff --git a/src/protocols/TearingControl.hpp b/src/protocols/TearingControl.hpp index 199397a35e4d..0b47c615c33b 100644 --- a/src/protocols/TearingControl.hpp +++ b/src/protocols/TearingControl.hpp @@ -9,7 +9,7 @@ class CTearingControlProtocol; class CTearingControl { public: - CTearingControl(SP resource_, wlr_surface* surf_); + CTearingControl(SP resource_, SP surf_); void onHint(wpTearingControlV1PresentationHint hint_); @@ -42,7 +42,7 @@ class CTearingControlProtocol : public IWaylandProtocol { private: void onManagerResourceDestroy(wl_resource* res); void onControllerDestroy(CTearingControl* control); - void onGetController(wl_client* client, CWpTearingControlManagerV1* pMgr, uint32_t id, wlr_surface* surf); + void onGetController(wl_client* client, CWpTearingControlManagerV1* pMgr, uint32_t id, SP surf); void onWindowDestroy(PHLWINDOW pWindow); // diff --git a/src/protocols/TextInputV1.cpp b/src/protocols/TextInputV1.cpp index 8fff4db5498c..7c16ef8c9f80 100644 --- a/src/protocols/TextInputV1.cpp +++ b/src/protocols/TextInputV1.cpp @@ -1,6 +1,7 @@ #include "TextInputV1.hpp" #include "../Compositor.hpp" +#include "core/Compositor.hpp" #define TEXT_INPUT_VERSION 1 @@ -168,7 +169,7 @@ void CTextInputV1ProtocolManager::handleActivate(wl_client* client, wl_resource* return; } PTI->active = true; - PTI->pTextInput->onEnabled(wlr_surface_from_resource(surface)); + PTI->pTextInput->onEnabled(CWLSurfaceResource::fromResource(surface)); } void CTextInputV1ProtocolManager::handleDeactivate(wl_client* client, wl_resource* resource, wl_resource* seat) { diff --git a/src/protocols/TextInputV3.cpp b/src/protocols/TextInputV3.cpp index b463c6d61359..1302a57f0c4a 100644 --- a/src/protocols/TextInputV3.cpp +++ b/src/protocols/TextInputV3.cpp @@ -1,5 +1,6 @@ #include "TextInputV3.hpp" #include +#include "core/Compositor.hpp" #define LOGM PROTO::textInputV3->protoLog @@ -66,12 +67,12 @@ CTextInputV3::~CTextInputV3() { events.destroy.emit(); } -void CTextInputV3::enter(wlr_surface* surf) { - resource->sendEnter(surf->resource); +void CTextInputV3::enter(SP surf) { + resource->sendEnter(surf->getResource()->resource()); } -void CTextInputV3::leave(wlr_surface* surf) { - resource->sendLeave(surf->resource); +void CTextInputV3::leave(SP surf) { + resource->sendLeave(surf->getResource()->resource()); } void CTextInputV3::preeditString(const std::string& text, int32_t cursorBegin, int32_t cursorEnd) { diff --git a/src/protocols/TextInputV3.hpp b/src/protocols/TextInputV3.hpp index 6d4f3d54b136..e4a8388726e0 100644 --- a/src/protocols/TextInputV3.hpp +++ b/src/protocols/TextInputV3.hpp @@ -14,8 +14,8 @@ class CTextInputV3 { CTextInputV3(SP resource_); ~CTextInputV3(); - void enter(wlr_surface* surf); - void leave(wlr_surface* surf); + void enter(SP surf); + void leave(SP surf); void preeditString(const std::string& text, int32_t cursorBegin, int32_t cursorEnd); void commitString(const std::string& text); void deleteSurroundingText(uint32_t beforeLength, uint32_t afterLength); diff --git a/src/protocols/Viewporter.cpp b/src/protocols/Viewporter.cpp new file mode 100644 index 000000000000..7bb9af3cc85c --- /dev/null +++ b/src/protocols/Viewporter.cpp @@ -0,0 +1,117 @@ +#include "Viewporter.hpp" +#include "core/Compositor.hpp" +#include + +#define LOGM PROTO::viewport->protoLog + +CViewportResource::CViewportResource(SP resource_, SP surface_) : surface(surface_), resource(resource_) { + if (!good()) + return; + + resource->setDestroy([this](CWpViewport* r) { PROTO::viewport->destroyResource(this); }); + resource->setOnDestroy([this](CWpViewport* r) { PROTO::viewport->destroyResource(this); }); + + resource->setSetDestination([this](CWpViewport* r, int32_t x, int32_t y) { + if (!surface) { + r->error(WP_VIEWPORT_ERROR_NO_SURFACE, "Surface is gone"); + return; + } + + if (x == -1 && y == -1) { + surface->pending.viewport.hasDestination = false; + return; + } + + if (x <= 0 || y <= 0) { + r->error(WP_VIEWPORT_ERROR_BAD_SIZE, "Size was <= 0"); + return; + } + + surface->pending.viewport.hasDestination = true; + surface->pending.viewport.destination = {x, y}; + }); + + resource->setSetSource([this](CWpViewport* r, wl_fixed_t fx, wl_fixed_t fy, wl_fixed_t fw, wl_fixed_t fh) { + if (!surface) { + r->error(WP_VIEWPORT_ERROR_NO_SURFACE, "Surface is gone"); + return; + } + + double x = wl_fixed_to_double(fx), y = wl_fixed_to_double(fy), w = wl_fixed_to_double(fw), h = wl_fixed_to_double(fh); + + if (x == -1 && y == -1 && w == -1 && h == -1) { + surface->pending.viewport.hasSource = false; + return; + } + + if (x < 0 || y < 0) { + r->error(WP_VIEWPORT_ERROR_BAD_SIZE, "Pos was < 0"); + return; + } + + if (w + x > surface->pending.size.x || h + y > surface->pending.size.y) { + r->error(WP_VIEWPORT_ERROR_BAD_VALUE, "Box doesn't fit"); + return; + } + + surface->pending.viewport.hasSource = true; + surface->pending.viewport.source = {x, y, w, h}; + }); +} + +CViewportResource::~CViewportResource() { + if (!surface) + return; + + surface->pending.viewport.hasDestination = false; + surface->pending.viewport.hasSource = false; +} + +bool CViewportResource::good() { + return resource->resource(); +} + +CViewporterResource::CViewporterResource(SP resource_) : resource(resource_) { + if (!good()) + return; + + resource->setDestroy([this](CWpViewporter* r) { PROTO::viewport->destroyResource(this); }); + resource->setOnDestroy([this](CWpViewporter* r) { PROTO::viewport->destroyResource(this); }); + + resource->setGetViewport([](CWpViewporter* r, uint32_t id, wl_resource* surf) { + const auto RESOURCE = PROTO::viewport->m_vViewports.emplace_back( + makeShared(makeShared(r->client(), r->version(), id), CWLSurfaceResource::fromResource(surf))); + + if (!RESOURCE->good()) { + r->noMemory(); + PROTO::viewport->m_vViewports.pop_back(); + return; + } + }); +} + +bool CViewporterResource::good() { + return resource->resource(); +} + +CViewporterProtocol::CViewporterProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CViewporterProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); + + if (!RESOURCE->good()) { + wl_client_post_no_memory(client); + m_vManagers.pop_back(); + return; + } +} + +void CViewporterProtocol::destroyResource(CViewporterResource* resource) { + std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == resource; }); +} + +void CViewporterProtocol::destroyResource(CViewportResource* resource) { + std::erase_if(m_vViewports, [&](const auto& other) { return other.get() == resource; }); +} diff --git a/src/protocols/Viewporter.hpp b/src/protocols/Viewporter.hpp new file mode 100644 index 000000000000..d2e566458af8 --- /dev/null +++ b/src/protocols/Viewporter.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include +#include +#include +#include "WaylandProtocol.hpp" +#include "viewporter.hpp" +#include "../helpers/signal/Signal.hpp" + +class CWLSurfaceResource; + +class CViewportResource { + public: + CViewportResource(SP resource_, SP surface_); + ~CViewportResource(); + + bool good(); + WP surface; + + private: + SP resource; +}; + +class CViewporterResource { + public: + CViewporterResource(SP resource_); + + bool good(); + + private: + SP resource; +}; + +class CViewporterProtocol : public IWaylandProtocol { + public: + CViewporterProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + private: + void destroyResource(CViewporterResource* resource); + void destroyResource(CViewportResource* resource); + + // + std::vector> m_vManagers; + std::vector> m_vViewports; + + friend class CViewporterResource; + friend class CViewportResource; +}; + +namespace PROTO { + inline UP viewport; +}; diff --git a/src/protocols/WaylandProtocol.hpp b/src/protocols/WaylandProtocol.hpp index a7487c15703d..16d346c58939 100644 --- a/src/protocols/WaylandProtocol.hpp +++ b/src/protocols/WaylandProtocol.hpp @@ -14,7 +14,7 @@ class IWaylandProtocol { public: IWaylandProtocol(const wl_interface* iface, const int& ver, const std::string& name); - ~IWaylandProtocol(); + virtual ~IWaylandProtocol(); virtual void onDisplayDestroy(); diff --git a/src/protocols/XDGActivation.cpp b/src/protocols/XDGActivation.cpp index 1d9814ac827b..40f33f02e1f6 100644 --- a/src/protocols/XDGActivation.cpp +++ b/src/protocols/XDGActivation.cpp @@ -1,6 +1,7 @@ #include "XDGActivation.hpp" #include "../managers/TokenManager.hpp" #include "../Compositor.hpp" +#include "core/Compositor.hpp" #include #define LOGM PROTO::activation->protoLog @@ -79,8 +80,8 @@ void CXDGActivationProtocol::bindManager(wl_client* client, void* data, uint32_t // remove token. It's been now spent. m_vSentTokens.erase(TOKEN); - wlr_surface* surf = wlr_surface_from_resource(surface); - const auto PWINDOW = g_pCompositor->getWindowFromSurface(surf); + SP surf = CWLSurfaceResource::fromResource(surface); + const auto PWINDOW = g_pCompositor->getWindowFromSurface(surf); if (!PWINDOW) { LOGM(WARN, "activate event for non-window or gone surface with token {}, ignoring", token); diff --git a/src/protocols/XDGOutput.cpp b/src/protocols/XDGOutput.cpp index 771f5f781a5c..03e58956a644 100644 --- a/src/protocols/XDGOutput.cpp +++ b/src/protocols/XDGOutput.cpp @@ -2,6 +2,7 @@ #include "../Compositor.hpp" #include "../config/ConfigValue.hpp" #include "../xwayland/XWayland.hpp" +#include "core/Output.hpp" #define OUTPUT_MANAGER_VERSION 3 #define OUTPUT_DONE_DEPRECATED_SINCE_VERSION 3 @@ -48,9 +49,9 @@ CXDGOutputProtocol::CXDGOutputProtocol(const wl_interface* iface, const int& ver } void CXDGOutputProtocol::onManagerGetXDGOutput(CZxdgOutputManagerV1* mgr, uint32_t id, wl_resource* outputResource) { - const auto OUTPUT = wlr_output_from_resource(outputResource); + const auto OUTPUT = CWLOutputResource::fromResource(outputResource); - const auto PMONITOR = g_pCompositor->getMonitorFromOutput(OUTPUT); + const auto PMONITOR = OUTPUT->monitor.get(); const auto CLIENT = mgr->client(); diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index cbb93de90ccb..18e0a7ea8a39 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -3,6 +3,7 @@ #include "../Compositor.hpp" #include "../managers/SeatManager.hpp" #include "core/Seat.hpp" +#include "core/Compositor.hpp" #define LOGM PROTO::xdgShell->protoLog @@ -288,7 +289,8 @@ void CXDGToplevelResource::close() { resource->sendClose(); } -CXDGSurfaceResource::CXDGSurfaceResource(SP resource_, SP owner_, wlr_surface* surface_) : owner(owner_), surface(surface_), resource(resource_) { +CXDGSurfaceResource::CXDGSurfaceResource(SP resource_, SP owner_, SP surface_) : + owner(owner_), surface(surface_), resource(resource_) { if (!good()) return; @@ -307,56 +309,50 @@ CXDGSurfaceResource::CXDGSurfaceResource(SP resource_, SPdestroyResource(this); }); - hyprListener_surfaceDestroy.initCallback( - &surface->events.destroy, - [this](void* owner, void* data) { - LOGM(WARN, "wl_surface destroyed before its xdg_surface role object"); - hyprListener_surfaceDestroy.removeCallback(); - hyprListener_surfaceCommit.removeCallback(); - - if (mapped) - events.unmap.emit(); - - mapped = false; - surface = nullptr; - events.destroy.emit(); - }, - nullptr, "CXDGSurfaceResource"); - - hyprListener_surfaceCommit.initCallback( - &surface->events.commit, - [this](void* owner, void* data) { - current = pending; + listeners.surfaceDestroy = surface->events.destroy.registerListener([this](std::any d) { + LOGM(WARN, "wl_surface destroyed before its xdg_surface role object"); + listeners.surfaceDestroy.reset(); + listeners.surfaceCommit.reset(); + + if (mapped) + events.unmap.emit(); + + mapped = false; + surface.reset(); + events.destroy.emit(); + }); + + listeners.surfaceCommit = surface->events.commit.registerListener([this](std::any d) { + current = pending; + if (toplevel) + toplevel->current = toplevel->pending; + + if (initialCommit && surface->pending.buffer) { + resource->error(-1, "Buffer attached before initial commit"); + return; + } + + if (surface->current.buffer && !mapped) { + // this forces apps to not draw CSD. if (toplevel) - toplevel->current = toplevel->pending; - - if (initialCommit && surface->pending.buffer_width > 0 && surface->pending.buffer_height > 0) { - resource->error(-1, "Buffer attached before initial commit"); - return; - } - - if (surface->pending.buffer_width > 0 && surface->pending.buffer_height > 0 && !mapped) { - // this forces apps to not draw CSD. - if (toplevel) - toplevel->setMaximized(true); - - mapped = true; - wlr_surface_map(surface); - events.map.emit(); - return; - } - - if (surface->pending.buffer_width <= 0 && surface->pending.buffer_height <= 0 && mapped) { - mapped = false; - wlr_surface_unmap(surface); - events.unmap.emit(); - return; - } - - events.commit.emit(); - initialCommit = false; - }, - nullptr, "CXDGSurfaceResource"); + toplevel->setMaximized(true); + + mapped = true; + surface->map(); + events.map.emit(); + return; + } + + if (!surface->current.buffer && mapped) { + mapped = false; + surface->unmap(); + events.unmap.emit(); + return; + } + + events.commit.emit(); + initialCommit = false; + }); resource->setGetToplevel([this](CXdgSurface* r, uint32_t id) { const auto RESOURCE = PROTO::xdgShell->m_vToplevels.emplace_back(makeShared(makeShared(r->client(), r->version(), id), self.lock())); @@ -649,7 +645,7 @@ CXDGWMBase::CXDGWMBase(SP resource_) : resource(resource_) { resource->setGetXdgSurface([this](CXdgWmBase* r, uint32_t id, wl_resource* surf) { const auto RESOURCE = PROTO::xdgShell->m_vSurfaces.emplace_back( - makeShared(makeShared(r->client(), r->version(), id), self.lock(), wlr_surface_from_resource(surf))); + makeShared(makeShared(r->client(), r->version(), id), self.lock(), CWLSurfaceResource::fromResource(surf))); if (!RESOURCE->good()) { r->noMemory(); @@ -724,9 +720,9 @@ void CXDGShellProtocol::addOrStartGrab(SP popup) { grabOwner = popup; grabbed.clear(); grab->clear(); - grab->add(popup->surface->surface); + grab->add(popup->surface->surface.lock()); if (popup->parent) - grab->add(popup->parent->surface); + grab->add(popup->parent->surface.lock()); g_pSeatManager->setGrab(grab); grabbed.emplace_back(popup); return; @@ -734,10 +730,10 @@ void CXDGShellProtocol::addOrStartGrab(SP popup) { grabbed.emplace_back(popup); - grab->add(popup->surface->surface); + grab->add(popup->surface->surface.lock()); if (popup->parent) - grab->add(popup->parent->surface); + grab->add(popup->parent->surface.lock()); } void CXDGShellProtocol::onPopupDestroy(WP popup) { @@ -752,5 +748,5 @@ void CXDGShellProtocol::onPopupDestroy(WP popup) { std::erase(grabbed, popup); if (popup->surface) - grab->remove(popup->surface->surface); + grab->remove(popup->surface->surface.lock()); } diff --git a/src/protocols/XDGShell.hpp b/src/protocols/XDGShell.hpp index 1dbeb209827f..cdba784af9b1 100644 --- a/src/protocols/XDGShell.hpp +++ b/src/protocols/XDGShell.hpp @@ -138,7 +138,7 @@ class CXDGToplevelResource { class CXDGSurfaceResource { public: - CXDGSurfaceResource(SP resource_, SP owner_, wlr_surface* surface_); + CXDGSurfaceResource(SP resource_, SP owner_, SP surface_); ~CXDGSurfaceResource(); static SP fromResource(wl_resource*); @@ -146,7 +146,7 @@ class CXDGSurfaceResource { bool good(); WP owner; - wlr_surface* surface = nullptr; + WP surface; WP toplevel; WP popup; @@ -184,8 +184,10 @@ class CXDGSurfaceResource { // std::vector> popups; - DYNLISTENER(surfaceDestroy); - DYNLISTENER(surfaceCommit); + struct { + CHyprSignalListener surfaceDestroy; + CHyprSignalListener surfaceCommit; + } listeners; friend class CXDGPopupResource; friend class CXDGToplevelResource; diff --git a/src/protocols/XWaylandShell.cpp b/src/protocols/XWaylandShell.cpp index 8b9905f8c0f1..6cc5256fb07d 100644 --- a/src/protocols/XWaylandShell.cpp +++ b/src/protocols/XWaylandShell.cpp @@ -1,9 +1,10 @@ #include "XWaylandShell.hpp" +#include "core/Compositor.hpp" #include #define LOGM PROTO::xwaylandShell->protoLog -CXWaylandSurfaceResource::CXWaylandSurfaceResource(SP resource_, wlr_surface* surface_) : surface(surface_), resource(resource_) { +CXWaylandSurfaceResource::CXWaylandSurfaceResource(SP resource_, SP surface_) : surface(surface_), resource(resource_) { if (!good()) return; @@ -45,7 +46,7 @@ CXWaylandShellResource::CXWaylandShellResource(SP resource_) : resource->setGetXwaylandSurface([this](CXwaylandShellV1* r, uint32_t id, wl_resource* surface) { const auto RESOURCE = PROTO::xwaylandShell->m_vSurfaces.emplace_back( - makeShared(makeShared(r->client(), r->version(), id), wlr_surface_from_resource(surface))); + makeShared(makeShared(r->client(), r->version(), id), CWLSurfaceResource::fromResource(surface))); if (!RESOURCE->good()) { r->noMemory(); diff --git a/src/protocols/XWaylandShell.hpp b/src/protocols/XWaylandShell.hpp index 2c03d172ee65..c8c0c04af2b2 100644 --- a/src/protocols/XWaylandShell.hpp +++ b/src/protocols/XWaylandShell.hpp @@ -7,9 +7,11 @@ #include "xwayland-shell-v1.hpp" #include "../helpers/signal/Signal.hpp" +class CWLSurfaceResource; + class CXWaylandSurfaceResource { public: - CXWaylandSurfaceResource(SP resource_, wlr_surface* surface_); + CXWaylandSurfaceResource(SP resource_, SP surface_); ~CXWaylandSurfaceResource(); bool good(); @@ -19,8 +21,8 @@ class CXWaylandSurfaceResource { CSignal destroy; } events; - uint64_t serial = 0; - wlr_surface* surface = nullptr; + uint64_t serial = 0; + WP surface; WP self; diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp new file mode 100644 index 000000000000..c5c63abc85a9 --- /dev/null +++ b/src/protocols/core/Compositor.cpp @@ -0,0 +1,338 @@ +#include "Compositor.hpp" +#include "Output.hpp" +#include "../types/WLBuffer.hpp" +#include +#include "Subcompositor.hpp" + +#define LOGM PROTO::compositor->protoLog + +class CDefaultSurfaceRole : public ISurfaceRole { + public: + virtual eSurfaceRole role() { + return SURFACE_ROLE_UNASSIGNED; + } +}; + +SP defaultRole = makeShared(); + +CWLCallbackResource::CWLCallbackResource(SP resource_) : resource(resource_) { + ; +} + +bool CWLCallbackResource::good() { + return resource->resource(); +} + +void CWLCallbackResource::send(timespec* now) { + resource->sendDone(now->tv_sec * 1000 + now->tv_nsec / 1000000); +} + +CWLRegionResource::CWLRegionResource(SP resource_) : resource(resource_) { + if (!good()) + return; + + resource->setDestroy([this](CWlRegion* r) { PROTO::compositor->destroyResource(this); }); + resource->setOnDestroy([this](CWlRegion* r) { PROTO::compositor->destroyResource(this); }); + + resource->setAdd([this](CWlRegion* r, int32_t x, int32_t y, int32_t w, int32_t h) { region.add(CBox{x, y, w, h}); }); + resource->setSubtract([this](CWlRegion* r, int32_t x, int32_t y, int32_t w, int32_t h) { region.subtract(CBox{x, y, w, h}); }); +} + +bool CWLRegionResource::good() { + return resource->resource(); +} + +CWLSurfaceResource::CWLSurfaceResource(SP resource_) : resource(resource_) { + if (!good()) + return; + + pClient = resource->client(); + + resource->setData(this); + + role = defaultRole; + + resource->setDestroy([this](CWlSurface* r) { + events.destroy.emit(); + PROTO::compositor->destroyResource(this); + }); + resource->setOnDestroy([this](CWlSurface* r) { + events.destroy.emit(); + PROTO::compositor->destroyResource(this); + }); + + resource->setAttach([this](CWlSurface* r, wl_resource* buffer, int32_t x, int32_t y) { + pending.offset = {x, y}; + + if (!buffer) + pending.buffer.reset(); + else { + auto res = CWLBufferResource::fromResource(buffer); + pending.buffer = res ? res->buffer : nullptr; + pending.size = res ? res->buffer->size : Vector2D{}; + } + + pending.newBuffer = true; + }); + + resource->setCommit([this](CWlSurface* r) { + CRegion bufferDamage = current.bufferDamage.copy().add(pending.bufferDamage); + + pending.size = pending.size / pending.scale; + if (pending.inputResource) + pending.input = pending.inputResource->region; + if (pending.opaqueResource) + pending.opaque = pending.opaqueResource->region; + current = pending; + + pending.reset(); + + if (current.buffer) { + current.buffer->update(bufferDamage); + // release the buffer, we've read the pixels and can now + // let the app know we're done + current.buffer->sendRelease(); + } + + events.commit.emit(); + }); + + resource->setDamage([this](CWlSurface* r, int32_t x, int32_t y, int32_t w, int32_t h) { pending.damage.add(CBox{x, y, w, h}); }); + resource->setDamageBuffer([this](CWlSurface* r, int32_t x, int32_t y, int32_t w, int32_t h) { pending.bufferDamage.add(CBox{x, y, w, h}); }); + + resource->setSetBufferScale([this](CWlSurface* r, int32_t scale) { pending.scale = scale; }); + resource->setSetBufferTransform([this](CWlSurface* r, uint32_t tr) { pending.transform = (wl_output_transform)tr; }); + + resource->setFrame([this](CWlSurface* r, uint32_t id) { + if (callback) + LOGM(WARN, "Callback already present in wl_surface.frame, will be overwritten"); + + callback = makeShared(makeShared(pClient, 1, id)); + }); + + resource->setOffset([this](CWlSurface* r, int32_t x, int32_t y) { pending.offset = {x, y}; }); +} + +CWLSurfaceResource::~CWLSurfaceResource() { + events.destroy.emit(); +} + +SP CWLSurfaceResource::fromResource(wl_resource* res) { + auto data = (CWLSurfaceResource*)(((CWlSurface*)wl_resource_get_user_data(res))->data()); + return data ? data->self.lock() : nullptr; +} + +bool CWLSurfaceResource::good() { + return resource->resource(); +} + +wl_client* CWLSurfaceResource::client() { + return pClient; +} + +void CWLSurfaceResource::enter(SP monitor) { + if (std::find(enteredOutputs.begin(), enteredOutputs.end(), monitor) != enteredOutputs.end()) + return; + + auto output = PROTO::outputs.at(monitor->szName)->outputResourceFrom(pClient); + + if (!output) { + LOGM(ERR, "Cannot enter surface {:x} to {}, client hasn't bound the output", (uintptr_t)this, monitor->szName); + return; + } + + enteredOutputs.emplace_back(monitor); + + resource->sendEnter(output->getResource().get()); +} + +void CWLSurfaceResource::leave(SP monitor) { + if (std::find(enteredOutputs.begin(), enteredOutputs.end(), monitor) == enteredOutputs.end()) + return; + + auto output = PROTO::outputs.at(monitor->szName)->outputResourceFrom(pClient); + + if (!output) { + LOGM(ERR, "Cannot leave surface {:x} from {}, client hasn't bound the output", (uintptr_t)this, monitor->szName); + return; + } + + std::erase(enteredOutputs, monitor); + + resource->sendLeave(output->getResource().get()); +} + +void CWLSurfaceResource::sendPreferredTransform(wl_output_transform t) { + if (resource->version() < 6) + return; + resource->sendPreferredBufferTransform(t); +} + +void CWLSurfaceResource::sendPreferredScale(int32_t scale) { + if (resource->version() < 6) + return; + resource->sendPreferredBufferScale(scale); +} + +void CWLSurfaceResource::frame(timespec* now) { + if (!callback) + return; + + callback->send(now); + + callback.reset(); +} + +void CWLSurfaceResource::resetRole() { + role = defaultRole; +} + +void CWLSurfaceResource::bfHelper(std::vector> nodes, std::function, void*)> fn, void* data) { + for (auto& n : nodes) { + fn(n, data); + } + + std::vector> nodes2; + + for (auto& n : nodes) { + for (auto& c : n->subsurfaces) { + nodes2.push_back(c->surface.lock()); + } + } + + if (!nodes2.empty()) + bfHelper(nodes2, fn, data); +} + +void CWLSurfaceResource::breadthfirst(std::function, void*)> fn, void* data) { + std::vector> surfs; + surfs.push_back(self.lock()); + bfHelper(surfs, fn, data); +} + +SP CWLSurfaceResource::at(const Vector2D& localCoords, bool allowsInput) { + SP found; + breadthfirst( + [localCoords](SP surface, void* data) { + Vector2D localOffset = {}; + if (surface->role->role() == SURFACE_ROLE_SUBSURFACE) { + CWLSubsurfaceResource* subsurface = (CWLSubsurfaceResource*)surface->role.get(); + localOffset = subsurface->posRelativeToParent(); + } + // if not, assume it's the first surface, in which case its offset is 0. + + CBox box = {localOffset, surface->current.size}; + + if (box.containsPoint(localCoords)) + *(SP*)data = surface; + }, + &found); + + return found ? found : self.lock(); // if no surface was found, we can return the base surf. +} + +uint32_t CWLSurfaceResource::id() { + return wl_resource_get_id(resource->resource()); +} + +void CWLSurfaceResource::map() { + if (mapped) + return; + + mapped = true; + + events.map.emit(); + + timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + frame(&now); + + //TODO: subsurfaces +} + +void CWLSurfaceResource::unmap() { + if (!mapped) + return; + + mapped = false; + + events.unmap.emit(); +} + +void CWLSurfaceResource::error(int code, const std::string& str) { + resource->error(code, str); +} + +SP CWLSurfaceResource::getResource() { + return resource; +} + +CBox CWLSurfaceResource::extends() { + // TODO: + return {{}, current.size}; +} + +CWLCompositorResource::CWLCompositorResource(SP resource_) : resource(resource_) { + if (!good()) + return; + + resource->setOnDestroy([this](CWlCompositor* r) { PROTO::compositor->destroyResource(this); }); + + resource->setCreateSurface([](CWlCompositor* r, uint32_t id) { + const auto RESOURCE = PROTO::compositor->m_vSurfaces.emplace_back(makeShared(makeShared(r->client(), r->version(), id))); + + if (!RESOURCE->good()) { + r->noMemory(); + PROTO::compositor->m_vSurfaces.pop_back(); + return; + } + + RESOURCE->self = RESOURCE; + + LOGM(LOG, "New wl_surface with id {} at {:x}", id, (uintptr_t)RESOURCE.get()); + + PROTO::compositor->events.newSurface.emit(RESOURCE); + }); + + resource->setCreateRegion([](CWlCompositor* r, uint32_t id) { + const auto RESOURCE = PROTO::compositor->m_vRegions.emplace_back(makeShared(makeShared(r->client(), r->version(), id))); + + if (!RESOURCE->good()) { + r->noMemory(); + PROTO::compositor->m_vRegions.pop_back(); + return; + } + + LOGM(LOG, "New wl_region with id {} at {:x}", id, (uintptr_t)RESOURCE.get()); + }); +} + +bool CWLCompositorResource::good() { + return resource->resource(); +} + +CWLCompositorProtocol::CWLCompositorProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CWLCompositorProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); + + if (!RESOURCE->good()) { + wl_client_post_no_memory(client); + m_vManagers.pop_back(); + return; + } +} + +void CWLCompositorProtocol::destroyResource(CWLCompositorResource* resource) { + std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == resource; }); +} + +void CWLCompositorProtocol::destroyResource(CWLSurfaceResource* resource) { + std::erase_if(m_vSurfaces, [&](const auto& other) { return other.get() == resource; }); +} + +void CWLCompositorProtocol::destroyResource(CWLRegionResource* resource) { + std::erase_if(m_vRegions, [&](const auto& other) { return other.get() == resource; }); +} diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp new file mode 100644 index 000000000000..e865a89810e0 --- /dev/null +++ b/src/protocols/core/Compositor.hpp @@ -0,0 +1,167 @@ +#pragma once + +/* + Implementations for: + - wl_compositor + - wl_surface + - wl_region + - wl_callback +*/ + +#include +#include +#include +#include "../WaylandProtocol.hpp" +#include "wayland.hpp" +#include "../../helpers/signal/Signal.hpp" +#include "../../helpers/Region.hpp" +#include "../types/Buffer.hpp" +#include "../types/SurfaceRole.hpp" + +class CWLOutputResource; +class CMonitor; +class CWLSurface; +class CWLSurfaceResource; +class CWLSubsurfaceResource; + +class CWLCallbackResource { + public: + CWLCallbackResource(SP resource_); + + bool good(); + void send(timespec* now); + + private: + SP resource; +}; + +class CWLRegionResource { + public: + CWLRegionResource(SP resource_); + + bool good(); + + CRegion region; + + private: + SP resource; +}; + +class CWLSurfaceResource { + public: + CWLSurfaceResource(SP resource_); + ~CWLSurfaceResource(); + + static SP fromResource(wl_resource* res); + + bool good(); + wl_client* client(); + void enter(SP monitor); + void leave(SP monitor); + void sendPreferredTransform(wl_output_transform t); + void sendPreferredScale(int32_t scale); + void frame(timespec* now); + uint32_t id(); + void map(); + void unmap(); + void error(int code, const std::string& str); + SP getResource(); + CBox extends(); + void resetRole(); + + struct { + CSignal commit; + CSignal map; + CSignal unmap; + CSignal newSubsurface; + CSignal destroy; + } events; + + struct { + WP opaqueResource; + WP inputResource; + CRegion opaque, input = CBox{{}, {INT32_MAX, INT32_MAX}}, damage, bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}} /* initial damage */; + wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; + int scale = 1; + SP buffer; + Vector2D offset; + Vector2D size; + bool newBuffer = false; + struct { + bool hasDestination = false; + bool hasSource = false; + Vector2D destination; + CBox source; + } viewport; + + // + void reset() { + opaqueResource.reset(); + inputResource.reset(); + damage.clear(); + bufferDamage.clear(); + transform = WL_OUTPUT_TRANSFORM_NORMAL; + scale = 1; + offset = {}; + size = {}; + newBuffer = false; + } + } current, pending; + + SP callback; + WP self; + WP hlSurface; + std::vector> enteredOutputs; + bool mapped = false; + std::vector> subsurfaces; + WP role; + + void breadthfirst(std::function, void*)> fn, void* data); + SP at(const Vector2D& localCoords, bool allowsInput = false); + + private: + SP resource; + wl_client* pClient = nullptr; + + void bfHelper(std::vector> nodes, std::function, void*)> fn, void* data); +}; + +class CWLCompositorResource { + public: + CWLCompositorResource(SP resource_); + + bool good(); + + private: + SP resource; +}; + +class CWLCompositorProtocol : public IWaylandProtocol { + public: + CWLCompositorProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + struct { + CSignal newSurface; // SP + } events; + + private: + void destroyResource(CWLCompositorResource* resource); + void destroyResource(CWLSurfaceResource* resource); + void destroyResource(CWLRegionResource* resource); + + // + std::vector> m_vManagers; + std::vector> m_vSurfaces; + std::vector> m_vRegions; + + friend class CWLSurfaceResource; + friend class CWLCompositorResource; + friend class CWLRegionResource; + friend class CWLCallbackResource; +}; + +namespace PROTO { + inline UP compositor; +}; diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index 354259fe1047..8c5647377460 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -4,6 +4,7 @@ #include "../../managers/PointerManager.hpp" #include "../../Compositor.hpp" #include "Seat.hpp" +#include "Compositor.hpp" #define LOGM PROTO::data->protoLog @@ -233,7 +234,7 @@ CWLDataDeviceResource::CWLDataDeviceResource(SP resource_) : reso source->dnd = true; - PROTO::data->initiateDrag(source, icon ? wlr_surface_from_resource(icon) : nullptr, wlr_surface_from_resource(origin)); + PROTO::data->initiateDrag(source, icon ? CWLSurfaceResource::fromResource(icon) : nullptr, CWLSurfaceResource::fromResource(origin)); }); } @@ -252,8 +253,8 @@ void CWLDataDeviceResource::sendDataOffer(SP offer) { resource->sendDataOfferRaw(nullptr); } -void CWLDataDeviceResource::sendEnter(uint32_t serial, wlr_surface* surf, const Vector2D& local, SP offer) { - resource->sendEnterRaw(serial, surf->resource, wl_fixed_from_double(local.x), wl_fixed_from_double(local.y), offer->resource->resource()); +void CWLDataDeviceResource::sendEnter(uint32_t serial, SP surf, const Vector2D& local, SP offer) { + resource->sendEnterRaw(serial, surf->getResource()->resource(), wl_fixed_from_double(local.x), wl_fixed_from_double(local.y), offer->resource->resource()); } void CWLDataDeviceResource::sendLeave() { @@ -454,7 +455,7 @@ void CWLDataDeviceProtocol::onKeyboardFocus() { updateDrag(); } -void CWLDataDeviceProtocol::initiateDrag(WP currentSource, wlr_surface* dragSurface, wlr_surface* origin) { +void CWLDataDeviceProtocol::initiateDrag(WP currentSource, SP dragSurface, SP origin) { if (dnd.currentSource) { LOGM(WARN, "New drag started while old drag still active??"); @@ -472,22 +473,18 @@ void CWLDataDeviceProtocol::initiateDrag(WP currentSource dnd.originSurface = origin; dnd.dndSurface = dragSurface; if (dragSurface) { - dnd.hyprListener_dndSurfaceDestroy.initCallback( - &dragSurface->events.destroy, [this](void* owner, void* data) { abortDrag(); }, nullptr, "CWLDataDeviceProtocol::drag"); - dnd.hyprListener_dndSurfaceCommit.initCallback( - &dragSurface->events.commit, - [this](void* owner, void* data) { - if (dnd.dndSurface->pending.buffer_width > 0 && dnd.dndSurface->pending.buffer_height > 0 && !dnd.dndSurface->mapped) { - wlr_surface_map(dnd.dndSurface); - return; - } - - if (dnd.dndSurface->pending.buffer_width <= 0 && dnd.dndSurface->pending.buffer_height <= 0 && dnd.dndSurface->mapped) { - wlr_surface_unmap(dnd.dndSurface); - return; - } - }, - nullptr, "CWLDataDeviceProtocol::drag"); + dnd.dndSurfaceDestroy = dragSurface->events.destroy.registerListener([this](std::any d) { abortDrag(); }); + dnd.dndSurfaceCommit = dragSurface->events.commit.registerListener([this](std::any d) { + if (dnd.dndSurface->current.buffer && !dnd.dndSurface->mapped) { + dnd.dndSurface->map(); + return; + } + + if (dnd.dndSurface->current.buffer <= 0 && dnd.dndSurface->mapped) { + dnd.dndSurface->unmap(); + return; + } + }); } dnd.mouseButton = g_pHookSystem->hookDynamic("mouseButton", [this](void* self, SCallbackInfo& info, std::any e) { @@ -506,7 +503,7 @@ void CWLDataDeviceProtocol::initiateDrag(WP currentSource dnd.mouseMove = g_pHookSystem->hookDynamic("mouseMove", [this](void* self, SCallbackInfo& info, std::any e) { auto V = std::any_cast(e); if (dnd.focusedDevice && g_pSeatManager->state.keyboardFocus) { - auto surf = CWLSurface::surfaceFromWlr(g_pSeatManager->state.keyboardFocus); + auto surf = CWLSurface::fromResource(g_pSeatManager->state.keyboardFocus.lock()); if (!surf) return; @@ -524,7 +521,7 @@ void CWLDataDeviceProtocol::initiateDrag(WP currentSource dnd.touchMove = g_pHookSystem->hookDynamic("touchMove", [this](void* self, SCallbackInfo& info, std::any e) { auto E = std::any_cast(e); if (dnd.focusedDevice && g_pSeatManager->state.keyboardFocus) { - auto surf = CWLSurface::surfaceFromWlr(g_pSeatManager->state.keyboardFocus); + auto surf = CWLSurface::fromResource(g_pSeatManager->state.keyboardFocus.lock()); if (!surf) return; @@ -572,14 +569,14 @@ void CWLDataDeviceProtocol::updateDrag() { dnd.focusedDevice->sendDataOffer(OFFER); OFFER->sendData(); - dnd.focusedDevice->sendEnter(wl_display_next_serial(g_pCompositor->m_sWLDisplay), g_pSeatManager->state.keyboardFocus, - Vector2D{g_pSeatManager->state.keyboardFocus->current.width, g_pSeatManager->state.keyboardFocus->current.height} / 2.F, OFFER); + dnd.focusedDevice->sendEnter(wl_display_next_serial(g_pCompositor->m_sWLDisplay), g_pSeatManager->state.keyboardFocus.lock(), + g_pSeatManager->state.keyboardFocus->current.size / 2.F, OFFER); } void CWLDataDeviceProtocol::resetDndState() { - dnd.dndSurface = nullptr; - dnd.hyprListener_dndSurfaceDestroy.removeCallback(); - dnd.hyprListener_dndSurfaceCommit.removeCallback(); + dnd.dndSurface.reset(); + dnd.dndSurfaceCommit.reset(); + dnd.dndSurfaceDestroy.reset(); dnd.mouseButton.reset(); dnd.mouseMove.reset(); dnd.touchUp.reset(); @@ -638,20 +635,18 @@ void CWLDataDeviceProtocol::abortDrag() { } void CWLDataDeviceProtocol::renderDND(CMonitor* pMonitor, timespec* when) { - if (!dnd.dndSurface || !wlr_surface_get_texture(dnd.dndSurface)) + if (!dnd.dndSurface || !dnd.dndSurface->current.buffer) return; const auto POS = g_pInputManager->getMouseCoordsInternal(); - CBox box = CBox{POS, {dnd.dndSurface->current.width, dnd.dndSurface->current.height}} - .translate(-pMonitor->vecPosition + g_pPointerManager->cursorSizeLogical() / 2.F) - .scale(pMonitor->scale); - g_pHyprOpenGL->renderTexture(wlr_surface_get_texture(dnd.dndSurface), &box, 1.F); + CBox box = CBox{POS, dnd.dndSurface->current.size}.translate(-pMonitor->vecPosition + g_pPointerManager->cursorSizeLogical() / 2.F).scale(pMonitor->scale); + g_pHyprOpenGL->renderTexture(dnd.dndSurface->current.buffer->texture, &box, 1.F); - box = CBox{POS, {dnd.dndSurface->current.width, dnd.dndSurface->current.height}}.translate(g_pPointerManager->cursorSizeLogical() / 2.F); + box = CBox{POS, dnd.dndSurface->current.size}.translate(g_pPointerManager->cursorSizeLogical() / 2.F); g_pHyprRenderer->damageBox(&box); - wlr_surface_send_frame_done(dnd.dndSurface, when); + dnd.dndSurface->frame(when); } bool CWLDataDeviceProtocol::dndActive() { diff --git a/src/protocols/core/DataDevice.hpp b/src/protocols/core/DataDevice.hpp index 3112b720f136..1b7c1476edb4 100644 --- a/src/protocols/core/DataDevice.hpp +++ b/src/protocols/core/DataDevice.hpp @@ -92,7 +92,7 @@ class CWLDataDeviceResource { wl_client* client(); void sendDataOffer(SP offer); - void sendEnter(uint32_t serial, wlr_surface* surf, const Vector2D& local, SP offer); + void sendEnter(uint32_t serial, SP surf, const Vector2D& local, SP offer); void sendLeave(); void sendMotion(uint32_t timeMs, const Vector2D& local); void sendDrop(); @@ -155,11 +155,11 @@ class CWLDataDeviceProtocol : public IWaylandProtocol { struct { WP focusedDevice; WP currentSource; - wlr_surface* dndSurface = nullptr; - wlr_surface* originSurface = nullptr; // READ-ONLY + WP dndSurface; + WP originSurface; bool overriddenCursor = false; - DYNLISTENER(dndSurfaceDestroy); - DYNLISTENER(dndSurfaceCommit); + CHyprSignalListener dndSurfaceDestroy; + CHyprSignalListener dndSurfaceCommit; // for ending a dnd SP mouseMove; @@ -169,7 +169,7 @@ class CWLDataDeviceProtocol : public IWaylandProtocol { } dnd; void abortDrag(); - void initiateDrag(WP currentSource, wlr_surface* dragSurface, wlr_surface* origin); + void initiateDrag(WP currentSource, SP dragSurface, SP origin); void updateDrag(); void dropDrag(); void completeDrag(); diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp new file mode 100644 index 000000000000..980df086137a --- /dev/null +++ b/src/protocols/core/Output.cpp @@ -0,0 +1,88 @@ +#include "Output.hpp" + +CWLOutputResource::CWLOutputResource(SP resource_, SP pMonitor) : monitor(pMonitor), resource(resource_) { + if (!good()) + return; + + resource->setData(this); + + pClient = resource->client(); + + resource->setOnDestroy([this](CWlOutput* r) { + if (monitor && PROTO::outputs.contains(monitor->szName)) + PROTO::outputs.at(monitor->szName)->destroyResource(this); + }); + resource->setRelease([this](CWlOutput* r) { + if (monitor && PROTO::outputs.contains(monitor->szName)) + PROTO::outputs.at(monitor->szName)->destroyResource(this); + }); + + resource->sendGeometry(monitor->vecSize.x, monitor->vecSize.y, monitor->output->phys_width, monitor->output->phys_height, monitor->output->subpixel, + monitor->output->make ? monitor->output->make : "null", monitor->output->model ? monitor->output->model : "null", monitor->transform); + if (resource->version() >= 4) { + resource->sendName(monitor->szName.c_str()); + resource->sendDescription(monitor->szDescription.c_str()); + } + + wlr_output_mode* mode; + wl_list_for_each(mode, &pMonitor->output->modes, link) { + uint32_t mask = 0; + if (mode->preferred) + mask |= WL_OUTPUT_MODE_PREFERRED; + if (mode == pMonitor->output->current_mode) + mask |= WL_OUTPUT_MODE_CURRENT; + resource->sendMode((wl_output_mode)mask, mode->width, mode->height, mode->refresh); + } + + if (resource->version() >= 2) + resource->sendDone(); +} + +SP CWLOutputResource::fromResource(wl_resource* res) { + auto data = (CWLOutputResource*)(((CWlOutput*)wl_resource_get_user_data(res))->data()); + return data ? data->self.lock() : nullptr; +} + +bool CWLOutputResource::good() { + return resource->resource(); +} + +wl_client* CWLOutputResource::client() { + return pClient; +} + +SP CWLOutputResource::getResource() { + return resource; +} + +CWLOutputProtocol::CWLOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name, SP pMonitor) : + IWaylandProtocol(iface, ver, name), monitor(pMonitor) { + ; +} + +void CWLOutputProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vOutputs.emplace_back(makeShared(makeShared(client, ver, id), monitor.lock())); + + if (!RESOURCE->good()) { + wl_client_post_no_memory(client); + m_vOutputs.pop_back(); + return; + } + + RESOURCE->self = RESOURCE; +} + +void CWLOutputProtocol::destroyResource(CWLOutputResource* resource) { + std::erase_if(m_vOutputs, [&](const auto& other) { return other.get() == resource; }); +} + +SP CWLOutputProtocol::outputResourceFrom(wl_client* client) { + for (auto& r : m_vOutputs) { + if (r->client() != client) + continue; + + return r; + } + + return nullptr; +} diff --git a/src/protocols/core/Output.hpp b/src/protocols/core/Output.hpp new file mode 100644 index 000000000000..967ea78cebf6 --- /dev/null +++ b/src/protocols/core/Output.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include +#include +#include +#include "../WaylandProtocol.hpp" +#include "wayland.hpp" + +class CMonitor; + +class CWLOutputResource { + public: + CWLOutputResource(SP resource_, SP pMonitor); + static SP fromResource(wl_resource*); + + bool good(); + wl_client* client(); + SP getResource(); + + WP monitor; + + WP self; + + private: + SP resource; + wl_client* pClient = nullptr; +}; + +class CWLOutputProtocol : public IWaylandProtocol { + public: + CWLOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name, SP pMonitor); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + SP outputResourceFrom(wl_client* client); + + WP monitor; + + private: + void destroyResource(CWLOutputResource* resource); + + // + std::vector> m_vOutputs; + + friend class CWLOutputResource; +}; + +namespace PROTO { + inline std::unordered_map> outputs; +}; diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp index 489fced749a8..00e25f830c43 100644 --- a/src/protocols/core/Seat.cpp +++ b/src/protocols/core/Seat.cpp @@ -1,4 +1,5 @@ #include "Seat.hpp" +#include "Compositor.hpp" #include "../../devices/IKeyboard.hpp" #include "../../managers/SeatManager.hpp" #include "../../config/ConfigValue.hpp" @@ -20,7 +21,7 @@ bool CWLTouchResource::good() { return resource->resource(); } -void CWLTouchResource::sendDown(wlr_surface* surface, uint32_t timeMs, int32_t id, const Vector2D& local) { +void CWLTouchResource::sendDown(SP surface, uint32_t timeMs, int32_t id, const Vector2D& local) { if (!owner) return; @@ -29,15 +30,14 @@ void CWLTouchResource::sendDown(wlr_surface* surface, uint32_t timeMs, int32_t i sendUp(timeMs, id); } - ASSERT(wl_resource_get_client(surface->resource) == owner->client()); + ASSERT(surface->client() == owner->client()); - currentSurface = surface; - hyprListener_surfaceDestroy.initCallback( - &surface->events.destroy, [this, id, timeMs](void* owner, void* data) { sendUp(timeMs + 10 /* hack */, id); }, this, "CWLTouchResource"); + currentSurface = surface; + listeners.destroySurface = surface->events.destroy.registerListener([this, timeMs, id](std::any d) { sendUp(timeMs + 10 /* hack */, id); }); // FIXME: // fix this once we get our own wlr_surface, this is horrible - resource->sendDownRaw(g_pSeatManager->nextSerial(owner.lock()), timeMs, surface->resource, id, wl_fixed_from_double(local.x), wl_fixed_from_double(local.y)); + resource->sendDown(g_pSeatManager->nextSerial(owner.lock()), timeMs, surface->getResource().get(), id, wl_fixed_from_double(local.x), wl_fixed_from_double(local.y)); } void CWLTouchResource::sendUp(uint32_t timeMs, int32_t id) { @@ -45,8 +45,8 @@ void CWLTouchResource::sendUp(uint32_t timeMs, int32_t id) { return; resource->sendUp(g_pSeatManager->nextSerial(owner.lock()), timeMs, id); - currentSurface = nullptr; - hyprListener_surfaceDestroy.removeCallback(); + currentSurface.reset(); + listeners.destroySurface.reset(); } void CWLTouchResource::sendMotion(uint32_t timeMs, int32_t id, const Vector2D& local) { @@ -97,7 +97,7 @@ CWLPointerResource::CWLPointerResource(SP resource_, SPonSetCursor(owner.lock(), serial, surf ? wlr_surface_from_resource(surf) : nullptr, {hotX, hotY}); + g_pSeatManager->onSetCursor(owner.lock(), serial, surf ? CWLSurfaceResource::fromResource(surf) : nullptr, {hotX, hotY}); }); } @@ -105,7 +105,7 @@ bool CWLPointerResource::good() { return resource->resource(); } -void CWLPointerResource::sendEnter(wlr_surface* surface, const Vector2D& local) { +void CWLPointerResource::sendEnter(SP surface, const Vector2D& local) { if (!owner || currentSurface == surface) return; @@ -114,22 +114,21 @@ void CWLPointerResource::sendEnter(wlr_surface* surface, const Vector2D& local) sendLeave(); } - ASSERT(wl_resource_get_client(surface->resource) == owner->client()); + ASSERT(surface->client() == owner->client()); - currentSurface = surface; - hyprListener_surfaceDestroy.initCallback( - &surface->events.destroy, [this](void* owner, void* data) { sendLeave(); }, this, "CWLPointerResource"); + currentSurface = surface; + listeners.destroySurface = surface->events.destroy.registerListener([this](std::any d) { sendLeave(); }); - resource->sendEnterRaw(g_pSeatManager->nextSerial(owner.lock()), surface->resource, wl_fixed_from_double(local.x), wl_fixed_from_double(local.y)); + resource->sendEnter(g_pSeatManager->nextSerial(owner.lock()), surface->getResource().get(), wl_fixed_from_double(local.x), wl_fixed_from_double(local.y)); } void CWLPointerResource::sendLeave() { if (!owner || !currentSurface) return; - resource->sendLeaveRaw(g_pSeatManager->nextSerial(owner.lock()), currentSurface->resource); - currentSurface = nullptr; - hyprListener_surfaceDestroy.removeCallback(); + resource->sendLeave(g_pSeatManager->nextSerial(owner.lock()), currentSurface->getResource().get()); + currentSurface.reset(); + listeners.destroySurface.reset(); } void CWLPointerResource::sendMotion(uint32_t timeMs, const Vector2D& local) { @@ -234,7 +233,7 @@ void CWLKeyboardResource::sendKeymap(SP keyboard) { close(fd); } -void CWLKeyboardResource::sendEnter(wlr_surface* surface) { +void CWLKeyboardResource::sendEnter(SP surface) { if (!owner || currentSurface == surface) return; @@ -243,16 +242,15 @@ void CWLKeyboardResource::sendEnter(wlr_surface* surface) { sendLeave(); } - ASSERT(wl_resource_get_client(surface->resource) == owner->client()); + ASSERT(surface->client() == owner->client()); - currentSurface = surface; - hyprListener_surfaceDestroy.initCallback( - &surface->events.destroy, [this](void* owner, void* data) { sendLeave(); }, this, "CWLKeyboardResource"); + currentSurface = surface; + listeners.destroySurface = surface->events.destroy.registerListener([this](std::any d) { sendLeave(); }); wl_array arr; wl_array_init(&arr); - resource->sendEnterRaw(g_pSeatManager->nextSerial(owner.lock()), surface->resource, &arr); + resource->sendEnter(g_pSeatManager->nextSerial(owner.lock()), surface->getResource().get(), &arr); wl_array_release(&arr); } @@ -261,9 +259,9 @@ void CWLKeyboardResource::sendLeave() { if (!owner || !currentSurface) return; - resource->sendLeaveRaw(g_pSeatManager->nextSerial(owner.lock()), currentSurface->resource); - currentSurface = nullptr; - hyprListener_surfaceDestroy.removeCallback(); + resource->sendLeave(g_pSeatManager->nextSerial(owner.lock()), currentSurface->getResource().get()); + currentSurface.reset(); + listeners.destroySurface.reset(); } void CWLKeyboardResource::sendKey(uint32_t timeMs, uint32_t key, wl_keyboard_key_state state) { diff --git a/src/protocols/core/Seat.hpp b/src/protocols/core/Seat.hpp index 4cd0d124638c..13199f1240d1 100644 --- a/src/protocols/core/Seat.hpp +++ b/src/protocols/core/Seat.hpp @@ -31,7 +31,7 @@ class CWLTouchResource { CWLTouchResource(SP resource_, SP owner_); bool good(); - void sendDown(wlr_surface* surface, uint32_t timeMs, int32_t id, const Vector2D& local); + void sendDown(SP surface, uint32_t timeMs, int32_t id, const Vector2D& local); void sendUp(uint32_t timeMs, int32_t id); void sendMotion(uint32_t timeMs, int32_t id, const Vector2D& local); void sendFrame(); @@ -42,10 +42,12 @@ class CWLTouchResource { WP owner; private: - SP resource; - wlr_surface* currentSurface = nullptr; + SP resource; + WP currentSurface; - DYNLISTENER(surfaceDestroy); + struct { + CHyprSignalListener destroySurface; + } listeners; }; class CWLPointerResource { @@ -53,7 +55,7 @@ class CWLPointerResource { CWLPointerResource(SP resource_, SP owner_); bool good(); - void sendEnter(wlr_surface* surface, const Vector2D& local); + void sendEnter(SP surface, const Vector2D& local); void sendLeave(); void sendMotion(uint32_t timeMs, const Vector2D& local); void sendButton(uint32_t timeMs, uint32_t button, wl_pointer_button_state state); @@ -68,10 +70,12 @@ class CWLPointerResource { WP owner; private: - SP resource; - wlr_surface* currentSurface = nullptr; + SP resource; + WP currentSurface; - DYNLISTENER(surfaceDestroy); + struct { + CHyprSignalListener destroySurface; + } listeners; }; class CWLKeyboardResource { @@ -80,7 +84,7 @@ class CWLKeyboardResource { bool good(); void sendKeymap(SP keeb); - void sendEnter(wlr_surface* surface); + void sendEnter(SP surface); void sendLeave(); void sendKey(uint32_t timeMs, uint32_t key, wl_keyboard_key_state state); void sendMods(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); @@ -89,10 +93,12 @@ class CWLKeyboardResource { WP owner; private: - SP resource; - wlr_surface* currentSurface = nullptr; + SP resource; + WP currentSurface; - DYNLISTENER(surfaceDestroy); + struct { + CHyprSignalListener destroySurface; + } listeners; }; class CWLSeatResource { diff --git a/src/protocols/core/Shm.cpp b/src/protocols/core/Shm.cpp new file mode 100644 index 000000000000..3a4b0a098012 --- /dev/null +++ b/src/protocols/core/Shm.cpp @@ -0,0 +1,209 @@ +#include "Shm.hpp" +#include +#include +#include +#include "../../render/Texture.hpp" +#include "../types/WLBuffer.hpp" +#include "../../Compositor.hpp" +#include "../../protocols/ToplevelExportWlrFuncs.hpp" + +#define LOGM PROTO::shm->protoLog + +static uint32_t shmFormatToDRM(uint32_t shm) { + switch (shm) { + case WL_SHM_FORMAT_XRGB8888: return DRM_FORMAT_XRGB8888; + case WL_SHM_FORMAT_ARGB8888: return DRM_FORMAT_ARGB8888; + default: return shm; + } + + return shm; +} + +static uint32_t drmFormatToSHM(uint32_t drm) { + switch (drm) { + case DRM_FORMAT_XRGB8888: return WL_SHM_FORMAT_XRGB8888; + case DRM_FORMAT_ARGB8888: return WL_SHM_FORMAT_ARGB8888; + default: return drm; + } + + return drm; +} + +CWLSHMBuffer::CWLSHMBuffer(SP pool_, uint32_t id, int32_t offset, const Vector2D& size_, int32_t stride_, uint32_t fmt_) { + size = size_; + pool = pool_->pool; + stride = stride_; + fmt = fmt_; + + texture = CTexture{shmFormatToDRM(fmt), (uint8_t*)pool->data + offset, stride, size_}; + + resource = CWLBufferResource::create(makeShared(pool_->resource->client(), 1, id)); + + success = true; +} + +CWLSHMBuffer::~CWLSHMBuffer() { + ; // empty +} + +eBufferCapability CWLSHMBuffer::caps() { + return BUFFER_CAPABILITY_DATAPTR; +} + +eBufferType CWLSHMBuffer::type() { + return BUFFER_TYPE_SHM; +} + +IWLBuffer::SSHMAttrs CWLSHMBuffer::shm() { + IWLBuffer::SSHMAttrs attrs; + attrs.success = true; + attrs.fd = pool->fd; + attrs.format = fmt; + attrs.size = size; + attrs.stride = stride; + attrs.offset = offset; + return attrs; +} + +std::tuple CWLSHMBuffer::beginDataPtr(uint32_t flags) { + return {(uint8_t*)pool->data + offset, fmt, size.x * size.y * 4}; +} + +void CWLSHMBuffer::endDataPtr() { + ; +} + +bool CWLSHMBuffer::good() { + return success; +} + +void CWLSHMBuffer::update(const CRegion& damage) { + texture.update(shmFormatToDRM(fmt), (uint8_t*)pool->data + offset, stride, damage); +} + +CSHMPool::CSHMPool(int fd_, size_t size_) : fd(fd_), size(size_) { + data = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); +} + +CSHMPool::~CSHMPool() { + munmap(data, size); +} + +void CSHMPool::resize(size_t size_) { + if (data) + munmap(data, size); + size = size_; + data = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + if (!data) + LOGM(ERR, "Couldn't mmap {} bytes from fd {} of shm client", size, fd); +} + +CWLSHMPoolResource::CWLSHMPoolResource(SP resource_, int fd_, size_t size_) : resource(resource_) { + if (!good()) + return; + + pool = makeShared(fd_, size_); + + resource->setDestroy([this](CWlShmPool* r) { PROTO::shm->destroyResource(this); }); + resource->setOnDestroy([this](CWlShmPool* r) { PROTO::shm->destroyResource(this); }); + + resource->setResize([this](CWlShmPool* r, int32_t size_) { pool->resize(size_); }); + + resource->setCreateBuffer([this](CWlShmPool* r, uint32_t id, int32_t offset, int32_t w, int32_t h, int32_t stride, uint32_t fmt) { + if (std::find(PROTO::shm->shmFormats.begin(), PROTO::shm->shmFormats.end(), fmt) == PROTO::shm->shmFormats.end()) { + r->error(WL_SHM_ERROR_INVALID_FORMAT, "Format invalid"); + return; + } + + const wlr_pixel_format_info* format = drm_get_pixel_format_info(shmFormatToDRM(fmt)); + ASSERT(format); + const auto BPB = format->bytes_per_block; + + if (offset < 0 || w <= 0 || h <= 0 || (uint32_t)stride != w * BPB) { + r->error(WL_SHM_ERROR_INVALID_STRIDE, "Invalid stride, w, h, or offset"); + return; + } + + const auto RESOURCE = PROTO::shm->m_vBuffers.emplace_back(makeShared(self.lock(), id, offset, Vector2D{w, h}, stride, fmt)); + + if (!RESOURCE->good()) { + r->noMemory(); + PROTO::shm->m_vBuffers.pop_back(); + return; + } + + // append instance so that buffer knows its owner + RESOURCE->resource->buffer = RESOURCE; + }); + + if (!pool->data) + resource->error(WL_SHM_ERROR_INVALID_FD, "Couldn't mmap from fd"); +} + +bool CWLSHMPoolResource::good() { + return resource->resource(); +} + +CWLSHMResource::CWLSHMResource(SP resource_) : resource(resource_) { + if (!good()) + return; + + resource->setOnDestroy([this](CWlShm* r) { PROTO::shm->destroyResource(this); }); + + resource->setCreatePool([](CWlShm* r, uint32_t id, int32_t fd, int32_t size) { + const auto RESOURCE = PROTO::shm->m_vPools.emplace_back(makeShared(makeShared(r->client(), r->version(), id), fd, size)); + + if (!RESOURCE->good()) { + r->noMemory(); + PROTO::shm->m_vPools.pop_back(); + return; + } + + RESOURCE->self = RESOURCE; + }); + + // send a few supported formats. No need for any other I think? + for (auto& s : PROTO::shm->shmFormats) { + resource->sendFormat((wl_shm_format)s); + } +} + +bool CWLSHMResource::good() { + return resource->resource(); +} + +CWLSHMProtocol::CWLSHMProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CWLSHMProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + if (shmFormats.empty()) { + size_t len = 0; + const uint32_t* formats = wlr_renderer_get_shm_texture_formats(g_pCompositor->m_sWLRRenderer, &len); + + for (size_t i = 0; i < len; ++i) { + shmFormats.push_back(drmFormatToSHM(formats[i])); + } + } + + const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); + + if (!RESOURCE->good()) { + wl_client_post_no_memory(client); + m_vManagers.pop_back(); + return; + } +} + +void CWLSHMProtocol::destroyResource(CWLSHMResource* resource) { + std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == resource; }); +} + +void CWLSHMProtocol::destroyResource(CWLSHMPoolResource* resource) { + std::erase_if(m_vPools, [&](const auto& other) { return other.get() == resource; }); +} + +void CWLSHMProtocol::destroyResource(CWLSHMBuffer* resource) { + std::erase_if(m_vBuffers, [&](const auto& other) { return other.get() == resource; }); +} diff --git a/src/protocols/core/Shm.hpp b/src/protocols/core/Shm.hpp new file mode 100644 index 000000000000..df1dcd71196f --- /dev/null +++ b/src/protocols/core/Shm.hpp @@ -0,0 +1,107 @@ +#pragma once + +/* + Implementations for: + - wl_shm + - wl_shm_pool + - wl_buffer with shm +*/ + +#include +#include +#include +#include "../WaylandProtocol.hpp" +#include "wayland.hpp" +#include "../types/Buffer.hpp" +#include "../../helpers/Vector2D.hpp" + +class CWLSHMPoolResource; + +class CSHMPool { + public: + CSHMPool(int fd, size_t size); + ~CSHMPool(); + + int fd = 0; + size_t size = 0; + void* data = nullptr; + + void resize(size_t size); +}; + +class CWLSHMBuffer : public IWLBuffer { + public: + CWLSHMBuffer(SP pool, uint32_t id, int32_t offset, const Vector2D& size, int32_t stride, uint32_t fmt); + virtual ~CWLSHMBuffer(); + + virtual eBufferCapability caps(); + virtual eBufferType type(); + virtual void update(const CRegion& damage); + virtual SSHMAttrs shm(); + virtual std::tuple beginDataPtr(uint32_t flags); + virtual void endDataPtr(); + + bool good(); + void updateTexture(); + + int32_t offset = 0, stride = 0; + uint32_t fmt = 0; + SP pool; + + private: + bool success = false; +}; + +class CWLSHMPoolResource { + public: + CWLSHMPoolResource(SP resource_, int fd, size_t size); + + bool good(); + + SP pool; + + WP self; + + private: + SP resource; + + friend class CWLSHMBuffer; +}; + +class CWLSHMResource { + public: + CWLSHMResource(SP resource_); + + bool good(); + + private: + SP resource; +}; + +class CWLSHMProtocol : public IWaylandProtocol { + public: + CWLSHMProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + private: + void destroyResource(CWLSHMResource* resource); + void destroyResource(CWLSHMPoolResource* resource); + void destroyResource(CWLSHMBuffer* resource); + + // + std::vector> m_vManagers; + std::vector> m_vPools; + std::vector> m_vBuffers; + + // + std::vector shmFormats; + + friend class CWLSHMResource; + friend class CWLSHMPoolResource; + friend class CWLSHMBuffer; +}; + +namespace PROTO { + inline UP shm; +}; diff --git a/src/protocols/core/Subcompositor.cpp b/src/protocols/core/Subcompositor.cpp new file mode 100644 index 000000000000..7ebe148d87ef --- /dev/null +++ b/src/protocols/core/Subcompositor.cpp @@ -0,0 +1,157 @@ +#include "Subcompositor.hpp" +#include "Compositor.hpp" +#include + +#define LOGM PROTO::subcompositor->protoLog + +CWLSubsurfaceResource::CWLSubsurfaceResource(SP resource_, SP surface_, SP parent_) : + surface(surface_), parent(parent_), resource(resource_) { + if (!good()) + return; + + resource->setOnDestroy([this](CWlSubsurface* r) { + events.destroy.emit(); + PROTO::subcompositor->destroyResource(this); + }); + resource->setDestroy([this](CWlSubsurface* r) { + events.destroy.emit(); + PROTO::subcompositor->destroyResource(this); + }); + + resource->setSetPosition([this](CWlSubsurface* r, int32_t x, int32_t y) { position = {x, y}; }); + + resource->setSetDesync([this](CWlSubsurface* r) { sync = false; }); + resource->setSetSync([this](CWlSubsurface* r) { sync = true; }); + + resource->setPlaceAbove([this](CWlSubsurface* r, wl_resource* surf) { + auto SURF = CWLSurfaceResource::fromResource(surf); + + if (!parent) + return; + + std::erase(parent->subsurfaces, self.lock()); + + auto it = std::find(parent->subsurfaces.begin(), parent->subsurfaces.end(), SURF); + + if (it == parent->subsurfaces.end()) { + LOGM(ERR, "Invalid surface reference in placeAbove"); + parent->subsurfaces.emplace_back(self.lock()); + } else + parent->subsurfaces.insert(it, self.lock()); + }); + + resource->setPlaceBelow([this](CWlSubsurface* r, wl_resource* surf) { + auto SURF = CWLSurfaceResource::fromResource(surf); + + if (!parent) + return; + + std::erase(parent->subsurfaces, self.lock()); + + auto it = std::find(parent->subsurfaces.begin(), parent->subsurfaces.end(), SURF); + + if (it == parent->subsurfaces.end()) { + LOGM(ERR, "Invalid surface reference in placeBelow"); + parent->subsurfaces.emplace_back(self.lock()); + } else + parent->subsurfaces.insert(it--, self.lock()); + }); + + listeners.commitSurface = surface->events.commit.registerListener([this](std::any d) { + if (surface->current.buffer && !surface->mapped) { + surface->map(); + return; + } + + if (!surface->current.buffer && surface->mapped) { + surface->unmap(); + return; + } + }); +} + +CWLSubsurfaceResource::~CWLSubsurfaceResource() { + events.destroy.emit(); + if (surface) + surface->resetRole(); +} + +Vector2D CWLSubsurfaceResource::posRelativeToParent() { + Vector2D pos = position; + SP surf = parent.lock(); + while (surf->role->role() == SURFACE_ROLE_SUBSURFACE) { + auto subsurface = (CWLSubsurfaceResource*)parent->role.get(); + pos += subsurface->position; + surf = subsurface->parent.lock(); + } + return pos; +} + +bool CWLSubsurfaceResource::good() { + return resource->resource(); +} + +eSurfaceRole CWLSubsurfaceResource::role() { + return SURFACE_ROLE_SUBSURFACE; +} + +CWLSubcompositorResource::CWLSubcompositorResource(SP resource_) : resource(resource_) { + if (!good()) + return; + + resource->setOnDestroy([this](CWlSubcompositor* r) { PROTO::subcompositor->destroyResource(this); }); + resource->setDestroy([this](CWlSubcompositor* r) { PROTO::subcompositor->destroyResource(this); }); + + resource->setGetSubsurface([](CWlSubcompositor* r, uint32_t id, wl_resource* surface, wl_resource* parent) { + auto SURF = CWLSurfaceResource::fromResource(surface); + auto PARENT = CWLSurfaceResource::fromResource(parent); + + if (!SURF || !PARENT) { + r->error(-1, "Invalid surface/parent"); + return; + } + + const auto RESOURCE = + PROTO::subcompositor->m_vSurfaces.emplace_back(makeShared(makeShared(r->client(), r->version(), id), SURF, PARENT)); + + if (!RESOURCE->good()) { + r->noMemory(); + PROTO::subcompositor->m_vSurfaces.pop_back(); + return; + } + + RESOURCE->self = RESOURCE; + SURF->role = RESOURCE; + SURF->subsurfaces.emplace_back(RESOURCE); + + LOGM(LOG, "New wl_subsurface with id {} at {:x}", id, (uintptr_t)RESOURCE.get()); + + PARENT->events.newSubsurface.emit(RESOURCE); + }); +} + +bool CWLSubcompositorResource::good() { + return resource->resource(); +} + +CWLSubcompositorProtocol::CWLSubcompositorProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CWLSubcompositorProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); + + if (!RESOURCE->good()) { + wl_client_post_no_memory(client); + m_vManagers.pop_back(); + return; + } +} + +void CWLSubcompositorProtocol::destroyResource(CWLSubcompositorResource* resource) { + std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == resource; }); +} + +void CWLSubcompositorProtocol::destroyResource(CWLSubsurfaceResource* resource) { + std::erase_if(m_vSurfaces, [&](const auto& other) { return other.get() == resource; }); +} diff --git a/src/protocols/core/Subcompositor.hpp b/src/protocols/core/Subcompositor.hpp new file mode 100644 index 000000000000..12acbdbd2a51 --- /dev/null +++ b/src/protocols/core/Subcompositor.hpp @@ -0,0 +1,79 @@ + +#pragma once + +/* + Implementations for: + - wl_subsurface + - wl_subcompositor +*/ + +#include +#include +#include +#include "../WaylandProtocol.hpp" +#include "wayland.hpp" +#include "../../helpers/signal/Signal.hpp" +#include "../types/SurfaceRole.hpp" + +class CWLSurfaceResource; + +class CWLSubsurfaceResource : public ISurfaceRole { + public: + CWLSubsurfaceResource(SP resource_, SP surface_, SP parent_); + ~CWLSubsurfaceResource(); + + Vector2D posRelativeToParent(); + bool good(); + virtual eSurfaceRole role(); + + bool sync = false; + Vector2D position; + + WP surface; + WP parent; + + WP self; + + struct { + CSignal destroy; + } events; + + private: + SP resource; + + struct { + CHyprSignalListener commitSurface; + } listeners; +}; + +class CWLSubcompositorResource { + public: + CWLSubcompositorResource(SP resource_); + + bool good(); + + private: + SP resource; +}; + +class CWLSubcompositorProtocol : public IWaylandProtocol { + public: + CWLSubcompositorProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + private: + void destroyResource(CWLSubcompositorResource* resource); + void destroyResource(CWLSubsurfaceResource* resource); + + // + std::vector> m_vManagers; + std::vector> m_vSurfaces; + + friend class CWLSubcompositorResource; + friend class CWLSubsurfaceResource; +}; + +namespace PROTO { + inline UP subcompositor; +}; diff --git a/src/protocols/types/Buffer.cpp b/src/protocols/types/Buffer.cpp new file mode 100644 index 000000000000..292ee0096ee2 --- /dev/null +++ b/src/protocols/types/Buffer.cpp @@ -0,0 +1,37 @@ +#include "Buffer.hpp" +#include "WLBuffer.hpp" + +IWLBuffer::SDMABUFAttrs IWLBuffer::dmabuf() { + return SDMABUFAttrs{}; +} + +IWLBuffer::SSHMAttrs IWLBuffer::shm() { + return SSHMAttrs{}; +} + +std::tuple IWLBuffer::beginDataPtr(uint32_t flags) { + return {nullptr, 0, 0}; +} + +void IWLBuffer::endDataPtr() { + ; // empty +} + +void IWLBuffer::sendRelease() { + if (!resource) + return; + resource->resource->sendRelease(); +} + +void IWLBuffer::lock() { + locks++; +} + +void IWLBuffer::unlock() { + locks--; + + ASSERT(locks >= 0); + + if (locks <= 0) + sendRelease(); +} diff --git a/src/protocols/types/Buffer.hpp b/src/protocols/types/Buffer.hpp new file mode 100644 index 000000000000..8063ab9e541f --- /dev/null +++ b/src/protocols/types/Buffer.hpp @@ -0,0 +1,70 @@ +#pragma once + +#include "../../defines.hpp" +#include "../../helpers/signal/Signal.hpp" +#include "../../render/Texture.hpp" + +#include +#include + +enum eBufferCapability { + BUFFER_CAPABILITY_DATAPTR = (1 << 0), +}; + +enum eBufferType { + BUFFER_TYPE_DMABUF = 0, + BUFFER_TYPE_SHM, + BUFFER_TYPE_MISC, +}; + +class CWLBufferResource; + +class IWLBuffer { + public: + virtual ~IWLBuffer(){}; + + struct SDMABUFAttrs { + bool success = false; + Vector2D size; + uint32_t format = 0; // fourcc + uint64_t modifier = 0; + + int planes = 1; + std::array offsets = {0}; + std::array strides = {0}; + std::array fds = {0}; + }; + + struct SSHMAttrs { + bool success = false; + int fd = 0; + uint32_t format = 0; + Vector2D size; + int stride = 0; + int64_t offset = 0; + }; + + virtual eBufferCapability caps() = 0; + virtual eBufferType type() = 0; + virtual void update(const CRegion& damage) = 0; + virtual SDMABUFAttrs dmabuf(); + virtual SSHMAttrs shm(); + virtual std::tuple beginDataPtr(uint32_t flags); + virtual void endDataPtr(); + virtual void sendRelease(); + virtual void lock(); + virtual void unlock(); + + Vector2D size; + + SP resource; + + CTexture texture; + + struct { + CSignal destroy; + } events; + + private: + int locks = 0; +}; diff --git a/src/protocols/types/SurfaceRole.hpp b/src/protocols/types/SurfaceRole.hpp new file mode 100644 index 000000000000..05c0ea66a9d4 --- /dev/null +++ b/src/protocols/types/SurfaceRole.hpp @@ -0,0 +1,14 @@ +#pragma once + +enum eSurfaceRole { + SURFACE_ROLE_UNASSIGNED = 0, + SURFACE_ROLE_XDG_SHELL, + SURFACE_ROLE_LAYER_SHELL, + SURFACE_ROLE_EASTER_EGG, + SURFACE_ROLE_SUBSURFACE, +}; + +class ISurfaceRole { + public: + virtual eSurfaceRole role() = 0; +}; diff --git a/src/protocols/types/WLBuffer.cpp b/src/protocols/types/WLBuffer.cpp new file mode 100644 index 000000000000..5a137f9ace32 --- /dev/null +++ b/src/protocols/types/WLBuffer.cpp @@ -0,0 +1,29 @@ +#include "WLBuffer.hpp" + +CWLBufferResource::CWLBufferResource(SP resource_) : resource(resource_) { + if (!good()) + return; + + resource->setOnDestroy([this](CWlBuffer* r) { events.destroy.emit(); }); + + resource->setData(this); +} + +bool CWLBufferResource::good() { + return resource->resource(); +} + +void CWLBufferResource::sendRelease() { + resource->sendRelease(); +} + +SP CWLBufferResource::fromResource(wl_resource* res) { + auto data = (CWLBufferResource*)(((CWlBuffer*)wl_resource_get_user_data(res))->data()); + return data ? data->self.lock() : nullptr; +} + +SP CWLBufferResource::create(SP resource) { + auto p = SP(new CWLBufferResource(resource)); + p->self = p; + return p; +} diff --git a/src/protocols/types/WLBuffer.hpp b/src/protocols/types/WLBuffer.hpp new file mode 100644 index 000000000000..cc46be774601 --- /dev/null +++ b/src/protocols/types/WLBuffer.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include +#include "../WaylandProtocol.hpp" +#include "wayland.hpp" +#include "../../helpers/signal/Signal.hpp" + +class IWLBuffer; + +class CWLBufferResource { + public: + static SP create(SP resource); + static SP fromResource(wl_resource* res); + + bool good(); + void sendRelease(); + + struct { + CSignal destroy; + } events; + + SP buffer; + + WP self; + + private: + CWLBufferResource(SP resource_); + + SP resource; + + friend class IWLBuffer; +}; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index a1e6f73ef2fd..7c99d06f0277 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -7,6 +7,7 @@ #include "../config/ConfigValue.hpp" #include "../desktop/LayerSurface.hpp" #include "../protocols/LayerShell.hpp" +#include "../protocols/core/Compositor.hpp" inline void loadGLProc(void* pProc, const char* name) { void* proc = (void*)eglGetProcAddress(name); @@ -863,18 +864,6 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion scissor((CBox*)nullptr); } -void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, CBox* pBox, float alpha, int round, bool allowCustomUV) { - RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); - - renderTexture(CTexture(tex), pBox, alpha, round, false, allowCustomUV); -} - -void CHyprOpenGLImpl::renderTextureWithDamage(wlr_texture* tex, CBox* pBox, CRegion* damage, float alpha, int round, bool allowCustomUV) { - RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); - - renderTextureWithDamage(CTexture(tex), pBox, damage, alpha, round, false, allowCustomUV); -} - void CHyprOpenGLImpl::renderTexture(const CTexture& tex, CBox* pBox, float alpha, int round, bool discardActive, bool allowCustomUV) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); @@ -1417,23 +1406,23 @@ void CHyprOpenGLImpl::preRender(CMonitor* pMonitor) { if (pWindow->m_sAdditionalConfigData.forceNoBlur) return false; - if (pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall) + if (pWindow->m_pWLSurface->small() && !pWindow->m_pWLSurface->m_bFillIgnoreSmall) return true; - const auto PSURFACE = pWindow->m_pWLSurface.wlr(); + const auto PSURFACE = pWindow->m_pWLSurface->resource(); const auto PWORKSPACE = pWindow->m_pWorkspace; const float A = pWindow->m_fAlpha.value() * pWindow->m_fActiveInactiveAlpha.value() * PWORKSPACE->m_fAlpha.value(); if (A >= 1.f) { - if (PSURFACE->opaque) - return false; + // if (PSURFACE->opaque) + // return false; CRegion inverseOpaque; - pixman_box32_t surfbox = {0, 0, PSURFACE->current.width, PSURFACE->current.height}; - CRegion opaqueRegion{&PSURFACE->current.opaque}; - inverseOpaque.set(opaqueRegion).invert(&surfbox).intersect(0, 0, PSURFACE->current.width, PSURFACE->current.height); + pixman_box32_t surfbox = {0, 0, PSURFACE->current.size.x, PSURFACE->current.size.y}; + CRegion opaqueRegion{PSURFACE->current.opaque}; + inverseOpaque.set(opaqueRegion).invert(&surfbox).intersect(0, 0, PSURFACE->current.size.x, PSURFACE->current.size.y); if (inverseOpaque.empty()) return false; @@ -1461,8 +1450,8 @@ void CHyprOpenGLImpl::preRender(CMonitor* pMonitor) { if (!ls->layerSurface || ls->xray != 1) continue; - if (ls->layerSurface->surface->opaque && ls->alpha.value() >= 1.f) - continue; + // if (ls->layerSurface->surface->opaque && ls->alpha.value() >= 1.f) + // continue; hasWindows = true; break; @@ -1545,7 +1534,7 @@ bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWin return false; } -void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, CBox* pBox, float a, wlr_surface* pSurface, int round, bool blockBlurOptimization, float blurA) { +void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, CBox* pBox, float a, SP pSurface, int round, bool blockBlurOptimization, float blurA) { RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!"); static auto PBLURENABLED = CConfigValue("decoration:blur:enabled"); @@ -1570,11 +1559,11 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, CBox* pBox, flo // amazing hack: the surface has an opaque region! CRegion inverseOpaque; - if (a >= 1.f && std::round(pSurface->current.width * m_RenderData.pMonitor->scale) == pBox->w && - std::round(pSurface->current.height * m_RenderData.pMonitor->scale) == pBox->h) { - pixman_box32_t surfbox = {0, 0, pSurface->current.width * pSurface->current.scale, pSurface->current.height * pSurface->current.scale}; - inverseOpaque = &pSurface->current.opaque; - inverseOpaque.invert(&surfbox).intersect(0, 0, pSurface->current.width * pSurface->current.scale, pSurface->current.height * pSurface->current.scale); + if (a >= 1.f && std::round(pSurface->current.size.x * m_RenderData.pMonitor->scale) == pBox->w && + std::round(pSurface->current.size.y * m_RenderData.pMonitor->scale) == pBox->h) { + pixman_box32_t surfbox = {0, 0, pSurface->current.size.x * pSurface->current.scale, pSurface->current.size.y * pSurface->current.scale}; + inverseOpaque = pSurface->current.opaque; + inverseOpaque.invert(&surfbox).intersect(0, 0, pSurface->current.size.x * pSurface->current.scale, pSurface->current.size.y * pSurface->current.scale); if (inverseOpaque.empty()) { renderTexture(tex, pBox, a, round, false, true); diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index ca9eecc629d1..1eee41b83c3f 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -132,74 +132,72 @@ class CHyprOpenGLImpl { public: CHyprOpenGLImpl(); - void begin(CMonitor*, const CRegion& damage, CFramebuffer* fb = nullptr, std::optional finalDamage = {}); - void beginSimple(CMonitor*, const CRegion& damage, CRenderbuffer* rb = nullptr, CFramebuffer* fb = nullptr); - void end(); + void begin(CMonitor*, const CRegion& damage, CFramebuffer* fb = nullptr, std::optional finalDamage = {}); + void beginSimple(CMonitor*, const CRegion& damage, CRenderbuffer* rb = nullptr, CFramebuffer* fb = nullptr); + void end(); - void renderRect(CBox*, const CColor&, int round = 0); - void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f, bool xray = false); - void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0); - void renderTexture(wlr_texture*, CBox*, float a, int round = 0, bool allowCustomUV = false); - void renderTextureWithDamage(wlr_texture*, CBox*, CRegion* damage, float a, int round = 0, bool allowCustomUV = false); - void renderTexture(const CTexture&, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); - void renderTextureWithDamage(const CTexture&, CBox*, CRegion* damage, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); - void renderTextureWithBlur(const CTexture&, CBox*, float a, wlr_surface* pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f); - void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0); - void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); - void renderTextureMatte(const CTexture& tex, CBox* pBox, CFramebuffer& matte); + void renderRect(CBox*, const CColor&, int round = 0); + void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f, bool xray = false); + void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0); + void renderTexture(const CTexture&, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); + void renderTextureWithDamage(const CTexture&, CBox*, CRegion* damage, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); + void renderTextureWithBlur(const CTexture&, CBox*, float a, SP pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f); + void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0); + void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); + void renderTextureMatte(const CTexture& tex, CBox* pBox, CFramebuffer& matte); - void setMonitorTransformEnabled(bool enabled); - void setRenderModifEnabled(bool enabled); + void setMonitorTransformEnabled(bool enabled); + void setRenderModifEnabled(bool enabled); - void saveMatrix(); - void setMatrixScaleTranslate(const Vector2D& translate, const float& scale); - void restoreMatrix(); + void saveMatrix(); + void setMatrixScaleTranslate(const Vector2D& translate, const float& scale); + void restoreMatrix(); - void blend(bool enabled); + void blend(bool enabled); - void makeWindowSnapshot(PHLWINDOW); - void makeRawWindowSnapshot(PHLWINDOW, CFramebuffer*); - void makeLayerSnapshot(PHLLS); - void renderSnapshot(PHLWINDOW); - void renderSnapshot(PHLLS); - bool shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWindow); + void makeWindowSnapshot(PHLWINDOW); + void makeRawWindowSnapshot(PHLWINDOW, CFramebuffer*); + void makeLayerSnapshot(PHLLS); + void renderSnapshot(PHLWINDOW); + void renderSnapshot(PHLLS); + bool shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWindow); - void clear(const CColor&); - void clearWithTex(); - void scissor(const CBox*, bool transform = true); - void scissor(const pixman_box32*, bool transform = true); - void scissor(const int x, const int y, const int w, const int h, bool transform = true); + void clear(const CColor&); + void clearWithTex(); + void scissor(const CBox*, bool transform = true); + void scissor(const pixman_box32*, bool transform = true); + void scissor(const int x, const int y, const int w, const int h, bool transform = true); - void destroyMonitorResources(CMonitor*); + void destroyMonitorResources(CMonitor*); - void markBlurDirtyForMonitor(CMonitor*); + void markBlurDirtyForMonitor(CMonitor*); - void preWindowPass(); - bool preBlurQueued(); - void preRender(CMonitor*); + void preWindowPass(); + bool preBlurQueued(); + void preRender(CMonitor*); - void saveBufferForMirror(CBox*); - void renderMirrored(); + void saveBufferForMirror(CBox*); + void renderMirrored(); - void applyScreenShader(const std::string& path); + void applyScreenShader(const std::string& path); - void bindOffMain(); - void renderOffToMain(CFramebuffer* off); - void bindBackOnMain(); + void bindOffMain(); + void renderOffToMain(CFramebuffer* off); + void bindBackOnMain(); - void setDamage(const CRegion& damage, std::optional finalDamage = {}); + void setDamage(const CRegion& damage, std::optional finalDamage = {}); - uint32_t getPreferredReadFormat(CMonitor* pMonitor); - const SGLPixelFormat* getPixelFormatFromDRM(uint32_t drmFormat); + uint32_t getPreferredReadFormat(CMonitor* pMonitor); + const SGLPixelFormat* getPixelFormatFromDRM(uint32_t drmFormat); - SCurrentRenderData m_RenderData; + SCurrentRenderData m_RenderData; - GLint m_iCurrentOutputFb = 0; + GLint m_iCurrentOutputFb = 0; - bool m_bReloadScreenShader = true; // at launch it can be set + bool m_bReloadScreenShader = true; // at launch it can be set - PHLWINDOWREF m_pCurrentWindow; // hack to get the current rendered window - PHLLS m_pCurrentLayer; // hack to get the current rendered layer + PHLWINDOWREF m_pCurrentWindow; // hack to get the current rendered window + PHLLS m_pCurrentLayer; // hack to get the current rendered layer std::map m_mWindowFramebuffers; std::map m_mLayerFramebuffers; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 40ae953eff68..78601f313ba6 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -13,6 +13,7 @@ #include "../protocols/XDGShell.hpp" #include "../protocols/PresentationTime.hpp" #include "../protocols/core/DataDevice.hpp" +#include "../protocols/core/Compositor.hpp" extern "C" { #include @@ -90,19 +91,19 @@ CHyprRenderer::CHyprRenderer() { wl_event_source_timer_update(m_pCursorTicker, 500); } -static void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { - const auto TEXTURE = wlr_surface_get_texture(surface); +static void renderSurface(SP surface, int x, int y, void* data) { + if (!surface->current.buffer) + return; + + const auto TEXTURE = surface->current.buffer->texture; const auto RDATA = (SRenderData*)data; const auto INTERACTIVERESIZEINPROGRESS = RDATA->pWindow && g_pInputManager->currentlyDraggedWindow.lock() == RDATA->pWindow && g_pInputManager->dragMode == MBIND_RESIZE; - if (!TEXTURE) - return; - TRACY_GPU_ZONE("RenderSurface"); double outputX = -RDATA->pMonitor->vecPosition.x, outputY = -RDATA->pMonitor->vecPosition.y; - auto* const PSURFACE = CWLSurface::surfaceFromWlr(surface); + auto PSURFACE = CWLSurface::fromResource(surface); const float ALPHA = RDATA->alpha * RDATA->fadeAlpha * (PSURFACE ? PSURFACE->m_pAlphaModifier : 1.F); @@ -140,7 +141,7 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data) } } else { // here we clamp to 2, these might be some tiny specks - windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, std::max(surface->current.width, 2), std::max(surface->current.height, 2)}; + windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, std::max((float)surface->current.size.x, 2.F), std::max((float)surface->current.size.y, 2.F)}; if (RDATA->pWindow && RDATA->pWindow->m_vRealSize.isBeingAnimated() && RDATA->surface && RDATA->surface != surface && RDATA->squishOversized /* subsurface */) { // adjust subsurfaces to the window windowBox.width = (windowBox.width / RDATA->pWindow->m_vReportedSize.x) * RDATA->pWindow->m_vRealSize.value().x; @@ -162,8 +163,8 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data) windowBox.round(); const bool MISALIGNEDFSV1 = std::floor(RDATA->pMonitor->scale) != RDATA->pMonitor->scale /* Fractional */ && surface->current.scale == 1 /* fs protocol */ && - windowBox.size() != Vector2D{surface->current.buffer_width, surface->current.buffer_height} /* misaligned */ && - DELTALESSTHAN(windowBox.width, surface->current.buffer_width, 3) && DELTALESSTHAN(windowBox.height, surface->current.buffer_height, 3) /* off by one-or-two */ && + windowBox.size() != surface->current.buffer->size /* misaligned */ && DELTALESSTHAN(windowBox.width, surface->current.buffer->size.x, 3) && + DELTALESSTHAN(windowBox.height, surface->current.buffer->size.y, 3) /* off by one-or-two */ && (!RDATA->pWindow || (!RDATA->pWindow->m_vRealSize.isBeingAnimated() && !INTERACTIVERESIZEINPROGRESS)) /* not window or not animated/resizing */; g_pHyprRenderer->calculateUVForSurface(RDATA->pWindow, surface, RDATA->surface == surface, windowBox.size(), MISALIGNEDFSV1); @@ -183,8 +184,8 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data) if (RDATA->dontRound) rounding = 0; - const bool WINDOWOPAQUE = RDATA->pWindow && RDATA->pWindow->m_pWLSurface.wlr() == surface ? RDATA->pWindow->opaque() : false; - const bool CANDISABLEBLEND = ALPHA >= 1.f && rounding == 0 && (WINDOWOPAQUE || surface->opaque); + const bool WINDOWOPAQUE = RDATA->pWindow && RDATA->pWindow->m_pWLSurface->resource() == surface ? RDATA->pWindow->opaque() : false; + const bool CANDISABLEBLEND = ALPHA >= 1.f && rounding == 0 && WINDOWOPAQUE; if (CANDISABLEBLEND) g_pHyprOpenGL->blend(false); @@ -195,16 +196,16 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data) if (RDATA->blur) g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, surface, rounding, RDATA->blockBlurOptimization, RDATA->fadeAlpha); else - g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA, rounding, true); + g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA, rounding); } else { if (RDATA->blur && RDATA->popup) g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, surface, rounding, true, RDATA->fadeAlpha); else - g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA, rounding, true); + g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA, rounding); } if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) { - wlr_surface_send_frame_done(surface, RDATA->when); + surface->frame(RDATA->when); auto FEEDBACK = makeShared(surface); FEEDBACK->attachMonitor(RDATA->pMonitor); FEEDBACK->presented(); @@ -506,7 +507,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec if (ignoreAllGeometry) decorate = false; - renderdata.surface = pWindow->m_pWLSurface.wlr(); + renderdata.surface = pWindow->m_pWLSurface->resource(); renderdata.dontRound = (pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) || (!pWindow->m_sSpecialRenderData.rounding); renderdata.fadeAlpha = pWindow->m_fAlpha.value() * (pWindow->m_bPinned ? 1.f : PWORKSPACE->m_fAlpha.value()); renderdata.alpha = pWindow->m_fActiveInactiveAlpha.value(); @@ -576,7 +577,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec if ((pWindow->m_bIsX11 && *PXWLUSENN) || pWindow->m_sAdditionalConfigData.nearestNeighbor.toUnderlying()) g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true; - if (!pWindow->m_sAdditionalConfigData.forceNoBlur && pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall && renderdata.blur && *PBLUR) { + if (!pWindow->m_sAdditionalConfigData.forceNoBlur && pWindow->m_pWLSurface->small() && !pWindow->m_pWLSurface->m_bFillIgnoreSmall && renderdata.blur && *PBLUR) { CBox wb = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h}; wb.scale(pMonitor->scale).round(); g_pHyprOpenGL->renderRectWithBlur(&wb, CColor(0, 0, 0, 0), renderdata.dontRound ? 0 : renderdata.rounding - 1, renderdata.fadeAlpha, @@ -584,7 +585,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec renderdata.blur = false; } - wlr_surface_for_each_surface(pWindow->m_pWLSurface.wlr(), renderSurface, &renderdata); + pWindow->m_pWLSurface->resource()->breadthfirst([](SP s, void* data) { renderSurface(s, 0, 0, data); }, &renderdata); g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false; @@ -641,14 +642,14 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec pWindow->m_pPopupHead->breadthfirst( [](CPopup* popup, void* data) { - if (!popup->m_sWLSurface.wlr()) + if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource()) return; auto pos = popup->coordsRelativeToParent(); auto rd = (SRenderData*)data; Vector2D oldPos = {rd->x, rd->y}; rd->x += pos.x; rd->y += pos.y; - wlr_surface_for_each_surface(popup->m_sWLSurface.wlr(), renderSurface, rd); + popup->m_pWLSurface->resource()->breadthfirst([](SP s, void* data) { renderSurface(s, 0, 0, data); }, data); rd->x = oldPos.x; rd->y = oldPos.y; }, @@ -698,7 +699,7 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, CMonitor* pMonitor, timespec* time SRenderData renderdata = {pMonitor, time, REALPOS.x, REALPOS.y}; renderdata.fadeAlpha = pLayer->alpha.value(); renderdata.blur = pLayer->forceBlur; - renderdata.surface = pLayer->layerSurface->surface; + renderdata.surface = pLayer->surface->resource(); renderdata.decorate = false; renderdata.w = REALSIZ.x; renderdata.h = REALSIZ.y; @@ -717,7 +718,7 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, CMonitor* pMonitor, timespec* time } if (!popups) - wlr_surface_for_each_surface(pLayer->layerSurface->surface, renderSurface, &renderdata); + pLayer->surface->resource()->breadthfirst([](SP s, void* data) { renderSurface(s, 0, 0, data); }, &renderdata); renderdata.squishOversized = false; // don't squish popups renderdata.dontRound = true; @@ -726,11 +727,11 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, CMonitor* pMonitor, timespec* time if (popups) { pLayer->popupHead->breadthfirst( [](CPopup* popup, void* data) { - if (!popup->m_sWLSurface.wlr()) + if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource()) return; Vector2D pos = popup->coordsRelativeToParent(); - renderSurface(popup->m_sWLSurface.wlr(), pos.x, pos.y, data); + renderSurface(popup->m_pWLSurface->resource(), pos.x, pos.y, data); }, &renderdata); } @@ -746,15 +747,15 @@ void CHyprRenderer::renderIMEPopup(CInputPopup* pPopup, CMonitor* pMonitor, time SRenderData renderdata = {pMonitor, time, POS.x, POS.y}; - const auto SURF = pPopup->getWlrSurface(); + const auto SURF = pPopup->getSurface(); renderdata.blur = false; renderdata.surface = SURF; renderdata.decorate = false; - renderdata.w = SURF->current.width; - renderdata.h = SURF->current.height; + renderdata.w = SURF->current.size.x; + renderdata.h = SURF->current.size.y; - wlr_surface_for_each_surface(SURF, renderSurface, &renderdata); + SURF->breadthfirst([](SP s, void* data) { renderSurface(s, 0, 0, data); }, &renderdata); } void CHyprRenderer::renderSessionLockSurface(SSessionLockSurface* pSurface, CMonitor* pMonitor, timespec* time) { @@ -766,7 +767,7 @@ void CHyprRenderer::renderSessionLockSurface(SSessionLockSurface* pSurface, CMon renderdata.w = pMonitor->vecSize.x; renderdata.h = pMonitor->vecSize.y; - wlr_surface_for_each_surface(pSurface->surface->surface(), renderSurface, &renderdata); + renderdata.surface->breadthfirst([](SP s, void* data) { renderSurface(s, 0, 0, data); }, &renderdata); } void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* time, const Vector2D& translate, const float& scale) { @@ -966,17 +967,15 @@ void CHyprRenderer::renderLockscreen(CMonitor* pMonitor, timespec* now, const CB } } -void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, wlr_surface* pSurface, bool main, const Vector2D& projSize, bool fixMisalignedFSV1) { +void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SP pSurface, bool main, const Vector2D& projSize, bool fixMisalignedFSV1) { if (!pWindow || !pWindow->m_bIsX11) { Vector2D uvTL; Vector2D uvBR = Vector2D(1, 1); - if (pSurface->current.viewport.has_src) { + if (pSurface->current.viewport.hasSource) { // we stretch it to dest. if no dest, to 1,1 - wlr_fbox bufferSource; - wlr_surface_get_buffer_source_box(pSurface, &bufferSource); - - Vector2D bufferSize = Vector2D(pSurface->buffer->texture->width, pSurface->buffer->texture->height); + Vector2D bufferSize = pSurface->current.buffer->size; + auto bufferSource = pSurface->current.viewport.source; // calculate UV for the basic src_box. Assume dest == size. Scale to dest later uvTL = Vector2D(bufferSource.x / bufferSize.x, bufferSource.y / bufferSize.y); @@ -991,8 +990,8 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, wlr_surface* pSurfa if (projSize != Vector2D{} && fixMisalignedFSV1) { // instead of nearest_neighbor (we will repeat / skip) // just cut off / expand surface - const Vector2D PIXELASUV = Vector2D{1, 1} / Vector2D{pSurface->buffer->texture->width, pSurface->buffer->texture->height}; - const Vector2D MISALIGNMENT = Vector2D{pSurface->buffer->texture->width, pSurface->buffer->texture->height} - projSize; + const Vector2D PIXELASUV = Vector2D{1, 1} / pSurface->current.buffer->size; + const Vector2D MISALIGNMENT = pSurface->current.buffer->size - projSize; if (MISALIGNMENT != Vector2D{}) uvBR -= MISALIGNMENT * PIXELASUV; } @@ -1013,10 +1012,10 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, wlr_surface* pSurfa // ignore X and Y, adjust uv if (geom.x != 0 || geom.y != 0 || geom.width > pWindow->m_vRealSize.value().x || geom.height > pWindow->m_vRealSize.value().y) { - const auto XPERC = (double)geom.x / (double)pSurface->current.width; - const auto YPERC = (double)geom.y / (double)pSurface->current.height; - const auto WPERC = (double)(geom.x + geom.width) / (double)pSurface->current.width; - const auto HPERC = (double)(geom.y + geom.height) / (double)pSurface->current.height; + const auto XPERC = (double)geom.x / (double)pSurface->current.size.x; + const auto YPERC = (double)geom.y / (double)pSurface->current.size.y; + const auto WPERC = (double)(geom.x + geom.width) / (double)pSurface->current.size.x; + const auto HPERC = (double)(geom.y + geom.height) / (double)pSurface->current.size.y; const auto TOADDTL = Vector2D(XPERC * (uvBR.x - uvTL.x), YPERC * (uvBR.y - uvTL.y)); uvBR = uvBR - Vector2D(1.0 - WPERC * (uvBR.x - uvTL.x), 1.0 - HPERC * (uvBR.y - uvTL.y)); @@ -1025,8 +1024,8 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, wlr_surface* pSurfa // TODO: make this passed to the func. Might break in the future. auto maxSize = pWindow->m_vRealSize.value(); - if (pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall) - maxSize = pWindow->m_pWLSurface.getViewporterCorrectedSize(); + if (pWindow->m_pWLSurface->small() && !pWindow->m_pWLSurface->m_bFillIgnoreSmall) + maxSize = pWindow->m_pWLSurface->getViewporterCorrectedSize(); if (geom.width > maxSize.x) uvBR.x = uvBR.x * (maxSize.x / geom.width); @@ -1048,53 +1047,51 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, wlr_surface* pSurfa } } -void countSubsurfacesIter(wlr_surface* pSurface, int x, int y, void* data) { - *(int*)data += 1; -} - bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) { - if (!pMonitor->mirrors.empty() || pMonitor->isMirror() || m_bDirectScanoutBlocked) - return false; // do not DS if this monitor is being mirrored. Will break the functionality. + return false; // FIXME: fix when we move to new lib for backend. - if (!wlr_output_is_direct_scanout_allowed(pMonitor->output)) - return false; + // if (!pMonitor->mirrors.empty() || pMonitor->isMirror() || m_bDirectScanoutBlocked) + // return false; // do not DS if this monitor is being mirrored. Will break the functionality. - const auto PCANDIDATE = pMonitor->solitaryClient.lock(); + // if (!wlr_output_is_direct_scanout_allowed(pMonitor->output)) + // return false; - if (!PCANDIDATE) - return false; + // const auto PCANDIDATE = pMonitor->solitaryClient.lock(); - const auto PSURFACE = g_pXWaylandManager->getWindowSurface(PCANDIDATE); + // if (!PCANDIDATE) + // return false; - if (!PSURFACE || PSURFACE->current.scale != pMonitor->output->scale || PSURFACE->current.transform != pMonitor->output->transform) - return false; + // const auto PSURFACE = g_pXWaylandManager->getWindowSurface(PCANDIDATE); - // finally, we should be GTG. - wlr_output_state_set_buffer(pMonitor->state.wlr(), &PSURFACE->buffer->base); + // if (!PSURFACE || PSURFACE->current.scale != pMonitor->output->scale || PSURFACE->current.transform != pMonitor->output->transform) + // return false; - if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) - return false; + // // finally, we should be GTG. + // wlr_output_state_set_buffer(pMonitor->state.wlr(), &PSURFACE->buffer->base); - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - wlr_surface_send_frame_done(PSURFACE, &now); - auto FEEDBACK = makeShared(PSURFACE); - FEEDBACK->attachMonitor(pMonitor); - FEEDBACK->presented(); - FEEDBACK->setPresentationType(true); - PROTO::presentation->queueData(FEEDBACK); - - if (pMonitor->state.commit()) { - if (m_pLastScanout.expired()) { - m_pLastScanout = PCANDIDATE; - Debug::log(LOG, "Entered a direct scanout to {:x}: \"{}\"", (uintptr_t)PCANDIDATE.get(), PCANDIDATE->m_szTitle); - } - } else { - m_pLastScanout.reset(); - return false; - } + // if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) + // return false; - return true; + // timespec now; + // clock_gettime(CLOCK_MONOTONIC, &now); + // PSURFACE->frame(&now); + // auto FEEDBACK = makeShared(PSURFACE); + // FEEDBACK->attachMonitor(pMonitor); + // FEEDBACK->presented(); + // FEEDBACK->setPresentationType(true); + // PROTO::presentation->queueData(FEEDBACK); + + // if (pMonitor->state.commit()) { + // if (m_pLastScanout.expired()) { + // m_pLastScanout = PCANDIDATE; + // Debug::log(LOG, "Entered a direct scanout to {:x}: \"{}\"", (uintptr_t)PCANDIDATE.get(), PCANDIDATE->m_szTitle); + // } + // } else { + // m_pLastScanout.reset(); + // return false; + // } + + // return true; } void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { @@ -1430,53 +1427,52 @@ void CHyprRenderer::renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, void CHyprRenderer::sendFrameEventsToWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now) { for (auto& w : g_pCompositor->m_vWindows) { - if (w->isHidden() || !w->m_bIsMapped || w->m_bFadingOut || !w->m_pWLSurface.wlr()) + if (w->isHidden() || !w->m_bIsMapped || w->m_bFadingOut || !w->m_pWLSurface->resource()) continue; if (!shouldRenderWindow(w, pMonitor)) continue; - wlr_surface_for_each_surface( - w->m_pWLSurface.wlr(), [](wlr_surface* s, int x, int y, void* data) { wlr_surface_send_frame_done(s, (timespec*)data); }, now); + w->m_pWLSurface->resource()->breadthfirst([now](SP r, void* d) { r->frame(now); }, nullptr); } for (auto& lsl : pMonitor->m_aLayerSurfaceLayers) { for (auto& ls : lsl) { - if (ls->fadingOut || !ls->surface.wlr()) + if (ls->fadingOut || !ls->surface->resource()) continue; - wlr_surface_for_each_surface( - ls->surface.wlr(), [](wlr_surface* s, int x, int y, void* data) { wlr_surface_send_frame_done(s, (timespec*)data); }, now); + ls->surface->resource()->breadthfirst([now](SP r, void* d) { r->frame(now); }, nullptr); } } } void CHyprRenderer::setWindowScanoutMode(PHLWINDOW pWindow) { - if (!g_pCompositor->m_sWLRLinuxDMABuf || g_pSessionLockManager->isSessionLocked()) - return; + // FIXME: fix when moved to new impl + // if (!g_pCompositor->m_sWLRLinuxDMABuf || g_pSessionLockManager->isSessionLocked()) + // return; - if (!pWindow->m_bIsFullscreen) { - wlr_linux_dmabuf_v1_set_surface_feedback(g_pCompositor->m_sWLRLinuxDMABuf, pWindow->m_pWLSurface.wlr(), nullptr); - Debug::log(LOG, "Scanout mode OFF set for {}", pWindow); - return; - } + // if (!pWindow->m_bIsFullscreen) { + // wlr_linux_dmabuf_v1_set_surface_feedback(g_pCompositor->m_sWLRLinuxDMABuf, pWindow->m_pWLSurface->resource(), nullptr); + // Debug::log(LOG, "Scanout mode OFF set for {}", pWindow); + // return; + // } - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + // const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); - const wlr_linux_dmabuf_feedback_v1_init_options INIT_OPTIONS = { - .main_renderer = g_pCompositor->m_sWLRRenderer, - .scanout_primary_output = PMONITOR->output, - }; + // const wlr_linux_dmabuf_feedback_v1_init_options INIT_OPTIONS = { + // .main_renderer = g_pCompositor->m_sWLRRenderer, + // .scanout_primary_output = PMONITOR->output, + // }; - wlr_linux_dmabuf_feedback_v1 feedback = {0}; + // wlr_linux_dmabuf_feedback_v1 feedback = {0}; - if (!wlr_linux_dmabuf_feedback_v1_init_with_options(&feedback, &INIT_OPTIONS)) - return; + // if (!wlr_linux_dmabuf_feedback_v1_init_with_options(&feedback, &INIT_OPTIONS)) + // return; - wlr_linux_dmabuf_v1_set_surface_feedback(g_pCompositor->m_sWLRLinuxDMABuf, pWindow->m_pWLSurface.wlr(), &feedback); - wlr_linux_dmabuf_feedback_v1_finish(&feedback); + // wlr_linux_dmabuf_v1_set_surface_feedback(g_pCompositor->m_sWLRLinuxDMABuf, pWindow->m_pWLSurface->resource(), &feedback); + // wlr_linux_dmabuf_feedback_v1_finish(&feedback); - Debug::log(LOG, "Scanout mode ON set for {}", pWindow); + // Debug::log(LOG, "Scanout mode ON set for {}", pWindow); } // taken from Sway. @@ -1662,26 +1658,25 @@ void CHyprRenderer::arrangeLayersForMonitor(const int& monitor) { g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitor); } -void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y, double scale) { +void CHyprRenderer::damageSurface(SP pSurface, double x, double y, double scale) { if (!pSurface) return; // wut? if (g_pCompositor->m_bUnsafeState) return; - const auto WLSURF = CWLSurface::surfaceFromWlr(pSurface); + const auto WLSURF = CWLSurface::fromResource(pSurface); CRegion damageBox = WLSURF ? WLSURF->logicalDamage() : CRegion{}; if (!WLSURF) { Debug::log(ERR, "BUG THIS: No CWLSurface for surface in damageSurface!!!"); - wlr_surface_get_effective_damage(pSurface, damageBox.pixman()); + return; } if (scale != 1.0) damageBox.scale(scale); // schedule frame events - if (!wl_list_empty(&pSurface->current.frame_callback_list)) - g_pCompositor->scheduleFrameForMonitor(g_pCompositor->getMonitorFromVector(Vector2D(x, y))); + g_pCompositor->scheduleFrameForMonitor(g_pCompositor->getMonitorFromVector(Vector2D(x, y))); if (damageBox.empty()) return; @@ -1836,7 +1831,6 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->onDisconnect(); pMonitor->events.modeChanged.emit(); - pMonitor->updateGlobal(); return true; } @@ -2242,12 +2236,11 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR EMIT_HOOK_EVENT("monitorLayoutChanged", nullptr); pMonitor->events.modeChanged.emit(); - pMonitor->updateGlobal(); return true; } -void CHyprRenderer::setCursorSurface(CWLSurface* surf, int hotspotX, int hotspotY, bool force) { +void CHyprRenderer::setCursorSurface(SP surf, int hotspotX, int hotspotY, bool force) { m_bCursorHasSurface = surf; m_sLastCursorData.name = ""; @@ -2464,8 +2457,8 @@ bool CHyprRenderer::canSkipBackBufferClear(CMonitor* pMonitor) { continue; // TODO: cache maybe? - CRegion opaque = &ls->layerSurface->surface->opaque_region; - CBox lsbox = {0, 0, ls->layerSurface->surface->current.buffer_width, ls->layerSurface->surface->current.buffer_height}; + CRegion opaque = ls->layerSurface->surface->current.opaque; + CBox lsbox = {{}, ls->layerSurface->surface->current.size}; opaque.invert(lsbox); if (!opaque.empty()) diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index da38fed2db03..55dc4d2a8ead 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -44,7 +44,7 @@ class CHyprRenderer { void renderMonitor(CMonitor* pMonitor); void arrangeLayersForMonitor(const int&); - void damageSurface(wlr_surface*, double, double, double scale = 1.0); + void damageSurface(SP, double, double, double scale = 1.0); void damageWindow(PHLWINDOW, bool forceFull = false); void damageBox(CBox*); void damageBox(const int& x, const int& y, const int& w, const int& h); @@ -57,14 +57,14 @@ class CHyprRenderer { void ensureCursorRenderingMode(); bool shouldRenderCursor(); void setCursorHidden(bool hide); - void calculateUVForSurface(PHLWINDOW, wlr_surface*, bool main = false, const Vector2D& projSize = {}, bool fixMisalignedFSV1 = false); + void calculateUVForSurface(PHLWINDOW, SP, bool main = false, const Vector2D& projSize = {}, bool fixMisalignedFSV1 = false); std::tuple getRenderTimes(CMonitor* pMonitor); // avg max min void renderLockscreen(CMonitor* pMonitor, timespec* now, const CBox& geometry); void setOccludedForBackLayers(CRegion& region, PHLWORKSPACE pWorkspace); void setOccludedForMainWorkspace(CRegion& region, PHLWORKSPACE pWorkspace); // TODO: merge occlusion methods bool canSkipBackBufferClear(CMonitor* pMonitor); void recheckSolitaryForMonitor(CMonitor* pMonitor); - void setCursorSurface(CWLSurface* surf, int hotspotX, int hotspotY, bool force = false); + void setCursorSurface(SP surf, int hotspotX, int hotspotY, bool force = false); void setCursorFromName(const std::string& name, bool force = false); void onRenderbufferDestroy(CRenderbuffer* rb); CRenderbuffer* getCurrentRBO(); @@ -98,10 +98,10 @@ class CHyprRenderer { CTimer m_tRenderTimer; struct { - int hotspotX; - int hotspotY; - std::optional surf = nullptr; - std::string name; + int hotspotX; + int hotspotY; + std::optional> surf; + std::string name; } m_sLastCursorData; private: diff --git a/src/render/Texture.cpp b/src/render/Texture.cpp index 1820d0fb75da..2db43b360bf1 100644 --- a/src/render/Texture.cpp +++ b/src/render/Texture.cpp @@ -1,9 +1,29 @@ #include "Texture.hpp" +#include "Renderer.hpp" +#include "../protocols/ToplevelExportWlrFuncs.hpp" CTexture::CTexture() { // naffin' } +CTexture::CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size_) { + g_pHyprRenderer->makeEGLCurrent(); + + const wlr_pixel_format_info* format = drm_get_pixel_format_info(drmFormat); + ASSERT(format); + auto glFmt = g_pHyprOpenGL->getPixelFormatFromDRM(drmFormat); + + m_vSize = size_; + allocate(); + glBindTexture(GL_TEXTURE_2D, m_iTexID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / format->bytes_per_block); + glTexImage2D(GL_TEXTURE_2D, 0, glFmt->glInternalFormat ? glFmt->glInternalFormat : glFmt->glFormat, size_.x, size_.y, 0, glFmt->glFormat, glFmt->glType, pixels); + glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); + glBindTexture(GL_TEXTURE_2D, 0); +} + CTexture::CTexture(wlr_texture* tex) { RASSERT(wlr_texture_is_gles2(tex), "wlr_texture provided to CTexture that isn't GLES2!"); wlr_gles2_texture_attribs attrs; @@ -20,6 +40,34 @@ CTexture::CTexture(wlr_texture* tex) { m_vSize = Vector2D(tex->width, tex->height); } +void CTexture::update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const CRegion& damage) { + g_pHyprRenderer->makeEGLCurrent(); + + const wlr_pixel_format_info* format = drm_get_pixel_format_info(drmFormat); + ASSERT(format); + auto glFmt = g_pHyprOpenGL->getPixelFormatFromDRM(drmFormat); + + glBindTexture(GL_TEXTURE_2D, m_iTexID); + + auto rects = damage.copy().intersect(CBox{{}, m_vSize}).getRects(); + + for (auto& rect : rects) { + glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / format->bytes_per_block); + glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, rect.x1); + glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, rect.y1); + + int width = rect.x2 - rect.x1; + int height = rect.y2 - rect.y1; + glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x1, rect.y1, width, height, glFmt->glFormat, glFmt->glType, pixels); + } + + glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0); + + glBindTexture(GL_TEXTURE_2D, 0); +} + void CTexture::destroyTexture() { if (m_iTexID) { glDeleteTextures(1, &m_iTexID); diff --git a/src/render/Texture.hpp b/src/render/Texture.hpp index 93a6aa5f0984..03bafcc284c7 100644 --- a/src/render/Texture.hpp +++ b/src/render/Texture.hpp @@ -12,10 +12,12 @@ enum TEXTURETYPE { class CTexture { public: CTexture(); + CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size); CTexture(wlr_texture*); void destroyTexture(); void allocate(); + void update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const CRegion& damage); TEXTURETYPE m_iType = TEXTURE_RGBA; GLenum m_iTarget = GL_TEXTURE_2D; diff --git a/src/xwayland/XSurface.cpp b/src/xwayland/XSurface.cpp index 8994e9753cbd..07cac8326a3f 100644 --- a/src/xwayland/XSurface.cpp +++ b/src/xwayland/XSurface.cpp @@ -1,6 +1,7 @@ #include "XSurface.hpp" #include "XWayland.hpp" #include "../protocols/XWaylandShell.hpp" +#include "../protocols/core/Compositor.hpp" #ifndef NO_XWAYLAND @@ -44,46 +45,41 @@ CXWaylandSurface::CXWaylandSurface(uint32_t xID_, CBox geometry_, bool OR) : xID } void CXWaylandSurface::ensureListeners() { - bool connected = hyprListener_surfaceDestroy.isConnected(); + bool connected = listeners.destroySurface; if (connected && !surface) { - hyprListener_surfaceDestroy.removeCallback(); - hyprListener_surfaceCommit.removeCallback(); + listeners.destroySurface.reset(); + listeners.commitSurface.reset(); } else if (!connected && surface) { - hyprListener_surfaceDestroy.initCallback( - &surface->events.destroy, - [this](void* owner, void* data) { - if (mapped) - unmap(); - - surface = nullptr; - hyprListener_surfaceDestroy.removeCallback(); - hyprListener_surfaceCommit.removeCallback(); - events.resourceChange.emit(); - }, - nullptr, "CXWaylandSurface"); - hyprListener_surfaceCommit.initCallback( - &surface->events.commit, - [this](void* owner, void* data) { - if (surface->pending.buffer_width > 0 && surface->pending.buffer_height > 0 && !mapped) { - map(); - return; - } - - if (surface->pending.buffer_width <= 0 && surface->pending.buffer_height <= 0 && mapped) { - unmap(); - return; - } - - events.commit.emit(); - }, - nullptr, "CXWaylandSurface"); + listeners.destroySurface = surface->events.destroy.registerListener([this](std::any d) { + if (mapped) + unmap(); + + surface.reset(); + listeners.destroySurface.reset(); + listeners.commitSurface.reset(); + events.resourceChange.emit(); + }); + + listeners.commitSurface = surface->events.commit.registerListener([this](std::any d) { + if (surface->pending.buffer && !mapped) { + map(); + return; + } + + if (!surface->pending.buffer && mapped) { + unmap(); + return; + } + + events.commit.emit(); + }); } if (resource) { listeners.destroyResource = resource->events.destroy.registerListener([this](std::any d) { unmap(); - surface = nullptr; + surface.reset(); events.resourceChange.emit(); }); } @@ -99,7 +95,7 @@ void CXWaylandSurface::map() { g_pXWayland->pWM->mappedSurfacesStacking.emplace_back(self); mapped = true; - wlr_surface_map(surface); + surface->map(); Debug::log(LOG, "XWayland surface {:x} mapping", (uintptr_t)this); @@ -118,7 +114,7 @@ void CXWaylandSurface::unmap() { std::erase(g_pXWayland->pWM->mappedSurfacesStacking, self); mapped = false; - wlr_surface_unmap(surface); + surface->unmap(); Debug::log(LOG, "XWayland surface {:x} unmapping", (uintptr_t)this); @@ -136,7 +132,7 @@ void CXWaylandSurface::considerMap() { return; } - if (surface->pending.buffer_width > 0 && surface->pending.buffer_height > 0) { + if (surface->pending.buffer) { Debug::log(LOG, "XWayland surface: considerMap, sure, we have a buffer"); map(); return; diff --git a/src/xwayland/XSurface.hpp b/src/xwayland/XSurface.hpp index 73cb89a54e0b..a3a695aa9e25 100644 --- a/src/xwayland/XSurface.hpp +++ b/src/xwayland/XSurface.hpp @@ -39,7 +39,7 @@ typedef struct { class CXWaylandSurface { public: - wlr_surface* surface = nullptr; + WP surface; WP resource; struct { @@ -109,11 +109,10 @@ class CXWaylandSurface { void considerMap(); void setWithdrawn(bool withdrawn); - DYNLISTENER(surfaceDestroy); - DYNLISTENER(surfaceCommit); - struct { CHyprSignalListener destroyResource; + CHyprSignalListener destroySurface; + CHyprSignalListener commitSurface; } listeners; friend class CXWM; diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 9e308314034d..92d3605e71af 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -6,6 +6,7 @@ #include #include "../Compositor.hpp" #include "../protocols/XWaylandShell.hpp" +#include "../protocols/core/Compositor.hpp" #include "../managers/SeatManager.hpp" #include "../protocols/core/Seat.hpp" #include @@ -296,7 +297,7 @@ void CXWM::handleClientMessage(xcb_client_message_event_t* e) { auto id = e->data.data32[0]; auto resource = wl_client_get_object(g_pXWayland->pServer->xwaylandClient, id); if (resource) { - auto wlrSurface = wlr_surface_from_resource(resource); + auto wlrSurface = CWLSurfaceResource::fromResource(resource); associate(XSURF, wlrSurface); } } else if (e->type == HYPRATOMS["WL_SURFACE_SERIAL"]) { @@ -318,7 +319,7 @@ void CXWM::handleClientMessage(xcb_client_message_event_t* e) { if (res->serial != XSURF->wlSerial || !XSURF->wlSerial) continue; - associate(XSURF, res->surface); + associate(XSURF, res->surface.lock()); break; } @@ -827,9 +828,7 @@ CXWM::CXWM() { initSelection(); - hyprListener_newSurface.initCallback( - &g_pCompositor->m_sWLRCompositor->events.new_surface, [this](void* owner, void* data) { onNewSurface((wlr_surface*)data); }, nullptr, "XWM"); - + listeners.newWLSurface = PROTO::compositor->events.newSurface.registerListener([this](std::any d) { onNewSurface(std::any_cast>(d)); }); listeners.newXShellSurface = PROTO::xwaylandShell->events.newSurface.registerListener([this](std::any d) { onNewResource(std::any_cast>(d)); }); createWMWindow(); @@ -892,13 +891,13 @@ void CXWM::sendState(SP surf) { xcb_change_property(connection, XCB_PROP_MODE_REPLACE, surf->xID, HYPRATOMS["_NET_WM_STATE"], XCB_ATOM_ATOM, 32, props.size(), props.data()); } -void CXWM::onNewSurface(wlr_surface* surf) { - if (wl_resource_get_client(surf->resource) != g_pXWayland->pServer->xwaylandClient) +void CXWM::onNewSurface(SP surf) { + if (surf->client() != g_pXWayland->pServer->xwaylandClient) return; Debug::log(LOG, "[xwm] New XWayland surface at {:x}", (uintptr_t)surf); - const auto WLID = wl_resource_get_id(surf->resource); + const auto WLID = surf->id(); for (auto& sr : surfaces) { if (sr->surface || sr->wlID != WLID) @@ -921,7 +920,7 @@ void CXWM::onNewResource(SP resource) { if (surf->resource || surf->wlSerial != resource->serial) continue; - associate(surf, resource->surface); + associate(surf, resource->surface.lock()); break; } } @@ -944,7 +943,7 @@ void CXWM::readWindowData(SP surf) { } } -void CXWM::associate(SP surf, wlr_surface* wlSurf) { +void CXWM::associate(SP surf, SP wlSurf) { if (surf->surface) return; @@ -970,7 +969,7 @@ void CXWM::dissociate(SP surf) { if (surf->mapped) surf->unmap(); - surf->surface = nullptr; + surf->surface.reset(); surf->events.resourceChange.emit(); Debug::log(LOG, "Dissociate for {:x}", (uintptr_t)surf.get()); diff --git a/src/xwayland/XWM.hpp b/src/xwayland/XWM.hpp index b312f4a9c392..123e6227ccd5 100644 --- a/src/xwayland/XWM.hpp +++ b/src/xwayland/XWM.hpp @@ -72,7 +72,7 @@ class CXWM { void createWMWindow(); void initSelection(); - void onNewSurface(wlr_surface* surf); + void onNewSurface(SP surf); void onNewResource(SP resource); void setActiveWindow(xcb_window_t window); @@ -86,7 +86,7 @@ class CXWM { SP windowForXID(xcb_window_t wid); void readWindowData(SP surf); - void associate(SP surf, wlr_surface* wlSurf); + void associate(SP surf, SP wlSurf); void dissociate(SP surf); void updateClientList(); @@ -146,9 +146,8 @@ class CXWM { SXSelection clipboard; - DYNLISTENER(newSurface); - struct { + CHyprSignalListener newWLSurface; CHyprSignalListener newXShellSurface; } listeners;