aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt6
-rw-r--r--flake.lock18
-rw-r--r--protocols/meson.build4
-rw-r--r--protocols/wayland-drm.xml189
-rw-r--r--src/Compositor.cpp182
-rw-r--r--src/Compositor.hpp165
-rw-r--r--src/debug/HyprDebugOverlay.cpp10
-rw-r--r--src/debug/HyprDebugOverlay.hpp3
-rw-r--r--src/debug/HyprNotificationOverlay.cpp8
-rw-r--r--src/debug/HyprNotificationOverlay.hpp2
-rw-r--r--src/desktop/LayerSurface.cpp57
-rw-r--r--src/desktop/LayerSurface.hpp2
-rw-r--r--src/desktop/Popup.cpp47
-rw-r--r--src/desktop/Popup.hpp2
-rw-r--r--src/desktop/Subsurface.cpp122
-rw-r--r--src/desktop/Subsurface.hpp25
-rw-r--r--src/desktop/WLSurface.cpp95
-rw-r--r--src/desktop/WLSurface.hpp77
-rw-r--r--src/desktop/Window.cpp90
-rw-r--r--src/desktop/Window.hpp4
-rw-r--r--src/devices/Tablet.cpp26
-rw-r--r--src/devices/Tablet.hpp38
-rw-r--r--src/events/Windows.cpp24
-rw-r--r--src/helpers/Format.cpp271
-rw-r--r--src/helpers/Format.hpp37
-rw-r--r--src/helpers/MiscFunctions.cpp66
-rw-r--r--src/helpers/MiscFunctions.hpp3
-rw-r--r--src/helpers/Monitor.cpp12
-rw-r--r--src/helpers/Monitor.hpp1
-rw-r--r--src/helpers/Region.cpp7
-rw-r--r--src/helpers/Region.hpp1
-rw-r--r--src/helpers/WLClasses.hpp13
-rw-r--r--src/helpers/memory/SharedPtr.hpp4
-rw-r--r--src/helpers/memory/WeakPtr.hpp2
-rw-r--r--src/helpers/signal/Signal.cpp29
-rw-r--r--src/hyprerror/HyprError.cpp15
-rw-r--r--src/hyprerror/HyprError.hpp2
-rw-r--r--src/layout/IHyprLayout.cpp5
-rw-r--r--src/macros.hpp12
-rw-r--r--src/managers/CursorManager.cpp4
-rw-r--r--src/managers/CursorManager.hpp2
-rw-r--r--src/managers/KeybindManager.cpp24
-rw-r--r--src/managers/PointerManager.cpp66
-rw-r--r--src/managers/PointerManager.hpp14
-rw-r--r--src/managers/ProtocolManager.cpp34
-rw-r--r--src/managers/SeatManager.cpp50
-rw-r--r--src/managers/SeatManager.hpp43
-rw-r--r--src/managers/SessionLockManager.cpp6
-rw-r--r--src/managers/SessionLockManager.hpp7
-rw-r--r--src/managers/XWaylandManager.cpp13
-rw-r--r--src/managers/XWaylandManager.hpp26
-rw-r--r--src/managers/input/IdleInhibitor.cpp4
-rw-r--r--src/managers/input/InputManager.cpp60
-rw-r--r--src/managers/input/InputManager.hpp24
-rw-r--r--src/managers/input/InputMethodPopup.cpp22
-rw-r--r--src/managers/input/InputMethodPopup.hpp16
-rw-r--r--src/managers/input/InputMethodRelay.cpp20
-rw-r--r--src/managers/input/InputMethodRelay.hpp10
-rw-r--r--src/managers/input/Tablets.cpp6
-rw-r--r--src/managers/input/TextInput.cpp71
-rw-r--r--src/managers/input/TextInput.hpp44
-rw-r--r--src/managers/input/Touch.cpp2
-rw-r--r--src/protocols/AlphaModifier.cpp43
-rw-r--r--src/protocols/AlphaModifier.hpp25
-rw-r--r--src/protocols/FocusGrab.cpp36
-rw-r--r--src/protocols/FocusGrab.hpp28
-rw-r--r--src/protocols/FractionalScale.cpp55
-rw-r--r--src/protocols/FractionalScale.hpp37
-rw-r--r--src/protocols/GammaControl.cpp11
-rw-r--r--src/protocols/IdleInhibit.cpp25
-rw-r--r--src/protocols/IdleInhibit.hpp17
-rw-r--r--src/protocols/InputMethodV2.cpp65
-rw-r--r--src/protocols/InputMethodV2.hpp16
-rw-r--r--src/protocols/LayerShell.cpp105
-rw-r--r--src/protocols/LayerShell.hpp21
-rw-r--r--src/protocols/LinuxDMABUF.cpp454
-rw-r--r--src/protocols/LinuxDMABUF.hpp138
-rw-r--r--src/protocols/MesaDRM.cpp133
-rw-r--r--src/protocols/MesaDRM.hpp60
-rw-r--r--src/protocols/OutputPower.cpp7
-rw-r--r--src/protocols/PointerConstraints.cpp31
-rw-r--r--src/protocols/PointerConstraints.hpp23
-rw-r--r--src/protocols/PointerGestures.cpp7
-rw-r--r--src/protocols/PresentationTime.cpp14
-rw-r--r--src/protocols/PresentationTime.hpp17
-rw-r--r--src/protocols/Screencopy.cpp84
-rw-r--r--src/protocols/Screencopy.hpp5
-rw-r--r--src/protocols/ServerDecorationKDE.cpp6
-rw-r--r--src/protocols/ServerDecorationKDE.hpp4
-rw-r--r--src/protocols/SessionLock.cpp89
-rw-r--r--src/protocols/SessionLock.hpp18
-rw-r--r--src/protocols/ShortcutsInhibit.cpp11
-rw-r--r--src/protocols/ShortcutsInhibit.hpp10
-rw-r--r--src/protocols/Tablet.cpp17
-rw-r--r--src/protocols/Tablet.hpp23
-rw-r--r--src/protocols/TearingControl.cpp12
-rw-r--r--src/protocols/TearingControl.hpp5
-rw-r--r--src/protocols/TextInputV1.cpp3
-rw-r--r--src/protocols/TextInputV3.cpp9
-rw-r--r--src/protocols/TextInputV3.hpp6
-rw-r--r--src/protocols/ToplevelExport.cpp63
-rw-r--r--src/protocols/ToplevelExportWlrFuncs.hpp243
-rw-r--r--src/protocols/Viewporter.cpp126
-rw-r--r--src/protocols/Viewporter.hpp55
-rw-r--r--src/protocols/WaylandProtocol.cpp6
-rw-r--r--src/protocols/WaylandProtocol.hpp3
-rw-r--r--src/protocols/XDGActivation.cpp5
-rw-r--r--src/protocols/XDGOutput.cpp5
-rw-r--r--src/protocols/XDGShell.cpp108
-rw-r--r--src/protocols/XDGShell.hpp11
-rw-r--r--src/protocols/XWaylandShell.cpp5
-rw-r--r--src/protocols/XWaylandShell.hpp8
-rw-r--r--src/protocols/core/Compositor.cpp467
-rw-r--r--src/protocols/core/Compositor.hpp175
-rw-r--r--src/protocols/core/DataDevice.cpp63
-rw-r--r--src/protocols/core/DataDevice.hpp13
-rw-r--r--src/protocols/core/Output.cpp107
-rw-r--r--src/protocols/core/Output.hpp61
-rw-r--r--src/protocols/core/Seat.cpp54
-rw-r--r--src/protocols/core/Seat.hpp31
-rw-r--r--src/protocols/core/Shm.cpp214
-rw-r--r--src/protocols/core/Shm.hpp111
-rw-r--r--src/protocols/core/Subcompositor.cpp192
-rw-r--r--src/protocols/core/Subcompositor.hpp82
-rw-r--r--src/protocols/types/Buffer.cpp41
-rw-r--r--src/protocols/types/Buffer.hpp74
-rw-r--r--src/protocols/types/DMABuffer.cpp75
-rw-r--r--src/protocols/types/DMABuffer.hpp28
-rw-r--r--src/protocols/types/SurfaceRole.hpp14
-rw-r--r--src/protocols/types/WLBuffer.cpp43
-rw-r--r--src/protocols/types/WLBuffer.hpp31
-rw-r--r--src/render/Framebuffer.cpp27
-rw-r--r--src/render/Framebuffer.hpp21
-rw-r--r--src/render/OpenGL.cpp453
-rw-r--r--src/render/OpenGL.hpp159
-rw-r--r--src/render/Renderbuffer.cpp24
-rw-r--r--src/render/Renderbuffer.hpp3
-rw-r--r--src/render/Renderer.cpp255
-rw-r--r--src/render/Renderer.hpp19
-rw-r--r--src/render/Texture.cpp106
-rw-r--r--src/render/Texture.hpp18
-rw-r--r--src/render/decorations/CHyprGroupBarDecoration.cpp50
-rw-r--r--src/render/decorations/CHyprGroupBarDecoration.hpp2
-rw-r--r--src/xwayland/XSurface.cpp66
-rw-r--r--src/xwayland/XSurface.hpp9
-rw-r--r--src/xwayland/XWM.cpp21
-rw-r--r--src/xwayland/XWM.hpp7
147 files changed, 5415 insertions, 2253 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e42a530a..43cbb50c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -116,7 +116,7 @@ pkg_check_modules(deps REQUIRED IMPORTED_TARGET
hyprlang>=0.3.2 hyprcursor>=0.1.7
)
-find_package(hyprwayland-scanner 0.3.8 REQUIRED)
+find_package(hyprwayland-scanner 0.3.10 REQUIRED)
file(GLOB_RECURSE SRCFILES "src/*.cpp")
@@ -277,7 +277,6 @@ target_link_libraries(Hyprland
protocol("protocols/wlr-screencopy-unstable-v1.xml" "wlr-screencopy-unstable-v1" true)
protocol("subprojects/hyprland-protocols/protocols/hyprland-global-shortcuts-v1.xml" "hyprland-global-shortcuts-v1" true)
protocol("subprojects/hyprland-protocols/protocols/hyprland-toplevel-export-v1.xml" "hyprland-toplevel-export-v1" true)
-protocol("unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml" "linux-dmabuf-unstable-v1" false)
protocol("unstable/text-input/text-input-unstable-v1.xml" "text-input-unstable-v1" false)
protocolNew("protocols" "wlr-gamma-control-unstable-v1" true)
@@ -291,6 +290,7 @@ protocolNew("protocols" "kde-server-decoration" true)
protocolNew("protocols" "wlr-data-control-unstable-v1" true)
protocolNew("subprojects/hyprland-protocols/protocols" "hyprland-focus-grab-v1" true)
protocolNew("protocols" "wlr-layer-shell-unstable-v1" true)
+protocolNew("protocols" "wayland-drm" true)
protocolNew("staging/tearing-control" "tearing-control-v1" false)
protocolNew("staging/fractional-scale" "fractional-scale-v1" false)
protocolNew("unstable/xdg-output" "xdg-output-unstable-v1" false)
@@ -312,6 +312,8 @@ 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)
+protocolNew("stable/linux-dmabuf" "linux-dmabuf-v1" false)
protocolWayland()
diff --git a/flake.lock b/flake.lock
index 8fc80b1d..ab886a15 100644
--- a/flake.lock
+++ b/flake.lock
@@ -13,11 +13,11 @@
]
},
"locked": {
- "lastModified": 1716576411,
- "narHash": "sha256-FIN1wMoyePBTtibCbaeJaoKNLuAYIGwLCWAYC1DJanw=",
+ "lastModified": 1717181720,
+ "narHash": "sha256-yv+QZWsusu/NWjydkxixHC2g+tIJ9v+xkE2EiVpJj6g=",
"owner": "hyprwm",
"repo": "hyprcursor",
- "rev": "57298fc4f13c807e50ada2c986a3114b7fc2e621",
+ "rev": "9e27a2c2ceb1e0b85bd55b0afefad196056fe87c",
"type": "github"
},
"original": {
@@ -84,11 +84,11 @@
]
},
"locked": {
- "lastModified": 1716058375,
- "narHash": "sha256-CwjWoVnBZE5SBpRx9dgSQGCr4Goxyfcyv3zZbOhVqzk=",
+ "lastModified": 1717784906,
+ "narHash": "sha256-YxmfxHfWed1fosaa7fC1u7XoKp1anEZU+7Lh/ojRKoM=",
"owner": "hyprwm",
"repo": "hyprwayland-scanner",
- "rev": "3afed4364790aebe0426077631af1e164a9650cc",
+ "rev": "0f30f9eca6e404130988554accbb64d1c9ec877d",
"type": "github"
},
"original": {
@@ -99,11 +99,11 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1716330097,
- "narHash": "sha256-8BO3B7e3BiyIDsaKA0tY8O88rClYRTjvAp66y+VBUeU=",
+ "lastModified": 1717602782,
+ "narHash": "sha256-pL9jeus5QpX5R+9rsp3hhZ+uplVHscNJh8n8VpqscM0=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "5710852ba686cc1fd0d3b8e22b3117d43ba374c2",
+ "rev": "e8057b67ebf307f01bdcc8fba94d94f75039d1f6",
"type": "github"
},
"original": {
diff --git a/protocols/meson.build b/protocols/meson.build
index f491bb09..f4978c23 100644
--- a/protocols/meson.build
+++ b/protocols/meson.build
@@ -24,7 +24,6 @@ hyprwayland_scanner = find_program(
)
protocols = [
- [wl_protocol_dir, 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml'],
[wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'],
['wlr-screencopy-unstable-v1.xml'],
[hl_protocol_dir, 'protocols/hyprland-toplevel-export-v1.xml'],
@@ -41,6 +40,7 @@ new_protocols = [
['wlr-output-management-unstable-v1.xml'],
['kde-server-decoration.xml'],
['wlr-layer-shell-unstable-v1.xml'],
+ ['wayland-drm.xml'],
['wlr-data-control-unstable-v1.xml'],
[hl_protocol_dir, 'protocols/hyprland-focus-grab-v1.xml'],
[wl_protocol_dir, 'staging/tearing-control/tearing-control-v1.xml'],
@@ -64,6 +64,8 @@ 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_protocol_dir, 'stable/linux-dmabuf/linux-dmabuf-v1.xml'],
]
wl_protos_src = []
diff --git a/protocols/wayland-drm.xml b/protocols/wayland-drm.xml
new file mode 100644
index 00000000..eaf2654a
--- /dev/null
+++ b/protocols/wayland-drm.xml
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="drm">
+
+ <copyright>
+ Copyright © 2008-2011 Kristian Høgsberg
+ Copyright © 2010-2011 Intel Corporation
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that\n the above copyright notice appear in
+ all copies and that both that copyright notice and this permission
+ notice appear in supporting documentation, and that the name of
+ the copyright holders not be used in advertising or publicity
+ pertaining to distribution of the software without specific,
+ written prior permission. The copyright holders make no
+ representations about the suitability of this software for any
+ purpose. It is provided "as is" without express or implied
+ warranty.
+
+ THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+ THIS SOFTWARE.
+ </copyright>
+
+ <!-- drm support. This object is created by the server and published
+ using the display's global event. -->
+ <interface name="wl_drm" version="2">
+ <enum name="error">
+ <entry name="authenticate_fail" value="0"/>
+ <entry name="invalid_format" value="1"/>
+ <entry name="invalid_name" value="2"/>
+ </enum>
+
+ <enum name="format">
+ <!-- The drm format codes match the #defines in drm_fourcc.h.
+ The formats actually supported by the compositor will be
+ reported by the format event. New codes must not be added,
+ unless directly taken from drm_fourcc.h. -->
+ <entry name="c8" value="0x20203843"/>
+ <entry name="rgb332" value="0x38424752"/>
+ <entry name="bgr233" value="0x38524742"/>
+ <entry name="xrgb4444" value="0x32315258"/>
+ <entry name="xbgr4444" value="0x32314258"/>
+ <entry name="rgbx4444" value="0x32315852"/>
+ <entry name="bgrx4444" value="0x32315842"/>
+ <entry name="argb4444" value="0x32315241"/>
+ <entry name="abgr4444" value="0x32314241"/>
+ <entry name="rgba4444" value="0x32314152"/>
+ <entry name="bgra4444" value="0x32314142"/>
+ <entry name="xrgb1555" value="0x35315258"/>
+ <entry name="xbgr1555" value="0x35314258"/>
+ <entry name="rgbx5551" value="0x35315852"/>
+ <entry name="bgrx5551" value="0x35315842"/>
+ <entry name="argb1555" value="0x35315241"/>
+ <entry name="abgr1555" value="0x35314241"/>
+ <entry name="rgba5551" value="0x35314152"/>
+ <entry name="bgra5551" value="0x35314142"/>
+ <entry name="rgb565" value="0x36314752"/>
+ <entry name="bgr565" value="0x36314742"/>
+ <entry name="rgb888" value="0x34324752"/>
+ <entry name="bgr888" value="0x34324742"/>
+ <entry name="xrgb8888" value="0x34325258"/>
+ <entry name="xbgr8888" value="0x34324258"/>
+ <entry name="rgbx8888" value="0x34325852"/>
+ <entry name="bgrx8888" value="0x34325842"/>
+ <entry name="argb8888" value="0x34325241"/>
+ <entry name="abgr8888" value="0x34324241"/>
+ <entry name="rgba8888" value="0x34324152"/>
+ <entry name="bgra8888" value="0x34324142"/>
+ <entry name="xrgb2101010" value="0x30335258"/>
+ <entry name="xbgr2101010" value="0x30334258"/>
+ <entry name="rgbx1010102" value="0x30335852"/>
+ <entry name="bgrx1010102" value="0x30335842"/>
+ <entry name="argb2101010" value="0x30335241"/>
+ <entry name="abgr2101010" value="0x30334241"/>
+ <entry name="rgba1010102" value="0x30334152"/>
+ <entry name="bgra1010102" value="0x30334142"/>
+ <entry name="yuyv" value="0x56595559"/>
+ <entry name="yvyu" value="0x55595659"/>
+ <entry name="uyvy" value="0x59565955"/>
+ <entry name="vyuy" value="0x59555956"/>
+ <entry name="ayuv" value="0x56555941"/>
+ <entry name="xyuv8888" value="0x56555958"/>
+ <entry name="nv12" value="0x3231564e"/>
+ <entry name="nv21" value="0x3132564e"/>
+ <entry name="nv16" value="0x3631564e"/>
+ <entry name="nv61" value="0x3136564e"/>
+ <entry name="yuv410" value="0x39565559"/>
+ <entry name="yvu410" value="0x39555659"/>
+ <entry name="yuv411" value="0x31315559"/>
+ <entry name="yvu411" value="0x31315659"/>
+ <entry name="yuv420" value="0x32315559"/>
+ <entry name="yvu420" value="0x32315659"/>
+ <entry name="yuv422" value="0x36315559"/>
+ <entry name="yvu422" value="0x36315659"/>
+ <entry name="yuv444" value="0x34325559"/>
+ <entry name="yvu444" value="0x34325659"/>
+ <entry name="abgr16f" value="0x48344241"/>
+ <entry name="xbgr16f" value="0x48344258"/>
+ </enum>
+
+ <!-- Call this request with the magic received from drmGetMagic().
+ It will be passed on to the drmAuthMagic() or
+ DRIAuthConnection() call. This authentication must be
+ completed before create_buffer could be used. -->
+ <request name="authenticate">
+ <arg name="id" type="uint"/>
+ </request>
+
+ <!-- Create a wayland buffer for the named DRM buffer. The DRM
+ surface must have a name using the flink ioctl -->
+ <request name="create_buffer">
+ <arg name="id" type="new_id" interface="wl_buffer"/>
+ <arg name="name" type="uint"/>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ <arg name="stride" type="uint"/>
+ <arg name="format" type="uint"/>
+ </request>
+
+ <!-- Create a wayland buffer for the named DRM buffer. The DRM
+ surface must have a name using the flink ioctl -->
+ <request name="create_planar_buffer">
+ <arg name="id" type="new_id" interface="wl_buffer"/>
+ <arg name="name" type="uint"/>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ <arg name="format" type="uint"/>
+ <arg name="offset0" type="int"/>
+ <arg name="stride0" type="int"/>
+ <arg name="offset1" type="int"/>
+ <arg name="stride1" type="int"/>
+ <arg name="offset2" type="int"/>
+ <arg name="stride2" type="int"/>
+ </request>
+
+ <!-- Notification of the path of the drm device which is used by
+ the server. The client should use this device for creating
+ local buffers. Only buffers created from this device should
+ be be passed to the server using this drm object's
+ create_buffer request. -->
+ <event name="device">
+ <arg name="name" type="string"/>
+ </event>
+
+ <event name="format">
+ <arg name="format" type="uint"/>
+ </event>
+
+ <!-- Raised if the authenticate request succeeded -->
+ <event name="authenticated"/>
+
+ <enum name="capability" since="2">
+ <description summary="wl_drm capability bitmask">
+ Bitmask of capabilities.
+ </description>
+ <entry name="prime" value="1" summary="wl_drm prime available"/>
+ </enum>
+
+ <event name="capabilities">
+ <arg name="value" type="uint"/>
+ </event>
+
+ <!-- Version 2 additions -->
+
+ <!-- Create a wayland buffer for the prime fd. Use for regular and planar
+ buffers. Pass 0 for offset and stride for unused planes. -->
+ <request name="create_prime_buffer" since="2">
+ <arg name="id" type="new_id" interface="wl_buffer"/>
+ <arg name="name" type="fd"/>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ <arg name="format" type="uint"/>
+ <arg name="offset0" type="int"/>
+ <arg name="stride0" type="int"/>
+ <arg name="offset1" type="int"/>
+ <arg name="stride1" type="int"/>
+ <arg name="offset2" type="int"/>
+ <arg name="stride2" type="int"/>
+ </request>
+
+ </interface>
+
+</protocol>
diff --git a/src/Compositor.cpp b/src/Compositor.cpp
index 73708b1b..b0456358 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,15 +202,6 @@ void CCompositor::initServer() {
throwError("wlr_gles2_renderer_create_with_drm_fd() failed!");
}
- 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);
-
- m_sWLRLinuxDMABuf = wlr_linux_dmabuf_v1_create_with_renderer(m_sWLDisplay, 4, m_sWLRRenderer);
- }
-
m_sWLRAllocator = wlr_allocator_autocreate(m_sWLRBackend, m_sWLRRenderer);
if (!m_sWLRAllocator) {
@@ -223,13 +216,7 @@ 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_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);
+ initManagers(STAGE_BASICINIT);
m_sWRLDRMLeaseMgr = wlr_drm_lease_v1_manager_create(m_sWLDisplay, m_sWLRBackend);
if (!m_sWRLDRMLeaseMgr) {
@@ -244,8 +231,6 @@ void CCompositor::initServer() {
throwError("wlr_headless_backend_create() failed!");
}
- wlr_single_pixel_buffer_manager_v1_create(m_sWLDisplay);
-
wlr_multi_backend_add(m_sWLRBackend, m_sWLRHeadlessBackend);
initManagers(STAGE_LATE);
@@ -320,7 +305,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();
@@ -393,12 +378,6 @@ void CCompositor::initManagers(eManagersInitStage stage) {
Debug::log(LOG, "Creating the HookSystem!");
g_pHookSystem = std::make_unique<CHookSystemManager>();
- Debug::log(LOG, "Creating the ProtocolManager!");
- g_pProtocolManager = std::make_unique<CProtocolManager>();
-
- Debug::log(LOG, "Creating the SeatManager!");
- g_pSeatManager = std::make_unique<CSeatManager>();
-
Debug::log(LOG, "Creating the KeybindManager!");
g_pKeybindManager = std::make_unique<CKeybindManager>();
@@ -423,6 +402,13 @@ void CCompositor::initManagers(eManagersInitStage stage) {
Debug::log(LOG, "Creating the PointerManager!");
g_pPointerManager = std::make_unique<CPointerManager>();
} break;
+ case STAGE_BASICINIT: {
+ Debug::log(LOG, "Creating the ProtocolManager!");
+ g_pProtocolManager = std::make_unique<CProtocolManager>();
+
+ Debug::log(LOG, "Creating the SeatManager!");
+ g_pSeatManager = std::make_unique<CSeatManager>();
+ } break;
case STAGE_LATE: {
Debug::log(LOG, "Creating the ThreadManager!");
g_pThreadManager = std::make_unique<CThreadManager>();
@@ -574,6 +560,8 @@ void CCompositor::startCompositor() {
createLockFile();
+ EMIT_HOOK_EVENT("ready", nullptr);
+
// This blocks until we are done.
Debug::log(LOG, "Hyprland is ready, running the event loop!");
g_pEventLoopManager->enterLoop(m_sWLDisplay, m_sWLEventLoop);
@@ -789,47 +777,32 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
return windowForWorkspace(false);
}
-wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, PHLWINDOW pWindow, Vector2D& sl) {
+SP<CWLSurfaceResource> CCompositor::vectorWindowToSurface(const Vector2D& pos, PHLWINDOW pWindow, Vector2D& sl) {
if (!validMapped(pWindow))
return nullptr;
RASSERT(!pWindow->m_bIsX11, "Cannot call vectorWindowToSurface on an X11 window!");
- double subx, suby;
-
- CBox geom = pWindow->m_pXDGSurface->current.geometry;
-
// try popups first
- const auto PPOPUP = pWindow->m_pPopupHead->at(pos);
+ 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 {
+ if (PPOPUP) {
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;
+ sl = pos - pWindow->m_vRealPosition.goal() - OFF;
+ return PPOPUP->m_pWLSurface->resource();
}
- if (found) {
- sl.x = subx;
- sl.y = suby;
- return found;
+ auto [surf, local] = pWindow->m_pWLSurface->resource()->at(pos - pWindow->m_vRealPosition.goal(), true);
+ if (surf) {
+ sl = local;
+ return surf;
}
- sl.x = pos.x - pWindow->m_vRealPosition.value().x;
- sl.y = pos.y - pWindow->m_vRealPosition.value().y;
-
- sl.x += geom.x;
- sl.y += geom.y;
-
- return pWindow->m_pWLSurface.wlr();
+ return nullptr;
}
-Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindow, wlr_surface* pSurface) {
+Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface) {
if (!validMapped(pWindow))
return {};
@@ -840,25 +813,22 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindo
if (PPOPUP)
return vec - PPOPUP->coordsGlobal();
- std::tuple<wlr_surface*, int, int> iterData = {pSurface, -1337, -1337};
+ std::tuple<SP<CWLSurfaceResource>, 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<wlr_surface*, int, int>*)data;
- if (surf == std::get<0>(*PDATA)) {
- std::get<1>(*PDATA) = x;
- std::get<2>(*PDATA) = y;
- }
+ pWindow->m_pWLSurface->resource()->breadthfirst(
+ [](SP<CWLSurfaceResource> surf, const Vector2D& offset, void* data) {
+ const auto PDATA = (std::tuple<SP<CWLSurfaceResource>, Vector2D>*)data;
+ if (surf == std::get<0>(*PDATA))
+ std::get<1>(*PDATA) = offset;
},
&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) {
@@ -881,7 +851,7 @@ CMonitor* CCompositor::getRealMonitorFromOutput(wlr_output* out) {
return nullptr;
}
-void CCompositor::focusWindow(PHLWINDOW pWindow, wlr_surface* pSurface) {
+void CCompositor::focusWindow(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface) {
static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse");
static auto PSPECIALFALLTHROUGH = CConfigValue<Hyprlang::INT>("input:special_fallthrough");
@@ -924,7 +894,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, wlr_surface* pSurface) {
g_pLayoutManager->getCurrentLayout()->onWindowFocusChange(nullptr);
- m_pLastFocus = nullptr;
+ m_pLastFocus.reset();
g_pInputManager->recheckIdleInhibitorStatus();
return;
@@ -976,7 +946,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);
@@ -1011,9 +981,9 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, wlr_surface* pSurface) {
g_pInputManager->sendMotionEventsToFocused();
}
-void CCompositor::focusSurface(wlr_surface* pSurface, PHLWINDOW pWindowOwner) {
+void CCompositor::focusSurface(SP<CWLSurfaceResource> 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))
@@ -1024,18 +994,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<CWLSurfaceResource>)nullptr);
+ m_pLastFocus.reset();
return;
}
@@ -1052,8 +1022,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();
@@ -1062,7 +1032,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<CWLSurfaceResource> 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)
@@ -1073,7 +1043,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();
}
}
}
@@ -1081,31 +1051,34 @@ wlr_surface* CCompositor::vectorToLayerPopupSurface(const Vector2D& pos, CMonito
return nullptr;
}
-wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<PHLLSREF>* layerSurfaces, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) {
+SP<CWLSurfaceResource> CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<PHLLSREF>* 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 [surf, local] = ls->layerSurface->surface->at(pos - ls->geometry.pos());
- if (SURFACEAT) {
- if (!pixman_region32_not_empty(&SURFACEAT->input_region))
+ if (surf) {
+ if (surf->current.input.empty())
continue;
*ppLayerSurfaceFound = ls.lock();
- return SURFACEAT;
+
+ *sCoords = local;
+
+ return surf;
}
}
return nullptr;
}
-PHLWINDOW CCompositor::getWindowFromSurface(wlr_surface* pSurface) {
+PHLWINDOW CCompositor::getWindowFromSurface(SP<CWLSurfaceResource> 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;
}
@@ -1244,7 +1217,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();
}
@@ -1646,11 +1619,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<wlr_surface*, bool>*)data;
- pair->second = pair->second || pSurface == pair->first;
-}
-
CMonitor* CCompositor::getMonitorInDirection(const char& dir) {
return this->getMonitorInDirection(m_pLastMonitor.get(), dir);
}
@@ -2389,24 +2357,24 @@ void CCompositor::closeWindow(PHLWINDOW pWindow) {
}
}
-PHLLS CCompositor::getLayerSurfaceFromSurface(wlr_surface* pSurface) {
- std::pair<wlr_surface*, bool> result = {pSurface, false};
+PHLLS CCompositor::getLayerSurfaceFromSurface(SP<CWLSurfaceResource> pSurface) {
+ std::pair<SP<CWLSurfaceResource>, 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<wlr_surface*, bool>*)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<CWLSurfaceResource> surf, const Vector2D& offset, void* data) {
+ if (surf == ((std::pair<SP<CWLSurfaceResource>, bool>*)data)->first) {
+ *(bool*)data = true;
+ return;
+ }
+ },
+ &result);
if (result.second)
return ls;
@@ -2738,13 +2706,13 @@ void CCompositor::leaveUnsafeState() {
}
}
-void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scale) {
+void CCompositor::setPreferredScaleForSurface(SP<CWLSurfaceResource> pSurface, double scale) {
PROTO::fractional->sendScale(pSurface, scale);
- wlr_surface_set_preferred_buffer_scale(pSurface, static_cast<int32_t>(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);
+ Debug::log(WARN, "Orphaned CWLSurfaceResource {:x} in setPreferredScaleForSurface", (uintptr_t)pSurface);
return;
}
@@ -2752,12 +2720,12 @@ void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scal
PSURFACE->m_iLastScale = static_cast<int32_t>(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<CWLSurfaceResource> 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);
+ Debug::log(WARN, "Orphaned CWLSurfaceResource {:x} in setPreferredTransformForSurface", (uintptr_t)pSurface);
return;
}
diff --git a/src/Compositor.hpp b/src/Compositor.hpp
index a297518d..793899ee 100644
--- a/src/Compositor.hpp
+++ b/src/Compositor.hpp
@@ -29,8 +29,11 @@
#include "plugins/PluginSystem.hpp"
#include "helpers/Watchdog.hpp"
+class CWLSurfaceResource;
+
enum eManagersInitStage {
STAGE_PRIORITY = 0,
+ STAGE_BASICINIT,
STAGE_LATE
};
@@ -79,7 +82,7 @@ class CCompositor {
void createLockFile();
void removeLockFile();
- wlr_surface* m_pLastFocus = nullptr;
+ WP<CWLSurfaceResource> m_pLastFocus;
PHLWINDOWREF m_pLastWindow;
WP<CMonitor> m_pLastMonitor;
@@ -96,86 +99,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<PHLLSREF>*, 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<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
- int getGroupsOnWorkspace(const int& id, std::optional<bool> onlyTiled = {}, std::optional<bool> 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<bool> floating = {});
- PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> 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<CWLSurfaceResource> pSurface = nullptr);
+ void focusSurface(SP<CWLSurfaceResource>, PHLWINDOW pWindowOwner = nullptr);
+ bool monitorExists(CMonitor*);
+ PHLWINDOW vectorToWindowUnified(const Vector2D&, uint8_t properties, PHLWINDOW pIgnoreWindow = nullptr);
+ SP<CWLSurfaceResource> vectorToLayerSurface(const Vector2D&, std::vector<PHLLSREF>*, Vector2D*, PHLLS*);
+ SP<CWLSurfaceResource> vectorToLayerPopupSurface(const Vector2D&, CMonitor* monitor, Vector2D*, PHLLS*);
+ SP<CWLSurfaceResource> vectorWindowToSurface(const Vector2D&, PHLWINDOW, Vector2D& sl);
+ Vector2D vectorToSurfaceLocal(const Vector2D&, PHLWINDOW, SP<CWLSurfaceResource>);
+ CMonitor* getMonitorFromOutput(wlr_output*);
+ CMonitor* getRealMonitorFromOutput(wlr_output*);
+ PHLWINDOW getWindowFromSurface(SP<CWLSurfaceResource>);
+ 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<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
+ int getGroupsOnWorkspace(const int& id, std::optional<bool> onlyTiled = {}, std::optional<bool> 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<bool> floating = {});
+ PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> 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<CWLSurfaceResource>);
+ 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<CWLSurfaceResource> pSurface, double scale);
+ void setPreferredTransformForSurface(SP<CWLSurfaceResource> pSurface, wl_output_transform transform);
+ void updateSuspendedStates();
+ PHLWINDOW windowForCPointer(CWindow*);
+
+ std::string explicitConfigPath;
private:
void initAllSignals();
diff --git a/src/debug/HyprDebugOverlay.cpp b/src/debug/HyprDebugOverlay.cpp
index 6d3ec907..889be8ea 100644
--- a/src/debug/HyprDebugOverlay.cpp
+++ b/src/debug/HyprDebugOverlay.cpp
@@ -3,6 +3,10 @@
#include "config/ConfigValue.hpp"
#include "../Compositor.hpp"
+CHyprDebugOverlay::CHyprDebugOverlay() {
+ m_pTexture = makeShared<CTexture>();
+}
+
void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float µs) {
m_dLastRenderTimes.push_back(µs / 1000.f);
@@ -222,8 +226,8 @@ void CHyprDebugOverlay::draw() {
// copy the data to an OpenGL texture we have
const auto DATA = cairo_image_surface_get_data(m_pCairoSurface);
- m_tTexture.allocate();
- glBindTexture(GL_TEXTURE_2D, m_tTexture.m_iTexID);
+ m_pTexture->allocate();
+ glBindTexture(GL_TEXTURE_2D, m_pTexture->m_iTexID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -235,5 +239,5 @@ void CHyprDebugOverlay::draw() {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
CBox pMonBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
- g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f);
+ g_pHyprOpenGL->renderTexture(m_pTexture, &pMonBox, 1.f);
}
diff --git a/src/debug/HyprDebugOverlay.hpp b/src/debug/HyprDebugOverlay.hpp
index f3beab45..a6063ee9 100644
--- a/src/debug/HyprDebugOverlay.hpp
+++ b/src/debug/HyprDebugOverlay.hpp
@@ -31,6 +31,7 @@ class CHyprMonitorDebugOverlay {
class CHyprDebugOverlay {
public:
+ CHyprDebugOverlay();
void draw();
void renderData(CMonitor*, float µs);
void renderDataNoOverlay(CMonitor*, float µs);
@@ -42,7 +43,7 @@ class CHyprDebugOverlay {
cairo_surface_t* m_pCairoSurface = nullptr;
cairo_t* m_pCairo = nullptr;
- CTexture m_tTexture;
+ SP<CTexture> m_pTexture;
friend class CHyprMonitorDebugOverlay;
friend class CHyprRenderer;
diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp
index e1fc810b..aec3853e 100644
--- a/src/debug/HyprNotificationOverlay.cpp
+++ b/src/debug/HyprNotificationOverlay.cpp
@@ -23,6 +23,8 @@ CHyprNotificationOverlay::CHyprNotificationOverlay() {
g_pHyprRenderer->damageBox(&m_bLastDamage);
});
+
+ m_pTexture = makeShared<CTexture>();
}
CHyprNotificationOverlay::~CHyprNotificationOverlay() {
@@ -227,8 +229,8 @@ void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
// copy the data to an OpenGL texture we have
const auto DATA = cairo_image_surface_get_data(m_pCairoSurface);
- m_tTexture.allocate();
- glBindTexture(GL_TEXTURE_2D, m_tTexture.m_iTexID);
+ m_pTexture->allocate();
+ glBindTexture(GL_TEXTURE_2D, m_pTexture->m_iTexID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -240,7 +242,7 @@ void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, MONSIZE.x, MONSIZE.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
CBox pMonBox = {0, 0, MONSIZE.x, MONSIZE.y};
- g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f);
+ g_pHyprOpenGL->renderTexture(m_pTexture, &pMonBox, 1.f);
}
bool CHyprNotificationOverlay::hasAny() {
diff --git a/src/debug/HyprNotificationOverlay.hpp b/src/debug/HyprNotificationOverlay.hpp
index 5c978089..352c44c9 100644
--- a/src/debug/HyprNotificationOverlay.hpp
+++ b/src/debug/HyprNotificationOverlay.hpp
@@ -58,7 +58,7 @@ class CHyprNotificationOverlay {
CMonitor* m_pLastMonitor = nullptr;
Vector2D m_vecLastSize = Vector2D(-1, -1);
- CTexture m_tTexture;
+ SP<CTexture> m_pTexture;
};
inline std::unique_ptr<CHyprNotificationOverlay> g_pHyprNotificationOverlay;
diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp
index 759eb09f..62cae8f6 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<CLayerShellResource> resource) {
@@ -9,6 +10,8 @@ PHLLS CLayerSurface::create(SP<CLayerShellResource> resource) {
CMonitor* pMonitor = resource->monitor.empty() ? g_pCompositor->getMonitorFromCursor() : g_pCompositor->getMonitorFromName(resource->monitor);
+ pLS->surface->assign(resource->surface.lock(), pLS);
+
if (!pMonitor) {
Debug::log(ERR, "New LS has no monitor??");
return pLS;
@@ -39,8 +42,6 @@ PHLLS CLayerSurface::create(SP<CLayerShellResource> resource) {
pLS->alpha.setValueAndWarp(0.f);
- pLS->surface.assign(resource->surface, pLS);
-
Debug::log(LOG, "LayerSurface {:x} (namespace {} layer {}) created on monitor {}", (uintptr_t)resource.get(), resource->layerNamespace, (int)pLS->layer, pMonitor->szName);
return pLS;
@@ -58,13 +59,16 @@ CLayerSurface::CLayerSurface(SP<CLayerShellResource> 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();
+ if (surface)
+ 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 +109,8 @@ void CLayerSurface::onDestroy() {
readyToDelete = true;
layerSurface.reset();
- surface.unassign();
+ if (surface)
+ surface->unassign();
}
void CLayerSurface::onMap() {
@@ -126,7 +131,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 +144,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 +165,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 +178,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,9 +202,9 @@ 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;
+ surface.reset();
if (!PMONITOR)
return;
@@ -208,11 +213,11 @@ void CLayerSurface::onUnmap() {
if (WASLASTFOCUS) {
g_pInputManager->releaseAllMouseButtons();
- Vector2D surfaceCoords;
- PHLLS pFoundLayerSurface;
- wlr_surface* foundSurface = nullptr;
+ Vector2D surfaceCoords;
+ PHLLS pFoundLayerSurface;
+ SP<CWLSurfaceResource> 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 +241,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 +289,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 +313,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 +324,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 d60a6dd0..9fa96d2d 100644
--- a/src/desktop/LayerSurface.hpp
+++ b/src/desktop/LayerSurface.hpp
@@ -36,7 +36,7 @@ class CLayerSurface {
bool keyboardExclusive = false;
- CWLSurface surface;
+ SP<CWLSurface> surface;
bool mapped = false;
uint32_t layer = 0;
diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp
index 6bc76fc7..f0fd556c 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 <ranges>
CPopup::CPopup(PHLWINDOW pOwner) : m_pWindowOwner(pOwner) {
@@ -14,7 +15,8 @@ CPopup::CPopup(PHLLS pOwner) : m_pLayerOwner(pOwner) {
}
CPopup::CPopup(SP<CXDGPopupResource> 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<CXDGPopupResource> popup, CPopup* pOwner) : m_pParent(pOwner),
}
CPopup::~CPopup() {
- m_sWLSurface.unassign();
+ if (m_pWLSurface)
+ m_pWLSurface->unassign();
}
void CPopup::initAllSignals() {
@@ -69,14 +72,14 @@ void CPopup::onMap() {
if (m_bMapped)
return;
- m_bMapped = true;
- m_vLastSize = {m_pResource->surface->surface->current.width, m_pResource->surface->surface->current.height};
+ m_bMapped = true;
+ 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());
- box.applyFromWlr().translate(COORDS).expand(4);
+ CBox box = m_pWLSurface->resource()->extends();
+ box.translate(COORDS).expand(4);
g_pHyprRenderer->damageBox(&box);
m_vLastPos = coordsRelativeToParent();
@@ -87,7 +90,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));
@@ -103,12 +106,12 @@ void CPopup::onUnmap() {
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());
- box.applyFromWlr().translate(COORDS).expand(4);
+ CBox box = m_pWLSurface->resource()->extends();
+ box.translate(COORDS).expand(4);
g_pHyprRenderer->damageBox(&box);
m_pSubsurfaceHead.reset();
@@ -143,7 +146,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<Hyprlang::INT>("debug:log_damage");
if (*PLOGDAMAGE)
@@ -157,11 +160,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);
@@ -171,7 +173,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;
@@ -211,7 +213,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;
@@ -260,9 +262,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();
}
@@ -318,9 +320,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 7fdabee6..91e569e7 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<CWLSurface> 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 21482ff7..71ee16f0 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<CWLSubsurfaceResource> 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<CWLSubsurfaceResource> 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,27 @@ 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<SP<CWLSubsurfaceResource>>(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<SP<CWLSubsurfaceResource>>(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<SP<CWLSubsurfaceResource>>(d)); });
else
- RASSERT(false, "CSubsurface::initSignals empty subsurface");
+ ASSERT(false);
}
}
@@ -93,21 +70,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<Hyprlang::INT>("debug:log_damage");
if (*PLOGDAMAGE)
@@ -117,7 +94,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 +104,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,20 +126,21 @@ 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<CWLSubsurfaceResource> pSubsurface) {
CSubsurface* PSUBSURFACE = nullptr;
if (!m_pWindowParent.expired())
PSUBSURFACE = m_vChildren.emplace_back(std::make_unique<CSubsurface>(pSubsurface, m_pWindowParent.lock())).get();
else if (m_pPopupParent)
PSUBSURFACE = m_vChildren.emplace_back(std::make_unique<CSubsurface>(pSubsurface, m_pPopupParent)).get();
- PSUBSURFACE->m_pParent = this;
ASSERT(PSUBSURFACE);
+
+ PSUBSURFACE->m_pParent = this;
}
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<CWLSurfaceResource> pSurface) {
+ for (auto& s : pSurface->subsurfaces) {
+ if (!s || s->surface->hlSurface /* already assigned */)
+ 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 f3a5ea4b..101f4f19 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<CWLSubsurfaceResource> pSubsurface, PHLWINDOW pOwner);
+ CSubsurface(SP<CWLSubsurfaceResource> pSubsurface, CPopup* pOwner);
~CSubsurface();
@@ -25,7 +26,7 @@ class CSubsurface {
void onCommit();
void onDestroy();
- void onNewSubsurface(wlr_subsurface* pSubsurface);
+ void onNewSubsurface(SP<CWLSubsurfaceResource> 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<CWLSubsurfaceResource> m_pSubsurface;
+ SP<CWLSurface> 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<CWLSurfaceResource> pSurface);
void checkSiblingDamage();
}; \ No newline at end of file
diff --git a/src/desktop/WLSurface.cpp b/src/desktop/WLSurface.cpp
index 78b50d45..c7a09b40 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<CWLSurfaceResource> pSurface) {
+ m_pResource = pSurface;
init();
m_bInert = false;
}
-void CWLSurface::assign(wlr_surface* pSurface, PHLWINDOW pOwner) {
+void CWLSurface::assign(SP<CWLSurfaceResource> 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<CWLSurfaceResource> 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<CWLSurfaceResource> 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<CWLSurfaceResource> 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<CWLSurfaceResource> 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->accumulateCurrentBufferDamage();
+ 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.size() * 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<CPointerConstraint> constraint) {
m_pConstraint = constraint;
}
-void CWLSurface::onCommit() {
- ;
-}
-
SP<CPointerConstraint> 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> CWLSurface::fromResource(SP<CWLSurfaceResource> pSurface) {
+ if (!pSurface)
+ return nullptr;
+ return pSurface->hlSurface.lock();
+}
diff --git a/src/desktop/WLSurface.hpp b/src/desktop/WLSurface.hpp
index 03e81b45..4ba381a9 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<CWLSurface> create() {
+ auto p = SP<CWLSurface>(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<CWLSurfaceResource> pSurface);
+ void assign(SP<CWLSurfaceResource> pSurface, PHLWINDOW pOwner);
+ void assign(SP<CWLSurfaceResource> pSurface, PHLLS pOwner);
+ void assign(SP<CWLSurfaceResource> pSurface, CSubsurface* pOwner);
+ void assign(SP<CWLSurfaceResource> 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<CWLSurfaceResource> 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<CWLSurfaceResource> 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<CWLSurfaceResource> 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<CWLSurface> fromResource(SP<CWLSurfaceResource> pSurface);
// used by the alpha-modifier protocol
float m_pAlphaModifier = 1.F;
@@ -88,15 +88,19 @@ class CWLSurface {
CSignal destroy;
} events;
+ WP<CWLSurface> self;
+
private:
- bool m_bInert = true;
+ CWLSurface() = default;
+
+ bool m_bInert = true;
- wlr_surface* m_pWLRSurface = nullptr;
+ WP<CWLSurfaceResource> 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<CPointerConstraint> 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 c478b766..5d6e32e9 100644
--- a/src/desktop/Window.cpp
+++ b/src/desktop/Window.cpp
@@ -9,6 +9,7 @@
#include "../config/ConfigValue.hpp"
#include "../managers/TokenManager.hpp"
#include "../protocols/XDGShell.hpp"
+#include "../protocols/core/Compositor.hpp"
#include "../xwayland/XWayland.hpp"
PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) {
@@ -51,12 +52,14 @@ PHLWINDOW CWindow::create(SP<CXDGSurfaceResource> resource) {
pWindow->addWindowDeco(std::make_unique<CHyprDropShadowDecoration>(pWindow));
pWindow->addWindowDeco(std::make_unique<CHyprBorderDecoration>(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<CXDGSurfaceResource> 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<uint32_t>(d)); });
listeners.unmap = m_pXDGSurface->events.unmap.registerListener([this](std::any d) { Events::listener_unmapWindow(this, nullptr); });
@@ -67,6 +70,8 @@ CWindow::CWindow(SP<CXDGSurfaceResource> resource) : m_pXDGSurface(resource) {
}
CWindow::CWindow(SP<CXWaylandSurface> 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); });
@@ -83,7 +88,7 @@ CWindow::CWindow(SP<CXWaylandSurface> 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();
}
@@ -124,12 +129,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;
@@ -151,11 +156,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;
@@ -340,17 +345,7 @@ 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() {
+void CWindow::updateSurfaceScaleTransformDetails(bool force) {
if (!m_bIsMapped || m_bHidden || g_pCompositor->m_bUnsafeState)
return;
@@ -363,26 +358,25 @@ void CWindow::updateSurfaceScaleTransformDetails() {
if (!PNEWMONITOR)
return;
- if (PNEWMONITOR != PLASTMONITOR) {
- if (PLASTMONITOR && PLASTMONITOR->m_bEnabled)
- wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendLeaveIter, PLASTMONITOR->output);
+ if (PNEWMONITOR != PLASTMONITOR || force) {
+ if (PLASTMONITOR && PLASTMONITOR->m_bEnabled && PNEWMONITOR != PLASTMONITOR)
+ m_pWLSurface->resource()->breadthfirst([PLASTMONITOR](SP<CWLSurfaceResource> s, const Vector2D& offset, 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<CWLSurfaceResource> s, const Vector2D& offset, 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<CWLSurfaceResource> s, const Vector2D& offset, 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) {
@@ -568,6 +562,8 @@ void CWindow::onMap() {
m_vReportedSize = m_vPendingReportedSize;
m_bAnimatingIn = true;
+ updateSurfaceScaleTransformDetails(true);
+
if (m_bIsX11)
return;
@@ -860,7 +856,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() {
@@ -1135,23 +1131,24 @@ 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)
return false;
- if (m_bIsX11 && m_pXWaylandSurface && m_pXWaylandSurface->surface)
- return m_pXWaylandSurface->surface->opaque;
+ if (m_bIsX11 && m_pXWaylandSurface && m_pXWaylandSurface->surface && m_pXWaylandSurface->surface->current.buffer)
+ return m_pXWaylandSurface->surface->current.buffer->opaque;
- if (m_pXDGSurface && m_pXDGSurface->surface->opaque)
- return true;
+ if (!m_pWLSurface->resource() || !m_pWLSurface->resource()->current.buffer)
+ return false;
- 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;
+ return m_pWLSurface->resource()->current.buffer->opaque;
}
float CWindow::rounding() {
@@ -1282,8 +1279,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<CWLSurfaceResource> r, const Vector2D& offset, void* d) { *((int*)d) += 1; }, &no);
return no;
}
@@ -1456,16 +1452,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 151d9809..85c74622 100644
--- a/src/desktop/Window.hpp
+++ b/src/desktop/Window.hpp
@@ -213,7 +213,7 @@ class CWindow {
public:
~CWindow();
- CWLSurface m_pWLSurface;
+ SP<CWLSurface> m_pWLSurface;
struct {
CSignal destroy;
@@ -396,7 +396,7 @@ class CWindow {
IHyprWindowDecoration* getDecorationByType(eDecorationType);
void removeDecorationByType(eDecorationType);
void updateToplevel();
- void updateSurfaceScaleTransformDetails();
+ void updateSurfaceScaleTransformDetails(bool force = false);
void moveToWorkspace(PHLWORKSPACE);
PHLWINDOW X11TransientFor();
void onUnmap();
diff --git a/src/devices/Tablet.cpp b/src/devices/Tablet.cpp
index f5b610a9..b5ab16c1 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> CTablet::create(wlr_tablet* tablet) {
SP<CTablet> pTab = SP<CTablet>(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<CWLSurfaceResource> CTabletTool::getSurface() {
+ return pSurface.lock();
}
-void CTabletTool::setSurface(wlr_surface* surf) {
+void CTabletTool::setSurface(SP<CWLSurfaceResource> 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 f2444972..1805f3ba 100644
--- a/src/devices/Tablet.hpp
+++ b/src/devices/Tablet.hpp
@@ -12,6 +12,7 @@ struct wlr_tablet_pad;
class CTabletTool;
class CTabletPad;
+class CWLSurfaceResource;
/*
A tablet device
@@ -197,32 +198,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<CWLSurfaceResource> getSurface();
+ void setSurface(SP<CWLSurfaceResource>);
- WP<CTabletTool> self;
- Vector2D tilt;
- bool active = false; // true if in proximity
- uint32_t toolCapabilities = 0;
+ WP<CTabletTool> self;
+ Vector2D tilt;
+ bool active = false; // true if in proximity
+ uint32_t toolCapabilities = 0;
- bool isDown = false;
- std::vector<uint32_t> buttonsDown;
- Vector2D absolutePos; // last known absolute position.
+ bool isDown = false;
+ std::vector<uint32_t> 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<CWLSurfaceResource> 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 5372a105..88b28c87 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 (PWINDOW->m_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.buffer) {
+ 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/Format.cpp b/src/helpers/Format.cpp
new file mode 100644
index 00000000..3d6b7cc3
--- /dev/null
+++ b/src/helpers/Format.cpp
@@ -0,0 +1,271 @@
+#include "Format.hpp"
+#include <vector>
+#include "../includes.hpp"
+
+/*
+ DRM formats are LE, while OGL is BE. The two primary formats
+ will be flipped, so we will set flipRB which will later use swizzle
+ to flip the red and blue channels.
+ This will not work on GLES2, but I want to drop support for it one day anyways.
+*/
+inline const std::vector<SPixelFormat> GLES3_FORMATS = {
+ {
+ .drmFormat = DRM_FORMAT_ARGB8888,
+ .flipRB = true,
+ .glFormat = GL_RGBA,
+ .glType = GL_UNSIGNED_BYTE,
+ .withAlpha = true,
+ .alphaStripped = DRM_FORMAT_XRGB8888,
+ .bytesPerBlock = 4,
+ },
+ {
+ .drmFormat = DRM_FORMAT_XRGB8888,
+ .flipRB = true,
+ .glFormat = GL_RGBA,
+ .glType = GL_UNSIGNED_BYTE,
+ .withAlpha = false,
+ .alphaStripped = DRM_FORMAT_XRGB8888,
+ .bytesPerBlock = 4,
+ },
+ {
+ .drmFormat = DRM_FORMAT_XBGR8888,
+ .glFormat = GL_RGBA,
+ .glType = GL_UNSIGNED_BYTE,
+ .withAlpha = false,
+ .alphaStripped = DRM_FORMAT_XBGR8888,
+ .bytesPerBlock = 4,
+ },
+ {
+ .drmFormat = DRM_FORMAT_ABGR8888,
+ .glFormat = GL_RGBA,
+ .glType = GL_UNSIGNED_BYTE,
+ .withAlpha = true,
+ .alphaStripped = DRM_FORMAT_XBGR8888,
+ .bytesPerBlock = 4,
+ },
+ {
+ .drmFormat = DRM_FORMAT_BGR888,
+ .glFormat = GL_RGB,
+ .glType = GL_UNSIGNED_BYTE,
+ .withAlpha = false,
+ .alphaStripped = DRM_FORMAT_BGR888,
+ .bytesPerBlock = 3,
+ },
+ {
+ .drmFormat = DRM_FORMAT_RGBX4444,
+ .glFormat = GL_RGBA,
+ .glType = GL_UNSIGNED_SHORT_4_4_4_4,
+ .withAlpha = false,
+ .alphaStripped = DRM_FORMAT_RGBX4444,
+ .bytesPerBlock = 2,
+ },
+ {
+ .drmFormat = DRM_FORMAT_RGBA4444,
+ .glFormat = GL_RGBA,
+ .glType = GL_UNSIGNED_SHORT_4_4_4_4,
+ .withAlpha = true,
+ .alphaStripped = DRM_FORMAT_RGBX4444,
+ .bytesPerBlock = 2,
+ },
+ {
+ .drmFormat = DRM_FORMAT_RGBX5551,
+ .glFormat = GL_RGBA,
+ .glType = GL_UNSIGNED_SHORT_5_5_5_1,
+ .withAlpha = false,
+ .alphaStripped = DRM_FORMAT_RGBX5551,
+ .bytesPerBlock = 2,
+ },
+ {
+ .drmFormat = DRM_FORMAT_RGBA5551,
+ .glFormat = GL_RGBA,
+ .glType = GL_UNSIGNED_SHORT_5_5_5_1,
+ .withAlpha = true,
+ .alphaStripped = DRM_FORMAT_RGBX5551,
+ .bytesPerBlock = 2,
+ },
+ {
+ .drmFormat = DRM_FORMAT_RGB565,
+ .glFormat = GL_RGB,
+ .glType = GL_UNSIGNED_SHORT_5_6_5,
+ .withAlpha = false,
+ .alphaStripped = DRM_FORMAT_RGB565,
+ .bytesPerBlock = 2,
+ },
+ {
+ .drmFormat = DRM_FORMAT_XBGR2101010,
+ .glFormat = GL_RGBA,
+ .glType = GL_UNSIGNED_INT_2_10_10_10_REV,
+ .withAlpha = false,
+ .alphaStripped = DRM_FORMAT_XBGR2101010,
+ .bytesPerBlock = 4,
+ },
+ {
+ .drmFormat = DRM_FORMAT_ABGR2101010,
+ .glFormat = GL_RGBA,
+ .glType = GL_UNSIGNED_INT_2_10_10_10_REV,
+ .withAlpha = true,
+ .alphaStripped = DRM_FORMAT_XBGR2101010,
+ .bytesPerBlock = 4,
+ },
+ {
+ .drmFormat = DRM_FORMAT_XRGB2101010,
+ .glFormat = GL_RGBA,
+ .glType = GL_UNSIGNED_INT_2_10_10_10_REV,
+ .withAlpha = false,
+ .alphaStripped = DRM_FORMAT_XRGB2101010,
+ .bytesPerBlock = 4,
+ },
+ {
+ .drmFormat = DRM_FORMAT_ARGB2101010,
+ .glFormat = GL_RGBA,
+ .glType = GL_UNSIGNED_INT_2_10_10_10_REV,
+ .withAlpha = true,
+ .alphaStripped = DRM_FORMAT_XRGB2101010,
+ .bytesPerBlock = 4,
+ },
+ {
+ .drmFormat = DRM_FORMAT_XBGR16161616F,
+ .glFormat = GL_RGBA,
+ .glType = GL_HALF_FLOAT,
+ .withAlpha = false,
+ .alphaStripped = DRM_FORMAT_XBGR16161616F,
+ .bytesPerBlock = 8,
+ },
+ {
+ .drmFormat = DRM_FORMAT_ABGR16161616F,
+ .glFormat = GL_RGBA,
+ .glType = GL_HALF_FLOAT,
+ .withAlpha = true,
+ .alphaStripped = DRM_FORMAT_XBGR16161616F,
+ .bytesPerBlock = 8,
+ },
+ {
+ .drmFormat = DRM_FORMAT_XBGR16161616,
+ .glInternalFormat = GL_RGBA16UI,
+ .glFormat = GL_RGBA,
+ .glType = GL_UNSIGNED_SHORT,
+ .withAlpha = false,
+ .alphaStripped = DRM_FORMAT_XBGR16161616,
+ .bytesPerBlock = 8,
+ },
+ {
+ .drmFormat = DRM_FORMAT_ABGR16161616,
+ .glInternalFormat = GL_RGBA16UI,
+ .glFormat = GL_RGBA,
+ .glType = GL_UNSIGNED_SHORT,
+ .withAlpha = true,
+ .alphaStripped = DRM_FORMAT_XBGR16161616,
+ .bytesPerBlock = 8,
+ },
+ {
+ .drmFormat = DRM_FORMAT_YVYU,
+ .bytesPerBlock = 4,
+ .blockSize = {2, 1},
+ },
+ {
+ .drmFormat = DRM_FORMAT_VYUY,
+ .bytesPerBlock = 4,
+ .blockSize = {2, 1},
+ },
+ {
+ .drmFormat = DRM_FORMAT_R8,
+ .bytesPerBlock = 1,
+ },
+ {
+ .drmFormat = DRM_FORMAT_GR88,
+ .bytesPerBlock = 2,
+ },
+ {
+ .drmFormat = DRM_FORMAT_RGB888,
+ .bytesPerBlock = 3,
+ },
+ {
+ .drmFormat = DRM_FORMAT_BGR888,
+ .bytesPerBlock = 3,
+ },
+ {
+ .drmFormat = DRM_FORMAT_RGBX4444,
+ .bytesPerBlock = 2,
+ },
+};
+
+SHMFormat FormatUtils::drmToShm(DRMFormat 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;
+}
+
+DRMFormat FormatUtils::shmToDRM(SHMFormat 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;
+}
+
+const SPixelFormat* FormatUtils::getPixelFormatFromDRM(DRMFormat drm) {
+ for (auto& fmt : GLES3_FORMATS) {
+ if (fmt.drmFormat == drm)
+ return &fmt;
+ }
+
+ return nullptr;
+}
+
+const SPixelFormat* FormatUtils::getPixelFormatFromGL(uint32_t glFormat, uint32_t glType, bool alpha) {
+ for (auto& fmt : GLES3_FORMATS) {
+ if (fmt.glFormat == (int)glFormat && fmt.glType == (int)glType && fmt.withAlpha == alpha)
+ return &fmt;
+ }
+
+ return nullptr;
+}
+
+bool FormatUtils::isFormatOpaque(DRMFormat drm) {
+ const auto FMT = FormatUtils::getPixelFormatFromDRM(drm);
+ if (!FMT)
+ return false;
+
+ return !FMT->withAlpha;
+}
+
+int FormatUtils::pixelsPerBlock(const SPixelFormat* const fmt) {
+ return fmt->blockSize.x * fmt->blockSize.y > 0 ? fmt->blockSize.x * fmt->blockSize.y : 1;
+}
+
+int FormatUtils::minStride(const SPixelFormat* const fmt, int32_t width) {
+ return std::ceil((width * fmt->bytesPerBlock) / pixelsPerBlock(fmt));
+}
+
+uint32_t FormatUtils::drmFormatToGL(DRMFormat drm) {
+ switch (drm) {
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_XBGR8888: return GL_RGBA; // doesn't matter, opengl is gucci in this case.
+ case DRM_FORMAT_XRGB2101010:
+ case DRM_FORMAT_XBGR2101010:
+#ifdef GLES2
+ return GL_RGB10_A2_EXT;
+#else
+ return GL_RGB10_A2;
+#endif
+ default: return GL_RGBA;
+ }
+ UNREACHABLE();
+ return GL_RGBA;
+}
+
+uint32_t FormatUtils::glFormatToType(uint32_t gl) {
+ return gl != GL_RGBA ?
+#ifdef GLES2
+ GL_UNSIGNED_INT_2_10_10_10_REV_EXT :
+#else
+ GL_UNSIGNED_INT_2_10_10_10_REV :
+#endif
+ GL_UNSIGNED_BYTE;
+}
diff --git a/src/helpers/Format.hpp b/src/helpers/Format.hpp
new file mode 100644
index 00000000..b86f44dd
--- /dev/null
+++ b/src/helpers/Format.hpp
@@ -0,0 +1,37 @@
+#pragma once
+
+#include <cstdint>
+#include "Vector2D.hpp"
+
+typedef uint32_t DRMFormat;
+typedef uint32_t SHMFormat;
+
+struct SPixelFormat {
+ DRMFormat drmFormat = 0; /* DRM_FORMAT_INVALID */
+ bool flipRB = false;
+ int glInternalFormat = 0;
+ int glFormat = 0;
+ int glType = 0;
+ bool withAlpha = true;
+ DRMFormat alphaStripped = 0; /* DRM_FORMAT_INVALID */
+ uint32_t bytesPerBlock = 0;
+ Vector2D blockSize;
+};
+
+struct SDRMFormat {
+ uint32_t format = 0;
+ std::vector<uint64_t> mods;
+};
+
+namespace FormatUtils {
+ SHMFormat drmToShm(DRMFormat drm);
+ DRMFormat shmToDRM(SHMFormat shm);
+
+ const SPixelFormat* getPixelFormatFromDRM(DRMFormat drm);
+ const SPixelFormat* getPixelFormatFromGL(uint32_t glFormat, uint32_t glType, bool alpha);
+ bool isFormatOpaque(DRMFormat drm);
+ int pixelsPerBlock(const SPixelFormat* const fmt);
+ int minStride(const SPixelFormat* const fmt, int32_t width);
+ uint32_t drmFormatToGL(DRMFormat drm);
+ uint32_t glFormatToType(uint32_t gl);
+};
diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp
index a520c9d4..32cd9868 100644
--- a/src/helpers/MiscFunctions.cpp
+++ b/src/helpers/MiscFunctions.cpp
@@ -857,33 +857,6 @@ void throwError(const std::string& err) {
throw std::runtime_error(err);
}
-uint32_t drmFormatToGL(uint32_t drm) {
- switch (drm) {
- case DRM_FORMAT_XRGB8888:
- case DRM_FORMAT_XBGR8888: return GL_RGBA; // doesn't matter, opengl is gucci in this case.
- case DRM_FORMAT_XRGB2101010:
- case DRM_FORMAT_XBGR2101010:
-#ifdef GLES2
- return GL_RGB10_A2_EXT;
-#else
- return GL_RGB10_A2;
-#endif
- default: return GL_RGBA;
- }
- UNREACHABLE();
- return GL_RGBA;
-}
-
-uint32_t glFormatToType(uint32_t gl) {
- return gl != GL_RGBA ?
-#ifdef GLES2
- GL_UNSIGNED_INT_2_10_10_10_REV_EXT :
-#else
- GL_UNSIGNED_INT_2_10_10_10_REV :
-#endif
- GL_UNSIGNED_BYTE;
-}
-
bool envEnabled(const std::string& env) {
const auto ENV = getenv(env.c_str());
if (!ENV)
@@ -922,3 +895,42 @@ int allocateSHMFile(size_t len) {
return fd;
}
+
+bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr) {
+ auto [fd, name] = openExclusiveShm();
+ if (fd < 0) {
+ return false;
+ }
+
+ // CLOEXEC is guaranteed to be set by shm_open
+ int ro_fd = shm_open(name.c_str(), O_RDONLY, 0);
+ if (ro_fd < 0) {
+ shm_unlink(name.c_str());
+ close(fd);
+ return false;
+ }
+
+ shm_unlink(name.c_str());
+
+ // Make sure the file cannot be re-opened in read-write mode (e.g. via
+ // "/proc/self/fd/" on Linux)
+ if (fchmod(fd, 0) != 0) {
+ close(fd);
+ close(ro_fd);
+ return false;
+ }
+
+ int ret;
+ do {
+ ret = ftruncate(fd, size);
+ } while (ret < 0 && errno == EINTR);
+ if (ret < 0) {
+ close(fd);
+ close(ro_fd);
+ return false;
+ }
+
+ *rw_fd_ptr = fd;
+ *ro_fd_ptr = ro_fd;
+ return true;
+}
diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp
index 80103eac..9d34174c 100644
--- a/src/helpers/MiscFunctions.hpp
+++ b/src/helpers/MiscFunctions.hpp
@@ -35,10 +35,9 @@ double normalizeAngleRad(double ang);
std::string replaceInString(std::string subject, const std::string& search, const std::string& replace);
std::vector<SCallstackFrameInfo> getBacktrace();
void throwError(const std::string& err);
-uint32_t drmFormatToGL(uint32_t drm);
-uint32_t glFormatToType(uint32_t gl);
bool envEnabled(const std::string& env);
int allocateSHMFile(size_t len);
+bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr);
template <typename... Args>
[[deprecated("use std::format instead")]] std::string getFormat(std::format_string<Args...> fmt, Args&&... args) {
diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp
index d13acf0c..5962b73d 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 e4456084..4bfbf53c 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/Region.cpp b/src/helpers/Region.cpp
index 20eaf452..9e572b34 100644
--- a/src/helpers/Region.cpp
+++ b/src/helpers/Region.cpp
@@ -4,6 +4,8 @@ extern "C" {
#include <wlr/util/region.h>
}
+constexpr const int64_t MAX_REGION_SIDE = 10000000;
+
CRegion::CRegion() {
pixman_region32_init(&m_rRegion);
}
@@ -103,6 +105,11 @@ CRegion& CRegion::transform(const wl_output_transform t, double w, double h) {
return *this;
}
+CRegion& CRegion::rationalize() {
+ intersect(CBox{-MAX_REGION_SIDE, -MAX_REGION_SIDE, MAX_REGION_SIDE * 2, MAX_REGION_SIDE * 2});
+ return *this;
+}
+
CRegion CRegion::copy() const {
return CRegion(*this);
}
diff --git a/src/helpers/Region.hpp b/src/helpers/Region.hpp
index 27f460f4..42693c21 100644
--- a/src/helpers/Region.hpp
+++ b/src/helpers/Region.hpp
@@ -50,6 +50,7 @@ class CRegion {
CRegion& invert(const CBox& box);
CRegion& scale(float scale);
CRegion& scale(const Vector2D& scale);
+ CRegion& rationalize();
CBox getExtents();
bool containsPoint(const Vector2D& vec) const;
bool empty() const;
diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp
index 30f5aebf..d5be9f40 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<CWLSurfaceResource> 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 77f5164a..02900911 100644
--- a/src/helpers/memory/SharedPtr.hpp
+++ b/src/helpers/memory/SharedPtr.hpp
@@ -60,7 +60,7 @@ namespace CSharedPointer_ {
bool _destroying = false;
void _destroy() {
- if (!_data)
+ if (!_data || _destroying)
return;
// first, we destroy the data, but keep the pointer.
@@ -297,6 +297,6 @@ static CSharedPointer<U> makeShared(Args&&... args) {
template <typename T>
struct std::hash<CSharedPointer<T>> {
std::size_t operator()(const CSharedPointer<T>& p) const noexcept {
- return std::hash<void*>{}(p->impl_);
+ return std::hash<void*>{}(p.impl_);
}
};
diff --git a/src/helpers/memory/WeakPtr.hpp b/src/helpers/memory/WeakPtr.hpp
index f0e72146..872f8e55 100644
--- a/src/helpers/memory/WeakPtr.hpp
+++ b/src/helpers/memory/WeakPtr.hpp
@@ -185,6 +185,6 @@ class CWeakPointer {
template <typename T>
struct std::hash<CWeakPointer<T>> {
std::size_t operator()(const CWeakPointer<T>& p) const noexcept {
- return std::hash<void*>{}(p->impl_);
+ return std::hash<void*>{}(p.impl_);
}
};
diff --git a/src/helpers/signal/Signal.cpp b/src/helpers/signal/Signal.cpp
index fdd2cc23..fd2d11c8 100644
--- a/src/helpers/signal/Signal.cpp
+++ b/src/helpers/signal/Signal.cpp
@@ -2,19 +2,40 @@
#include <algorithm>
void CSignal::emit(std::any data) {
- bool dirty = false;
+ bool dirty = false;
+ std::vector<SP<CSignalListener>> listeners;
for (auto& l : m_vListeners) {
- if (const CHyprSignalListener L = l.lock())
- L->emit(data);
- else
+ if (l.expired()) {
dirty = true;
+ continue;
+ }
+
+ listeners.emplace_back(l.lock());
}
+ std::vector<CStaticSignalListener*> statics;
for (auto& l : m_vStaticListeners) {
+ statics.emplace_back(l.get());
+ }
+
+ for (auto& l : listeners) {
+ // if there is only one lock, it means the event is only held by the listeners
+ // vector and was removed during our iteration
+ if (l.strongRef() == 1) {
+ dirty = true;
+ continue;
+ }
l->emit(data);
}
+ for (auto& l : statics) {
+ l->emit(data);
+ }
+
+ // release SPs
+ listeners.clear();
+
if (dirty)
std::erase_if(m_vListeners, [](const auto& other) { return other.expired(); });
}
diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp
index d147a6bb..a325d858 100644
--- a/src/hyprerror/HyprError.cpp
+++ b/src/hyprerror/HyprError.cpp
@@ -22,6 +22,8 @@ CHyprError::CHyprError() {
if (m_fFadeOpacity.isBeingAnimated() || m_bMonitorChanged)
g_pHyprRenderer->damageBox(&m_bDamageBox);
});
+
+ m_pTexture = makeShared<CTexture>();
}
CHyprError::~CHyprError() {
@@ -34,9 +36,8 @@ void CHyprError::queueCreate(std::string message, const CColor& color) {
}
void CHyprError::createQueued() {
- if (m_bIsCreated) {
- m_tTexture.destroyTexture();
- }
+ if (m_bIsCreated)
+ m_pTexture->destroyTexture();
m_fFadeOpacity.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn"));
@@ -136,8 +137,8 @@ void CHyprError::createQueued() {
// copy the data to an OpenGL texture we have
const auto DATA = cairo_image_surface_get_data(CAIROSURFACE);
- m_tTexture.allocate();
- glBindTexture(GL_TEXTURE_2D, m_tTexture.m_iTexID);
+ m_pTexture->allocate();
+ glBindTexture(GL_TEXTURE_2D, m_pTexture->m_iTexID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -170,7 +171,7 @@ void CHyprError::draw() {
if (!m_fFadeOpacity.isBeingAnimated()) {
if (m_fFadeOpacity.value() == 0.f) {
m_bQueuedDestroy = false;
- m_tTexture.destroyTexture();
+ m_pTexture->destroyTexture();
m_bIsCreated = false;
m_szQueued = "";
return;
@@ -193,7 +194,7 @@ void CHyprError::draw() {
m_bMonitorChanged = false;
- g_pHyprOpenGL->renderTexture(m_tTexture, &monbox, m_fFadeOpacity.value(), 0);
+ g_pHyprOpenGL->renderTexture(m_pTexture, &monbox, m_fFadeOpacity.value(), 0);
}
void CHyprError::destroy() {
diff --git a/src/hyprerror/HyprError.hpp b/src/hyprerror/HyprError.hpp
index aaa8bd12..8dbb4521 100644
--- a/src/hyprerror/HyprError.hpp
+++ b/src/hyprerror/HyprError.hpp
@@ -21,7 +21,7 @@ class CHyprError {
CColor m_cQueued;
bool m_bQueuedDestroy = false;
bool m_bIsCreated = false;
- CTexture m_tTexture;
+ SP<CTexture> m_pTexture;
CAnimatedVariable<float> m_fFadeOpacity;
CBox m_bDamageBox = {0, 0, 0, 0};
diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp
index 7fadf188..b4270bb8 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/macros.hpp b/src/macros.hpp
index 66dfe783..4c6d621c 100644
--- a/src/macros.hpp
+++ b/src/macros.hpp
@@ -89,4 +89,14 @@
}
#else
#define UNREACHABLE() std::unreachable();
-#endif \ No newline at end of file
+#endif
+
+#define GLCALL(__CALL__) \
+ { \
+ __CALL__; \
+ auto err = glGetError(); \
+ if (err != GL_NO_ERROR) { \
+ Debug::log(ERR, "[GLES] Error in call at {}@{}: 0x{:x}", __LINE__, \
+ ([]() constexpr -> std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })(), err); \
+ } \
+ }
diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp
index e3ebce80..4430d0f4 100644
--- a/src/managers/CursorManager.cpp
+++ b/src/managers/CursorManager.cpp
@@ -117,8 +117,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<CWLSurface> 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 e76b6829..6fbff636 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<CWLSurface> surf, const Vector2D& hotspot);
void setXCursor(const std::string& name);
bool changeTheme(const std::string& name, const int size);
diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp
index f7009afb..5811f4a1 100644
--- a/src/managers/KeybindManager.cpp
+++ b/src/managers/KeybindManager.cpp
@@ -2003,14 +2003,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);
@@ -2044,10 +2044,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();
}
}
@@ -2057,7 +2057,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) {
@@ -2136,7 +2136,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
@@ -2154,15 +2154,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;
@@ -2195,10 +2195,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 66d12076..80a7ee76 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 <wlr/interfaces/wlr_output.h>
#include <wlr/render/interface.h>
@@ -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<CWLSurface> 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();
@@ -451,7 +449,7 @@ bool CPointerManager::setHWCursorBuffer(SP<SMonitorPointerState> state, wlr_buff
return true;
}
-wlr_buffer* CPointerManager::renderHWCursorBuffer(SP<CPointerManager::SMonitorPointerState> state, wlr_texture* texture) {
+wlr_buffer* CPointerManager::renderHWCursorBuffer(SP<CPointerManager::SMonitorPointerState> state, SP<CTexture> texture) {
auto output = state->monitor->output;
int w = currentCursorImage.size.x, h = currentCursorImage.size.y;
@@ -528,7 +526,7 @@ void CPointerManager::renderSoftwareCursorsFor(SP<CMonitor> 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;
}
@@ -550,7 +548,7 @@ void CPointerManager::renderSoftwareCursorsFor(SP<CMonitor> pMonitor, timespec*
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<CMonitor> 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())))
+SP<CTexture> CPointerManager::getCurrentCursorTexture() {
+ if (!currentCursorImage.pBuffer && (!currentCursorImage.surface || !currentCursorImage.surface->resource()->current.buffer))
return nullptr;
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 = makeShared<CTexture>(currentCursorImage.pBufferTexture);
+ }
+ return currentCursorImage.bufferTex;
}
- return wlr_surface_get_texture(currentCursorImage.surface->wlr());
+ return currentCursorImage.surface->resource()->current.buffer->texture;
}
void CPointerManager::attachPointer(SP<IPointer> pointer) {
diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp
index db9f27e7..b71a79c3 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<IHID> dev);
void setCursorBuffer(wlr_buffer* buf, const Vector2D& hotspot, const float& scale);
- void setCursorSurface(CWLSurface* buf, const Vector2D& hotspot);
+ void setCursorSurface(SP<CWLSurface> buf, const Vector2D& hotspot);
void resetCursorImage(bool apply = true);
void lockSoftwareForMonitor(SP<CMonitor> pMonitor);
@@ -76,7 +77,7 @@ class CPointerManager {
Vector2D transformedHotspot(SP<CMonitor> pMonitor);
- wlr_texture* getCurrentCursorTexture();
+ SP<CTexture> getCurrentCursorTexture();
struct SPointerListener {
CHyprSignalListener destroy;
@@ -129,8 +130,9 @@ class CPointerManager {
} currentMonitorLayout;
struct {
- wlr_buffer* pBuffer = nullptr;
- CWLSurface* surface = nullptr;
+ wlr_buffer* pBuffer = nullptr;
+ SP<CTexture> bufferTex;
+ WP<CWLSurface> 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
@@ -165,7 +167,7 @@ class CPointerManager {
std::vector<SP<SMonitorPointerState>> monitorStates;
SP<SMonitorPointerState> stateFor(SP<CMonitor> mon);
bool attemptHardwareCursor(SP<SMonitorPointerState> state);
- wlr_buffer* renderHWCursorBuffer(SP<SMonitorPointerState> state, wlr_texture* texture);
+ wlr_buffer* renderHWCursorBuffer(SP<SMonitorPointerState> state, SP<CTexture> texture);
bool setHWCursorBuffer(SP<SMonitorPointerState> state, wlr_buffer* buf);
struct {
diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp
index feff69e0..bd435b27 100644
--- a/src/managers/ProtocolManager.cpp
+++ b/src/managers/ProtocolManager.cpp
@@ -32,17 +32,45 @@
#include "../protocols/DataDeviceWlr.hpp"
#include "../protocols/PrimarySelection.hpp"
#include "../protocols/XWaylandShell.hpp"
+#include "../protocols/Viewporter.hpp"
+#include "../protocols/MesaDRM.hpp"
+#include "../protocols/LinuxDMABUF.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"
+
+#include "../helpers/Monitor.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<CMonitor*>(param);
+ if (PROTO::outputs.contains(M->szName))
+ PROTO::outputs.erase(M->szName);
+ PROTO::outputs.emplace(M->szName, std::make_unique<CWLOutputProtocol>(&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<CMonitor*>(param);
+ if (!PROTO::outputs.contains(M->szName))
+ return;
+ PROTO::outputs.at(M->szName)->remove();
+ });
+
// Core
- PROTO::seat = std::make_unique<CWLSeatProtocol>(&wl_seat_interface, 9, "WLSeat");
- PROTO::data = std::make_unique<CWLDataDeviceProtocol>(&wl_data_device_manager_interface, 3, "WLDataDevice");
+ PROTO::seat = std::make_unique<CWLSeatProtocol>(&wl_seat_interface, 9, "WLSeat");
+ PROTO::data = std::make_unique<CWLDataDeviceProtocol>(&wl_data_device_manager_interface, 3, "WLDataDevice");
+ PROTO::compositor = std::make_unique<CWLCompositorProtocol>(&wl_compositor_interface, 6, "WLCompositor");
+ PROTO::subcompositor = std::make_unique<CWLSubcompositorProtocol>(&wl_subcompositor_interface, 1, "WLSubcompositor");
+ PROTO::shm = std::make_unique<CWLSHMProtocol>(&wl_shm_interface, 1, "WLSHM");
// Extensions
+ PROTO::viewport = std::make_unique<CViewporterProtocol>(&wp_viewporter_interface, 1, "Viewporter");
PROTO::tearing = std::make_unique<CTearingControlProtocol>(&wp_tearing_control_manager_v1_interface, 1, "TearingControl");
PROTO::fractional = std::make_unique<CFractionalScaleProtocol>(&wp_fractional_scale_manager_v1_interface, 1, "FractionalScale");
PROTO::xdgOutput = std::make_unique<CXDGOutputProtocol>(&zxdg_output_manager_v1_interface, 3, "XDGOutput");
@@ -75,6 +103,8 @@ CProtocolManager::CProtocolManager() {
PROTO::dataWlr = std::make_unique<CDataDeviceWLRProtocol>(&zwlr_data_control_manager_v1_interface, 2, "DataDeviceWlr");
PROTO::primarySelection = std::make_unique<CPrimarySelectionProtocol>(&zwp_primary_selection_device_manager_v1_interface, 1, "PrimarySelection");
PROTO::xwaylandShell = std::make_unique<CXWaylandShellProtocol>(&xwayland_shell_v1_interface, 1, "XWaylandShell");
+ PROTO::mesaDRM = std::make_unique<CMesaDRMProtocol>(&wl_drm_interface, 2, "MesaDRM");
+ PROTO::linuxDma = std::make_unique<CLinuxDMABufV1Protocol>(&zwp_linux_dmabuf_v1_interface, 5, "LinuxDMABUF");
// Old protocol implementations.
// TODO: rewrite them to use hyprwayland-scanner.
diff --git a/src/managers/SeatManager.cpp b/src/managers/SeatManager.cpp
index 7899386b..399ef419 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 <algorithm>
@@ -98,7 +99,7 @@ void CSeatManager::updateActiveKeyboardData() {
PROTO::seat->updateKeymap();
}
-void CSeatManager::setKeyboardFocus(wlr_surface* surf) {
+void CSeatManager::setKeyboardFocus(SP<CWLSurfaceResource> 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) {
auto client = state.keyboardFocusResource->client();
@@ -132,7 +133,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;
@@ -147,8 +148,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();
}
@@ -187,7 +187,7 @@ void CSeatManager::sendKeyboardMods(uint32_t depressed, uint32_t latched, uint32
}
}
-void CSeatManager::setPointerFocus(wlr_surface* surf, const Vector2D& local) {
+void CSeatManager::setPointerFocus(SP<CWLSurfaceResource> surf, const Vector2D& local) {
if (state.pointerFocus == surf)
return;
@@ -196,7 +196,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();
@@ -224,7 +224,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;
@@ -243,8 +243,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();
}
@@ -340,11 +339,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<CWLSurfaceResource> 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();
@@ -369,7 +368,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;
@@ -383,8 +382,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();
}
@@ -486,7 +484,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;
@@ -498,13 +496,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<CWLSurfaceResource> surf = seatGrab->surfs.at(0).lock();
if (seatGrab->keyboard)
setKeyboardFocus(surf);
if (seatGrab->pointer)
@@ -512,7 +510,7 @@ void CSeatManager::refocusGrab() {
}
}
-void CSeatManager::onSetCursor(SP<CWLSeatResource> seatResource, uint32_t serial, wlr_surface* surf, const Vector2D& hotspot) {
+void CSeatManager::onSetCursor(SP<CWLSeatResource> seatResource, uint32_t serial, SP<CWLSurfaceResource> 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;
@@ -599,10 +597,10 @@ void CSeatManager::setGrab(SP<CSeatGrab> grab) {
}
void CSeatManager::resendEnterEvents() {
- wlr_surface* kb = state.keyboardFocus;
- wlr_surface* pt = state.pointerFocus;
+ SP<CWLSurfaceResource> kb = state.keyboardFocus.lock();
+ SP<CWLSurfaceResource> pt = state.pointerFocus.lock();
- auto last = lastLocalCoords;
+ auto last = lastLocalCoords;
setKeyboardFocus(nullptr);
setPointerFocus(nullptr, {});
@@ -611,15 +609,15 @@ void CSeatManager::resendEnterEvents() {
setPointerFocus(pt, last);
}
-bool CSeatGrab::accepts(wlr_surface* surf) {
+bool CSeatGrab::accepts(SP<CWLSurfaceResource> surf) {
return std::find(surfs.begin(), surfs.end(), surf) != surfs.end();
}
-void CSeatGrab::add(wlr_surface* surf) {
+void CSeatGrab::add(SP<CWLSurfaceResource> surf) {
surfs.push_back(surf);
}
-void CSeatGrab::remove(wlr_surface* surf) {
+void CSeatGrab::remove(SP<CWLSurfaceResource> 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 35456cb3..e74d9ace 100644
--- a/src/managers/SeatManager.hpp
+++ b/src/managers/SeatManager.hpp
@@ -11,7 +11,7 @@
constexpr size_t MAX_SERIAL_STORE_LEN = 100;
-struct wlr_surface;
+class CWLSurfaceResource;
class CWLSeatResource;
class IPointer;
class IKeyboard;
@@ -29,9 +29,9 @@ class IKeyboard;
*/
class CSeatGrab {
public:
- bool accepts(wlr_surface* surf);
- void add(wlr_surface* surf);
- void remove(wlr_surface* surf);
+ bool accepts(SP<CWLSurfaceResource> surf);
+ void add(SP<CWLSurfaceResource> surf);
+ void remove(SP<CWLSurfaceResource> surf);
void setCallback(std::function<void()> onEnd_);
void clear();
@@ -42,8 +42,8 @@ class CSeatGrab {
bool removeOnInput = true; // on hard input e.g. click outside, remove
private:
- std::vector<wlr_surface*> surfs; // read-only
- std::function<void()> onEnd;
+ std::vector<WP<CWLSurfaceResource>> surfs;
+ std::function<void()> onEnd;
friend class CSeatManager;
};
@@ -57,11 +57,11 @@ class CSeatManager {
void setKeyboard(SP<IKeyboard> keeb);
void updateActiveKeyboardData(); // updates the clients with the keymap and repeat info
- void setKeyboardFocus(wlr_surface* surf);
+ void setKeyboardFocus(SP<CWLSurfaceResource> 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<CWLSurfaceResource> 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();
@@ -69,7 +69,7 @@ class CSeatManager {
void sendPointerAxis(uint32_t timeMs, wl_pointer_axis axis, double value, int32_t discrete, int32_t value120, 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<CWLSurfaceResource> 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();
@@ -83,24 +83,24 @@ class CSeatManager {
// pops the serial if it was valid, meaning it is consumed.
bool serialValid(SP<CWLSeatResource> seatResource, uint32_t serial);
- void onSetCursor(SP<CWLSeatResource> seatResource, uint32_t serial, wlr_surface* surf, const Vector2D& hotspot);
+ void onSetCursor(SP<CWLSeatResource> seatResource, uint32_t serial, SP<CWLSurfaceResource> surf, const Vector2D& hotspot);
SP<CWLSeatResource> seatResourceForClient(wl_client* client);
struct {
- wlr_surface* keyboardFocus = nullptr;
- WP<CWLSeatResource> keyboardFocusResource;
+ WP<CWLSurfaceResource> keyboardFocus;
+ WP<CWLSeatResource> keyboardFocusResource;
- wlr_surface* pointerFocus = nullptr;
- WP<CWLSeatResource> pointerFocusResource;
+ WP<CWLSurfaceResource> pointerFocus;
+ WP<CWLSeatResource> pointerFocusResource;
- wlr_surface* touchFocus = nullptr;
- WP<CWLSeatResource> touchFocusResource;
+ WP<CWLSurfaceResource> touchFocus;
+ WP<CWLSeatResource> touchFocusResource;
} state;
struct SSetCursorEvent {
- wlr_surface* surf = nullptr;
- Vector2D hotspot;
+ SP<CWLSurfaceResource> surf = nullptr;
+ Vector2D hotspot;
};
struct {
@@ -149,14 +149,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 fd4841f4..3bec1c4b 100644
--- a/src/managers/SessionLockManager.cpp
+++ b/src/managers/SessionLockManager.cpp
@@ -20,7 +20,7 @@ SSessionLockSurface::SSessionLockSurface(SP<CSessionLockSurface> 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<CSessionLock> 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<CWLSurfaceResource> 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 d655a2bc..ea1b2029 100644
--- a/src/managers/SessionLockManager.hpp
+++ b/src/managers/SessionLockManager.hpp
@@ -8,13 +8,14 @@
class CSessionLockSurface;
class CSessionLock;
+class CWLSurfaceResource;
struct SSessionLockSurface {
SSessionLockSurface(SP<CSessionLockSurface> surface_);
WP<CSessionLockSurface> surface;
- wlr_surface* pWlrSurface = nullptr;
- uint64_t iMonitorID = -1;
+ WP<CWLSurfaceResource> pWlrSurface;
+ uint64_t iMonitorID = -1;
bool mapped = false;
@@ -49,7 +50,7 @@ class CSessionLockManager {
bool isSessionLocked();
bool isSessionLockPresent();
- bool isSurfaceSessionLock(wlr_surface*);
+ bool isSurfaceSessionLock(SP<CWLSurfaceResource>);
void removeSessionLockSurface(SSessionLockSurface*);
diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp
index 4aebefcb..12387900 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<CWLSurfaceResource> CHyprXWaylandManager::getWindowSurface(PHLWINDOW pWindow) {
+ return pWindow->m_pWLSurface->resource();
}
-void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate) {
+void CHyprXWaylandManager::activateSurface(SP<CWLSurfaceResource> 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,10 +132,6 @@ 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);
-}
-
bool CHyprXWaylandManager::shouldBeFloated(PHLWINDOW pWindow, bool pending) {
if (pWindow->m_bIsX11) {
for (auto& a : pWindow->m_pXWaylandSurface->atoms)
diff --git a/src/managers/XWaylandManager.hpp b/src/managers/XWaylandManager.hpp
index 5bbab802..a9f95974 100644
--- a/src/managers/XWaylandManager.hpp
+++ b/src/managers/XWaylandManager.hpp
@@ -5,25 +5,25 @@
class CWindow; // because clangd
typedef SP<CWindow> PHLWINDOW;
+class CWLSurfaceResource;
class CHyprXWaylandManager {
public:
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<CWLSurfaceResource> getWindowSurface(PHLWINDOW);
+ void activateSurface(SP<CWLSurfaceResource>, bool);
+ void activateWindow(PHLWINDOW, bool);
+ void getGeometryForWindow(PHLWINDOW, CBox*);
+ void sendCloseWindow(PHLWINDOW);
+ void setWindowSize(PHLWINDOW, Vector2D, bool force = false);
+ void setWindowFullscreen(PHLWINDOW, bool);
+ bool shouldBeFloated(PHLWINDOW, bool pending = false);
+ void checkBorders(PHLWINDOW);
+ Vector2D getMaxSizeForWindow(PHLWINDOW);
+ Vector2D getMinSizeForWindow(PHLWINDOW);
+ Vector2D xwaylandToWaylandCoords(const Vector2D&);
};
inline std::unique_ptr<CHyprXWaylandManager> g_pXWaylandManager; \ No newline at end of file
diff --git a/src/managers/input/IdleInhibitor.cpp b/src/managers/input/IdleInhibitor.cpp
index a71059e4..a38acdbf 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 27d04699..c12ac389 100644
--- a/src/managers/input/InputManager.cpp
+++ b/src/managers/input/InputManager.cpp
@@ -43,7 +43,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;
@@ -58,6 +58,8 @@ CInputManager::CInputManager() {
m_sListeners.newVirtualMouse =
PROTO::virtualPointer->events.newPointer.registerListener([this](std::any data) { this->newVirtualMouse(std::any_cast<SP<CVirtualPointerV1Resource>>(data)); });
m_sListeners.setCursor = g_pSeatManager->events.setCursor.registerListener([this](std::any d) { this->processMouseRequest(d); });
+
+ m_sCursorSurfaceInfo.wlSurface = CWLSurface::create();
}
CInputManager::~CInputManager() {
@@ -115,8 +117,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);
@@ -125,7 +127,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) {
@@ -141,14 +143,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<CWLSurfaceResource> 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;
@@ -191,12 +193,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) {
@@ -223,7 +225,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.
@@ -233,7 +235,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();
@@ -275,7 +277,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();
}
}
@@ -306,7 +308,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();
}
}
@@ -345,7 +347,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();
}
}
@@ -369,9 +371,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();
@@ -423,7 +425,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;
@@ -441,7 +443,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");
@@ -555,11 +557,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) {
@@ -573,7 +575,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() {
@@ -586,8 +588,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);
}
@@ -696,7 +698,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);
@@ -1399,7 +1401,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 f7d9ae57..9fdf061c 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<CWLSurfaceResource> 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<IKeyboard>);
// this will be set after a refocus()
- wlr_surface* m_pFoundSurfaceToFocus = nullptr;
- PHLLSREF m_pFoundLSToFocus;
- PHLWINDOWREF m_pFoundWindowToFocus;
+ WP<CWLSurfaceResource> 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<CWLSurface> 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 9ff584e6..a8757030 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<CInputMethodPopupV2> 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<CWLSurface> 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<CWLSurfaceResource> CInputPopup::getSurface() {
+ return surface->resource();
}
diff --git a/src/managers/input/InputMethodPopup.hpp b/src/managers/input/InputMethodPopup.hpp
index 61b45d74..9c5491bf 100644
--- a/src/managers/input/InputMethodPopup.hpp
+++ b/src/managers/input/InputMethodPopup.hpp
@@ -12,18 +12,18 @@ class CInputPopup {
public:
CInputPopup(SP<CInputMethodPopupV2> 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<CWLSurfaceResource> getSurface();
- void onCommit();
+ void onCommit();
private:
- CWLSurface* queryOwner();
+ SP<CWLSurface> queryOwner();
void updateBox();
void onDestroy();
@@ -31,7 +31,7 @@ class CInputPopup {
void onUnmap();
WP<CInputMethodPopupV2> popup;
- CWLSurface surface;
+ SP<CWLSurface> surface;
CBox lastBoxLocal;
uint64_t lastMonitor = -1;
diff --git a/src/managers/input/InputMethodRelay.cpp b/src/managers/input/InputMethodRelay.cpp
index abf18fba..92ab14d8 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<wlr_surface*>(param)); });
+ static auto P =
+ g_pHookSystem->hookDynamic("keyboardFocus", [&](void* self, SCallbackInfo& info, std::any param) { onKeyboardFocus(std::any_cast<SP<CWLSurfaceResource>>(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<SP<CInputMethodV2>>(ime)); });
@@ -54,17 +56,17 @@ void CInputMethodRelay::onNewIME(SP<CInputMethodV2> 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<CWLSurfaceResource> 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<CWLSurfaceResource> 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<CWLSurfaceResource> 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 2896e8e8..e942add8 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<CWLSurfaceResource>);
CTextInput* getFocusedTextInput();
- void setIMEPopupFocus(CInputPopup*, wlr_surface*);
+ void setIMEPopupFocus(CInputPopup*, SP<CWLSurfaceResource>);
void removePopup(CInputPopup*);
CInputPopup* popupFromCoords(const Vector2D& point);
- CInputPopup* popupFromSurface(const wlr_surface* surface);
+ CInputPopup* popupFromSurface(const SP<CWLSurfaceResource> surface);
void updateAllPopups();
@@ -44,7 +44,7 @@ class CInputMethodRelay {
std::vector<std::unique_ptr<CTextInput>> m_vTextInputs;
std::vector<std::unique_ptr<CInputPopup>> m_vIMEPopups;
- wlr_surface* m_pLastKbFocus = nullptr;
+ WP<CWLSurfaceResource> 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 56e817ec..f1157e4b 100644
--- a/src/managers/input/Tablets.cpp
+++ b/src/managers/input/Tablets.cpp
@@ -20,7 +20,7 @@ static void unfocusTool(SP<CTabletTool> tool) {
PROTO::tablet->proximityOut(tool);
}
-static void focusTool(SP<CTabletTool> tool, SP<CTablet> tablet, wlr_surface* surf) {
+static void focusTool(SP<CTabletTool> tool, SP<CTablet> tablet, SP<CWLSurfaceResource> surf) {
if (tool->getSurface() == surf || !surf)
return;
@@ -37,7 +37,7 @@ static void focusTool(SP<CTabletTool> tool, SP<CTablet> tablet, wlr_surface* sur
}
static void refocusTablet(SP<CTablet> tab, SP<CTabletTool> 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<CTablet> tab, SP<CTabletTool> 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 b3f0b0cb..4c7ffe6e 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<CWLSurfaceResource> 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<CWLSurfaceResource> 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<CWLSurfaceResource> 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<CWLSurfaceResource> 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<CWLSurfaceResource> CTextInput::focusedSurface() {
+ return pFocusedSurface.lock();
}
wl_client* CTextInput::client() {
diff --git a/src/managers/input/TextInput.hpp b/src/managers/input/TextInput.hpp
index ff21da95..30fbb4cc 100644
--- a/src/managers/input/TextInput.hpp
+++ b/src/managers/input/TextInput.hpp
@@ -6,12 +6,12 @@
#include "../../helpers/signal/Listener.hpp"
#include <memory>
-struct wlr_surface;
struct wl_client;
struct STextInputV1;
class CTextInputV3;
class CInputMethodV2;
+class CWLSurfaceResource;
class CTextInput {
public:
@@ -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<CInputMethodV2> ime);
- void updateIMEState(SP<CInputMethodV2> ime);
+ bool isV3();
+ void enter(SP<CWLSurfaceResource> pSurface);
+ void leave();
+ void tiV1Destroyed();
+ wl_client* client();
+ void commitStateToIME(SP<CInputMethodV2> ime);
+ void updateIMEState(SP<CInputMethodV2> ime);
- void onEnabled(wlr_surface* surfV1 = nullptr);
- void onDisabled();
- void onCommit();
+ void onEnabled(SP<CWLSurfaceResource> surfV1 = nullptr);
+ void onDisabled();
+ void onCommit();
- bool hasCursorRectangle();
- CBox cursorBox();
+ bool hasCursorRectangle();
+ CBox cursorBox();
- wlr_surface* focusedSurface();
+ SP<CWLSurfaceResource> focusedSurface();
private:
- void setFocusedSurface(wlr_surface* pSurface);
- void initCallbacks();
+ void setFocusedSurface(SP<CWLSurfaceResource> pSurface);
+ void initCallbacks();
- wlr_surface* pFocusedSurface = nullptr;
- int enterLocks = 0;
- WP<CTextInputV3> pV3Input;
- STextInputV1* pV1Input = nullptr;
+ WP<CWLSurfaceResource> pFocusedSurface;
+ int enterLocks = 0;
+ WP<CTextInputV3> 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 7748813b..a1f949c2 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 b9b99f69..04dcd0a8 100644
--- a/src/protocols/AlphaModifier.cpp
+++ b/src/protocols/AlphaModifier.cpp
@@ -2,10 +2,11 @@
#include <algorithm>
#include "../desktop/WLSurface.hpp"
#include "../render/Renderer.hpp"
+#include "core/Compositor.hpp"
#define LOGM PROTO::alphaModifier->protoLog
-CAlphaModifier::CAlphaModifier(SP<CWpAlphaModifierSurfaceV1> resource_, wlr_surface* surface_) : resource(resource_), pSurface(surface_) {
+CAlphaModifier::CAlphaModifier(SP<CWpAlphaModifierSurfaceV1> resource_, SP<CWLSurfaceResource> surface_) : resource(resource_), pSurface(surface_) {
if (!resource->resource())
return;
@@ -18,8 +19,7 @@ CAlphaModifier::CAlphaModifier(SP<CWpAlphaModifierSurfaceV1> 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<CWpAlphaModifierSurfaceV1> resource_, wlr_surf
}
CAlphaModifier::~CAlphaModifier() {
- hyprListener_surfaceDestroy.removeCallback();
+ ;
}
bool CAlphaModifier::good() {
return resource->resource();
}
-wlr_surface* CAlphaModifier::getSurface() {
- return pSurface;
+SP<CWLSurfaceResource> 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<CWLSurfaceResource> 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 457d1b4c..d49d1e4e 100644
--- a/src/protocols/AlphaModifier.hpp
+++ b/src/protocols/AlphaModifier.hpp
@@ -5,23 +5,28 @@
#include <unordered_map>
#include "WaylandProtocol.hpp"
#include "alpha-modifier-v1.hpp"
+#include "../helpers/signal/Listener.hpp"
+
+class CWLSurfaceResource;
class CAlphaModifier {
public:
- CAlphaModifier(SP<CWpAlphaModifierSurfaceV1> resource_, wlr_surface* surface);
+ CAlphaModifier(SP<CWpAlphaModifierSurfaceV1> resource_, SP<CWLSurfaceResource> surface);
~CAlphaModifier();
- bool good();
- wlr_surface* getSurface();
- void onSurfaceDestroy();
+ bool good();
+ SP<CWLSurfaceResource> getSurface();
+ void onSurfaceDestroy();
private:
SP<CWpAlphaModifierSurfaceV1> resource;
- wlr_surface* pSurface = nullptr;
+ WP<CWLSurfaceResource> pSurface;
void setSurfaceAlpha(float a);
- DYNLISTENER(surfaceDestroy);
+ struct {
+ CHyprSignalListener destroySurface;
+ } listeners;
};
class CAlphaModifierProtocol : public IWaylandProtocol {
@@ -33,15 +38,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<CWLSurfaceResource> surface);
//
- std::vector<UP<CWpAlphaModifierV1>> m_vManagers;
- std::unordered_map<wlr_surface*, UP<CAlphaModifier>> m_mAlphaModifiers; // xdg_toplevel -> deco
+ std::vector<UP<CWpAlphaModifierV1>> m_vManagers;
+ std::unordered_map<WP<CWLSurfaceResource>, UP<CAlphaModifier>> m_mAlphaModifiers; // xdg_toplevel -> deco
friend class CAlphaModifier;
};
namespace PROTO {
inline UP<CAlphaModifierProtocol> alphaModifier;
-}; \ No newline at end of file
+};
diff --git a/src/protocols/FocusGrab.cpp b/src/protocols/FocusGrab.cpp
index 5f0771e0..40f9af44 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 <hyprland-focus-grab-v1.hpp>
#include "../managers/input/InputManager.hpp"
#include "../managers/SeatManager.hpp"
+#include "core/Compositor.hpp"
#include <cstdint>
#include <memory>
#include <wayland-server.h>
#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<CWLSurfaceResource> surface) {
+ listeners.destroy = surface->events.destroy.registerListener([=](std::any d) { grab->eraseSurface(surface); });
}
CFocusGrabSurfaceState::~CFocusGrabSurfaceState() {
- hyprListener_surfaceDestroy.removeCallback();
+ ;
}
CFocusGrab::CFocusGrab(SP<CHyprlandFocusGrabV1> resource_) : resource(resource_) {
@@ -29,8 +29,8 @@ CFocusGrab::CFocusGrab(SP<CHyprlandFocusGrabV1> 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<CWLSurfaceResource> 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<CWLSurfaceResource> 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<CFocusGrabSurfaceState>(this, surface));
}
}
-void CFocusGrab::removeSurface(wlr_surface* surface) {
+void CFocusGrab::removeSurface(SP<CWLSurfaceResource> 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<CWLSurfaceResource> 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<CWLSurfaceResource> 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 40922c22..80166f9f 100644
--- a/src/protocols/FocusGrab.hpp
+++ b/src/protocols/FocusGrab.hpp
@@ -6,13 +6,15 @@
#include <cstdint>
#include <unordered_map>
#include <vector>
+#include "../helpers/signal/Listener.hpp"
class CFocusGrab;
class CSeatGrab;
+class CWLSurfaceResource;
class CFocusGrabSurfaceState {
public:
- CFocusGrabSurfaceState(CFocusGrab* grab, wlr_surface* surface);
+ CFocusGrabSurfaceState(CFocusGrab* grab, SP<CWLSurfaceResource> surface);
~CFocusGrabSurfaceState();
enum State {
@@ -22,7 +24,9 @@ class CFocusGrabSurfaceState {
} state = PendingAddition;
private:
- DYNLISTENER(surfaceDestroy);
+ struct {
+ CHyprSignalListener destroy;
+ } listeners;
};
class CFocusGrab {
@@ -31,23 +35,23 @@ class CFocusGrab {
~CFocusGrab();
bool good();
- bool isSurfaceComitted(wlr_surface* surface);
+ bool isSurfaceComitted(SP<CWLSurfaceResource> 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<CWLSurfaceResource> surface);
+ void removeSurface(SP<CWLSurfaceResource> surface);
+ void eraseSurface(SP<CWLSurfaceResource> surface);
+ void refocusKeyboard();
+ void commit(bool removeOnly = false);
- SP<CHyprlandFocusGrabV1> resource;
- std::unordered_map<wlr_surface*, UP<CFocusGrabSurfaceState>> m_mSurfaces;
- SP<CSeatGrab> grab;
+ SP<CHyprlandFocusGrabV1> resource;
+ std::unordered_map<WP<CWLSurfaceResource>, UP<CFocusGrabSurfaceState>> m_mSurfaces;
+ SP<CSeatGrab> 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 691ab697..6d225e99 100644
--- a/src/protocols/FractionalScale.cpp
+++ b/src/protocols/FractionalScale.cpp
@@ -1,13 +1,9 @@
#include "FractionalScale.hpp"
+#include <algorithm>
+#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<CWLSurfaceResource> 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<CWLSurfaceResource> 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<CWpFractionalScaleV1> resource_, wlr_surface* surf_) : resource(resource_), surface(surf_) {
+CFractionalScaleAddon::CFractionalScaleAddon(SP<CWpFractionalScaleV1> resource_, SP<CWLSurfaceResource> 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<CWLSurfaceResource> CFractionalScaleAddon::surf() {
+ return surface.lock();
} \ No newline at end of file
diff --git a/src/protocols/FractionalScale.hpp b/src/protocols/FractionalScale.hpp
index 10ebf49a..f6d1f96f 100644
--- a/src/protocols/FractionalScale.hpp
+++ b/src/protocols/FractionalScale.hpp
@@ -6,19 +6,20 @@
#include "fractional-scale-v1.hpp"
class CFractionalScaleProtocol;
+class CWLSurfaceResource;
class CFractionalScaleAddon {
public:
- CFractionalScaleAddon(SP<CWpFractionalScaleV1> resource_, wlr_surface* surf_);
+ CFractionalScaleAddon(SP<CWpFractionalScaleV1> resource_, SP<CWLSurfaceResource> surf_);
- void setScale(const float& scale);
- void onSurfaceDestroy();
+ void setScale(const float& scale);
+ void onSurfaceDestroy();
- bool good();
+ bool good();
- wlr_surface* surf();
+ SP<CWLSurfaceResource> surf();
- bool operator==(const wl_resource* other) const {
+ bool operator==(const wl_resource* other) const {
return other == resource->resource();
}
@@ -28,42 +29,36 @@ class CFractionalScaleAddon {
private:
SP<CWpFractionalScaleV1> resource;
- float scale = 1.F;
- wlr_surface* surface = nullptr;
+ float scale = 1.F;
+ WP<CWLSurfaceResource> 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<CWLSurfaceResource> surf);
+ void sendScale(SP<CWLSurfaceResource> 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<CWLSurfaceResource> surface);
//
- std::unordered_map<wlr_surface*, SSurfaceListener> m_mSurfaceDestroyListeners;
- std::unordered_map<wlr_surface*, float> m_mSurfaceScales;
- std::unordered_map<wlr_surface*, UP<CFractionalScaleAddon>> m_mAddons;
- std::vector<UP<CWpFractionalScaleManagerV1>> m_vManagers;
+ std::unordered_map<WP<CWLSurfaceResource>, float> m_mSurfaceScales;
+ std::unordered_map<WP<CWLSurfaceResource>, UP<CFractionalScaleAddon>> m_mAddons;
+ std::vector<UP<CWpFractionalScaleManagerV1>> m_vManagers;
friend class CFractionalScaleAddon;
};
namespace PROTO {
inline UP<CFractionalScaleProtocol> fractional;
-}; \ No newline at end of file
+};
diff --git a/src/protocols/GammaControl.cpp b/src/protocols/GammaControl.cpp
index c8db7100..7c3b39ce 100644
--- a/src/protocols/GammaControl.cpp
+++ b/src/protocols/GammaControl.cpp
@@ -3,6 +3,7 @@
#include <unistd.h>
#include "../helpers/Monitor.hpp"
#include "../Compositor.hpp"
+#include "../protocols/core/Output.hpp"
#define LOGM PROTO::gamma->protoLog
@@ -10,15 +11,15 @@ CGammaControl::CGammaControl(SP<CZwlrGammaControlV1> 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<CZwlrGammaControlV1> 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 0ff11a56..89eb3108 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<CIdleInhibitorResource> resource_, wlr_surface* surf_) : resource(resource_), surface(surf_) {
+CIdleInhibitor::CIdleInhibitor(SP<CIdleInhibitorResource> resource_, SP<CWLSurfaceResource> surf_) : resource(resource_), surface(surf_) {
;
}
-CIdleInhibitorResource::CIdleInhibitorResource(SP<CZwpIdleInhibitorV1> 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<CZwpIdleInhibitorV1> resource_, SP<CWLSurfaceResource> 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<CWLSurfaceResource> surface) {
const auto CLIENT = pMgr->client();
const auto RESOURCE = m_vInhibitors.emplace_back(makeShared<CIdleInhibitorResource>(makeShared<CZwpIdleInhibitorV1>(CLIENT, pMgr->version(), id), surface));
diff --git a/src/protocols/IdleInhibit.hpp b/src/protocols/IdleInhibit.hpp
index b59e8789..3cbfd78d 100644
--- a/src/protocols/IdleInhibit.hpp
+++ b/src/protocols/IdleInhibit.hpp
@@ -7,22 +7,23 @@
#include "../helpers/signal/Signal.hpp"
class CIdleInhibitorResource;
+class CWLSurfaceResource;
class CIdleInhibitor {
public:
- CIdleInhibitor(SP<CIdleInhibitorResource> resource_, wlr_surface* surf_);
+ CIdleInhibitor(SP<CIdleInhibitorResource> resource_, SP<CWLSurfaceResource> surf_);
struct {
CHyprSignalListener destroy;
} listeners;
WP<CIdleInhibitorResource> resource;
- wlr_surface* surface = nullptr;
+ WP<CWLSurfaceResource> surface;
};
class CIdleInhibitorResource {
public:
- CIdleInhibitorResource(SP<CZwpIdleInhibitorV1> resource_, wlr_surface* surface_);
+ CIdleInhibitorResource(SP<CZwpIdleInhibitorV1> resource_, SP<CWLSurfaceResource> surface_);
~CIdleInhibitorResource();
SP<CIdleInhibitor> inhibitor;
@@ -33,10 +34,12 @@ class CIdleInhibitorResource {
private:
SP<CZwpIdleInhibitorV1> resource;
- wlr_surface* surface = nullptr;
+ WP<CWLSurfaceResource> surface;
bool destroySent = false;
- DYNLISTENER(surfaceDestroy);
+ struct {
+ CHyprSignalListener destroySurface;
+ } listeners;
};
class CIdleInhibitProtocol : public IWaylandProtocol {
@@ -51,7 +54,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<CWLSurfaceResource> surface);
void removeInhibitor(CIdleInhibitorResource*);
@@ -64,4 +67,4 @@ class CIdleInhibitProtocol : public IWaylandProtocol {
namespace PROTO {
inline UP<CIdleInhibitProtocol> idleInhibit;
-} \ No newline at end of file
+}
diff --git a/src/protocols/InputMethodV2.cpp b/src/protocols/InputMethodV2.cpp
index 93ca38c0..5d0bd417 100644
--- a/src/protocols/InputMethodV2.cpp
+++ b/src/protocols/InputMethodV2.cpp
@@ -3,6 +3,7 @@
#include "../managers/SeatManager.hpp"
#include "../devices/IKeyboard.hpp"
#include <sys/mman.h>
+#include "core/Compositor.hpp"
#define LOGM PROTO::ime->protoLog
@@ -83,51 +84,45 @@ wl_client* CInputMethodKeyboardGrabV2::client() {
return resource->client();
}
-CInputMethodPopupV2::CInputMethodPopupV2(SP<CZwpInputPopupSurfaceV2> resource_, SP<CInputMethodV2> owner_, wlr_surface* wlrSurface) : resource(resource_), owner(owner_) {
+CInputMethodPopupV2::CInputMethodPopupV2(SP<CZwpInputPopupSurfaceV2> resource_, SP<CInputMethodV2> owner_, SP<CWLSurfaceResource> 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<CWLSurfaceResource> CInputMethodPopupV2::surface() {
+ return pSurface.lock();
}
void CInputMethodV2::SState::reset() {
@@ -194,7 +189,7 @@ CInputMethodV2::CInputMethodV2(SP<CZwpInputMethodV2> resource_) : resource(resou
resource->setGetInputPopupSurface([this](CZwpInputMethodV2* r, uint32_t id, wl_resource* surface) {
const auto RESOURCE = PROTO::ime->m_vPopups.emplace_back(
- makeShared<CInputMethodPopupV2>(makeShared<CZwpInputPopupSurfaceV2>(r->client(), r->version(), id), self.lock(), wlr_surface_from_resource(surface)));
+ makeShared<CInputMethodPopupV2>(makeShared<CZwpInputPopupSurfaceV2>(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 1f5d2598..bc21270c 100644
--- a/src/protocols/InputMethodV2.hpp
+++ b/src/protocols/InputMethodV2.hpp
@@ -101,12 +101,12 @@ class CInputMethodKeyboardGrabV2 {
class CInputMethodPopupV2 {
public:
- CInputMethodPopupV2(SP<CZwpInputPopupSurfaceV2> resource_, SP<CInputMethodV2> owner_, wlr_surface* surface);
+ CInputMethodPopupV2(SP<CZwpInputPopupSurfaceV2> resource_, SP<CInputMethodV2> owner_, SP<CWLSurfaceResource> surface);
~CInputMethodPopupV2();
- bool good();
- void sendInputRectangle(const CBox& box);
- wlr_surface* surface();
+ bool good();
+ void sendInputRectangle(const CBox& box);
+ SP<CWLSurfaceResource> surface();
struct {
CSignal map;
@@ -120,10 +120,12 @@ class CInputMethodPopupV2 {
private:
SP<CZwpInputPopupSurfaceV2> resource;
WP<CInputMethodV2> owner;
- wlr_surface* pSurface = nullptr;
+ WP<CWLSurfaceResource> 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 962b89a3..8fa6dd27 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<CZwlrLayerSurfaceV1> resource_, wlr_surface* surf_, std::string namespace_, CMonitor* pMonitor, zwlrLayerShellV1Layer layer) :
+CLayerShellResource::CLayerShellResource(SP<CZwlrLayerSurfaceV1> resource_, SP<CWLSurfaceResource> surf_, std::string namespace_, CMonitor* pMonitor, zwlrLayerShellV1Layer layer) :
layerNamespace(namespace_), surface(surf_), resource(resource_) {
if (!good())
return;
@@ -31,57 +33,52 @@ CLayerShellResource::CLayerShellResource(SP<CZwlrLayerSurfaceV1> 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<CLayerShellResource>(makeShared<CZwlrLayerSurfaceV1>(CLIENT, pMgr->version(), id), wlr_surface_from_resource(surface), namespace_, PMONITOR, layer));
+ makeShared<CLayerShellResource>(makeShared<CZwlrLayerSurfaceV1>(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 9ed6bc66..f348e86b 100644
--- a/src/protocols/LayerShell.hpp
+++ b/src/protocols/LayerShell.hpp
@@ -10,10 +10,11 @@
#include "../helpers/signal/Signal.hpp"
class CMonitor;
+class CWLSurfaceResource;
class CLayerShellResource {
public:
- CLayerShellResource(SP<CZwlrLayerSurfaceV1> resource_, wlr_surface* surf_, std::string namespace_, CMonitor* pMonitor, zwlrLayerShellV1Layer layer);
+ CLayerShellResource(SP<CZwlrLayerSurfaceV1> resource_, SP<CWLSurfaceResource> surf_, std::string namespace_, CMonitor* pMonitor, zwlrLayerShellV1Layer layer);
~CLayerShellResource();
bool good();
@@ -54,18 +55,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<CWLSurfaceResource> surface;
+ bool mapped = false;
+ bool configured = false;
private:
SP<CZwlrLayerSurfaceV1> resource;
- DYNLISTENER(destroySurface);
- DYNLISTENER(commitSurface);
+ struct {
+ CHyprSignalListener commitSurface;
+ CHyprSignalListener destroySurface;
+ } listeners;
bool closed = false;
diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp
new file mode 100644
index 00000000..f7911f6e
--- /dev/null
+++ b/src/protocols/LinuxDMABUF.cpp
@@ -0,0 +1,454 @@
+#include "LinuxDMABUF.hpp"
+#include <algorithm>
+#include <set>
+#include <tuple>
+#include "../helpers/MiscFunctions.hpp"
+#include <sys/mman.h>
+#include <xf86drm.h>
+#include <fcntl.h>
+#include "core/Compositor.hpp"
+#include "types/DMABuffer.hpp"
+#include "types/WLBuffer.hpp"
+#include "../managers/HookSystemManager.hpp"
+#include "../render/OpenGL.hpp"
+#include "../Compositor.hpp"
+
+#define LOGM PROTO::linuxDma->protoLog
+
+static std::optional<dev_t> devIDFromFD(int fd) {
+ struct stat stat;
+ if (fstat(fd, &stat) != 0)
+ return {};
+ return stat.st_rdev;
+}
+
+CCompiledDMABUFFeedback::CCompiledDMABUFFeedback(dev_t device, std::vector<SDMABufTranche> tranches_) {
+ std::set<std::pair<uint32_t, uint64_t>> formats;
+ for (auto& t : tranches_) {
+ for (auto& fmt : t.formats) {
+ for (auto& mod : fmt.mods) {
+ formats.insert(std::make_pair<>(fmt.format, mod));
+ }
+ }
+ }
+
+ tableLen = formats.size() * sizeof(SDMABUFFeedbackTableEntry);
+ int fds[2] = {0};
+ allocateSHMFilePair(tableLen, &fds[0], &fds[1]);
+
+ auto arr = (SDMABUFFeedbackTableEntry*)mmap(nullptr, tableLen, PROT_READ | PROT_WRITE, MAP_SHARED, fds[0], 0);
+
+ if (!arr) {
+ LOGM(ERR, "mmap failed");
+ close(fds[0]);
+ close(fds[1]);
+ return;
+ }
+
+ close(fds[0]);
+
+ std::vector<std::pair<uint32_t, uint64_t>> formatsVec;
+ for (auto& f : formats) {
+ formatsVec.push_back(f);
+ }
+
+ size_t i = 0;
+ for (auto& [fmt, mod] : formatsVec) {
+ arr[i++] = SDMABUFFeedbackTableEntry{
+ .fmt = fmt,
+ .modifier = mod,
+ };
+ }
+
+ munmap(arr, tableLen);
+
+ mainDevice = device;
+ tableFD = fds[1];
+ tranches = formatsVec;
+
+ // TODO: maybe calculate indices? currently we send all as available which could be wrong? I ain't no kernel dev tho.
+}
+
+CCompiledDMABUFFeedback::~CCompiledDMABUFFeedback() {
+ close(tableFD);
+}
+
+CLinuxDMABuffer::CLinuxDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs attrs) {
+ buffer = makeShared<CDMABuffer>(id, client, attrs);
+
+ buffer->resource->buffer = buffer;
+
+ listeners.bufferResourceDestroy = buffer->events.destroy.registerListener([this](std::any d) {
+ listeners.bufferResourceDestroy.reset();
+ PROTO::linuxDma->destroyResource(this);
+ });
+
+ if (!buffer->success)
+ LOGM(ERR, "Possibly compositor bug: buffer failed to create");
+}
+
+CLinuxDMABuffer::~CLinuxDMABuffer() {
+ buffer.reset();
+ listeners.bufferResourceDestroy.reset();
+}
+
+bool CLinuxDMABuffer::good() {
+ return buffer && buffer->good();
+}
+
+CLinuxDMABBUFParamsResource::CLinuxDMABBUFParamsResource(SP<CZwpLinuxBufferParamsV1> resource_) : resource(resource_) {
+ if (!good())
+ return;
+
+ resource->setOnDestroy([this](CZwpLinuxBufferParamsV1* r) { PROTO::linuxDma->destroyResource(this); });
+ resource->setDestroy([this](CZwpLinuxBufferParamsV1* r) { PROTO::linuxDma->destroyResource(this); });
+
+ attrs = makeShared<SDMABUFAttrs>();
+
+ attrs->success = true;
+
+ resource->setAdd([this](CZwpLinuxBufferParamsV1* r, int32_t fd, uint32_t plane, uint32_t offset, uint32_t stride, uint32_t modHi, uint32_t modLo) {
+ if (used) {
+ r->error(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED, "Already used");
+ return;
+ }
+
+ if (plane > 3) {
+ r->error(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_IDX, "plane > 3");
+ return;
+ }
+
+ if (attrs->fds.at(plane) != -1) {
+ r->error(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_IDX, "plane used");
+ return;
+ }
+
+ attrs->fds[plane] = fd;
+ attrs->strides[plane] = stride;
+ attrs->offsets[plane] = offset;
+ attrs->modifier = ((uint64_t)modHi << 32) | modLo;
+ });
+
+ resource->setCreate([this](CZwpLinuxBufferParamsV1* r, int32_t w, int32_t h, uint32_t fmt, zwpLinuxBufferParamsV1Flags flags) {
+ if (used) {
+ r->error(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED, "Already used");
+ return;
+ }
+
+ if (flags > 0) {
+ r->sendFailed();
+ LOGM(ERR, "DMABUF flags are not supported");
+ return;
+ }
+
+ attrs->size = {w, h};
+ attrs->format = fmt;
+ attrs->planes = 4 - std::count(attrs->fds.begin(), attrs->fds.end(), -1);
+
+ create(0);
+ });
+
+ resource->setCreateImmed([this](CZwpLinuxBufferParamsV1* r, uint32_t id, int32_t w, int32_t h, uint32_t fmt, zwpLinuxBufferParamsV1Flags flags) {
+ if (used) {
+ r->error(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED, "Already used");
+ return;
+ }
+
+ if (flags > 0) {
+ r->sendFailed();
+ LOGM(ERR, "DMABUF flags are not supported");
+ return;
+ }
+
+ attrs->size = {w, h};
+ attrs->format = fmt;
+ attrs->planes = 4 - std::count(attrs->fds.begin(), attrs->fds.end(), -1);
+
+ create(id);
+ });
+}
+
+CLinuxDMABBUFParamsResource::~CLinuxDMABBUFParamsResource() {
+ ;
+}
+
+bool CLinuxDMABBUFParamsResource::good() {
+ return resource->resource();
+}
+
+void CLinuxDMABBUFParamsResource::create(uint32_t id) {
+ used = true;
+
+ if (!verify()) {
+ LOGM(ERR, "Failed creating a dmabuf: verify() said no");
+ return; // if verify failed, we errored the resource.
+ }
+
+ if (!commence()) {
+ LOGM(ERR, "Failed creating a dmabuf: commence() said no");
+ resource->sendFailed();
+ return;
+ }
+
+ LOGM(LOG, "Creating a dmabuf, with id {}: size {}, fmt {}, planes {}", id, attrs->size, attrs->format, attrs->planes);
+ for (int i = 0; i < attrs->planes; ++i) {
+ LOGM(LOG, " | plane {}: mod {} fd {} stride {} offset {}", i, attrs->modifier, attrs->fds[i], attrs->strides[i], attrs->offsets[i]);
+ }
+
+ auto buf = PROTO::linuxDma->m_vBuffers.emplace_back(makeShared<CLinuxDMABuffer>(id, resource->client(), *attrs));
+
+ if (!buf->good() || !buf->buffer->success) {
+ resource->sendFailed();
+ return;
+ }
+
+ if (!id)
+ resource->sendCreated(PROTO::linuxDma->m_vBuffers.back()->buffer->resource->getResource());
+
+ createdBuffer = buf;
+}
+
+bool CLinuxDMABBUFParamsResource::commence() {
+ if (PROTO::linuxDma->mainDeviceFD < 0)
+ return true;
+
+ for (int i = 0; i < attrs->planes; i++) {
+ uint32_t handle = 0;
+
+ if (drmPrimeFDToHandle(PROTO::linuxDma->mainDeviceFD, attrs->fds.at(i), &handle)) {
+ LOGM(ERR, "Failed to import dmabuf fd");
+ return false;
+ }
+
+ if (drmCloseBufferHandle(PROTO::linuxDma->mainDeviceFD, handle)) {
+ LOGM(ERR, "Failed to close dmabuf handle");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool CLinuxDMABBUFParamsResource::verify() {
+ if (attrs->planes <= 0) {
+ resource->error(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, "No planes added");
+ return false;
+ }
+
+ if (attrs->fds.at(0) < 0) {
+ resource->error(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, "No plane 0");
+ return false;
+ }
+
+ bool empty = false;
+ for (auto& plane : attrs->fds) {
+ if (empty && plane != -1) {
+ resource->error(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_FORMAT, "Gap in planes");
+ return false;
+ }
+
+ if (plane == -1) {
+ empty = true;
+ continue;
+ }
+ }
+
+ if (attrs->size.x < 1 || attrs->size.y < 1) {
+ resource->error(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_DIMENSIONS, "x/y < 1");
+ return false;
+ }
+
+ for (size_t i = 0; i < (size_t)attrs->planes; ++i) {
+ if ((uint64_t)attrs->offsets.at(i) + (uint64_t)attrs->strides.at(i) * attrs->size.y > UINT32_MAX) {
+ resource->error(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
+ std::format("size overflow on plane {}: offset {} + stride {} * height {} = {}, overflows UINT32_MAX", i, (uint64_t)attrs->offsets.at(i),
+ (uint64_t)attrs->strides.at(i), attrs->size.y, (uint64_t)attrs->offsets.at(i) + (uint64_t)attrs->strides.at(i)));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+CLinuxDMABUFFeedbackResource::CLinuxDMABUFFeedbackResource(SP<CZwpLinuxDmabufFeedbackV1> resource_, SP<CWLSurfaceResource> surface_) : surface(surface_), resource(resource_) {
+ if (!good())
+ return;
+
+ resource->setOnDestroy([this](CZwpLinuxDmabufFeedbackV1* r) { PROTO::linuxDma->destroyResource(this); });
+ resource->setDestroy([this](CZwpLinuxDmabufFeedbackV1* r) { PROTO::linuxDma->destroyResource(this); });
+
+ if (surface)
+ LOGM(ERR, "FIXME: surface feedback stub");
+
+ auto* feedback = PROTO::linuxDma->defaultFeedback.get();
+
+ resource->sendFormatTable(feedback->tableFD, feedback->tableLen);
+
+ // send default feedback
+ struct wl_array deviceArr = {
+ .size = sizeof(feedback->mainDevice),
+ .data = (void*)&feedback->mainDevice,
+ };
+ resource->sendMainDevice(&deviceArr);
+ resource->sendTrancheTargetDevice(&deviceArr);
+ resource->sendTrancheFlags((zwpLinuxDmabufFeedbackV1TrancheFlags)0);
+
+ wl_array indices;
+ wl_array_init(&indices);
+ for (size_t i = 0; i < feedback->tranches.size(); ++i) {
+ *((uint16_t*)wl_array_add(&indices, sizeof(uint16_t))) = i;
+ }
+ resource->sendTrancheFormats(&indices);
+ wl_array_release(&indices);
+ resource->sendTrancheDone();
+
+ resource->sendDone();
+}
+
+CLinuxDMABUFFeedbackResource::~CLinuxDMABUFFeedbackResource() {
+ ;
+}
+
+bool CLinuxDMABUFFeedbackResource::good() {
+ return resource->resource();
+}
+
+CLinuxDMABUFResource::CLinuxDMABUFResource(SP<CZwpLinuxDmabufV1> resource_) : resource(resource_) {
+ if (!good())
+ return;
+
+ resource->setOnDestroy([this](CZwpLinuxDmabufV1* r) { PROTO::linuxDma->destroyResource(this); });
+ resource->setDestroy([this](CZwpLinuxDmabufV1* r) { PROTO::linuxDma->destroyResource(this); });
+
+ resource->setGetDefaultFeedback([](CZwpLinuxDmabufV1* r, uint32_t id) {
+ const auto RESOURCE =
+ PROTO::linuxDma->m_vFeedbacks.emplace_back(makeShared<CLinuxDMABUFFeedbackResource>(makeShared<CZwpLinuxDmabufFeedbackV1>(r->client(), r->version(), id), nullptr));
+
+ if (!RESOURCE->good()) {
+ r->noMemory();
+ PROTO::linuxDma->m_vFeedbacks.pop_back();
+ return;
+ }
+ });
+
+ resource->setGetSurfaceFeedback([](CZwpLinuxDmabufV1* r, uint32_t id, wl_resource* surf) {
+ const auto RESOURCE = PROTO::linuxDma->m_vFeedbacks.emplace_back(
+ makeShared<CLinuxDMABUFFeedbackResource>(makeShared<CZwpLinuxDmabufFeedbackV1>(r->client(), r->version(), id), CWLSurfaceResource::fromResource(surf)));
+
+ if (!RESOURCE->good()) {
+ r->noMemory();
+ PROTO::linuxDma->m_vFeedbacks.pop_back();
+ return;
+ }
+ });
+
+ resource->setCreateParams([](CZwpLinuxDmabufV1* r, uint32_t id) {
+ const auto RESOURCE = PROTO::linuxDma->m_vParams.emplace_back(makeShared<CLinuxDMABBUFParamsResource>(makeShared<CZwpLinuxBufferParamsV1>(r->client(), r->version(), id)));
+
+ if (!RESOURCE->good()) {
+ r->noMemory();
+ PROTO::linuxDma->m_vParams.pop_back();
+ return;
+ }
+ });
+
+ if (resource->version() < 4)
+ sendMods();
+}
+
+bool CLinuxDMABUFResource::good() {
+ return resource->resource();
+}
+
+void CLinuxDMABUFResource::sendMods() {
+ for (auto& [fmt, mod] : PROTO::linuxDma->defaultFeedback->tranches) {
+ if (resource->version() < 3) {
+ if (mod == DRM_FORMAT_MOD_INVALID)
+ resource->sendFormat(fmt);
+ continue;
+ }
+
+ // TODO: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1166
+
+ resource->sendModifier(fmt, mod >> 32, mod & 0xFFFFFFFF);
+ }
+}
+
+CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
+ static auto P = g_pHookSystem->hookDynamic("ready", [this](void* self, SCallbackInfo& info, std::any d) {
+ int rendererFD = wlr_renderer_get_drm_fd(g_pCompositor->m_sWLRRenderer);
+ auto dev = devIDFromFD(rendererFD);
+
+ if (!dev.has_value()) {
+ LOGM(ERR, "failed to get drm dev");
+ PROTO::linuxDma.reset();
+ return;
+ }
+
+ mainDevice = *dev;
+
+ auto fmts = g_pHyprOpenGL->getDRMFormats();
+
+ SDMABufTranche tranche = {
+ .device = *dev,
+ .formats = fmts,
+ };
+
+ std::vector<SDMABufTranche> tches;
+ tches.push_back(tranche);
+
+ defaultFeedback = std::make_unique<CCompiledDMABUFFeedback>(*dev, tches);
+
+ drmDevice* device = nullptr;
+ if (drmGetDeviceFromDevId(mainDevice, 0, &device) != 0) {
+ LOGM(ERR, "failed to get drm dev");
+ PROTO::linuxDma.reset();
+ return;
+ }
+
+ if (device->available_nodes & (1 << DRM_NODE_RENDER)) {
+ const char* name = device->nodes[DRM_NODE_RENDER];
+ mainDeviceFD = open(name, O_RDWR | O_CLOEXEC);
+ drmFreeDevice(&device);
+ if (mainDeviceFD < 0) {
+ LOGM(ERR, "failed to open drm dev");
+ PROTO::linuxDma.reset();
+ return;
+ }
+ } else {
+ LOGM(ERR, "DRM device {} has no render node!!", device->nodes[DRM_NODE_PRIMARY]);
+ drmFreeDevice(&device);
+ }
+ });
+}
+
+CLinuxDMABufV1Protocol::~CLinuxDMABufV1Protocol() {
+ if (mainDeviceFD >= 0)
+ close(mainDeviceFD);
+}
+
+void CLinuxDMABufV1Protocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
+ const auto RESOURCE = m_vManagers.emplace_back(makeShared<CLinuxDMABUFResource>(makeShared<CZwpLinuxDmabufV1>(client, ver, id)));
+
+ if (!RESOURCE->good()) {
+ wl_client_post_no_memory(client);
+ m_vManagers.pop_back();
+ return;
+ }
+}
+
+void CLinuxDMABufV1Protocol::destroyResource(CLinuxDMABUFResource* resource) {
+ std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == resource; });
+}
+
+void CLinuxDMABufV1Protocol::destroyResource(CLinuxDMABUFFeedbackResource* resource) {
+ std::erase_if(m_vFeedbacks, [&](const auto& other) { return other.get() == resource; });
+}
+
+void CLinuxDMABufV1Protocol::destroyResource(CLinuxDMABBUFParamsResource* resource) {
+ std::erase_if(m_vParams, [&](const auto& other) { return other.get() == resource; });
+}
+
+void CLinuxDMABufV1Protocol::destroyResource(CLinuxDMABuffer* resource) {
+ std::erase_if(m_vBuffers, [&](const auto& other) { return other.get() == resource; });
+}
diff --git a/src/protocols/LinuxDMABUF.hpp b/src/protocols/LinuxDMABUF.hpp
new file mode 100644
index 00000000..2b8ce736
--- /dev/null
+++ b/src/protocols/LinuxDMABUF.hpp
@@ -0,0 +1,138 @@
+#pragma once
+
+#include <memory>
+#include <vector>
+#include <cstdint>
+#include "WaylandProtocol.hpp"
+#include "wayland.hpp"
+#include "linux-dmabuf-v1.hpp"
+#include "../helpers/signal/Signal.hpp"
+
+class CDMABuffer;
+struct SDRMFormat;
+struct SDMABUFAttrs;
+class CWLSurfaceResource;
+
+class CLinuxDMABuffer {
+ public:
+ CLinuxDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs attrs);
+ ~CLinuxDMABuffer();
+
+ bool good();
+
+ private:
+ SP<CDMABuffer> buffer;
+
+ struct {
+ CHyprSignalListener bufferResourceDestroy;
+ } listeners;
+
+ friend class CLinuxDMABBUFParamsResource;
+};
+
+#pragma pack(push, 1)
+struct SDMABUFFeedbackTableEntry {
+ uint32_t fmt = 0;
+ char pad[4];
+ uint64_t modifier = 0;
+};
+#pragma pack(pop)
+
+class SCompiledDMABUFTranche {
+ dev_t device = 0;
+ uint32_t flags = 0;
+ std::vector<uint16_t> indices;
+};
+
+struct SDMABufTranche {
+ dev_t device = 0;
+ uint32_t flags = 0;
+ std::vector<SDRMFormat> formats;
+};
+
+class CCompiledDMABUFFeedback {
+ public:
+ CCompiledDMABUFFeedback(dev_t device, std::vector<SDMABufTranche> tranches);
+ ~CCompiledDMABUFFeedback();
+
+ dev_t mainDevice = 0;
+ int tableFD = -1;
+ size_t tableLen = 0;
+ std::vector<std::pair<uint32_t, uint64_t>> tranches;
+};
+
+class CLinuxDMABBUFParamsResource {
+ public:
+ CLinuxDMABBUFParamsResource(SP<CZwpLinuxBufferParamsV1> resource_);
+ ~CLinuxDMABBUFParamsResource();
+
+ bool good();
+ void create(uint32_t id); // 0 means not immed
+
+ SP<SDMABUFAttrs> attrs;
+ WP<CLinuxDMABuffer> createdBuffer;
+ bool used = false;
+
+ private:
+ SP<CZwpLinuxBufferParamsV1> resource;
+
+ bool verify();
+ bool commence();
+};
+
+class CLinuxDMABUFFeedbackResource {
+ public:
+ CLinuxDMABUFFeedbackResource(SP<CZwpLinuxDmabufFeedbackV1> resource_, SP<CWLSurfaceResource> surface_);
+ ~CLinuxDMABUFFeedbackResource();
+
+ bool good();
+
+ SP<CWLSurfaceResource> surface; // optional, for surface feedbacks
+
+ private:
+ SP<CZwpLinuxDmabufFeedbackV1> resource;
+};
+
+class CLinuxDMABUFResource {
+ public:
+ CLinuxDMABUFResource(SP<CZwpLinuxDmabufV1> resource_);
+
+ bool good();
+ void sendMods();
+
+ private:
+ SP<CZwpLinuxDmabufV1> resource;
+};
+
+class CLinuxDMABufV1Protocol : public IWaylandProtocol {
+ public:
+ CLinuxDMABufV1Protocol(const wl_interface* iface, const int& ver, const std::string& name);
+ ~CLinuxDMABufV1Protocol();
+
+ virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
+
+ private:
+ void destroyResource(CLinuxDMABUFResource* resource);
+ void destroyResource(CLinuxDMABUFFeedbackResource* resource);
+ void destroyResource(CLinuxDMABBUFParamsResource* resource);
+ void destroyResource(CLinuxDMABuffer* resource);
+
+ //
+ std::vector<SP<CLinuxDMABUFResource>> m_vManagers;
+ std::vector<SP<CLinuxDMABUFFeedbackResource>> m_vFeedbacks;
+ std::vector<SP<CLinuxDMABBUFParamsResource>> m_vParams;
+ std::vector<SP<CLinuxDMABuffer>> m_vBuffers;
+
+ UP<CCompiledDMABUFFeedback> defaultFeedback;
+ dev_t mainDevice;
+ int mainDeviceFD = -1;
+
+ friend class CLinuxDMABUFResource;
+ friend class CLinuxDMABUFFeedbackResource;
+ friend class CLinuxDMABBUFParamsResource;
+ friend class CLinuxDMABuffer;
+};
+
+namespace PROTO {
+ inline UP<CLinuxDMABufV1Protocol> linuxDma;
+};
diff --git a/src/protocols/MesaDRM.cpp b/src/protocols/MesaDRM.cpp
new file mode 100644
index 00000000..0bcf4a9c
--- /dev/null
+++ b/src/protocols/MesaDRM.cpp
@@ -0,0 +1,133 @@
+#include "MesaDRM.hpp"
+#include <algorithm>
+#include <xf86drm.h>
+#include "../Compositor.hpp"
+#include <wlr/render/drm_format_set.h>
+#include "types/WLBuffer.hpp"
+
+#define LOGM PROTO::mesaDRM->protoLog
+
+CMesaDRMBufferResource::CMesaDRMBufferResource(uint32_t id, wl_client* client, SDMABUFAttrs attrs_) {
+ LOGM(LOG, "Creating a Mesa dmabuf, with id {}: size {}, fmt {}, planes {}", id, attrs_.size, attrs_.format, attrs_.planes);
+ for (int i = 0; i < attrs_.planes; ++i) {
+ LOGM(LOG, " | plane {}: mod {} fd {} stride {} offset {}", i, attrs_.modifier, attrs_.fds[i], attrs_.strides[i], attrs_.offsets[i]);
+ }
+
+ buffer = makeShared<CDMABuffer>(id, client, attrs_);
+ buffer->resource->buffer = buffer;
+
+ listeners.bufferResourceDestroy = buffer->events.destroy.registerListener([this](std::any d) {
+ listeners.bufferResourceDestroy.reset();
+ PROTO::mesaDRM->destroyResource(this);
+ });
+
+ if (!buffer->success)
+ LOGM(ERR, "Possibly compositor bug: buffer failed to create");
+}
+
+CMesaDRMBufferResource::~CMesaDRMBufferResource() {
+ if (buffer && buffer->resource)
+ buffer->resource->sendRelease();
+ buffer.reset();
+ listeners.bufferResourceDestroy.reset();
+}
+
+bool CMesaDRMBufferResource::good() {
+ return buffer && buffer->good();
+}
+
+CMesaDRMResource::CMesaDRMResource(SP<CWlDrm> resource_) : resource(resource_) {
+ if (!good())
+ return;
+
+ resource->setOnDestroy([this](CWlDrm* r) { PROTO::mesaDRM->destroyResource(this); });
+
+ resource->setAuthenticate([this](CWlDrm* r, uint32_t token) {
+ // we don't need this
+ resource->sendAuthenticated();
+ });
+
+ resource->setCreateBuffer([](CWlDrm* r, uint32_t, uint32_t, int32_t, int32_t, uint32_t, uint32_t) { r->error(WL_DRM_ERROR_INVALID_NAME, "Not supported, use prime instead"); });
+
+ resource->setCreatePlanarBuffer([](CWlDrm* r, uint32_t, uint32_t, int32_t, int32_t, uint32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t) {
+ r->error(WL_DRM_ERROR_INVALID_NAME, "Not supported, use prime instead");
+ });
+
+ resource->setCreatePrimeBuffer(
+ [this](CWlDrm* r, uint32_t id, int32_t nameFd, int32_t w, int32_t h, uint32_t fmt, int32_t off0, int32_t str0, int32_t off1, int32_t str1, int32_t off2, int32_t str2) {
+ if (off0 < 0 || w <= 0 || h <= 0) {
+ r->error(WL_DRM_ERROR_INVALID_FORMAT, "Invalid w, h, or offset");
+ return;
+ }
+
+ SDMABUFAttrs attrs;
+ attrs.success = true;
+ attrs.size = {w, h};
+ attrs.modifier = DRM_FORMAT_MOD_INVALID;
+ attrs.planes = 1;
+ attrs.offsets[0] = off0;
+ attrs.strides[0] = str0;
+ attrs.fds[0] = nameFd;
+ attrs.format = fmt;
+
+ const auto RESOURCE = PROTO::mesaDRM->m_vBuffers.emplace_back(makeShared<CMesaDRMBufferResource>(id, resource->client(), attrs));
+
+ if (!RESOURCE->good()) {
+ r->noMemory();
+ PROTO::mesaDRM->m_vBuffers.pop_back();
+ return;
+ }
+
+ // append instance so that buffer knows its owner
+ RESOURCE->buffer->resource->buffer = RESOURCE->buffer;
+ });
+
+ resource->sendDevice(PROTO::mesaDRM->nodeName.c_str());
+ resource->sendCapabilities(WL_DRM_CAPABILITY_PRIME);
+
+ auto fmts = g_pHyprOpenGL->getDRMFormats();
+ for (auto& fmt : fmts) {
+ resource->sendFormat(fmt.format);
+ }
+}
+
+bool CMesaDRMResource::good() {
+ return resource->resource();
+}
+
+CMesaDRMProtocol::CMesaDRMProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
+ drmDevice* dev = nullptr;
+ int drmFD = wlr_renderer_get_drm_fd(g_pCompositor->m_sWLRRenderer);
+ if (drmGetDevice2(drmFD, 0, &dev) != 0) {
+ LOGM(ERR, "Failed to get device");
+ PROTO::mesaDRM.reset();
+ return;
+ }
+
+ if (dev->available_nodes & (1 << DRM_NODE_RENDER)) {
+ nodeName = dev->nodes[DRM_NODE_RENDER];
+ } else {
+ ASSERT(dev->available_nodes & (1 << DRM_NODE_PRIMARY));
+ LOGM(WARN, "No DRM render node, falling back to primary {}", dev->nodes[DRM_NODE_PRIMARY]);
+ nodeName = dev->nodes[DRM_NODE_PRIMARY];
+ }
+ drmFreeDevice(&dev);
+}
+
+void CMesaDRMProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
+ const auto RESOURCE = m_vManagers.emplace_back(makeShared<CMesaDRMResource>(makeShared<CWlDrm>(client, ver, id)));
+
+ if (!RESOURCE->good()) {
+ wl_client_post_no_memory(client);
+ m_vManagers.pop_back();
+ return;
+ }
+}
+
+void CMesaDRMProtocol::destroyResource(CMesaDRMResource* resource) {
+ std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == resource; });
+}
+
+void CMesaDRMProtocol::destroyResource(CMesaDRMBufferResource* resource) {
+ std::erase_if(m_vBuffers, [&](const auto& other) { return other.get() == resource; });
+}
diff --git a/src/protocols/MesaDRM.hpp b/src/protocols/MesaDRM.hpp
new file mode 100644
index 00000000..ad31a182
--- /dev/null
+++ b/src/protocols/MesaDRM.hpp
@@ -0,0 +1,60 @@
+#pragma once
+
+#include <memory>
+#include <vector>
+#include <cstdint>
+#include "WaylandProtocol.hpp"
+#include "wayland-drm.hpp"
+#include "types/Buffer.hpp"
+#include "types/DMABuffer.hpp"
+
+class CMesaDRMBufferResource {
+ public:
+ CMesaDRMBufferResource(uint32_t id, wl_client* client, SDMABUFAttrs attrs);
+ ~CMesaDRMBufferResource();
+
+ bool good();
+
+ private:
+ SP<CDMABuffer> buffer;
+
+ struct {
+ CHyprSignalListener bufferResourceDestroy;
+ } listeners;
+
+ friend class CMesaDRMResource;
+};
+
+class CMesaDRMResource {
+ public:
+ CMesaDRMResource(SP<CWlDrm> resource_);
+
+ bool good();
+
+ private:
+ SP<CWlDrm> resource;
+};
+
+class CMesaDRMProtocol : public IWaylandProtocol {
+ public:
+ CMesaDRMProtocol(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(CMesaDRMResource* resource);
+ void destroyResource(CMesaDRMBufferResource* resource);
+
+ //
+ std::vector<SP<CMesaDRMResource>> m_vManagers;
+ std::vector<SP<CMesaDRMBufferResource>> m_vBuffers;
+
+ std::string nodeName = "";
+
+ friend class CMesaDRMResource;
+ friend class CMesaDRMBufferResource;
+};
+
+namespace PROTO {
+ inline UP<CMesaDRMProtocol> mesaDRM;
+};
diff --git a/src/protocols/OutputPower.cpp b/src/protocols/OutputPower.cpp
index db241048..ef287cfa 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<COutputPower>(makeShared<CZwlrOutputPowerV1>(CLIENT, pMgr->version(), id), PMONITOR)).get();
+ const auto RESOURCE = m_vOutputPowers.emplace_back(std::make_unique<COutputPower>(makeShared<CZwlrOutputPowerV1>(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 87abdcdd..c7b78a5b 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<CZwpLockedPointerV1> resource_, wlr_surface* surf, wl_resource* region_, zwpPointerConstraintsV1Lifetime lifetime) :
+CPointerConstraint::CPointerConstraint(SP<CZwpLockedPointerV1> resource_, SP<CWLSurfaceResource> surf, wl_resource* region_, zwpPointerConstraintsV1Lifetime lifetime) :
resourceL(resource_), locked(true) {
if (!resource_->resource())
return;
@@ -14,13 +15,13 @@ CPointerConstraint::CPointerConstraint(SP<CZwpLockedPointerV1> 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;
if (region_)
- region.set(wlr_region_from_resource(region_));
+ region.set(CWLRegionResource::fromResource(region_)->region);
resource_->setSetRegion([this](CZwpLockedPointerV1* p, wl_resource* region) { onSetRegion(region); });
resource_->setSetCursorPositionHint([this](CZwpLockedPointerV1* p, wl_fixed_t x, wl_fixed_t y) {
@@ -45,7 +46,7 @@ CPointerConstraint::CPointerConstraint(SP<CZwpLockedPointerV1> resource_, wlr_su
sharedConstructions();
}
-CPointerConstraint::CPointerConstraint(SP<CZwpConfinedPointerV1> resource_, wlr_surface* surf, wl_resource* region_, zwpPointerConstraintsV1Lifetime lifetime) :
+CPointerConstraint::CPointerConstraint(SP<CZwpConfinedPointerV1> resource_, SP<CWLSurfaceResource> surf, wl_resource* region_, zwpPointerConstraintsV1Lifetime lifetime) :
resourceC(resource_), locked(false) {
if (!resource_->resource())
return;
@@ -53,13 +54,13 @@ CPointerConstraint::CPointerConstraint(SP<CZwpConfinedPointerV1> 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;
if (region_)
- region.set(wlr_region_from_resource(region_));
+ region.set(CWLRegionResource::fromResource(region_)->region);
resource_->setSetRegion([this](CZwpConfinedPointerV1* p, wl_resource* region) { onSetRegion(region); });
@@ -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)
@@ -152,15 +153,15 @@ void CPointerConstraint::onSetRegion(wl_resource* wlRegion) {
return;
}
- const auto REGION = wlr_region_from_resource(wlRegion);
+ const auto REGION = region.set(CWLRegionResource::fromResource(wlRegion)->region);
region.set(REGION);
positionHint = region.closestPoint(positionHint);
g_pInputManager->simulateMouseMovement(); // to warp the cursor if anything's amiss
}
-CWLSurface* CPointerConstraint::owner() {
- return pHLSurface;
+SP<CWLSurface> 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<CPointerConstraint>(makeShared<CZwpLockedPointerV1>(CLIENT, pMgr->version(), id), wlr_surface_from_resource(surface), region, lifetime));
+ makeShared<CPointerConstraint>(makeShared<CZwpLockedPointerV1>(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<CPointerConstraint>(makeShared<CZwpConfinedPointerV1>(CLIENT, pMgr->version(), id), wlr_surface_from_resource(surface), region, lifetime));
+ makeShared<CPointerConstraint>(makeShared<CZwpConfinedPointerV1>(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 93e57c46..06bebb02 100644
--- a/src/protocols/PointerConstraints.hpp
+++ b/src/protocols/PointerConstraints.hpp
@@ -12,31 +12,32 @@
#include "../helpers/signal/Listener.hpp"
class CWLSurface;
+class CWLSurfaceResource;
class CPointerConstraint {
public:
- CPointerConstraint(SP<CZwpLockedPointerV1> resource_, wlr_surface* surf, wl_resource* region, zwpPointerConstraintsV1Lifetime lifetime);
- CPointerConstraint(SP<CZwpConfinedPointerV1> resource_, wlr_surface* surf, wl_resource* region, zwpPointerConstraintsV1Lifetime lifetime);
+ CPointerConstraint(SP<CZwpLockedPointerV1> resource_, SP<CWLSurfaceResource> surf, wl_resource* region, zwpPointerConstraintsV1Lifetime lifetime);
+ CPointerConstraint(SP<CZwpConfinedPointerV1> resource_, SP<CWLSurfaceResource> 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<CWLSurface> owner();
- CRegion logicConstraintRegion();
- bool isLocked();
- Vector2D logicPositionHint();
+ CRegion logicConstraintRegion();
+ bool isLocked();
+ Vector2D logicPositionHint();
private:
SP<CZwpLockedPointerV1> resourceL;
SP<CZwpConfinedPointerV1> resourceC;
wl_client* pClient = nullptr;
- CWLSurface* pHLSurface = nullptr;
+ WP<CWLSurface> pHLSurface;
CRegion region;
bool hintSet = false;
diff --git a/src/protocols/PointerGestures.cpp b/src/protocols/PointerGestures.cpp
index 2bfd74da..86510779 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 e21c8403..0275b53f 100644
--- a/src/protocols/PresentationTime.cpp
+++ b/src/protocols/PresentationTime.cpp
@@ -2,10 +2,11 @@
#include <algorithm>
#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<CWLSurfaceResource> surf) : surface(surf) {
;
}
@@ -25,7 +26,7 @@ void CQueuedPresentationData::discarded() {
wasPresented = false;
}
-CPresentationFeedback::CPresentationFeedback(SP<CWpPresentationFeedback> resource_, wlr_surface* surf) : resource(resource_), surface(surf) {
+CPresentationFeedback::CPresentationFeedback(SP<CWpPresentationFeedback> resource_, SP<CWLSurfaceResource> surf) : resource(resource_), surface(surf) {
if (!good())
return;
@@ -69,7 +70,7 @@ void CPresentationFeedback::sendQueued(SP<CQueuedPresentationData> 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<CMonitor*>(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<CPresentationFeedback>(makeShared<CWpPresentationFeedback>(CLIENT, pMgr->version(), id), wlr_surface_from_resource(surf))).get();
+ m_vFeedbacks.emplace_back(makeShared<CPresentationFeedback>(makeShared<CWpPresentationFeedback>(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<CQueuedPresentationData> data) {
diff --git a/src/protocols/PresentationTime.hpp b/src/protocols/PresentationTime.hpp
index 2df1c781..2c6ce3e9 100644
--- a/src/protocols/PresentationTime.hpp
+++ b/src/protocols/PresentationTime.hpp
@@ -7,10 +7,11 @@
#include "presentation-time.hpp"
class CMonitor;
+class CWLSurfaceResource;
class CQueuedPresentationData {
public:
- CQueuedPresentationData(wlr_surface* surf);
+ CQueuedPresentationData(SP<CWLSurfaceResource> surf);
void setPresentationType(bool zeroCopy);
void attachMonitor(CMonitor* pMonitor);
@@ -19,10 +20,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<CWLSurfaceResource> surface;
DYNLISTENER(destroySurface);
@@ -32,7 +33,7 @@ class CQueuedPresentationData {
class CPresentationFeedback {
public:
- CPresentationFeedback(SP<CWpPresentationFeedback> resource_, wlr_surface* surf);
+ CPresentationFeedback(SP<CWpPresentationFeedback> resource_, SP<CWLSurfaceResource> surf);
bool good();
@@ -40,8 +41,8 @@ class CPresentationFeedback {
private:
SP<CWpPresentationFeedback> resource;
- wlr_surface* surface = nullptr; // READ-ONLY
- bool done = false;
+ WP<CWLSurfaceResource> surface;
+ bool done = false;
friend class CPresentationProtocol;
};
diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp
index 622d9d68..0c4eac86 100644
--- a/src/protocols/Screencopy.cpp
+++ b/src/protocols/Screencopy.cpp
@@ -2,11 +2,13 @@
#include "../Compositor.hpp"
#include "../managers/eventLoop/EventLoopManager.hpp"
#include "../managers/PointerManager.hpp"
+#include "core/Output.hpp"
+#include "types/WLBuffer.hpp"
+#include "types/Buffer.hpp"
+#include "../helpers/Format.hpp"
#include <algorithm>
-#include "ToplevelExportWlrFuncs.hpp"
-
#define SCREENCOPY_VERSION 3
static void bindManagerInt(wl_client* client, void* data, uint32_t version, uint32_t id) {
@@ -202,8 +204,8 @@ void CScreencopyProtocolManager::removeFrame(SScreencopyFrame* frame, bool force
std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other == frame; });
wl_resource_set_user_data(frame->resource, nullptr);
- if (frame->buffer && frame->buffer->n_locks > 0)
- wlr_buffer_unlock(frame->buffer);
+ if (frame->buffer && frame->buffer->locked())
+ frame->buffer->unlock();
removeClient(frame->client, force);
m_lFrames.remove(*frame);
}
@@ -214,7 +216,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");
@@ -256,7 +258,7 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r
return;
}
- const auto PSHMINFO = drm_get_pixel_format_info(PFRAME->shmFormat);
+ const auto PSHMINFO = FormatUtils::getPixelFormatFromDRM(PFRAME->shmFormat);
if (!PSHMINFO) {
Debug::log(ERR, "No pixel format supported by renderer in capture output");
zwlr_screencopy_frame_v1_send_failed(PFRAME->resource);
@@ -279,9 +281,9 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r
wlr_output_effective_resolution(PFRAME->pMonitor->output, &ow, &oh);
PFRAME->box.transform(PFRAME->pMonitor->transform, ow, oh).scale(PFRAME->pMonitor->scale).round();
- PFRAME->shmStride = pixel_format_info_min_stride(PSHMINFO, PFRAME->box.w);
+ PFRAME->shmStride = FormatUtils::minStride(PSHMINFO, PFRAME->box.w);
- zwlr_screencopy_frame_v1_send_buffer(PFRAME->resource, convert_drm_format_to_wl_shm(PFRAME->shmFormat), PFRAME->box.width, PFRAME->box.height, PFRAME->shmStride);
+ zwlr_screencopy_frame_v1_send_buffer(PFRAME->resource, FormatUtils::drmToShm(PFRAME->shmFormat), PFRAME->box.width, PFRAME->box.height, PFRAME->shmStride);
if (wl_resource_get_version(resource) >= 3) {
if (PFRAME->dmabufFormat != DRM_FORMAT_INVALID) {
@@ -307,7 +309,7 @@ void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resou
return;
}
- const auto PBUFFER = wlr_buffer_try_from_resource(buffer);
+ const auto PBUFFER = CWLBufferResource::fromResource(buffer);
if (!PBUFFER) {
Debug::log(ERR, "[sc] invalid buffer in {:x}", (uintptr_t)PFRAME);
wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer");
@@ -315,7 +317,9 @@ void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resou
return;
}
- if (PBUFFER->width != PFRAME->box.width || PBUFFER->height != PFRAME->box.height) {
+ PBUFFER->buffer->lock();
+
+ if (PBUFFER->buffer->size != PFRAME->box.size()) {
Debug::log(ERR, "[sc] invalid dimensions in {:x}", (uintptr_t)PFRAME);
wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer dimensions");
removeFrame(PFRAME);
@@ -329,28 +333,22 @@ void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resou
return;
}
- wlr_dmabuf_attributes dmabufAttrs;
- void* wlrBufferAccessData;
- uint32_t wlrBufferAccessFormat;
- size_t wlrBufferAccessStride;
- if (wlr_buffer_get_dmabuf(PBUFFER, &dmabufAttrs)) {
- PFRAME->bufferCap = WLR_BUFFER_CAP_DMABUF;
+ if (auto attrs = PBUFFER->buffer->dmabuf(); attrs.success) {
+ PFRAME->bufferDMA = true;
- if (dmabufAttrs.format != PFRAME->dmabufFormat) {
+ if (attrs.format != PFRAME->dmabufFormat) {
Debug::log(ERR, "[sc] invalid buffer dma format in {:x}", (uintptr_t)PFRAME);
wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer format");
removeFrame(PFRAME);
return;
}
- } else if (wlr_buffer_begin_data_ptr_access(PBUFFER, WLR_BUFFER_DATA_PTR_ACCESS_WRITE, &wlrBufferAccessData, &wlrBufferAccessFormat, &wlrBufferAccessStride)) {
- wlr_buffer_end_data_ptr_access(PBUFFER);
-
- if (wlrBufferAccessFormat != PFRAME->shmFormat) {
+ } else if (auto attrs = PBUFFER->buffer->shm(); attrs.success) {
+ if (attrs.format != PFRAME->shmFormat) {
Debug::log(ERR, "[sc] invalid buffer shm format in {:x}", (uintptr_t)PFRAME);
wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer format");
removeFrame(PFRAME);
return;
- } else if ((int)wlrBufferAccessStride != PFRAME->shmStride) {
+ } else if ((int)attrs.stride != PFRAME->shmStride) {
Debug::log(ERR, "[sc] invalid buffer shm stride in {:x}", (uintptr_t)PFRAME);
wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer stride");
removeFrame(PFRAME);
@@ -363,7 +361,7 @@ void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resou
return;
}
- PFRAME->buffer = PBUFFER;
+ PFRAME->buffer = PBUFFER->buffer;
m_vFramesAwaitingWrite.emplace_back(PFRAME);
@@ -432,7 +430,7 @@ void CScreencopyProtocolManager::shareFrame(SScreencopyFrame* frame) {
clock_gettime(CLOCK_MONOTONIC, &now);
uint32_t flags = 0;
- if (frame->bufferCap == WLR_BUFFER_CAP_DMABUF) {
+ if (frame->bufferDMA) {
if (!copyFrameDmabuf(frame)) {
Debug::log(ERR, "[sc] dmabuf copy failed in {:x}", (uintptr_t)frame);
zwlr_screencopy_frame_v1_send_failed(frame->resource);
@@ -471,7 +469,7 @@ void CScreencopyProtocolManager::sendFrameDamage(SScreencopyFrame* frame) {
// std::clamp(RECT.x2 - RECT.x1, 0, frame->buffer->width - RECT.x1), std::clamp(RECT.y2 - RECT.y1, 0, frame->buffer->height - RECT.y1));
// }
- zwlr_screencopy_frame_v1_send_damage(frame->resource, 0, 0, frame->buffer->width, frame->buffer->height);
+ zwlr_screencopy_frame_v1_send_damage(frame->resource, 0, 0, frame->buffer->size.x, frame->buffer->size.y);
}
bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* now) {
@@ -479,13 +477,10 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec*
if (!sourceTex)
return false;
- void* data;
- uint32_t format;
- size_t stride;
- if (!wlr_buffer_begin_data_ptr_access(frame->buffer, WLR_BUFFER_DATA_PTR_ACCESS_WRITE, &data, &format, &stride)) {
- wlr_texture_destroy(sourceTex);
- return false;
- }
+ auto TEXTURE = makeShared<CTexture>(sourceTex);
+
+ auto shm = frame->buffer->shm();
+ auto [pixelData, fmt, bufLen] = frame->buffer->beginDataPtr(0); // no need for end, cuz it's shm
CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX};
@@ -496,14 +491,13 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec*
if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb, true)) {
wlr_texture_destroy(sourceTex);
- wlr_buffer_end_data_ptr_access(frame->buffer);
return false;
}
CBox monbox = CBox{0, 0, frame->pMonitor->vecTransformedSize.x, frame->pMonitor->vecTransformedSize.y}.translate({-frame->box.x, -frame->box.y});
g_pHyprOpenGL->setMonitorTransformEnabled(true);
g_pHyprOpenGL->setRenderModifEnabled(false);
- g_pHyprOpenGL->renderTexture(sourceTex, &monbox, 1);
+ g_pHyprOpenGL->renderTexture(TEXTURE, &monbox, 1);
g_pHyprOpenGL->setRenderModifEnabled(true);
g_pHyprOpenGL->setMonitorTransformEnabled(false);
@@ -513,14 +507,15 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec*
glBindFramebuffer(GL_FRAMEBUFFER, fb.m_iFb);
#endif
- const auto PFORMAT = g_pHyprOpenGL->getPixelFormatFromDRM(format);
+ const auto PFORMAT = FormatUtils::getPixelFormatFromDRM(shm.format);
if (!PFORMAT) {
g_pHyprRenderer->endRender();
wlr_texture_destroy(sourceTex);
- wlr_buffer_end_data_ptr_access(frame->buffer);
return false;
}
+ auto glFormat = PFORMAT->flipRB ? GL_BGRA_EXT : GL_RGBA;
+
g_pHyprOpenGL->m_RenderData.blockScreenShader = true;
g_pHyprRenderer->endRender();
@@ -530,21 +525,20 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec*
glPixelStorei(GL_PACK_ALIGNMENT, 1);
- const wlr_pixel_format_info* drmFmtWlr = drm_get_pixel_format_info(format);
- uint32_t packStride = pixel_format_info_min_stride(drmFmtWlr, frame->box.w);
+ const auto drmFmt = FormatUtils::getPixelFormatFromDRM(shm.format);
+ uint32_t packStride = FormatUtils::minStride(drmFmt, frame->box.w);
- if (packStride == stride) {
- glReadPixels(0, 0, frame->box.w, frame->box.h, PFORMAT->glFormat, PFORMAT->glType, data);
+ if (packStride == (uint32_t)shm.stride) {
+ glReadPixels(0, 0, frame->box.w, frame->box.h, glFormat, PFORMAT->glType, pixelData);
} else {
for (size_t i = 0; i < frame->box.h; ++i) {
uint32_t y = i;
- glReadPixels(0, y, frame->box.w, 1, PFORMAT->glFormat, PFORMAT->glType, ((unsigned char*)data) + i * stride);
+ glReadPixels(0, y, frame->box.w, 1, glFormat, PFORMAT->glType, ((unsigned char*)pixelData) + i * shm.stride);
}
}
g_pHyprOpenGL->m_RenderData.pMonitor = nullptr;
- wlr_buffer_end_data_ptr_access(frame->buffer);
wlr_texture_destroy(sourceTex);
return true;
@@ -555,9 +549,11 @@ bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) {
if (!sourceTex)
return false;
+ auto TEXTURE = makeShared<CTexture>(sourceTex);
+
CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX};
- if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer, nullptr, true))
+ if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer.lock(), nullptr, true))
return false;
CBox monbox = CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y}
@@ -565,7 +561,7 @@ bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) {
.transform(wlr_output_transform_invert(frame->pMonitor->output->transform), frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y);
g_pHyprOpenGL->setMonitorTransformEnabled(true);
g_pHyprOpenGL->setRenderModifEnabled(false);
- g_pHyprOpenGL->renderTexture(sourceTex, &monbox, 1);
+ g_pHyprOpenGL->renderTexture(TEXTURE, &monbox, 1);
g_pHyprOpenGL->setRenderModifEnabled(true);
g_pHyprOpenGL->setMonitorTransformEnabled(false);
diff --git a/src/protocols/Screencopy.hpp b/src/protocols/Screencopy.hpp
index 1bdf6963..be434285 100644
--- a/src/protocols/Screencopy.hpp
+++ b/src/protocols/Screencopy.hpp
@@ -10,6 +10,7 @@
#include "../managers/eventLoop/EventLoopTimer.hpp"
class CMonitor;
+class IWLBuffer;
enum eClientOwners {
CLIENT_SCREENCOPY = 0,
@@ -53,9 +54,9 @@ struct SScreencopyFrame {
bool withDamage = false;
bool lockedSWCursors = false;
- wlr_buffer_cap bufferCap = WLR_BUFFER_CAP_SHM;
+ bool bufferDMA = false;
- wlr_buffer* buffer = nullptr;
+ WP<IWLBuffer> buffer;
CMonitor* pMonitor = nullptr;
PHLWINDOWREF pWindow;
diff --git a/src/protocols/ServerDecorationKDE.cpp b/src/protocols/ServerDecorationKDE.cpp
index d47467b3..42da52a9 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<COrgKdeKwinServerDecoration> resource_, wlr_surface* surf) : resource(resource_) {
+CServerDecorationKDE::CServerDecorationKDE(SP<COrgKdeKwinServerDecoration> resource_, SP<CWLSurfaceResource> 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<CServerDecorationKDE>(makeShared<COrgKdeKwinServerDecoration>(CLIENT, pMgr->version(), id), wlr_surface_from_resource(surf))).get();
+ m_vDecos.emplace_back(std::make_unique<CServerDecorationKDE>(makeShared<COrgKdeKwinServerDecoration>(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 ec7a852f..ab082b17 100644
--- a/src/protocols/ServerDecorationKDE.hpp
+++ b/src/protocols/ServerDecorationKDE.hpp
@@ -6,9 +6,11 @@
#include "WaylandProtocol.hpp"
#include "kde-server-decoration.hpp"
+class CWLSurfaceResource;
+
class CServerDecorationKDE {
public:
- CServerDecorationKDE(SP<COrgKdeKwinServerDecoration> resource_, wlr_surface* surf);
+ CServerDecorationKDE(SP<COrgKdeKwinServerDecoration> resource_, SP<CWLSurfaceResource> surf);
bool good();
diff --git a/src/protocols/SessionLock.cpp b/src/protocols/SessionLock.cpp
index fd803eda..ae45b0f1 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<CExtSessionLockSurfaceV1> resource_, wlr_surface* surface_, CMonitor* pMonitor_, WP<CSessionLock> owner_) :
+CSessionLockSurface::CSessionLockSurface(SP<CExtSessionLockSurfaceV1> resource_, SP<CWLSurfaceResource> surface_, CMonitor* pMonitor_, WP<CSessionLock> owner_) :
resource(resource_), sessionLock(owner_), pSurface(surface_), pMonitor(pMonitor_) {
if (!resource->resource())
return;
@@ -21,45 +23,38 @@ CSessionLockSurface::CSessionLockSurface(SP<CExtSessionLockSurfaceV1> 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<CExtSessionLockSurfaceV1> 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<CWLSurfaceResource> CSessionLockSurface::surface() {
+ return pSurface.lock();
}
CSessionLock::CSessionLock(SP<CExtSessionLockV1> 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<CSessionLock> sessionLock;
for (auto& l : m_vLocks) {
diff --git a/src/protocols/SessionLock.hpp b/src/protocols/SessionLock.hpp
index 6b0c4e08..a0c67e88 100644
--- a/src/protocols/SessionLock.hpp
+++ b/src/protocols/SessionLock.hpp
@@ -9,16 +9,17 @@
class CMonitor;
class CSessionLock;
+class CWLSurfaceResource;
class CSessionLockSurface {
public:
- CSessionLockSurface(SP<CExtSessionLockSurfaceV1> resource_, wlr_surface* surface_, CMonitor* pMonitor_, WP<CSessionLock> owner_);
+ CSessionLockSurface(SP<CExtSessionLockSurfaceV1> resource_, SP<CWLSurfaceResource> surface_, CMonitor* pMonitor_, WP<CSessionLock> owner_);
~CSessionLockSurface();
- bool good();
- bool inert();
- CMonitor* monitor();
- wlr_surface* surface();
+ bool good();
+ bool inert();
+ CMonitor* monitor();
+ SP<CWLSurfaceResource> surface();
struct {
CSignal map;
@@ -29,7 +30,7 @@ class CSessionLockSurface {
private:
SP<CExtSessionLockSurfaceV1> resource;
WP<CSessionLock> sessionLock;
- wlr_surface* pSurface = nullptr;
+ WP<CWLSurfaceResource> pSurface;
CMonitor* pMonitor = nullptr;
bool ackdConfigure = false;
@@ -37,11 +38,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 af9724b5..211a7a01 100644
--- a/src/protocols/ShortcutsInhibit.cpp
+++ b/src/protocols/ShortcutsInhibit.cpp
@@ -1,10 +1,11 @@
#include "ShortcutsInhibit.hpp"
#include <algorithm>
#include "../Compositor.hpp"
+#include "core/Compositor.hpp"
#define LOGM PROTO::shortcutsInhibit->protoLog
-CKeyboardShortcutsInhibitor::CKeyboardShortcutsInhibitor(SP<CZwpKeyboardShortcutsInhibitorV1> resource_, wlr_surface* surf) : resource(resource_), pSurface(surf) {
+CKeyboardShortcutsInhibitor::CKeyboardShortcutsInhibitor(SP<CZwpKeyboardShortcutsInhibitorV1> resource_, SP<CWLSurfaceResource> surf) : resource(resource_), pSurface(surf) {
if (!resource->resource())
return;
@@ -16,8 +17,8 @@ CKeyboardShortcutsInhibitor::CKeyboardShortcutsInhibitor(SP<CZwpKeyboardShortcut
resource->sendActive();
}
-wlr_surface* CKeyboardShortcutsInhibitor::surface() {
- return pSurface;
+SP<CWLSurfaceResource> 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<CWLSurfaceResource> 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 4e06938f..ba1c134c 100644
--- a/src/protocols/ShortcutsInhibit.hpp
+++ b/src/protocols/ShortcutsInhibit.hpp
@@ -6,17 +6,19 @@
#include "WaylandProtocol.hpp"
#include "keyboard-shortcuts-inhibit-unstable-v1.hpp"
+class CWLSurfaceResource;
+
class CKeyboardShortcutsInhibitor {
public:
- CKeyboardShortcutsInhibitor(SP<CZwpKeyboardShortcutsInhibitorV1> resource_, wlr_surface* surf);
+ CKeyboardShortcutsInhibitor(SP<CZwpKeyboardShortcutsInhibitorV1> resource_, SP<CWLSurfaceResource> surf);
// read-only pointer, may be invalid
- wlr_surface* surface();
- bool good();
+ SP<CWLSurfaceResource> surface();
+ bool good();
private:
SP<CZwpKeyboardShortcutsInhibitorV1> resource;
- wlr_surface* pSurface = nullptr;
+ WP<CWLSurfaceResource> pSurface;
};
class CKeyboardShortcutsInhibitProtocol : public IWaylandProtocol {
diff --git a/src/protocols/Tablet.cpp b/src/protocols/Tablet.cpp
index 54c55176..393dfd38 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 <algorithm>
#define LOGM PROTO::tablet->protoLog
@@ -160,11 +161,11 @@ CTabletToolV2Resource::CTabletToolV2Resource(SP<CZwpTabletToolV2> 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<CTabletTool> tool) {
}
}
-void CTabletV2Protocol::proximityIn(SP<CTabletTool> tool, SP<CTablet> tablet, wlr_surface* surf) {
+void CTabletV2Protocol::proximityIn(SP<CTabletTool> tool, SP<CTablet> tablet, SP<CWLSurfaceResource> surf) {
proximityOut(tool);
- const auto CLIENT = wl_resource_get_client(surf->resource);
+ const auto CLIENT = surf->client();
SP<CTabletToolV2Resource> toolResource;
SP<CTabletV2Resource> tabletResource;
@@ -587,7 +588,7 @@ void CTabletV2Protocol::proximityIn(SP<CTabletTool> tool, SP<CTablet> 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<CTabletTool> 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 74a45c63..c61395c9 100644
--- a/src/protocols/Tablet.hpp
+++ b/src/protocols/Tablet.hpp
@@ -12,6 +12,7 @@ class CTabletTool;
class CTabletPad;
class CEventLoopTimer;
class CTabletSeat;
+class CWLSurfaceResource;
class CTabletPadStripV2Resource {
public:
@@ -112,19 +113,19 @@ class CTabletToolV2Resource {
CTabletToolV2Resource(SP<CZwpTabletToolV2> resource_, SP<CTabletTool> tool_, SP<CTabletSeat> 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<CWLSurfaceResource> lastSurf;
- WP<CTabletTool> tool;
- WP<CTabletSeat> seat;
- wl_event_source* frameSource = nullptr;
+ WP<CTabletTool> tool;
+ WP<CTabletSeat> seat;
+ wl_event_source* frameSource = nullptr;
- bool inert = false; // removed was sent
+ bool inert = false; // removed was sent
private:
SP<CZwpTabletToolV2> resource;
@@ -180,7 +181,7 @@ class CTabletV2Protocol : public IWaylandProtocol {
void tilt(SP<CTabletTool> tool, const Vector2D& value);
void up(SP<CTabletTool> tool);
void down(SP<CTabletTool> tool);
- void proximityIn(SP<CTabletTool> tool, SP<CTablet> tablet, wlr_surface* surf);
+ void proximityIn(SP<CTabletTool> tool, SP<CTablet> tablet, SP<CWLSurfaceResource> surf);
void proximityOut(SP<CTabletTool> tool);
void buttonTool(SP<CTabletTool> tool, uint32_t button, uint32_t state);
void motion(SP<CTabletTool> tool, const Vector2D& value);
diff --git a/src/protocols/TearingControl.cpp b/src/protocols/TearingControl.cpp
index df3126fe..7f3c0a18 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<CWLSurfaceResource> surf) {
const auto CONTROLLER = m_vTearingControllers.emplace_back(std::make_unique<CTearingControl>(makeShared<CWpTearingControlV1>(client, pMgr->version(), id), surf)).get();
if (!CONTROLLER->good()) {
@@ -44,14 +46,14 @@ void CTearingControlProtocol::onWindowDestroy(PHLWINDOW pWindow) {
//
-CTearingControl::CTearingControl(SP<CWpTearingControlV1> resource_, wlr_surface* surf_) : resource(resource_) {
+CTearingControl::CTearingControl(SP<CWpTearingControlV1> resource_, SP<CWLSurfaceResource> 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 199397a3..d81a27cd 100644
--- a/src/protocols/TearingControl.hpp
+++ b/src/protocols/TearingControl.hpp
@@ -6,10 +6,11 @@
class CWindow;
class CTearingControlProtocol;
+class CWLSurfaceResource;
class CTearingControl {
public:
- CTearingControl(SP<CWpTearingControlV1> resource_, wlr_surface* surf_);
+ CTearingControl(SP<CWpTearingControlV1> resource_, SP<CWLSurfaceResource> surf_);
void onHint(wpTearingControlV1PresentationHint hint_);
@@ -42,7 +43,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<CWLSurfaceResource> surf);
void onWindowDestroy(PHLWINDOW pWindow);
//
diff --git a/src/protocols/TextInputV1.cpp b/src/protocols/TextInputV1.cpp
index 8fff4db5..7c16ef8c 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 b463c6d6..1302a57f 100644
--- a/src/protocols/TextInputV3.cpp
+++ b/src/protocols/TextInputV3.cpp
@@ -1,5 +1,6 @@
#include "TextInputV3.hpp"
#include <algorithm>
+#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<CWLSurfaceResource> surf) {
+ resource->sendEnter(surf->getResource()->resource());
}
-void CTextInputV3::leave(wlr_surface* surf) {
- resource->sendLeave(surf->resource);
+void CTextInputV3::leave(SP<CWLSurfaceResource> 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 6d4f3d54..3959e72b 100644
--- a/src/protocols/TextInputV3.hpp
+++ b/src/protocols/TextInputV3.hpp
@@ -9,13 +9,15 @@
#include "../helpers/signal/Signal.hpp"
#include "../helpers/Box.hpp"
+class CWLSurfaceResource;
+
class CTextInputV3 {
public:
CTextInputV3(SP<CZwpTextInputV3> resource_);
~CTextInputV3();
- void enter(wlr_surface* surf);
- void leave(wlr_surface* surf);
+ void enter(SP<CWLSurfaceResource> surf);
+ void leave(SP<CWLSurfaceResource> 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/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp
index 14629214..80f9defa 100644
--- a/src/protocols/ToplevelExport.cpp
+++ b/src/protocols/ToplevelExport.cpp
@@ -2,11 +2,12 @@
#include "../Compositor.hpp"
#include "ForeignToplevelWlr.hpp"
#include "../managers/PointerManager.hpp"
+#include "types/WLBuffer.hpp"
+#include "types/Buffer.hpp"
+#include "../helpers/Format.hpp"
#include <algorithm>
-#include "ToplevelExportWlrFuncs.hpp"
-
#define TOPLEVEL_EXPORT_VERSION 2
static void bindManagerInt(wl_client* client, void* data, uint32_t version, uint32_t id) {
@@ -131,8 +132,8 @@ void CToplevelExportProtocolManager::removeFrame(SScreencopyFrame* frame, bool f
std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other == frame; });
wl_resource_set_user_data(frame->resource, nullptr);
- if (frame->buffer && frame->buffer->n_locks > 0)
- wlr_buffer_unlock(frame->buffer);
+ if (frame->buffer && frame->buffer->locked() > 0)
+ frame->buffer->unlock();
removeClient(frame->client, force);
m_lFrames.remove(*frame);
}
@@ -184,7 +185,7 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou
return;
}
- const auto PSHMINFO = drm_get_pixel_format_info(PFRAME->shmFormat);
+ const auto PSHMINFO = FormatUtils::getPixelFormatFromDRM(PFRAME->shmFormat);
if (!PSHMINFO) {
Debug::log(ERR, "No pixel format supported by renderer in capture toplevel");
hyprland_toplevel_export_frame_v1_send_failed(resource);
@@ -203,9 +204,9 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou
wlr_output_effective_resolution(PMONITOR->output, &ow, &oh);
PFRAME->box.transform(PMONITOR->transform, ow, oh).round();
- PFRAME->shmStride = pixel_format_info_min_stride(PSHMINFO, PFRAME->box.w);
+ PFRAME->shmStride = FormatUtils::minStride(PSHMINFO, PFRAME->box.w);
- hyprland_toplevel_export_frame_v1_send_buffer(PFRAME->resource, convert_drm_format_to_wl_shm(PFRAME->shmFormat), PFRAME->box.width, PFRAME->box.height, PFRAME->shmStride);
+ hyprland_toplevel_export_frame_v1_send_buffer(PFRAME->resource, FormatUtils::drmToShm(PFRAME->shmFormat), PFRAME->box.width, PFRAME->box.height, PFRAME->shmStride);
if (PFRAME->dmabufFormat != DRM_FORMAT_INVALID) {
hyprland_toplevel_export_frame_v1_send_linux_dmabuf(PFRAME->resource, PFRAME->dmabufFormat, PFRAME->box.width, PFRAME->box.height);
@@ -238,14 +239,16 @@ void CToplevelExportProtocolManager::copyFrame(wl_client* client, wl_resource* r
return;
}
- const auto PBUFFER = wlr_buffer_try_from_resource(buffer);
+ const auto PBUFFER = CWLBufferResource::fromResource(buffer);
if (!PBUFFER) {
wl_resource_post_error(PFRAME->resource, HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer");
removeFrame(PFRAME);
return;
}
- if (PBUFFER->width != PFRAME->box.width || PBUFFER->height != PFRAME->box.height) {
+ PBUFFER->buffer->lock();
+
+ if (PBUFFER->buffer->size != PFRAME->box.size()) {
wl_resource_post_error(PFRAME->resource, HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer dimensions");
removeFrame(PFRAME);
return;
@@ -257,26 +260,20 @@ void CToplevelExportProtocolManager::copyFrame(wl_client* client, wl_resource* r
return;
}
- wlr_dmabuf_attributes dmabufAttrs;
- void* wlrBufferAccessData;
- uint32_t wlrBufferAccessFormat;
- size_t wlrBufferAccessStride;
- if (wlr_buffer_get_dmabuf(PBUFFER, &dmabufAttrs)) {
- PFRAME->bufferCap = WLR_BUFFER_CAP_DMABUF;
+ if (auto attrs = PBUFFER->buffer->dmabuf(); attrs.success) {
+ PFRAME->bufferDMA = true;
- if (dmabufAttrs.format != PFRAME->dmabufFormat) {
+ if (attrs.format != PFRAME->dmabufFormat) {
wl_resource_post_error(PFRAME->resource, HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer format");
removeFrame(PFRAME);
return;
}
- } else if (wlr_buffer_begin_data_ptr_access(PBUFFER, WLR_BUFFER_DATA_PTR_ACCESS_WRITE, &wlrBufferAccessData, &wlrBufferAccessFormat, &wlrBufferAccessStride)) {
- wlr_buffer_end_data_ptr_access(PBUFFER);
-
- if (wlrBufferAccessFormat != PFRAME->shmFormat) {
+ } else if (auto attrs = PBUFFER->buffer->shm(); attrs.success) {
+ if (attrs.format != PFRAME->shmFormat) {
wl_resource_post_error(PFRAME->resource, HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer format");
removeFrame(PFRAME);
return;
- } else if ((int)wlrBufferAccessStride != PFRAME->shmStride) {
+ } else if ((int)attrs.stride != PFRAME->shmStride) {
wl_resource_post_error(PFRAME->resource, HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer stride");
removeFrame(PFRAME);
return;
@@ -287,7 +284,7 @@ void CToplevelExportProtocolManager::copyFrame(wl_client* client, wl_resource* r
return;
}
- PFRAME->buffer = PBUFFER;
+ PFRAME->buffer = PBUFFER->buffer;
m_vFramesAwaitingWrite.emplace_back(PFRAME);
}
@@ -338,7 +335,7 @@ void CToplevelExportProtocolManager::shareFrame(SScreencopyFrame* frame) {
clock_gettime(CLOCK_MONOTONIC, &now);
uint32_t flags = 0;
- if (frame->bufferCap == WLR_BUFFER_CAP_DMABUF) {
+ if (frame->bufferDMA) {
if (!copyFrameDmabuf(frame, &now)) {
hyprland_toplevel_export_frame_v1_send_failed(frame->resource);
return;
@@ -363,11 +360,8 @@ void CToplevelExportProtocolManager::sendDamage(SScreencopyFrame* frame) {
}
bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* now) {
- void* data;
- uint32_t format;
- size_t stride;
- if (!wlr_buffer_begin_data_ptr_access(frame->buffer, WLR_BUFFER_DATA_PTR_ACCESS_WRITE, &data, &format, &stride))
- return false;
+ auto shm = frame->buffer->shm();
+ auto [pixelData, fmt, bufLen] = frame->buffer->beginDataPtr(0); // no need for end, cuz it's shm
// render the client
const auto PMONITOR = g_pCompositor->getMonitorFromID(frame->pWindow->m_iMonitorID);
@@ -383,10 +377,8 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times
g_pPointerManager->damageCursor(PMONITOR->self.lock());
}
- if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &outFB)) {
- wlr_buffer_end_data_ptr_access(frame->buffer);
+ if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &outFB))
return false;
- }
g_pHyprOpenGL->clear(CColor(0, 0, 0, 1.0));
@@ -398,10 +390,9 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times
if (frame->overlayCursor)
g_pPointerManager->renderSoftwareCursorsFor(PMONITOR->self.lock(), now, fakeDamage, g_pInputManager->getMouseCoordsInternal() - frame->pWindow->m_vRealPosition.value());
- const auto PFORMAT = g_pHyprOpenGL->getPixelFormatFromDRM(format);
+ const auto PFORMAT = FormatUtils::getPixelFormatFromDRM(shm.format);
if (!PFORMAT) {
g_pHyprRenderer->endRender();
- wlr_buffer_end_data_ptr_access(frame->buffer);
return false;
}
@@ -418,9 +409,7 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times
glPixelStorei(GL_PACK_ALIGNMENT, 1);
- glReadPixels(0, 0, frame->box.width, frame->box.height, PFORMAT->glFormat, PFORMAT->glType, data);
-
- wlr_buffer_end_data_ptr_access(frame->buffer);
+ glReadPixels(0, 0, frame->box.width, frame->box.height, PFORMAT->glFormat, PFORMAT->glType, pixelData);
if (frame->overlayCursor) {
g_pPointerManager->unlockSoftwareForMonitor(PMONITOR->self.lock());
@@ -435,7 +424,7 @@ bool CToplevelExportProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame, ti
CRegion fakeDamage{0, 0, INT16_MAX, INT16_MAX};
- if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer))
+ if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer.lock()))
return false;
g_pHyprOpenGL->clear(CColor(0, 0, 0, 1.0));
diff --git a/src/protocols/ToplevelExportWlrFuncs.hpp b/src/protocols/ToplevelExportWlrFuncs.hpp
deleted file mode 100644
index b6f387e8..00000000
--- a/src/protocols/ToplevelExportWlrFuncs.hpp
+++ /dev/null
@@ -1,243 +0,0 @@
-#include <GLES2/gl2ext.h>
-
-#ifndef DRM_WLR_FUNCS
-#define DRM_WLR_FUNCS
-
-struct wlr_pixel_format_info {
- uint32_t drm_format;
-
- /* Equivalent of the format if it has an alpha channel,
- * DRM_FORMAT_INVALID (0) if NA
- */
- uint32_t opaque_substitute;
-
- /* Bytes per block (including padding) */
- uint32_t bytes_per_block;
- /* Size of a block in pixels (zero for 1×1) */
- uint32_t block_width, block_height;
-
- /* True if the format has an alpha channel */
- bool has_alpha;
-};
-
-static const struct wlr_pixel_format_info pixel_format_info[] = {
- {
- .drm_format = DRM_FORMAT_XRGB8888,
- .bytes_per_block = 4,
- },
- {
- .drm_format = DRM_FORMAT_ARGB8888,
- .opaque_substitute = DRM_FORMAT_XRGB8888,
- .bytes_per_block = 4,
- .has_alpha = true,
- },
- {
- .drm_format = DRM_FORMAT_XBGR8888,
- .bytes_per_block = 4,
- },
- {
- .drm_format = DRM_FORMAT_ABGR8888,
- .opaque_substitute = DRM_FORMAT_XBGR8888,
- .bytes_per_block = 4,
- .has_alpha = true,
- },
- {
- .drm_format = DRM_FORMAT_RGBX8888,
- .bytes_per_block = 4,
- },
- {
- .drm_format = DRM_FORMAT_RGBA8888,
- .opaque_substitute = DRM_FORMAT_RGBX8888,
- .bytes_per_block = 4,
- .has_alpha = true,
- },
- {
- .drm_format = DRM_FORMAT_BGRX8888,
- .bytes_per_block = 4,
- },
- {
- .drm_format = DRM_FORMAT_BGRA8888,
- .opaque_substitute = DRM_FORMAT_BGRX8888,
- .bytes_per_block = 4,
- .has_alpha = true,
- },
- {
- .drm_format = DRM_FORMAT_R8,
- .bytes_per_block = 1,
- },
- {
- .drm_format = DRM_FORMAT_GR88,
- .bytes_per_block = 2,
- },
- {
- .drm_format = DRM_FORMAT_RGB888,
- .bytes_per_block = 3,
- },
- {
- .drm_format = DRM_FORMAT_BGR888,
- .bytes_per_block = 3,
- },
- {
- .drm_format = DRM_FORMAT_RGBX4444,
- .bytes_per_block = 2,
- },
- {
- .drm_format = DRM_FORMAT_RGBA4444,
- .opaque_substitute = DRM_FORMAT_RGBX4444,
- .bytes_per_block = 2,
- .has_alpha = true,
- },
- {
- .drm_format = DRM_FORMAT_BGRX4444,
- .bytes_per_block = 2,
- },
- {
- .drm_format = DRM_FORMAT_BGRA4444,
- .opaque_substitute = DRM_FORMAT_BGRX4444,
- .bytes_per_block = 2,
- .has_alpha = true,
- },
- {
- .drm_format = DRM_FORMAT_RGBX5551,
- .bytes_per_block = 2,
- },
- {
- .drm_format = DRM_FORMAT_RGBA5551,
- .opaque_substitute = DRM_FORMAT_RGBX5551,
- .bytes_per_block = 2,
- .has_alpha = true,
- },
- {
- .drm_format = DRM_FORMAT_BGRX5551,
- .bytes_per_block = 2,
- },
- {
- .drm_format = DRM_FORMAT_BGRA5551,
- .opaque_substitute = DRM_FORMAT_BGRX5551,
- .bytes_per_block = 2,
- .has_alpha = true,
- },
- {
- .drm_format = DRM_FORMAT_XRGB1555,
- .bytes_per_block = 2,
- },
- {
- .drm_format = DRM_FORMAT_ARGB1555,
- .opaque_substitute = DRM_FORMAT_XRGB1555,
- .bytes_per_block = 2,
- .has_alpha = true,
- },
- {
- .drm_format = DRM_FORMAT_RGB565,
- .bytes_per_block = 2,
- },
- {
- .drm_format = DRM_FORMAT_BGR565,
- .bytes_per_block = 2,
- },
- {
- .drm_format = DRM_FORMAT_XRGB2101010,
- .bytes_per_block = 4,
- },
- {
- .drm_format = DRM_FORMAT_ARGB2101010,
- .opaque_substitute = DRM_FORMAT_XRGB2101010,
- .bytes_per_block = 4,
- .has_alpha = true,
- },
- {
- .drm_format = DRM_FORMAT_XBGR2101010,
- .bytes_per_block = 4,
- },
- {
- .drm_format = DRM_FORMAT_ABGR2101010,
- .opaque_substitute = DRM_FORMAT_XBGR2101010,
- .bytes_per_block = 4,
- .has_alpha = true,
- },
- {
- .drm_format = DRM_FORMAT_XBGR16161616F,
- .bytes_per_block = 8,
- },
- {
- .drm_format = DRM_FORMAT_ABGR16161616F,
- .opaque_substitute = DRM_FORMAT_XBGR16161616F,
- .bytes_per_block = 8,
- .has_alpha = true,
- },
- {
- .drm_format = DRM_FORMAT_XBGR16161616,
- .bytes_per_block = 8,
- },
- {
- .drm_format = DRM_FORMAT_ABGR16161616,
- .opaque_substitute = DRM_FORMAT_XBGR16161616,
- .bytes_per_block = 8,
- .has_alpha = true,
- },
- {
- .drm_format = DRM_FORMAT_YVYU,
- .bytes_per_block = 4,
- .block_width = 2,
- .block_height = 1,
- },
- {
- .drm_format = DRM_FORMAT_VYUY,
- .bytes_per_block = 4,
- .block_width = 2,
- .block_height = 1,
- },
-};
-
-static const size_t pixel_format_info_size = sizeof(pixel_format_info) / sizeof(pixel_format_info[0]);
-
-static const struct wlr_pixel_format_info* drm_get_pixel_format_info(uint32_t fmt) {
- for (size_t i = 0; i < pixel_format_info_size; ++i) {
- if (pixel_format_info[i].drm_format == fmt) {
- return &pixel_format_info[i];
- }
- }
-
- return NULL;
-}
-
-/*static uint32_t convert_wl_shm_format_to_drm(enum wl_shm_format fmt) {
- switch (fmt) {
- case WL_SHM_FORMAT_XRGB8888: return DRM_FORMAT_XRGB8888;
- case WL_SHM_FORMAT_ARGB8888: return DRM_FORMAT_ARGB8888;
- default: return (uint32_t)fmt;
- }
-}*/
-
-static enum wl_shm_format convert_drm_format_to_wl_shm(uint32_t fmt) {
- switch (fmt) {
- case DRM_FORMAT_XRGB8888: return WL_SHM_FORMAT_XRGB8888;
- case DRM_FORMAT_ARGB8888: return WL_SHM_FORMAT_ARGB8888;
- default: return (enum wl_shm_format)fmt;
- }
-}
-
-static uint32_t pixel_format_info_pixels_per_block(const struct wlr_pixel_format_info* info) {
- uint32_t pixels = info->block_width * info->block_height;
- return pixels > 0 ? pixels : 1;
-}
-
-static int32_t div_round_up(int32_t dividend, int32_t divisor) {
- int32_t quotient = dividend / divisor;
- if (dividend % divisor != 0) {
- quotient++;
- }
- return quotient;
-}
-
-static int32_t pixel_format_info_min_stride(const wlr_pixel_format_info* fmt, int32_t width) {
- int32_t pixels_per_block = (int32_t)pixel_format_info_pixels_per_block(fmt);
- int32_t bytes_per_block = (int32_t)fmt->bytes_per_block;
- if (width > INT32_MAX / bytes_per_block) {
- wlr_log(WLR_DEBUG, "Invalid width %d (overflow)", width);
- return 0;
- }
- return div_round_up(width * bytes_per_block, pixels_per_block);
-}
-
-#endif \ No newline at end of file
diff --git a/src/protocols/Viewporter.cpp b/src/protocols/Viewporter.cpp
new file mode 100644
index 00000000..8cb69dbe
--- /dev/null
+++ b/src/protocols/Viewporter.cpp
@@ -0,0 +1,126 @@
+#include "Viewporter.hpp"
+#include "core/Compositor.hpp"
+#include <algorithm>
+
+#define LOGM PROTO::viewport->protoLog
+
+CViewportResource::CViewportResource(SP<CWpViewport> resource_, SP<CWLSurfaceResource> 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;
+ }
+
+ 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();
+}
+
+void CViewportResource::verify() {
+ if (!surface)
+ return;
+
+ if (surface->pending.viewport.hasSource) {
+ auto& src = surface->pending.viewport.source;
+
+ if (src.w + src.x > surface->pending.size.x || src.h + src.y > surface->pending.size.y) {
+ resource->error(WP_VIEWPORT_ERROR_BAD_VALUE, "Box doesn't fit");
+ return;
+ }
+ }
+}
+
+CViewporterResource::CViewporterResource(SP<CWpViewporter> 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<CViewportResource>(makeShared<CWpViewport>(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<CViewporterResource>(makeShared<CWpViewporter>(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 00000000..01278203
--- /dev/null
+++ b/src/protocols/Viewporter.hpp
@@ -0,0 +1,55 @@
+#pragma once
+
+#include <memory>
+#include <vector>
+#include <cstdint>
+#include "WaylandProtocol.hpp"
+#include "viewporter.hpp"
+#include "../helpers/signal/Signal.hpp"
+
+class CWLSurfaceResource;
+
+class CViewportResource {
+ public:
+ CViewportResource(SP<CWpViewport> resource_, SP<CWLSurfaceResource> surface_);
+ ~CViewportResource();
+
+ bool good();
+ void verify();
+ WP<CWLSurfaceResource> surface;
+
+ private:
+ SP<CWpViewport> resource;
+};
+
+class CViewporterResource {
+ public:
+ CViewporterResource(SP<CWpViewporter> resource_);
+
+ bool good();
+
+ private:
+ SP<CWpViewporter> 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<SP<CViewporterResource>> m_vManagers;
+ std::vector<SP<CViewportResource>> m_vViewports;
+
+ friend class CViewporterResource;
+ friend class CViewportResource;
+};
+
+namespace PROTO {
+ inline UP<CViewporterProtocol> viewport;
+};
diff --git a/src/protocols/WaylandProtocol.cpp b/src/protocols/WaylandProtocol.cpp
index 30120235..23a6721c 100644
--- a/src/protocols/WaylandProtocol.cpp
+++ b/src/protocols/WaylandProtocol.cpp
@@ -10,6 +10,8 @@ static void displayDestroyInternal(struct wl_listener* listener, void* data) {
}
void IWaylandProtocol::onDisplayDestroy() {
+ wl_list_remove(&m_liDisplayDestroy.link);
+ wl_list_init(&m_liDisplayDestroy.link);
wl_global_destroy(m_pGlobal);
}
@@ -30,3 +32,7 @@ IWaylandProtocol::IWaylandProtocol(const wl_interface* iface, const int& ver, co
IWaylandProtocol::~IWaylandProtocol() {
onDisplayDestroy();
}
+
+void IWaylandProtocol::removeGlobal() {
+ wl_global_remove(m_pGlobal);
+}
diff --git a/src/protocols/WaylandProtocol.hpp b/src/protocols/WaylandProtocol.hpp
index a7487c15..b443e253 100644
--- a/src/protocols/WaylandProtocol.hpp
+++ b/src/protocols/WaylandProtocol.hpp
@@ -14,9 +14,10 @@
class IWaylandProtocol {
public:
IWaylandProtocol(const wl_interface* iface, const int& ver, const std::string& name);
- ~IWaylandProtocol();
+ virtual ~IWaylandProtocol();
virtual void onDisplayDestroy();
+ virtual void removeGlobal();
virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) = 0;
diff --git a/src/protocols/XDGActivation.cpp b/src/protocols/XDGActivation.cpp
index 1d9814ac..40f33f02 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 <algorithm>
#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<CWLSurfaceResource> 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 771f5f78..03e58956 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 80e3487d..97de49f6 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<CXdgSurface> resource_, SP<CXDGWMBase> owner_, wlr_surface* surface_) : owner(owner_), surface(surface_), resource(resource_) {
+CXDGSurfaceResource::CXDGSurfaceResource(SP<CXdgSurface> resource_, SP<CXDGWMBase> owner_, SP<CWLSurfaceResource> surface_) :
+ owner(owner_), surface(surface_), resource(resource_) {
if (!good())
return;
@@ -307,56 +309,50 @@ CXDGSurfaceResource::CXDGSurfaceResource(SP<CXdgSurface> resource_, SP<CXDGWMBas
PROTO::xdgShell->destroyResource(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<CXDGToplevelResource>(makeShared<CXdgToplevel>(r->client(), r->version(), id), self.lock()));
@@ -649,7 +645,7 @@ CXDGWMBase::CXDGWMBase(SP<CXdgWmBase> resource_) : resource(resource_) {
resource->setGetXdgSurface([this](CXdgWmBase* r, uint32_t id, wl_resource* surf) {
const auto RESOURCE = PROTO::xdgShell->m_vSurfaces.emplace_back(
- makeShared<CXDGSurfaceResource>(makeShared<CXdgSurface>(r->client(), r->version(), id), self.lock(), wlr_surface_from_resource(surf)));
+ makeShared<CXDGSurfaceResource>(makeShared<CXdgSurface>(r->client(), r->version(), id), self.lock(), CWLSurfaceResource::fromResource(surf)));
if (!RESOURCE->good()) {
r->noMemory();
@@ -724,9 +720,9 @@ void CXDGShellProtocol::addOrStartGrab(SP<CXDGPopupResource> 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<CXDGPopupResource> 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<CXDGPopupResource> popup) {
@@ -752,5 +748,5 @@ void CXDGShellProtocol::onPopupDestroy(WP<CXDGPopupResource> 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 1dbeb209..fe2517a2 100644
--- a/src/protocols/XDGShell.hpp
+++ b/src/protocols/XDGShell.hpp
@@ -16,6 +16,7 @@ class CXDGSurfaceResource;
class CXDGToplevelResource;
class CXDGPopupResource;
class CSeatGrab;
+class CWLSurfaceResource;
struct SXDGPositionerState {
Vector2D requestedSize;
@@ -138,7 +139,7 @@ class CXDGToplevelResource {
class CXDGSurfaceResource {
public:
- CXDGSurfaceResource(SP<CXdgSurface> resource_, SP<CXDGWMBase> owner_, wlr_surface* surface_);
+ CXDGSurfaceResource(SP<CXdgSurface> resource_, SP<CXDGWMBase> owner_, SP<CWLSurfaceResource> surface_);
~CXDGSurfaceResource();
static SP<CXDGSurfaceResource> fromResource(wl_resource*);
@@ -146,7 +147,7 @@ class CXDGSurfaceResource {
bool good();
WP<CXDGWMBase> owner;
- wlr_surface* surface = nullptr;
+ WP<CWLSurfaceResource> surface;
WP<CXDGToplevelResource> toplevel;
WP<CXDGPopupResource> popup;
@@ -184,8 +185,10 @@ class CXDGSurfaceResource {
//
std::vector<WP<CXDGPopupResource>> 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 8b9905f8..6cc5256f 100644
--- a/src/protocols/XWaylandShell.cpp
+++ b/src/protocols/XWaylandShell.cpp
@@ -1,9 +1,10 @@
#include "XWaylandShell.hpp"
+#include "core/Compositor.hpp"
#include <algorithm>
#define LOGM PROTO::xwaylandShell->protoLog
-CXWaylandSurfaceResource::CXWaylandSurfaceResource(SP<CXwaylandSurfaceV1> resource_, wlr_surface* surface_) : surface(surface_), resource(resource_) {
+CXWaylandSurfaceResource::CXWaylandSurfaceResource(SP<CXwaylandSurfaceV1> resource_, SP<CWLSurfaceResource> surface_) : surface(surface_), resource(resource_) {
if (!good())
return;
@@ -45,7 +46,7 @@ CXWaylandShellResource::CXWaylandShellResource(SP<CXwaylandShellV1> resource_) :
resource->setGetXwaylandSurface([this](CXwaylandShellV1* r, uint32_t id, wl_resource* surface) {
const auto RESOURCE = PROTO::xwaylandShell->m_vSurfaces.emplace_back(
- makeShared<CXWaylandSurfaceResource>(makeShared<CXwaylandSurfaceV1>(r->client(), r->version(), id), wlr_surface_from_resource(surface)));
+ makeShared<CXWaylandSurfaceResource>(makeShared<CXwaylandSurfaceV1>(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 2c03d172..c8c0c04a 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<CXwaylandSurfaceV1> resource_, wlr_surface* surface_);
+ CXWaylandSurfaceResource(SP<CXwaylandSurfaceV1> resource_, SP<CWLSurfaceResource> 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<CWLSurfaceResource> surface;
WP<CXWaylandSurfaceResource> self;
diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp
new file mode 100644
index 00000000..e8503ae8
--- /dev/null
+++ b/src/protocols/core/Compositor.cpp
@@ -0,0 +1,467 @@
+#include "Compositor.hpp"
+#include "Output.hpp"
+#include "../types/WLBuffer.hpp"
+#include <algorithm>
+#include <ranges>
+#include "Subcompositor.hpp"
+#include "../Viewporter.hpp"
+#include "../../helpers/Monitor.hpp"
+
+#define LOGM PROTO::compositor->protoLog
+
+class CDefaultSurfaceRole : public ISurfaceRole {
+ public:
+ virtual eSurfaceRole role() {
+ return SURFACE_ROLE_UNASSIGNED;
+ }
+};
+
+SP<CDefaultSurfaceRole> defaultRole = makeShared<CDefaultSurfaceRole>();
+
+CWLCallbackResource::CWLCallbackResource(SP<CWlCallback> 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<CWlRegion> resource_) : resource(resource_) {
+ if (!good())
+ return;
+
+ resource->setData(this);
+
+ 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();
+}
+
+SP<CWLRegionResource> CWLRegionResource::fromResource(wl_resource* res) {
+ auto data = (CWLRegionResource*)(((CWlRegion*)wl_resource_get_user_data(res))->data());
+ return data ? data->self.lock() : nullptr;
+}
+
+CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : resource(resource_) {
+ if (!good())
+ return;
+
+ pClient = resource->client();
+
+ resource->setData(this);
+
+ role = defaultRole;
+
+ resource->setDestroy([this](CWlSurface* r) { destroy(); });
+ resource->setOnDestroy([this](CWlSurface* r) { destroy(); });
+
+ resource->setAttach([this](CWlSurface* r, wl_resource* buffer, int32_t x, int32_t y) {
+ pending.offset = {x, y};
+
+ if (!buffer) {
+ pending.buffer.reset();
+ pending.texture.reset();
+ } else {
+ auto res = CWLBufferResource::fromResource(buffer);
+ pending.buffer = res && res->buffer ? res->buffer.lock() : nullptr;
+ pending.size = res && res->buffer ? res->buffer->size : Vector2D{};
+ pending.texture = res && res->buffer ? res->buffer->texture : nullptr;
+ }
+
+ Vector2D oldBufSize = current.buffer ? current.buffer->size : Vector2D{};
+ Vector2D newBufSize = pending.buffer ? pending.buffer->size : Vector2D{};
+
+ if (oldBufSize != newBufSize)
+ pending.bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}};
+
+ bufferReleased = false;
+ });
+
+ resource->setCommit([this](CWlSurface* r) {
+ if (pending.buffer)
+ pending.bufferDamage.intersect(CBox{{}, pending.buffer->size});
+
+ if (!pending.buffer)
+ pending.size = {};
+ else if (pending.viewport.hasDestination)
+ pending.size = pending.viewport.destination;
+ else if (pending.viewport.hasSource)
+ pending.size = pending.viewport.source.size();
+ else {
+ Vector2D tfs = pending.transform % 2 == 1 ? Vector2D{pending.buffer->size.y, pending.buffer->size.x} : pending.buffer->size;
+ pending.size = tfs / pending.scale;
+ }
+
+ if (viewportResource)
+ viewportResource->verify();
+
+ pending.damage.intersect(CBox{{}, pending.size});
+
+ CRegion previousBufferDamage = accumulateCurrentBufferDamage();
+
+ current = pending;
+ pending.damage.clear();
+ pending.bufferDamage.clear();
+
+ if (current.buffer && !bufferReleased) {
+ // without previous dolphin et al are weird vvv
+ //CRegion surfaceDamage =
+ // current.damage.copy().scale(current.scale).transform(current.transform, current.size.x, current.size.y).add(current.bufferDamage).add(previousBufferDamage);
+ current.buffer->update(CBox{{}, {INT32_MAX, INT32_MAX}}); // FIXME: figure this out to not use this hack. QT apps are wonky without this.
+
+ // release the buffer, glTexImage2D is synchronous (as in, data is consumed after the call returns)
+ // so we can let the app know we're done.
+ // for dma buffers, this doesn't matter.
+ current.buffer->sendRelease();
+ bufferReleased = true;
+ }
+
+ // TODO: we should _accumulate_ and not replace above if sync
+ if (role->role() == SURFACE_ROLE_SUBSURFACE) {
+ auto subsurface = (CWLSubsurfaceResource*)role.get();
+ if (subsurface->sync)
+ return;
+
+ events.commit.emit();
+ } else {
+ // send commit to all synced surfaces in this tree.
+ breadthfirst(
+ [](SP<CWLSurfaceResource> surf, const Vector2D& offset, void* data) {
+ if (surf->role->role() == SURFACE_ROLE_SUBSURFACE) {
+ auto subsurface = (CWLSubsurfaceResource*)surf->role.get();
+ if (!subsurface->sync)
+ return;
+ }
+ surf->events.commit.emit();
+ },
+ nullptr);
+ }
+ });
+
+ 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->setSetInputRegion([this](CWlSurface* r, wl_resource* region) {
+ if (!region) {
+ pending.input = CBox{{}, {INT32_MAX, INT32_MAX}};
+ return;
+ }
+
+ auto RG = CWLRegionResource::fromResource(region);
+ pending.input = RG->region;
+ });
+
+ resource->setSetOpaqueRegion([this](CWlSurface* r, wl_resource* region) {
+ if (!region) {
+ pending.opaque = CBox{{}, {}};
+ return;
+ }
+
+ auto RG = CWLRegionResource::fromResource(region);
+ pending.opaque = RG->region;
+ });
+
+ resource->setFrame([this](CWlSurface* r, uint32_t id) { callbacks.emplace_back(makeShared<CWLCallbackResource>(makeShared<CWlCallback>(pClient, 1, id))); });
+
+ resource->setOffset([this](CWlSurface* r, int32_t x, int32_t y) { pending.offset = {x, y}; });
+}
+
+CWLSurfaceResource::~CWLSurfaceResource() {
+ events.destroy.emit();
+}
+
+void CWLSurfaceResource::destroy() {
+ if (mapped)
+ unmap();
+ events.destroy.emit();
+ PROTO::compositor->destroyResource(this);
+}
+
+SP<CWLSurfaceResource> 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<CMonitor> monitor) {
+ if (std::find(enteredOutputs.begin(), enteredOutputs.end(), monitor) != enteredOutputs.end())
+ return;
+
+ if (!PROTO::outputs.contains(monitor->szName)) {
+ // can happen on unplug/replug
+ LOGM(ERR, "enter() called on a non-existent output global");
+ return;
+ }
+
+ auto output = PROTO::outputs.at(monitor->szName)->outputResourceFrom(pClient);
+
+ if (!output || !output->getResource() || !output->getResource()->resource()) {
+ 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<CMonitor> 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 (callbacks.empty())
+ return;
+
+ for (auto& c : callbacks) {
+ c->send(now);
+ }
+
+ callbacks.clear();
+}
+
+void CWLSurfaceResource::resetRole() {
+ role = defaultRole;
+}
+
+void CWLSurfaceResource::bfHelper(std::vector<SP<CWLSurfaceResource>> nodes, std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data) {
+ for (auto& n : nodes) {
+
+ Vector2D offset = {};
+ if (n->role->role() == SURFACE_ROLE_SUBSURFACE) {
+ auto subsurface = (CWLSubsurfaceResource*)n->role.get();
+ offset = subsurface->posRelativeToParent();
+ }
+
+ fn(n, offset, data);
+ }
+
+ std::vector<SP<CWLSurfaceResource>> nodes2;
+
+ for (auto& n : nodes) {
+ std::erase_if(n->subsurfaces, [](const auto& e) { return e.expired(); });
+ for (auto& c : n->subsurfaces) {
+ nodes2.push_back(c->surface.lock());
+ }
+ }
+
+ if (!nodes2.empty())
+ bfHelper(nodes2, fn, data);
+}
+
+void CWLSurfaceResource::breadthfirst(std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data) {
+ std::vector<SP<CWLSurfaceResource>> surfs;
+ surfs.push_back(self.lock());
+ bfHelper(surfs, fn, data);
+}
+
+std::pair<SP<CWLSurfaceResource>, Vector2D> CWLSurfaceResource::at(const Vector2D& localCoords, bool allowsInput) {
+ std::vector<std::pair<SP<CWLSurfaceResource>, Vector2D>> surfs;
+ breadthfirst([](SP<CWLSurfaceResource> surf, const Vector2D& offset,
+ void* data) { ((std::vector<std::pair<SP<CWLSurfaceResource>, Vector2D>>*)data)->emplace_back(std::make_pair<>(surf, offset)); },
+ &surfs);
+
+ for (auto& [surf, pos] : surfs | std::views::reverse) {
+ if (!allowsInput) {
+ const auto BOX = CBox{pos, surf->current.size};
+ if (BOX.containsPoint(localCoords))
+ return {surf, localCoords - pos};
+ } else {
+ const auto REGION = surf->current.input.copy().intersect(CBox{{}, surf->current.size}).translate(pos);
+ if (REGION.containsPoint(localCoords))
+ return {surf, localCoords - pos};
+ }
+ }
+
+ return {nullptr, {}};
+}
+
+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);
+
+ current.bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}};
+ pending.bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}};
+}
+
+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<CWlSurface> CWLSurfaceResource::getResource() {
+ return resource;
+}
+
+CBox CWLSurfaceResource::extends() {
+ CRegion full = CBox{{}, current.size};
+ breadthfirst(
+ [](SP<CWLSurfaceResource> surf, const Vector2D& offset, void* d) {
+ if (surf->role->role() != SURFACE_ROLE_SUBSURFACE)
+ return;
+
+ ((CRegion*)d)->add(CBox{offset, surf->current.size});
+ },
+ &full);
+ return full.getExtents();
+}
+
+Vector2D CWLSurfaceResource::sourceSize() {
+ if (!current.buffer)
+ return {};
+
+ if (current.viewport.hasSource)
+ return current.viewport.source.size();
+
+ Vector2D trc = current.transform % 2 == 1 ? Vector2D{current.buffer->size.y, current.buffer->size.x} : current.buffer->size;
+ return trc / current.scale;
+}
+
+CRegion CWLSurfaceResource::accumulateCurrentBufferDamage() {
+ if (!current.buffer)
+ return {};
+
+ CRegion surfaceDamage = current.damage;
+ if (current.viewport.hasDestination) {
+ Vector2D scale = sourceSize() / current.viewport.destination;
+ surfaceDamage.scale(scale);
+ }
+
+ if (current.viewport.hasSource)
+ surfaceDamage.translate(current.viewport.source.pos());
+
+ Vector2D trc = current.transform % 2 == 1 ? Vector2D{current.buffer->size.y, current.buffer->size.x} : current.buffer->size;
+
+ return surfaceDamage.scale(current.scale).transform(wlr_output_transform_invert(current.transform), trc.x, trc.y).add(current.bufferDamage);
+}
+
+CWLCompositorResource::CWLCompositorResource(SP<CWlCompositor> 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<CWLSurfaceResource>(makeShared<CWlSurface>(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<CWLRegionResource>(makeShared<CWlRegion>(r->client(), r->version(), id)));
+
+ if (!RESOURCE->good()) {
+ r->noMemory();
+ PROTO::compositor->m_vRegions.pop_back();
+ return;
+ }
+
+ RESOURCE->self = RESOURCE;
+
+ 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<CWLCompositorResource>(makeShared<CWlCompositor>(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 00000000..f50144bf
--- /dev/null
+++ b/src/protocols/core/Compositor.hpp
@@ -0,0 +1,175 @@
+#pragma once
+
+/*
+ Implementations for:
+ - wl_compositor
+ - wl_surface
+ - wl_region
+ - wl_callback
+*/
+
+#include <memory>
+#include <vector>
+#include <cstdint>
+#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 CViewportResource;
+
+class CWLCallbackResource {
+ public:
+ CWLCallbackResource(SP<CWlCallback> resource_);
+
+ bool good();
+ void send(timespec* now);
+
+ private:
+ SP<CWlCallback> resource;
+};
+
+class CWLRegionResource {
+ public:
+ CWLRegionResource(SP<CWlRegion> resource_);
+ static SP<CWLRegionResource> fromResource(wl_resource* res);
+
+ bool good();
+
+ CRegion region;
+ WP<CWLRegionResource> self;
+
+ private:
+ SP<CWlRegion> resource;
+};
+
+class CWLSurfaceResource {
+ public:
+ CWLSurfaceResource(SP<CWlSurface> resource_);
+ ~CWLSurfaceResource();
+
+ static SP<CWLSurfaceResource> fromResource(wl_resource* res);
+
+ bool good();
+ wl_client* client();
+ void enter(SP<CMonitor> monitor);
+ void leave(SP<CMonitor> 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<CWlSurface> getResource();
+ CBox extends();
+ void resetRole();
+ Vector2D sourceSize();
+
+ struct {
+ CSignal commit;
+ CSignal map;
+ CSignal unmap;
+ CSignal newSubsurface;
+ CSignal destroy;
+ } events;
+
+ struct {
+ 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<IWLBuffer> buffer;
+ SP<CTexture> texture;
+ Vector2D offset;
+ Vector2D size;
+ struct {
+ bool hasDestination = false;
+ bool hasSource = false;
+ Vector2D destination;
+ CBox source;
+ } viewport;
+
+ //
+ void reset() {
+ damage.clear();
+ bufferDamage.clear();
+ transform = WL_OUTPUT_TRANSFORM_NORMAL;
+ scale = 1;
+ offset = {};
+ size = {};
+ }
+ } current, pending;
+
+ std::vector<SP<CWLCallbackResource>> callbacks;
+ WP<CWLSurfaceResource> self;
+ WP<CWLSurface> hlSurface;
+ std::vector<WP<CMonitor>> enteredOutputs;
+ bool mapped = false;
+ std::vector<WP<CWLSubsurfaceResource>> subsurfaces;
+ WP<ISurfaceRole> role;
+ WP<CViewportResource> viewportResource;
+
+ void breadthfirst(std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data);
+ CRegion accumulateCurrentBufferDamage();
+
+ // returns a pair: found surface (null if not found) and surface local coords.
+ // localCoords param is relative to 0,0 of this surface
+ std::pair<SP<CWLSurfaceResource>, Vector2D> at(const Vector2D& localCoords, bool allowsInput = false);
+
+ private:
+ SP<CWlSurface> resource;
+ wl_client* pClient = nullptr;
+
+ // tracks whether we should release the buffer
+ bool bufferReleased = false;
+
+ void destroy();
+ void bfHelper(std::vector<SP<CWLSurfaceResource>> nodes, std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data);
+};
+
+class CWLCompositorResource {
+ public:
+ CWLCompositorResource(SP<CWlCompositor> resource_);
+
+ bool good();
+
+ private:
+ SP<CWlCompositor> 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<CWLSurfaceResource>
+ } events;
+
+ private:
+ void destroyResource(CWLCompositorResource* resource);
+ void destroyResource(CWLSurfaceResource* resource);
+ void destroyResource(CWLRegionResource* resource);
+
+ //
+ std::vector<SP<CWLCompositorResource>> m_vManagers;
+ std::vector<SP<CWLSurfaceResource>> m_vSurfaces;
+ std::vector<SP<CWLRegionResource>> m_vRegions;
+
+ friend class CWLSurfaceResource;
+ friend class CWLCompositorResource;
+ friend class CWLRegionResource;
+ friend class CWLCallbackResource;
+};
+
+namespace PROTO {
+ inline UP<CWLCompositorProtocol> compositor;
+};
diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp
index 354259fe..ca044e93 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<CWlDataDevice> 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<CWLDataOfferResource> offer) {
resource->sendDataOfferRaw(nullptr);
}
-void CWLDataDeviceResource::sendEnter(uint32_t serial, wlr_surface* surf, const Vector2D& local, SP<CWLDataOfferResource> 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<CWLSurfaceResource> surf, const Vector2D& local, SP<CWLDataOfferResource> 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<CWLDataSourceResource> currentSource, wlr_surface* dragSurface, wlr_surface* origin) {
+void CWLDataDeviceProtocol::initiateDrag(WP<CWLDataSourceResource> currentSource, SP<CWLSurfaceResource> dragSurface, SP<CWLSurfaceResource> origin) {
if (dnd.currentSource) {
LOGM(WARN, "New drag started while old drag still active??");
@@ -472,22 +473,18 @@ void CWLDataDeviceProtocol::initiateDrag(WP<CWLDataSourceResource> 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<CWLDataSourceResource> currentSource
dnd.mouseMove = g_pHookSystem->hookDynamic("mouseMove", [this](void* self, SCallbackInfo& info, std::any e) {
auto V = std::any_cast<const Vector2D>(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<CWLDataSourceResource> currentSource
dnd.touchMove = g_pHookSystem->hookDynamic("touchMove", [this](void* self, SCallbackInfo& info, std::any e) {
auto E = std::any_cast<ITouch::SMotionEvent>(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 || !dnd.dndSurface->current.buffer->texture)
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 3112b720..f31725ee 100644
--- a/src/protocols/core/DataDevice.hpp
+++ b/src/protocols/core/DataDevice.hpp
@@ -23,6 +23,7 @@ class CWLDataDeviceManagerResource;
class CWLDataSourceResource;
class CWLDataOfferResource;
+class CWLSurfaceResource;
class CMonitor;
class CWLDataOfferResource {
@@ -92,7 +93,7 @@ class CWLDataDeviceResource {
wl_client* client();
void sendDataOffer(SP<CWLDataOfferResource> offer);
- void sendEnter(uint32_t serial, wlr_surface* surf, const Vector2D& local, SP<CWLDataOfferResource> offer);
+ void sendEnter(uint32_t serial, SP<CWLSurfaceResource> surf, const Vector2D& local, SP<CWLDataOfferResource> offer);
void sendLeave();
void sendMotion(uint32_t timeMs, const Vector2D& local);
void sendDrop();
@@ -155,11 +156,11 @@ class CWLDataDeviceProtocol : public IWaylandProtocol {
struct {
WP<CWLDataDeviceResource> focusedDevice;
WP<CWLDataSourceResource> currentSource;
- wlr_surface* dndSurface = nullptr;
- wlr_surface* originSurface = nullptr; // READ-ONLY
+ WP<CWLSurfaceResource> dndSurface;
+ WP<CWLSurfaceResource> originSurface;
bool overriddenCursor = false;
- DYNLISTENER(dndSurfaceDestroy);
- DYNLISTENER(dndSurfaceCommit);
+ CHyprSignalListener dndSurfaceDestroy;
+ CHyprSignalListener dndSurfaceCommit;
// for ending a dnd
SP<HOOK_CALLBACK_FN> mouseMove;
@@ -169,7 +170,7 @@ class CWLDataDeviceProtocol : public IWaylandProtocol {
} dnd;
void abortDrag();
- void initiateDrag(WP<CWLDataSourceResource> currentSource, wlr_surface* dragSurface, wlr_surface* origin);
+ void initiateDrag(WP<CWLDataSourceResource> currentSource, SP<CWLSurfaceResource> dragSurface, SP<CWLSurfaceResource> 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 00000000..3778e453
--- /dev/null
+++ b/src/protocols/core/Output.cpp
@@ -0,0 +1,107 @@
+#include "Output.hpp"
+#include "../../helpers/Monitor.hpp"
+
+CWLOutputResource::CWLOutputResource(SP<CWlOutput> resource_, SP<CMonitor> 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(0, 0, 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());
+ }
+
+ updateState();
+}
+
+SP<CWLOutputResource> 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<CWlOutput> CWLOutputResource::getResource() {
+ return resource;
+}
+
+void CWLOutputResource::updateState() {
+ if (!monitor)
+ return;
+
+ if (resource->version() >= 2)
+ resource->sendScale(std::ceil(monitor->scale));
+
+ resource->sendMode((wl_output_mode)(WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED), monitor->vecSize.x, monitor->vecSize.y, monitor->refreshRate * 1000.0);
+
+ if (resource->version() >= 2)
+ resource->sendDone();
+}
+
+CWLOutputProtocol::CWLOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name, SP<CMonitor> pMonitor) :
+ IWaylandProtocol(iface, ver, name), monitor(pMonitor), szName(pMonitor->szName) {
+
+ listeners.modeChanged = monitor->events.modeChanged.registerListener([this](std::any d) {
+ for (auto& o : m_vOutputs) {
+ o->updateState();
+ }
+ });
+}
+
+void CWLOutputProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
+ const auto RESOURCE = m_vOutputs.emplace_back(makeShared<CWLOutputResource>(makeShared<CWlOutput>(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; });
+
+ if (m_vOutputs.empty() && defunct)
+ PROTO::outputs.erase(szName);
+}
+
+SP<CWLOutputResource> CWLOutputProtocol::outputResourceFrom(wl_client* client) {
+ for (auto& r : m_vOutputs) {
+ if (r->client() != client)
+ continue;
+
+ return r;
+ }
+
+ return nullptr;
+}
+
+void CWLOutputProtocol::remove() {
+ if (defunct)
+ return;
+
+ defunct = true;
+ removeGlobal();
+}
diff --git a/src/protocols/core/Output.hpp b/src/protocols/core/Output.hpp
new file mode 100644
index 00000000..5c274612
--- /dev/null
+++ b/src/protocols/core/Output.hpp
@@ -0,0 +1,61 @@
+#pragma once
+
+#include <memory>
+#include <vector>
+#include <cstdint>
+#include "../WaylandProtocol.hpp"
+#include "wayland.hpp"
+#include "../../helpers/signal/Listener.hpp"
+
+class CMonitor;
+
+class CWLOutputResource {
+ public:
+ CWLOutputResource(SP<CWlOutput> resource_, SP<CMonitor> pMonitor);
+ static SP<CWLOutputResource> fromResource(wl_resource*);
+
+ bool good();
+ wl_client* client();
+ SP<CWlOutput> getResource();
+ void updateState();
+
+ WP<CMonitor> monitor;
+
+ WP<CWLOutputResource> self;
+
+ private:
+ SP<CWlOutput> resource;
+ wl_client* pClient = nullptr;
+};
+
+class CWLOutputProtocol : public IWaylandProtocol {
+ public:
+ CWLOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name, SP<CMonitor> pMonitor);
+
+ virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
+
+ SP<CWLOutputResource> outputResourceFrom(wl_client* client);
+
+ WP<CMonitor> monitor;
+
+ // will mark the protocol for removal, will be removed when no. of bound outputs is 0 (or when overwritten by a new global)
+ void remove();
+
+ private:
+ void destroyResource(CWLOutputResource* resource);
+
+ //
+ std::vector<SP<CWLOutputResource>> m_vOutputs;
+ bool defunct = false;
+ std::string szName = "";
+
+ struct {
+ CHyprSignalListener modeChanged;
+ } listeners;
+
+ friend class CWLOutputResource;
+};
+
+namespace PROTO {
+ inline std::unordered_map<std::string, UP<CWLOutputProtocol>> outputs;
+};
diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp
index 9d5cf496..8bf03909 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<CWLSurfaceResource> surface, uint32_t timeMs, int32_t id, const Vector2D& local) {
if (!owner)
return;
@@ -29,15 +30,12 @@ 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 +43,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 +95,7 @@ CWLPointerResource::CWLPointerResource(SP<CWlPointer> resource_, SP<CWLSeatResou
return;
}
- g_pSeatManager->onSetCursor(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 +103,7 @@ bool CWLPointerResource::good() {
return resource->resource();
}
-void CWLPointerResource::sendEnter(wlr_surface* surface, const Vector2D& local) {
+void CWLPointerResource::sendEnter(SP<CWLSurfaceResource> surface, const Vector2D& local) {
if (!owner || currentSurface == surface)
return;
@@ -114,22 +112,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) {
@@ -237,7 +234,7 @@ void CWLKeyboardResource::sendKeymap(SP<IKeyboard> keyboard) {
close(fd);
}
-void CWLKeyboardResource::sendEnter(wlr_surface* surface) {
+void CWLKeyboardResource::sendEnter(SP<CWLSurfaceResource> surface) {
if (!owner || currentSurface == surface)
return;
@@ -246,16 +243,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);
}
@@ -264,9 +260,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 4cd0d124..524783f9 100644
--- a/src/protocols/core/Seat.hpp
+++ b/src/protocols/core/Seat.hpp
@@ -20,6 +20,7 @@
constexpr const char* HL_SEAT_NAME = "Hyprland";
class IKeyboard;
+class CWLSurfaceResource;
class CWLPointerResource;
class CWLKeyboardResource;
@@ -31,7 +32,7 @@ class CWLTouchResource {
CWLTouchResource(SP<CWlTouch> resource_, SP<CWLSeatResource> owner_);
bool good();
- void sendDown(wlr_surface* surface, uint32_t timeMs, int32_t id, const Vector2D& local);
+ void sendDown(SP<CWLSurfaceResource> 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 +43,12 @@ class CWLTouchResource {
WP<CWLSeatResource> owner;
private:
- SP<CWlTouch> resource;
- wlr_surface* currentSurface = nullptr;
+ SP<CWlTouch> resource;
+ WP<CWLSurfaceResource> currentSurface;
- DYNLISTENER(surfaceDestroy);
+ struct {
+ CHyprSignalListener destroySurface;
+ } listeners;
};
class CWLPointerResource {
@@ -53,7 +56,7 @@ class CWLPointerResource {
CWLPointerResource(SP<CWlPointer> resource_, SP<CWLSeatResource> owner_);
bool good();
- void sendEnter(wlr_surface* surface, const Vector2D& local);
+ void sendEnter(SP<CWLSurfaceResource> 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 +71,12 @@ class CWLPointerResource {
WP<CWLSeatResource> owner;
private:
- SP<CWlPointer> resource;
- wlr_surface* currentSurface = nullptr;
+ SP<CWlPointer> resource;
+ WP<CWLSurfaceResource> currentSurface;
- DYNLISTENER(surfaceDestroy);
+ struct {
+ CHyprSignalListener destroySurface;
+ } listeners;
};
class CWLKeyboardResource {
@@ -80,7 +85,7 @@ class CWLKeyboardResource {
bool good();
void sendKeymap(SP<IKeyboard> keeb);
- void sendEnter(wlr_surface* surface);
+ void sendEnter(SP<CWLSurfaceResource> 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 +94,12 @@ class CWLKeyboardResource {
WP<CWLSeatResource> owner;
private:
- SP<CWlKeyboard> resource;
- wlr_surface* currentSurface = nullptr;
+ SP<CWlKeyboard> resource;
+ WP<CWLSurfaceResource> 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 00000000..0c01cf80
--- /dev/null
+++ b/src/protocols/core/Shm.cpp
@@ -0,0 +1,214 @@
+#include "Shm.hpp"
+#include <algorithm>
+#include <sys/mman.h>
+#include <drm_fourcc.h>
+#include "../../render/Texture.hpp"
+#include "../types/WLBuffer.hpp"
+#include "../../Compositor.hpp"
+#include "../../helpers/Format.hpp"
+
+#define LOGM PROTO::shm->protoLog
+
+CWLSHMBuffer::CWLSHMBuffer(SP<CWLSHMPoolResource> pool_, uint32_t id, int32_t offset_, const Vector2D& size_, int32_t stride_, uint32_t fmt_) {
+ if (!pool_->pool->data)
+ return;
+
+ g_pHyprRenderer->makeEGLCurrent();
+
+ size = size_;
+ pool = pool_->pool;
+ stride = stride_;
+ fmt = fmt_;
+ offset = offset_;
+ opaque = FormatUtils::isFormatOpaque(FormatUtils::shmToDRM(fmt_));
+
+ texture = makeShared<CTexture>(FormatUtils::shmToDRM(fmt), (uint8_t*)pool->data + offset, stride, size_);
+
+ resource = CWLBufferResource::create(makeShared<CWlBuffer>(pool_->resource->client(), 1, id));
+
+ listeners.bufferResourceDestroy = events.destroy.registerListener([this](std::any d) {
+ listeners.bufferResourceDestroy.reset();
+ PROTO::shm->destroyResource(this);
+ });
+
+ success = texture->m_iTexID;
+
+ if (!success)
+ Debug::log(ERR, "Failed creating a shm texture: null texture id");
+}
+
+CWLSHMBuffer::~CWLSHMBuffer() {
+ ;
+}
+
+eBufferCapability CWLSHMBuffer::caps() {
+ return BUFFER_CAPABILITY_DATAPTR;
+}
+
+eBufferType CWLSHMBuffer::type() {
+ return BUFFER_TYPE_SHM;
+}
+
+SSHMAttrs CWLSHMBuffer::shm() {
+ SSHMAttrs attrs;
+ attrs.success = true;
+ attrs.fd = pool->fd;
+ attrs.format = FormatUtils::shmToDRM(fmt);
+ attrs.size = size;
+ attrs.stride = stride;
+ attrs.offset = offset;
+ return attrs;
+}
+
+std::tuple<uint8_t*, uint32_t, size_t> 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(FormatUtils::shmToDRM(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);
+ close(fd);
+}
+
+void CSHMPool::resize(size_t size_) {
+ LOGM(LOG, "Resizing a SHM pool from {} to {}", size, 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<CWlShmPool> resource_, int fd_, size_t size_) : resource(resource_) {
+ if (!good())
+ return;
+
+ pool = makeShared<CSHMPool>(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_) {
+ if (size_ < (int32_t)pool->size) {
+ r->error(-1, "Shrinking a shm pool is illegal");
+ return;
+ }
+ 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 (!pool || !pool->data) {
+ r->error(-1, "The provided shm pool failed to allocate properly");
+ return;
+ }
+
+ 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;
+ }
+
+ if (offset < 0 || w <= 0 || h <= 0 || stride <= 0) {
+ r->error(WL_SHM_ERROR_INVALID_STRIDE, "Invalid stride, w, h, or offset");
+ return;
+ }
+
+ const auto RESOURCE = PROTO::shm->m_vBuffers.emplace_back(makeShared<CWLSHMBuffer>(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<CWlShm> 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<CWLSHMPoolResource>(makeShared<CWlShmPool>(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(FormatUtils::drmToShm(formats[i]));
+ }
+ }
+
+ const auto RESOURCE = m_vManagers.emplace_back(makeShared<CWLSHMResource>(makeShared<CWlShm>(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 00000000..862ea112
--- /dev/null
+++ b/src/protocols/core/Shm.hpp
@@ -0,0 +1,111 @@
+#pragma once
+
+/*
+ Implementations for:
+ - wl_shm
+ - wl_shm_pool
+ - wl_buffer with shm
+*/
+
+#include <memory>
+#include <vector>
+#include <cstdint>
+#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<CWLSHMPoolResource> 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<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
+ virtual void endDataPtr();
+
+ bool good();
+ void updateTexture();
+
+ int32_t offset = 0, stride = 0;
+ uint32_t fmt = 0;
+ SP<CSHMPool> pool;
+
+ private:
+ bool success = false;
+
+ struct {
+ CHyprSignalListener bufferResourceDestroy;
+ } listeners;
+};
+
+class CWLSHMPoolResource {
+ public:
+ CWLSHMPoolResource(SP<CWlShmPool> resource_, int fd, size_t size);
+
+ bool good();
+
+ SP<CSHMPool> pool;
+
+ WP<CWLSHMPoolResource> self;
+
+ private:
+ SP<CWlShmPool> resource;
+
+ friend class CWLSHMBuffer;
+};
+
+class CWLSHMResource {
+ public:
+ CWLSHMResource(SP<CWlShm> resource_);
+
+ bool good();
+
+ private:
+ SP<CWlShm> 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<SP<CWLSHMResource>> m_vManagers;
+ std::vector<SP<CWLSHMPoolResource>> m_vPools;
+ std::vector<SP<CWLSHMBuffer>> m_vBuffers;
+
+ //
+ std::vector<uint32_t> shmFormats;
+
+ friend class CWLSHMResource;
+ friend class CWLSHMPoolResource;
+ friend class CWLSHMBuffer;
+};
+
+namespace PROTO {
+ inline UP<CWLSHMProtocol> shm;
+};
diff --git a/src/protocols/core/Subcompositor.cpp b/src/protocols/core/Subcompositor.cpp
new file mode 100644
index 00000000..213fdc42
--- /dev/null
+++ b/src/protocols/core/Subcompositor.cpp
@@ -0,0 +1,192 @@
+#include "Subcompositor.hpp"
+#include "Compositor.hpp"
+#include <algorithm>
+
+#define LOGM PROTO::subcompositor->protoLog
+
+CWLSubsurfaceResource::CWLSubsurfaceResource(SP<CWlSubsurface> resource_, SP<CWLSurfaceResource> surface_, SP<CWLSurfaceResource> parent_) :
+ surface(surface_), parent(parent_), resource(resource_) {
+ if (!good())
+ return;
+
+ resource->setOnDestroy([this](CWlSubsurface* r) { destroy(); });
+ resource->setDestroy([this](CWlSubsurface* r) { destroy(); });
+
+ 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();
+}
+
+void CWLSubsurfaceResource::destroy() {
+ if (surface && surface->mapped)
+ surface->unmap();
+ events.destroy.emit();
+ PROTO::subcompositor->destroyResource(this);
+}
+
+Vector2D CWLSubsurfaceResource::posRelativeToParent() {
+ Vector2D pos = position;
+ SP<CWLSurfaceResource> surf = parent.lock();
+
+ // some apps might create cycles, which I believe _technically_ are not a protocol error
+ // in some cases, notably firefox likes to do that, so we keep track of what
+ // surfaces we've visited and if we hit a surface we've visited we bail out.
+ std::vector<SP<CWLSurfaceResource>> surfacesVisited;
+
+ while (surf->role->role() == SURFACE_ROLE_SUBSURFACE &&
+ std::find_if(surfacesVisited.begin(), surfacesVisited.end(), [surf](const auto& other) { return surf == other; }) == surfacesVisited.end()) {
+ surfacesVisited.emplace_back(surf);
+ 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;
+}
+
+SP<CWLSurfaceResource> CWLSubsurfaceResource::t1Parent() {
+ SP<CWLSurfaceResource> surf = parent.lock();
+ std::vector<SP<CWLSurfaceResource>> surfacesVisited;
+
+ while (surf->role->role() == SURFACE_ROLE_SUBSURFACE &&
+ std::find_if(surfacesVisited.begin(), surfacesVisited.end(), [surf](const auto& other) { return surf == other; }) == surfacesVisited.end()) {
+ surfacesVisited.emplace_back(surf);
+ auto subsurface = (CWLSubsurfaceResource*)parent->role.get();
+ surf = subsurface->parent.lock();
+ }
+ return surf;
+}
+
+CWLSubcompositorResource::CWLSubcompositorResource(SP<CWlSubcompositor> 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 || SURF == PARENT) {
+ r->error(WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE, "Invalid surface/parent");
+ return;
+ }
+
+ SP<CWLSurfaceResource> t1Parent = nullptr;
+
+ if (PARENT->role->role() == SURFACE_ROLE_SUBSURFACE) {
+ auto subsurface = (CWLSubsurfaceResource*)PARENT->role.get();
+ t1Parent = subsurface->t1Parent();
+ } else
+ t1Parent = PARENT;
+
+ if (t1Parent == SURF) {
+ r->error(WL_SUBCOMPOSITOR_ERROR_BAD_PARENT, "Bad parent, t1 parent == surf");
+ return;
+ }
+
+ const auto RESOURCE =
+ PROTO::subcompositor->m_vSurfaces.emplace_back(makeShared<CWLSubsurfaceResource>(makeShared<CWlSubsurface>(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;
+ PARENT->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<CWLSubcompositorResource>(makeShared<CWlSubcompositor>(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 00000000..abcfbf6d
--- /dev/null
+++ b/src/protocols/core/Subcompositor.hpp
@@ -0,0 +1,82 @@
+
+#pragma once
+
+/*
+ Implementations for:
+ - wl_subsurface
+ - wl_subcompositor
+*/
+
+#include <memory>
+#include <vector>
+#include <cstdint>
+#include "../WaylandProtocol.hpp"
+#include "wayland.hpp"
+#include "../../helpers/signal/Signal.hpp"
+#include "../types/SurfaceRole.hpp"
+
+class CWLSurfaceResource;
+
+class CWLSubsurfaceResource : public ISurfaceRole {
+ public:
+ CWLSubsurfaceResource(SP<CWlSubsurface> resource_, SP<CWLSurfaceResource> surface_, SP<CWLSurfaceResource> parent_);
+ ~CWLSubsurfaceResource();
+
+ Vector2D posRelativeToParent();
+ bool good();
+ virtual eSurfaceRole role();
+ SP<CWLSurfaceResource> t1Parent();
+
+ bool sync = false;
+ Vector2D position;
+
+ WP<CWLSurfaceResource> surface;
+ WP<CWLSurfaceResource> parent;
+
+ WP<CWLSubsurfaceResource> self;
+
+ struct {
+ CSignal destroy;
+ } events;
+
+ private:
+ SP<CWlSubsurface> resource;
+
+ void destroy();
+
+ struct {
+ CHyprSignalListener commitSurface;
+ } listeners;
+};
+
+class CWLSubcompositorResource {
+ public:
+ CWLSubcompositorResource(SP<CWlSubcompositor> resource_);
+
+ bool good();
+
+ private:
+ SP<CWlSubcompositor> 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<SP<CWLSubcompositorResource>> m_vManagers;
+ std::vector<SP<CWLSubsurfaceResource>> m_vSurfaces;
+
+ friend class CWLSubcompositorResource;
+ friend class CWLSubsurfaceResource;
+};
+
+namespace PROTO {
+ inline UP<CWLSubcompositorProtocol> subcompositor;
+};
diff --git a/src/protocols/types/Buffer.cpp b/src/protocols/types/Buffer.cpp
new file mode 100644
index 00000000..5ed942e1
--- /dev/null
+++ b/src/protocols/types/Buffer.cpp
@@ -0,0 +1,41 @@
+#include "Buffer.hpp"
+#include "WLBuffer.hpp"
+
+SDMABUFAttrs IWLBuffer::dmabuf() {
+ return SDMABUFAttrs{};
+}
+
+SSHMAttrs IWLBuffer::shm() {
+ return SSHMAttrs{};
+}
+
+std::tuple<uint8_t*, uint32_t, size_t> IWLBuffer::beginDataPtr(uint32_t flags) {
+ return {nullptr, 0, 0};
+}
+
+void IWLBuffer::endDataPtr() {
+ ; // empty
+}
+
+void IWLBuffer::sendRelease() {
+ if (!resource || !resource->resource)
+ return;
+ resource->resource->sendRelease();
+}
+
+void IWLBuffer::lock() {
+ locks++;
+}
+
+void IWLBuffer::unlock() {
+ locks--;
+
+ ASSERT(locks >= 0);
+
+ if (locks <= 0)
+ sendRelease();
+}
+
+bool IWLBuffer::locked() {
+ return locks;
+}
diff --git a/src/protocols/types/Buffer.hpp b/src/protocols/types/Buffer.hpp
new file mode 100644
index 00000000..c9902f8d
--- /dev/null
+++ b/src/protocols/types/Buffer.hpp
@@ -0,0 +1,74 @@
+#pragma once
+
+#include "../../defines.hpp"
+#include "../../helpers/signal/Signal.hpp"
+#include "../../render/Texture.hpp"
+
+#include <array>
+#include <tuple>
+
+enum eBufferCapability {
+ BUFFER_CAPABILITY_DATAPTR = (1 << 0),
+};
+
+enum eBufferType {
+ BUFFER_TYPE_DMABUF = 0,
+ BUFFER_TYPE_SHM,
+ BUFFER_TYPE_MISC,
+};
+
+class CWLBufferResource;
+
+struct SDMABUFAttrs {
+ bool success = false;
+ Vector2D size;
+ uint32_t format = 0; // fourcc
+ uint64_t modifier = 0;
+
+ int planes = 1;
+ std::array<uint32_t, 4> offsets = {0};
+ std::array<uint32_t, 4> strides = {0};
+ std::array<int, 4> fds = {-1, -1, -1, -1};
+};
+
+struct SSHMAttrs {
+ bool success = false;
+ int fd = 0;
+ uint32_t format = 0;
+ Vector2D size;
+ int stride = 0;
+ int64_t offset = 0;
+};
+
+class IWLBuffer {
+ public:
+ virtual ~IWLBuffer() {
+ ;
+ };
+
+ virtual eBufferCapability caps() = 0;
+ virtual eBufferType type() = 0;
+ virtual void update(const CRegion& damage) = 0;
+ virtual SDMABUFAttrs dmabuf();
+ virtual SSHMAttrs shm();
+ virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
+ virtual void endDataPtr();
+ virtual void sendRelease();
+ virtual void lock();
+ virtual void unlock();
+ virtual bool locked();
+
+ Vector2D size;
+ bool opaque = false;
+
+ SP<CWLBufferResource> resource;
+
+ SP<CTexture> texture;
+
+ struct {
+ CSignal destroy;
+ } events;
+
+ private:
+ int locks = 0;
+};
diff --git a/src/protocols/types/DMABuffer.cpp b/src/protocols/types/DMABuffer.cpp
new file mode 100644
index 00000000..930e71e6
--- /dev/null
+++ b/src/protocols/types/DMABuffer.cpp
@@ -0,0 +1,75 @@
+#include "DMABuffer.hpp"
+#include "WLBuffer.hpp"
+#include "../../render/Renderer.hpp"
+#include "../../helpers/Format.hpp"
+
+CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs attrs_) : attrs(attrs_) {
+ g_pHyprRenderer->makeEGLCurrent();
+
+ listeners.resourceDestroy = events.destroy.registerListener([this](std::any d) {
+ closeFDs();
+ listeners.resourceDestroy.reset();
+ });
+
+ size = attrs.size;
+ resource = CWLBufferResource::create(makeShared<CWlBuffer>(client, 1, id));
+
+ auto eglImage = g_pHyprOpenGL->createEGLImage(attrs);
+
+ if (!eglImage)
+ return;
+
+ texture = makeShared<CTexture>(attrs, eglImage); // texture takes ownership of the eglImage
+ opaque = FormatUtils::isFormatOpaque(attrs.format);
+ success = texture->m_iTexID;
+
+ if (!success)
+ Debug::log(ERR, "Failed to create a dmabuf: texture is null");
+}
+
+CDMABuffer::~CDMABuffer() {
+ closeFDs();
+}
+
+eBufferCapability CDMABuffer::caps() {
+ return BUFFER_CAPABILITY_DATAPTR;
+}
+
+eBufferType CDMABuffer::type() {
+ return BUFFER_TYPE_DMABUF;
+}
+
+void CDMABuffer::update(const CRegion& damage) {
+ ;
+}
+
+SDMABUFAttrs CDMABuffer::dmabuf() {
+ return attrs;
+}
+
+std::tuple<uint8_t*, uint32_t, size_t> CDMABuffer::beginDataPtr(uint32_t flags) {
+ // FIXME:
+ return {nullptr, 0, 0};
+}
+
+void CDMABuffer::endDataPtr() {
+ // FIXME:
+}
+
+bool CDMABuffer::good() {
+ return success;
+}
+
+void CDMABuffer::updateTexture() {
+ ;
+}
+
+void CDMABuffer::closeFDs() {
+ for (int i = 0; i < attrs.planes; ++i) {
+ if (attrs.fds[i] == -1)
+ continue;
+ close(attrs.fds[i]);
+ attrs.fds[i] = -1;
+ }
+ attrs.planes = 0;
+} \ No newline at end of file
diff --git a/src/protocols/types/DMABuffer.hpp b/src/protocols/types/DMABuffer.hpp
new file mode 100644
index 00000000..e06b5791
--- /dev/null
+++ b/src/protocols/types/DMABuffer.hpp
@@ -0,0 +1,28 @@
+#pragma once
+
+#include "Buffer.hpp"
+
+class CDMABuffer : public IWLBuffer {
+ public:
+ CDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs attrs_);
+ virtual ~CDMABuffer();
+
+ virtual eBufferCapability caps();
+ virtual eBufferType type();
+ virtual void update(const CRegion& damage);
+ virtual SDMABUFAttrs dmabuf();
+ virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
+ virtual void endDataPtr();
+ bool good();
+ void updateTexture();
+ void closeFDs();
+
+ bool success = false;
+
+ private:
+ SDMABUFAttrs attrs;
+
+ struct {
+ CHyprSignalListener resourceDestroy;
+ } listeners;
+}; \ No newline at end of file
diff --git a/src/protocols/types/SurfaceRole.hpp b/src/protocols/types/SurfaceRole.hpp
new file mode 100644
index 00000000..05c0ea66
--- /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 00000000..e53538cb
--- /dev/null
+++ b/src/protocols/types/WLBuffer.cpp
@@ -0,0 +1,43 @@
+#include "WLBuffer.hpp"
+#include "Buffer.hpp"
+
+CWLBufferResource::CWLBufferResource(SP<CWlBuffer> resource_) : resource(resource_) {
+ if (!good())
+ return;
+
+ resource->setOnDestroy([this](CWlBuffer* r) {
+ if (buffer.expired())
+ return;
+ buffer->events.destroy.emit();
+ });
+ resource->setDestroy([this](CWlBuffer* r) {
+ if (buffer.expired())
+ return;
+ buffer->events.destroy.emit();
+ });
+
+ resource->setData(this);
+}
+
+bool CWLBufferResource::good() {
+ return resource->resource();
+}
+
+void CWLBufferResource::sendRelease() {
+ resource->sendRelease();
+}
+
+wl_resource* CWLBufferResource::getResource() {
+ return resource->resource();
+}
+
+SP<CWLBufferResource> CWLBufferResource::fromResource(wl_resource* res) {
+ auto data = (CWLBufferResource*)(((CWlBuffer*)wl_resource_get_user_data(res))->data());
+ return data ? data->self.lock() : nullptr;
+}
+
+SP<CWLBufferResource> CWLBufferResource::create(SP<CWlBuffer> resource) {
+ auto p = SP<CWLBufferResource>(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 00000000..ac177965
--- /dev/null
+++ b/src/protocols/types/WLBuffer.hpp
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <memory>
+#include <vector>
+#include <cstdint>
+#include "../WaylandProtocol.hpp"
+#include "wayland.hpp"
+#include "../../helpers/signal/Signal.hpp"
+
+class IWLBuffer;
+
+class CWLBufferResource {
+ public:
+ static SP<CWLBufferResource> create(SP<CWlBuffer> resource);
+ static SP<CWLBufferResource> fromResource(wl_resource* res);
+
+ bool good();
+ void sendRelease();
+ wl_resource* getResource();
+
+ WP<IWLBuffer> buffer;
+
+ WP<CWLBufferResource> self;
+
+ private:
+ CWLBufferResource(SP<CWlBuffer> resource_);
+
+ SP<CWlBuffer> resource;
+
+ friend class IWLBuffer;
+};
diff --git a/src/render/Framebuffer.cpp b/src/render/Framebuffer.cpp
index 83325dd7..67629e23 100644
--- a/src/render/Framebuffer.cpp
+++ b/src/render/Framebuffer.cpp
@@ -1,22 +1,26 @@
#include "Framebuffer.hpp"
#include "OpenGL.hpp"
+CFramebuffer::CFramebuffer() {
+ m_cTex = makeShared<CTexture>();
+}
+
bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) {
bool firstAlloc = false;
RASSERT((w > 1 && h > 1), "cannot alloc a FB with negative / zero size! (attempted {}x{})", w, h);
- uint32_t glFormat = drmFormatToGL(drmFormat);
- uint32_t glType = glFormatToType(glFormat);
+ uint32_t glFormat = FormatUtils::drmFormatToGL(drmFormat);
+ uint32_t glType = FormatUtils::glFormatToType(glFormat);
if (m_iFb == (uint32_t)-1) {
firstAlloc = true;
glGenFramebuffers(1, &m_iFb);
}
- if (m_cTex.m_iTexID == 0) {
+ if (m_cTex->m_iTexID == 0) {
firstAlloc = true;
- glGenTextures(1, &m_cTex.m_iTexID);
- glBindTexture(GL_TEXTURE_2D, m_cTex.m_iTexID);
+ m_cTex->allocate();
+ glBindTexture(GL_TEXTURE_2D, m_cTex->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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -24,11 +28,11 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) {
}
if (firstAlloc || m_vSize != Vector2D(w, h)) {
- glBindTexture(GL_TEXTURE_2D, m_cTex.m_iTexID);
+ glBindTexture(GL_TEXTURE_2D, m_cTex->m_iTexID);
glTexImage2D(GL_TEXTURE_2D, 0, glFormat, w, h, 0, GL_RGBA, glType, 0);
glBindFramebuffer(GL_FRAMEBUFFER, m_iFb);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_cTex.m_iTexID, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_cTex->m_iTexID, 0);
// TODO: Allow this with gles2
#ifndef GLES2
@@ -87,12 +91,9 @@ void CFramebuffer::release() {
if (m_iFb != (uint32_t)-1 && m_iFb)
glDeleteFramebuffers(1, &m_iFb);
- if (m_cTex.m_iTexID)
- glDeleteTextures(1, &m_cTex.m_iTexID);
-
- m_cTex.m_iTexID = 0;
- m_iFb = -1;
- m_vSize = Vector2D();
+ m_cTex->destroyTexture();
+ m_iFb = -1;
+ m_vSize = Vector2D();
}
CFramebuffer::~CFramebuffer() {
diff --git a/src/render/Framebuffer.hpp b/src/render/Framebuffer.hpp
index 22809158..a46a4859 100644
--- a/src/render/Framebuffer.hpp
+++ b/src/render/Framebuffer.hpp
@@ -5,19 +5,20 @@
class CFramebuffer {
public:
+ CFramebuffer();
~CFramebuffer();
- bool alloc(int w, int h, uint32_t format = GL_RGBA);
- void addStencil();
- void bind();
- void release();
- void reset();
- bool isAllocated();
+ bool alloc(int w, int h, uint32_t format = GL_RGBA);
+ void addStencil();
+ void bind();
+ void release();
+ void reset();
+ bool isAllocated();
- Vector2D m_vSize;
+ Vector2D m_vSize;
- CTexture m_cTex;
- GLuint m_iFb = -1;
+ SP<CTexture> m_cTex;
+ GLuint m_iFb = -1;
- CTexture* m_pStencilTex = nullptr;
+ SP<CTexture> m_pStencilTex;
}; \ No newline at end of file
diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp
index a1e6f73e..d4e8faa6 100644
--- a/src/render/OpenGL.cpp
+++ b/src/render/OpenGL.cpp
@@ -7,6 +7,8 @@
#include "../config/ConfigValue.hpp"
#include "../desktop/LayerSurface.hpp"
#include "../protocols/LayerShell.hpp"
+#include "../protocols/core/Compositor.hpp"
+#include <xf86drm.h>
inline void loadGLProc(void* pProc, const char* name) {
void* proc = (void*)eglGetProcAddress(name);
@@ -21,7 +23,8 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
RASSERT(eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)),
"Couldn't unset current EGL!");
- auto* const EXTENSIONS = (const char*)glGetString(GL_EXTENSIONS);
+ auto* const EXTENSIONS = (const char*)glGetString(GL_EXTENSIONS);
+ const std::string EGLEXTENSIONS = (const char*)eglQueryString(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_EXTENSIONS);
RASSERT(EXTENSIONS, "Couldn't retrieve openGL extensions!");
@@ -33,12 +36,25 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
Debug::log(LOG, "Using: {}", (char*)glGetString(GL_VERSION));
Debug::log(LOG, "Vendor: {}", (char*)glGetString(GL_VENDOR));
Debug::log(LOG, "Renderer: {}", (char*)glGetString(GL_RENDERER));
- Debug::log(LOG, "Supported extensions size: {}", std::count(m_szExtensions.begin(), m_szExtensions.end(), ' '));
+ Debug::log(LOG, "Supported extensions: ({}) {}", std::count(m_szExtensions.begin(), m_szExtensions.end(), ' '), m_szExtensions);
loadGLProc(&m_sProc.glEGLImageTargetRenderbufferStorageOES, "glEGLImageTargetRenderbufferStorageOES");
+ loadGLProc(&m_sProc.eglCreateImageKHR, "eglCreateImageKHR");
loadGLProc(&m_sProc.eglDestroyImageKHR, "eglDestroyImageKHR");
+ loadGLProc(&m_sProc.eglQueryDmaBufFormatsEXT, "eglQueryDmaBufFormatsEXT");
+ loadGLProc(&m_sProc.eglQueryDmaBufModifiersEXT, "eglQueryDmaBufModifiersEXT");
+ loadGLProc(&m_sProc.glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES");
- m_sExts.EXT_read_format_bgra = m_szExtensions.contains("GL_EXT_read_format_bgra");
+ m_sExts.EXT_read_format_bgra = m_szExtensions.contains("GL_EXT_read_format_bgra");
+ m_sExts.EXT_image_dma_buf_import = EGLEXTENSIONS.contains("EXT_image_dma_buf_import");
+ m_sExts.EXT_image_dma_buf_import_modifiers = EGLEXTENSIONS.contains("EXT_image_dma_buf_import_modifiers");
+
+ RASSERT(m_szExtensions.contains("GL_EXT_texture_format_BGRA8888"), "GL_EXT_texture_format_BGRA8888 support by the GPU driver is required");
+
+ if (!m_sExts.EXT_read_format_bgra)
+ Debug::log(WARN, "Your GPU does not support GL_EXT_read_format_bgra, this may cause issues with texture importing");
+ if (!m_sExts.EXT_image_dma_buf_import || !m_sExts.EXT_image_dma_buf_import_modifiers)
+ Debug::log(WARN, "Your GPU does not support DMABUFs, this will possibly cause issues and will take a hit on the performance.");
#ifdef USE_TRACY_GPU
@@ -54,6 +70,8 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
Debug::log(WARN, "!RENDERER: Using the legacy GLES2 renderer!");
#endif
+ initDRMFormats();
+
static auto P = g_pHookSystem->hookDynamic("preRender", [&](void* self, SCallbackInfo& info, std::any data) { preRender(std::any_cast<CMonitor*>(data)); });
RASSERT(eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT), "Couldn't unset current EGL!");
@@ -61,6 +79,171 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
m_tGlobalTimer.reset();
}
+std::vector<uint64_t> CHyprOpenGLImpl::getModsForFormat(EGLint format) {
+ // TODO: return std::expected when clang supports it
+
+ if (!m_sExts.EXT_image_dma_buf_import_modifiers)
+ return {};
+
+ EGLint len = 0;
+ if (!m_sProc.eglQueryDmaBufModifiersEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), format, 0, nullptr, nullptr, &len)) {
+ Debug::log(ERR, "EGL: Failed to query mods");
+ return {};
+ }
+
+ if (len <= 0)
+ return {};
+
+ std::vector<uint64_t> mods;
+ std::vector<EGLBoolean> external;
+
+ mods.resize(len);
+ external.resize(len);
+
+ m_sProc.eglQueryDmaBufModifiersEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), format, len, mods.data(), external.data(), &len);
+
+ std::vector<uint64_t> result;
+ for (size_t i = 0; i < mods.size(); ++i) {
+ if (external.at(i))
+ continue;
+
+ result.push_back(mods.at(i));
+ }
+
+ return result;
+}
+
+void CHyprOpenGLImpl::initDRMFormats() {
+ const auto DISABLE_MODS = envEnabled("HYPRLAND_EGL_NO_MODIFIERS");
+ if (DISABLE_MODS)
+ Debug::log(WARN, "HYPRLAND_EGL_NO_MODIFIERS set, disabling modifiers");
+
+ if (!m_sExts.EXT_image_dma_buf_import) {
+ Debug::log(ERR, "EGL: No dmabuf import, DMABufs will not work.");
+ return;
+ }
+
+ std::vector<EGLint> formats;
+
+ if (!m_sExts.EXT_image_dma_buf_import_modifiers || !m_sProc.eglQueryDmaBufFormatsEXT) {
+ formats.push_back(DRM_FORMAT_ARGB8888);
+ formats.push_back(DRM_FORMAT_XRGB8888);
+ Debug::log(WARN, "EGL: No mod support");
+ } else {
+ EGLint len = 0;
+ m_sProc.eglQueryDmaBufFormatsEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), 0, nullptr, &len);
+ formats.resize(len);
+ m_sProc.eglQueryDmaBufFormatsEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), len, formats.data(), &len);
+ }
+
+ if (formats.size() == 0) {
+ Debug::log(ERR, "EGL: Failed to get formats, DMABufs will not work.");
+ return;
+ }
+
+ wlr_log(WLR_DEBUG, "Supported DMA-BUF formats:");
+
+ std::vector<SDRMFormat> dmaFormats;
+
+ for (auto& fmt : formats) {
+ std::vector<uint64_t> mods;
+ if (!DISABLE_MODS)
+ mods = getModsForFormat(fmt);
+ else
+ mods = {DRM_FORMAT_MOD_LINEAR};
+
+ m_bHasModifiers = m_bHasModifiers || mods.size() > 0;
+
+ if (mods.size() == 0)
+ continue;
+
+ dmaFormats.push_back(SDRMFormat{
+ .format = fmt,
+ .mods = mods,
+ });
+
+ std::vector<std::pair<uint64_t, std::string>> modifierData;
+
+ auto fmtName = drmGetFormatName(fmt);
+ Debug::log(LOG, "EGL: GPU Supports Format {} (0x{:x})", fmtName ? fmtName : "?unknown?", fmt);
+ for (auto& mod : mods) {
+ auto modName = drmGetFormatModifierName(mod);
+ modifierData.emplace_back(std::make_pair<>(mod, modName ? modName : "?unknown?"));
+ free(modName);
+ }
+ free(fmtName);
+
+ mods.clear();
+ std::sort(modifierData.begin(), modifierData.end(), [](const auto& a, const auto& b) {
+ if (a.first == 0)
+ return false;
+ if (a.second.contains("DCC"))
+ return false;
+ return true;
+ });
+
+ for (auto& [m, name] : modifierData) {
+ Debug::log(LOG, "EGL: | with modifier {} (0x{:x})", name, m);
+ mods.emplace_back(m);
+ }
+ }
+
+ Debug::log(LOG, "EGL: {} formats found in total. Some modifiers may be omitted as they are external-only.", dmaFormats.size());
+
+ drmFormats = dmaFormats;
+}
+
+EGLImageKHR CHyprOpenGLImpl::createEGLImage(const SDMABUFAttrs& attrs) {
+ std::vector<uint32_t> attribs;
+
+ attribs.push_back(EGL_WIDTH);
+ attribs.push_back(attrs.size.x);
+ attribs.push_back(EGL_HEIGHT);
+ attribs.push_back(attrs.size.y);
+ attribs.push_back(EGL_LINUX_DRM_FOURCC_EXT);
+ attribs.push_back(attrs.format);
+
+ struct {
+ EGLint fd;
+ EGLint offset;
+ EGLint pitch;
+ EGLint modlo;
+ EGLint modhi;
+ } attrNames[4] = {
+ {EGL_DMA_BUF_PLANE0_FD_EXT, EGL_DMA_BUF_PLANE0_OFFSET_EXT, EGL_DMA_BUF_PLANE0_PITCH_EXT, EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT},
+ {EGL_DMA_BUF_PLANE1_FD_EXT, EGL_DMA_BUF_PLANE1_OFFSET_EXT, EGL_DMA_BUF_PLANE1_PITCH_EXT, EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT, EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT},
+ {EGL_DMA_BUF_PLANE2_FD_EXT, EGL_DMA_BUF_PLANE2_OFFSET_EXT, EGL_DMA_BUF_PLANE2_PITCH_EXT, EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT, EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT},
+ {EGL_DMA_BUF_PLANE3_FD_EXT, EGL_DMA_BUF_PLANE3_OFFSET_EXT, EGL_DMA_BUF_PLANE3_PITCH_EXT, EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT, EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT}};
+
+ for (int i = 0; i < attrs.planes; i++) {
+ attribs.push_back(attrNames[i].fd);
+ attribs.push_back(attrs.fds[i]);
+ attribs.push_back(attrNames[i].offset);
+ attribs.push_back(attrs.offsets[i]);
+ attribs.push_back(attrNames[i].pitch);
+ attribs.push_back(attrs.strides[i]);
+ if (m_bHasModifiers && attrs.modifier != DRM_FORMAT_MOD_INVALID) {
+ attribs.push_back(attrNames[i].modlo);
+ attribs.push_back(attrs.modifier & 0xFFFFFFFF);
+ attribs.push_back(attrNames[i].modhi);
+ attribs.push_back(attrs.modifier >> 32);
+ }
+ }
+
+ attribs.push_back(EGL_IMAGE_PRESERVED_KHR);
+ attribs.push_back(EGL_TRUE);
+
+ attribs.push_back(EGL_NONE);
+
+ EGLImageKHR image = m_sProc.eglCreateImageKHR(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, (int*)attribs.data());
+ if (image == EGL_NO_IMAGE_KHR) {
+ Debug::log(ERR, "EGL: EGLCreateImageKHR failed: {}", eglGetError());
+ return EGL_NO_IMAGE_KHR;
+ }
+
+ return image;
+}
+
void CHyprOpenGLImpl::logShaderError(const GLuint& shader, bool program) {
GLint maxLength = 0;
if (program)
@@ -339,12 +522,12 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, const CRegion& damage_, CFramebu
// ensure a framebuffer for the monitor exists
if (m_RenderData.pCurrentMonData->offloadFB.m_vSize != pMonitor->vecPixelSize) {
- m_RenderData.pCurrentMonData->stencilTex.allocate();
+ m_RenderData.pCurrentMonData->stencilTex->allocate();
- m_RenderData.pCurrentMonData->offloadFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
- m_RenderData.pCurrentMonData->mirrorFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
- m_RenderData.pCurrentMonData->mirrorSwapFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
- m_RenderData.pCurrentMonData->offMainFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
+ m_RenderData.pCurrentMonData->offloadFB.m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex;
+ m_RenderData.pCurrentMonData->mirrorFB.m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex;
+ m_RenderData.pCurrentMonData->mirrorSwapFB.m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex;
+ m_RenderData.pCurrentMonData->offMainFB.m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex;
m_RenderData.pCurrentMonData->offloadFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat);
m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat);
@@ -381,8 +564,8 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, const CRegion& damage_, CFramebu
// we can render to the rbo / fbo (fake) directly
const auto PFBO = fb ? fb : PRBO->getFB();
m_RenderData.currentFB = PFBO;
- if (PFBO->m_pStencilTex != &m_RenderData.pCurrentMonData->stencilTex) {
- PFBO->m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
+ if (PFBO->m_pStencilTex != m_RenderData.pCurrentMonData->stencilTex) {
+ PFBO->m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex;
PFBO->addStencil();
}
PFBO->bind();
@@ -863,19 +1046,7 @@ 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) {
+void CHyprOpenGLImpl::renderTexture(SP<CTexture> tex, CBox* pBox, float alpha, int round, bool discardActive, bool allowCustomUV) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
renderTextureInternalWithDamage(tex, pBox, alpha, &m_RenderData.damage, round, discardActive, false, allowCustomUV, true);
@@ -883,7 +1054,7 @@ void CHyprOpenGLImpl::renderTexture(const CTexture& tex, CBox* pBox, float alpha
scissor((CBox*)nullptr);
}
-void CHyprOpenGLImpl::renderTextureWithDamage(const CTexture& tex, CBox* pBox, CRegion* damage, float alpha, int round, bool discardActive, bool allowCustomUV) {
+void CHyprOpenGLImpl::renderTextureWithDamage(SP<CTexture> tex, CBox* pBox, CRegion* damage, float alpha, int round, bool discardActive, bool allowCustomUV) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
renderTextureInternalWithDamage(tex, pBox, alpha, damage, round, discardActive, false, allowCustomUV, true);
@@ -891,10 +1062,10 @@ void CHyprOpenGLImpl::renderTextureWithDamage(const CTexture& tex, CBox* pBox, C
scissor((CBox*)nullptr);
}
-void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, CBox* pBox, float alpha, CRegion* damage, int round, bool discardActive, bool noAA, bool allowCustomUV,
+void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, CBox* pBox, float alpha, CRegion* damage, int round, bool discardActive, bool noAA, bool allowCustomUV,
bool allowDim) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
- RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
+ RASSERT((tex->m_iTexID > 0), "Attempted to draw NULL texture!");
TRACY_GPU_ZONE("RenderTextureInternalWithDamage");
@@ -934,11 +1105,11 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, CBox*
shader = &m_RenderData.pCurrentMonData->m_shPASSTHRURGBA;
usingFinalShader = true;
} else {
- switch (tex.m_iType) {
+ switch (tex->m_iType) {
case TEXTURE_RGBA: shader = &m_RenderData.pCurrentMonData->m_shRGBA; break;
case TEXTURE_RGBX: shader = &m_RenderData.pCurrentMonData->m_shRGBX; break;
case TEXTURE_EXTERNAL: shader = &m_RenderData.pCurrentMonData->m_shEXT; break;
- default: RASSERT(false, "tex.m_iTarget unsupported!");
+ default: RASSERT(false, "tex->m_iTarget unsupported!");
}
}
}
@@ -947,14 +1118,14 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, CBox*
shader = &m_RenderData.pCurrentMonData->m_shRGBX;
glActiveTexture(GL_TEXTURE0);
- glBindTexture(tex.m_iTarget, tex.m_iTexID);
+ glBindTexture(tex->m_iTarget, tex->m_iTexID);
if (m_RenderData.useNearestNeighbor) {
- glTexParameteri(tex.m_iTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(tex.m_iTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(tex->m_iTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(tex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
} else {
- glTexParameteri(tex.m_iTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(tex.m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(tex->m_iTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(tex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
glUseProgram(shader->program);
@@ -1057,12 +1228,12 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, CBox*
glDisableVertexAttribArray(shader->posAttrib);
glDisableVertexAttribArray(shader->texAttrib);
- glBindTexture(tex.m_iTarget, 0);
+ glBindTexture(tex->m_iTarget, 0);
}
-void CHyprOpenGLImpl::renderTexturePrimitive(const CTexture& tex, CBox* pBox) {
+void CHyprOpenGLImpl::renderTexturePrimitive(SP<CTexture> tex, CBox* pBox) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
- RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
+ RASSERT((tex->m_iTexID > 0), "Attempted to draw NULL texture!");
TRACY_GPU_ZONE("RenderTexturePrimitive");
@@ -1083,7 +1254,7 @@ void CHyprOpenGLImpl::renderTexturePrimitive(const CTexture& tex, CBox* pBox) {
CShader* shader = &m_RenderData.pCurrentMonData->m_shPASSTHRURGBA;
glActiveTexture(GL_TEXTURE0);
- glBindTexture(tex.m_iTarget, tex.m_iTexID);
+ glBindTexture(tex->m_iTarget, tex->m_iTexID);
glUseProgram(shader->program);
@@ -1111,12 +1282,12 @@ void CHyprOpenGLImpl::renderTexturePrimitive(const CTexture& tex, CBox* pBox) {
glDisableVertexAttribArray(shader->posAttrib);
glDisableVertexAttribArray(shader->texAttrib);
- glBindTexture(tex.m_iTarget, 0);
+ glBindTexture(tex->m_iTarget, 0);
}
-void CHyprOpenGLImpl::renderTextureMatte(const CTexture& tex, CBox* pBox, CFramebuffer& matte) {
+void CHyprOpenGLImpl::renderTextureMatte(SP<CTexture> tex, CBox* pBox, CFramebuffer& matte) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
- RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
+ RASSERT((tex->m_iTexID > 0), "Attempted to draw NULL texture!");
TRACY_GPU_ZONE("RenderTextureMatte");
@@ -1148,10 +1319,10 @@ void CHyprOpenGLImpl::renderTextureMatte(const CTexture& tex, CBox* pBox, CFrame
glUniform1i(shader->alphaMatte, 1);
glActiveTexture(GL_TEXTURE0);
- glBindTexture(tex.m_iTarget, tex.m_iTexID);
+ glBindTexture(tex->m_iTarget, tex->m_iTexID);
glActiveTexture(GL_TEXTURE0 + 1);
- glBindTexture(matte.m_cTex.m_iTarget, matte.m_cTex.m_iTexID);
+ glBindTexture(matte.m_cTex->m_iTarget, matte.m_cTex->m_iTexID);
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@@ -1169,7 +1340,7 @@ void CHyprOpenGLImpl::renderTextureMatte(const CTexture& tex, CBox* pBox, CFrame
glDisableVertexAttribArray(shader->posAttrib);
glDisableVertexAttribArray(shader->texAttrib);
- glBindTexture(tex.m_iTarget, 0);
+ glBindTexture(tex->m_iTarget, 0);
}
// This probably isn't the fastest
@@ -1221,9 +1392,9 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
glActiveTexture(GL_TEXTURE0);
- glBindTexture(m_RenderData.currentFB->m_cTex.m_iTarget, m_RenderData.currentFB->m_cTex.m_iTexID);
+ glBindTexture(m_RenderData.currentFB->m_cTex->m_iTarget, m_RenderData.currentFB->m_cTex->m_iTexID);
- glTexParameteri(m_RenderData.currentFB->m_cTex.m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(m_RenderData.currentFB->m_cTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glUseProgram(m_RenderData.pCurrentMonData->m_shBLURPREPARE.program);
@@ -1265,9 +1436,9 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
glActiveTexture(GL_TEXTURE0);
- glBindTexture(currentRenderToFB->m_cTex.m_iTarget, currentRenderToFB->m_cTex.m_iTexID);
+ glBindTexture(currentRenderToFB->m_cTex->m_iTarget, currentRenderToFB->m_cTex->m_iTexID);
- glTexParameteri(currentRenderToFB->m_cTex.m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(currentRenderToFB->m_cTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glUseProgram(pShader->program);
@@ -1315,7 +1486,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
// draw the things.
// first draw is swap -> mirr
PMIRRORFB->bind();
- glBindTexture(PMIRRORSWAPFB->m_cTex.m_iTarget, PMIRRORSWAPFB->m_cTex.m_iTexID);
+ glBindTexture(PMIRRORSWAPFB->m_cTex->m_iTarget, PMIRRORSWAPFB->m_cTex->m_iTexID);
// damage region will be scaled, make a temp
CRegion tempDamage{damage};
@@ -1343,9 +1514,9 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
glActiveTexture(GL_TEXTURE0);
- glBindTexture(currentRenderToFB->m_cTex.m_iTarget, currentRenderToFB->m_cTex.m_iTexID);
+ glBindTexture(currentRenderToFB->m_cTex->m_iTarget, currentRenderToFB->m_cTex->m_iTexID);
- glTexParameteri(currentRenderToFB->m_cTex.m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(currentRenderToFB->m_cTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glUseProgram(m_RenderData.pCurrentMonData->m_shBLURFINISH.program);
@@ -1383,7 +1554,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
}
// finish
- glBindTexture(PMIRRORFB->m_cTex.m_iTarget, 0);
+ glBindTexture(PMIRRORFB->m_cTex->m_iTarget, 0);
blend(BLENDBEFORE);
@@ -1417,23 +1588,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 +1632,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;
@@ -1527,7 +1698,7 @@ bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWin
static auto PBLURNEWOPTIMIZE = CConfigValue<Hyprlang::INT>("decoration:blur:new_optimizations");
static auto PBLURXRAY = CConfigValue<Hyprlang::INT>("decoration:blur:xray");
- if (!m_RenderData.pCurrentMonData->blurFB.m_cTex.m_iTexID)
+ if (!m_RenderData.pCurrentMonData->blurFB.m_cTex->m_iTexID)
return false;
if (pWindow && pWindow->m_sAdditionalConfigData.xray.toUnderlying() == 0)
@@ -1545,7 +1716,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(SP<CTexture> tex, CBox* pBox, float a, SP<CWLSurfaceResource> pSurface, int round, bool blockBlurOptimization, float blurA) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!");
static auto PBLURENABLED = CConfigValue<Hyprlang::INT>("decoration:blur:enabled");
@@ -1570,11 +1741,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);
@@ -1765,7 +1936,7 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFr
g_pHyprRenderer->makeEGLCurrent();
- pFramebuffer->m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
+ pFramebuffer->m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex;
pFramebuffer->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat);
@@ -1903,7 +2074,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLWINDOW pWindow) {
const auto FBDATA = &m_mWindowFramebuffers.at(ref);
- if (!FBDATA->m_cTex.m_iTexID)
+ if (!FBDATA->m_cTex->m_iTexID)
return;
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
@@ -1942,7 +2113,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLLS pLayer) {
const auto FBDATA = &m_mLayerFramebuffers.at(pLayer);
- if (!FBDATA->m_cTex.m_iTexID)
+ if (!FBDATA->m_cTex->m_iTexID)
return;
const auto PMONITOR = g_pCompositor->getMonitorFromID(pLayer->monitorID);
@@ -2077,7 +2248,7 @@ void CHyprOpenGLImpl::renderMirrored() {
monbox.y = (monitor->vecTransformedSize.y - monbox.h) / 2;
const auto PFB = &m_mMonitorRenderResources[mirrored].monitorMirrorFB;
- if (!PFB->isAllocated() || PFB->m_cTex.m_iTexID <= 0)
+ if (!PFB->isAllocated() || PFB->m_cTex->m_iTexID <= 0)
return;
// replace monitor projection to undo the mirrored monitor's projection
@@ -2179,12 +2350,12 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
}
// create a new one with cairo
- CTexture tex;
+ SP<CTexture> tex = makeShared<CTexture>();
- const auto CAIROISURFACE = cairo_image_surface_create_from_png(texPath.c_str());
- const auto CAIROFORMAT = cairo_image_surface_get_format(CAIROISURFACE);
+ const auto CAIROISURFACE = cairo_image_surface_create_from_png(texPath.c_str());
+ const auto CAIROFORMAT = cairo_image_surface_get_format(CAIROISURFACE);
- tex.allocate();
+ tex->allocate();
const Vector2D IMAGESIZE = {cairo_image_surface_get_width(CAIROISURFACE), cairo_image_surface_get_height(CAIROISURFACE)};
// calc the target box
@@ -2220,8 +2391,8 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
cairo_surface_flush(CAIROSURFACE);
- CBox box = {origin.x, origin.y, IMAGESIZE.x * scale, IMAGESIZE.y * scale};
- tex.m_vSize = IMAGESIZE * scale;
+ CBox box = {origin.x, origin.y, IMAGESIZE.x * scale, IMAGESIZE.y * scale};
+ tex->m_vSize = IMAGESIZE * scale;
// copy the data to an OpenGL texture we have
const GLint glIFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ?
@@ -2235,7 +2406,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
const GLint glType = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_FLOAT : GL_UNSIGNED_BYTE;
const auto DATA = cairo_image_surface_get_data(CAIROSURFACE);
- glBindTexture(GL_TEXTURE_2D, tex.m_iTexID);
+ glBindTexture(GL_TEXTURE_2D, tex->m_iTexID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
#ifndef GLES2
@@ -2244,7 +2415,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
}
#endif
- glTexImage2D(GL_TEXTURE_2D, 0, glIFormat, tex.m_vSize.x, tex.m_vSize.y, 0, glFormat, glType, DATA);
+ glTexImage2D(GL_TEXTURE_2D, 0, glIFormat, tex->m_vSize.x, tex->m_vSize.y, 0, glFormat, glType, DATA);
cairo_surface_destroy(CAIROSURFACE);
cairo_surface_destroy(CAIROISURFACE);
@@ -2293,7 +2464,7 @@ void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) {
RESIT->second.monitorMirrorFB.release();
RESIT->second.blurFB.release();
RESIT->second.offMainFB.release();
- RESIT->second.stencilTex.destroyTexture();
+ RESIT->second.stencilTex->destroyTexture();
g_pHyprOpenGL->m_mMonitorRenderResources.erase(RESIT);
}
@@ -2343,109 +2514,6 @@ void CHyprOpenGLImpl::setRenderModifEnabled(bool enabled) {
m_RenderData.renderModif.enabled = enabled;
}
-inline const SGLPixelFormat GLES2_FORMATS[] = {
- {
- .drmFormat = DRM_FORMAT_ARGB8888,
- .glFormat = GL_BGRA_EXT,
- .glType = GL_UNSIGNED_BYTE,
- .withAlpha = true,
- },
- {
- .drmFormat = DRM_FORMAT_XRGB8888,
- .glFormat = GL_BGRA_EXT,
- .glType = GL_UNSIGNED_BYTE,
- .withAlpha = false,
- },
- {
- .drmFormat = DRM_FORMAT_XBGR8888,
- .glFormat = GL_RGBA,
- .glType = GL_UNSIGNED_BYTE,
- .withAlpha = false,
- },
- {
- .drmFormat = DRM_FORMAT_ABGR8888,
- .glFormat = GL_RGBA,
- .glType = GL_UNSIGNED_BYTE,
- .withAlpha = true,
- },
- {
- .drmFormat = DRM_FORMAT_BGR888,
- .glFormat = GL_RGB,
- .glType = GL_UNSIGNED_BYTE,
- .withAlpha = false,
- },
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- {
- .drmFormat = DRM_FORMAT_RGBX4444,
- .glFormat = GL_RGBA,
- .glType = GL_UNSIGNED_SHORT_4_4_4_4,
- .withAlpha = false,
- },
- {
- .drmFormat = DRM_FORMAT_RGBA4444,
- .glFormat = GL_RGBA,
- .glType = GL_UNSIGNED_SHORT_4_4_4_4,
- .withAlpha = true,
- },
- {
- .drmFormat = DRM_FORMAT_RGBX5551,
- .glFormat = GL_RGBA,
- .glType = GL_UNSIGNED_SHORT_5_5_5_1,
- .withAlpha = false,
- },
- {
- .drmFormat = DRM_FORMAT_RGBA5551,
- .glFormat = GL_RGBA,
- .glType = GL_UNSIGNED_SHORT_5_5_5_1,
- .withAlpha = true,
- },
- {
- .drmFormat = DRM_FORMAT_RGB565,
- .glFormat = GL_RGB,
- .glType = GL_UNSIGNED_SHORT_5_6_5,
- .withAlpha = false,
- },
- {
- .drmFormat = DRM_FORMAT_XBGR2101010,
- .glFormat = GL_RGBA,
- .glType = GL_UNSIGNED_INT_2_10_10_10_REV_EXT,
- .withAlpha = false,
- },
- {
- .drmFormat = DRM_FORMAT_ABGR2101010,
- .glFormat = GL_RGBA,
- .glType = GL_UNSIGNED_INT_2_10_10_10_REV_EXT,
- .withAlpha = true,
- },
- {
- .drmFormat = DRM_FORMAT_XBGR16161616F,
- .glFormat = GL_RGBA,
- .glType = GL_HALF_FLOAT_OES,
- .withAlpha = false,
- },
- {
- .drmFormat = DRM_FORMAT_ABGR16161616F,
- .glFormat = GL_RGBA,
- .glType = GL_HALF_FLOAT_OES,
- .withAlpha = true,
- },
- {
- .drmFormat = DRM_FORMAT_XBGR16161616,
- .glInternalFormat = GL_RGBA16_EXT,
- .glFormat = GL_RGBA,
- .glType = GL_UNSIGNED_SHORT,
- .withAlpha = false,
- },
- {
- .drmFormat = DRM_FORMAT_ABGR16161616,
- .glInternalFormat = GL_RGBA16_EXT,
- .glFormat = GL_RGBA,
- .glType = GL_UNSIGNED_SHORT,
- .withAlpha = true,
- },
-#endif
-};
-
uint32_t CHyprOpenGLImpl::getPreferredReadFormat(CMonitor* pMonitor) {
GLint glf = -1, glt = -1, as = 0;
/*glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &glf);
@@ -2453,14 +2521,12 @@ uint32_t CHyprOpenGLImpl::getPreferredReadFormat(CMonitor* pMonitor) {
glGetIntegerv(GL_ALPHA_BITS, &as);*/
if (glf == 0 || glt == 0) {
- glf = drmFormatToGL(pMonitor->drmFormat);
- glt = glFormatToType(glf);
+ glf = FormatUtils::drmFormatToGL(pMonitor->drmFormat);
+ glt = FormatUtils::glFormatToType(glf);
}
- for (auto& fmt : GLES2_FORMATS) {
- if (fmt.glFormat == glf && fmt.glType == glt && fmt.withAlpha == (as > 0))
- return fmt.drmFormat;
- }
+ if (const auto FMT = FormatUtils::getPixelFormatFromGL(glf, glt, as > 0); FMT)
+ return FMT->drmFormat;
if (m_sExts.EXT_read_format_bgra)
return DRM_FORMAT_XRGB8888;
@@ -2468,13 +2534,8 @@ uint32_t CHyprOpenGLImpl::getPreferredReadFormat(CMonitor* pMonitor) {
return DRM_FORMAT_XBGR8888;
}
-const SGLPixelFormat* CHyprOpenGLImpl::getPixelFormatFromDRM(uint32_t drmFormat) {
- for (auto& fmt : GLES2_FORMATS) {
- if (fmt.drmFormat == drmFormat)
- return &fmt;
- }
-
- return nullptr;
+std::vector<SDRMFormat> CHyprOpenGLImpl::getDRMFormats() {
+ return drmFormats;
}
void SRenderModifData::applyToBox(CBox& box) {
diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp
index ca9eecc6..db0f8ea1 100644
--- a/src/render/OpenGL.hpp
+++ b/src/render/OpenGL.hpp
@@ -5,6 +5,7 @@
#include "../helpers/Color.hpp"
#include "../helpers/Timer.hpp"
#include "../helpers/Region.hpp"
+#include "../helpers/Format.hpp"
#include <list>
#include <unordered_map>
#include <map>
@@ -54,14 +55,6 @@ struct SRenderModifData {
bool enabled = true;
};
-struct SGLPixelFormat {
- uint32_t drmFormat = DRM_FORMAT_INVALID;
- GLint glInternalFormat = 0;
- GLint glFormat = 0;
- GLint glType = 0;
- bool withAlpha = false;
-};
-
struct SMonitorRenderData {
CFramebuffer offloadFB;
CFramebuffer mirrorFB; // these are used for some effects,
@@ -70,7 +63,7 @@ struct SMonitorRenderData {
CFramebuffer monitorMirrorFB; // used for mirroring outputs, does not contain artifacts like offloadFB
- CTexture stencilTex;
+ SP<CTexture> stencilTex = makeShared<CTexture>();
CFramebuffer blurFB;
bool blurFBDirty = true;
@@ -132,74 +125,73 @@ class CHyprOpenGLImpl {
public:
CHyprOpenGLImpl();
- void begin(CMonitor*, const CRegion& damage, CFramebuffer* fb = nullptr, std::optional<CRegion> 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<CRegion> 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(SP<CTexture>, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false);
+ void renderTextureWithDamage(SP<CTexture>, CBox*, CRegion* damage, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false);
+ void renderTextureWithBlur(SP<CTexture>, CBox*, float a, SP<CWLSurfaceResource> 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(SP<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<CRegion> finalDamage = {});
+ void setDamage(const CRegion& damage, std::optional<CRegion> finalDamage = {});
- uint32_t getPreferredReadFormat(CMonitor* pMonitor);
- const SGLPixelFormat* getPixelFormatFromDRM(uint32_t drmFormat);
+ uint32_t getPreferredReadFormat(CMonitor* pMonitor);
+ std::vector<SDRMFormat> getDRMFormats();
+ EGLImageKHR createEGLImage(const SDMABUFAttrs& attrs);
- 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<PHLWINDOWREF, CFramebuffer> m_mWindowFramebuffers;
std::map<PHLLSREF, CFramebuffer> m_mLayerFramebuffers;
@@ -208,41 +200,52 @@ class CHyprOpenGLImpl {
struct {
PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES = nullptr;
+ PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES = nullptr;
+ PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR = nullptr;
PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR = nullptr;
+ PFNEGLQUERYDMABUFFORMATSEXTPROC eglQueryDmaBufFormatsEXT = nullptr;
+ PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT = nullptr;
} m_sProc;
struct {
- bool EXT_read_format_bgra = false;
+ bool EXT_read_format_bgra = false;
+ bool EXT_image_dma_buf_import = false;
+ bool EXT_image_dma_buf_import_modifiers = false;
} m_sExts;
private:
- std::list<GLuint> m_lBuffers;
- std::list<GLuint> m_lTextures;
+ std::list<GLuint> m_lBuffers;
+ std::list<GLuint> m_lTextures;
+
+ std::vector<SDRMFormat> drmFormats;
+ bool m_bHasModifiers = false;
- int m_iDRMFD;
- std::string m_szExtensions;
+ int m_iDRMFD;
+ std::string m_szExtensions;
- bool m_bFakeFrame = false;
- bool m_bEndFrame = false;
- bool m_bApplyFinalShader = false;
- bool m_bBlend = false;
- bool m_bOffloadedFramebuffer = false;
+ bool m_bFakeFrame = false;
+ bool m_bEndFrame = false;
+ bool m_bApplyFinalShader = false;
+ bool m_bBlend = false;
+ bool m_bOffloadedFramebuffer = false;
- CShader m_sFinalScreenShader;
- CTimer m_tGlobalTimer;
+ CShader m_sFinalScreenShader;
+ CTimer m_tGlobalTimer;
- void logShaderError(const GLuint&, bool program = false);
- GLuint createProgram(const std::string&, const std::string&, bool dynamic = false);
- GLuint compileShader(const GLuint&, std::string, bool dynamic = false);
- void createBGTextureForMonitor(CMonitor*);
- void initShaders();
+ void logShaderError(const GLuint&, bool program = false);
+ GLuint createProgram(const std::string&, const std::string&, bool dynamic = false);
+ GLuint compileShader(const GLuint&, std::string, bool dynamic = false);
+ void createBGTextureForMonitor(CMonitor*);
+ void initShaders();
+ void initDRMFormats();
+ std::vector<uint64_t> getModsForFormat(EGLint format);
// returns the out FB, can be either Mirror or MirrorSwap
CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage);
- void renderTextureInternalWithDamage(const CTexture&, CBox* pBox, float a, CRegion* damage, int round = 0, bool discardOpaque = false, bool noAA = false,
+ void renderTextureInternalWithDamage(SP<CTexture>, CBox* pBox, float a, CRegion* damage, int round = 0, bool discardOpaque = false, bool noAA = false,
bool allowCustomUV = false, bool allowDim = false);
- void renderTexturePrimitive(const CTexture& tex, CBox* pBox);
+ void renderTexturePrimitive(SP<CTexture> tex, CBox* pBox);
void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size);
void preBlurForCurrentMonitor();
diff --git a/src/render/Renderbuffer.cpp b/src/render/Renderbuffer.cpp
index 5003f600..694485c2 100644
--- a/src/render/Renderbuffer.cpp
+++ b/src/render/Renderbuffer.cpp
@@ -1,6 +1,7 @@
#include "Renderbuffer.hpp"
#include "OpenGL.hpp"
#include "../Compositor.hpp"
+#include "../protocols/types/Buffer.hpp"
#include <dlfcn.h>
@@ -61,6 +62,29 @@ CRenderbuffer::CRenderbuffer(wlr_buffer* buffer, uint32_t format) : m_pWlrBuffer
&buffer->events.destroy, [this](void* owner, void* data) { g_pHyprRenderer->onRenderbufferDestroy(this); }, this, "CRenderbuffer");
}
+CRenderbuffer::CRenderbuffer(SP<IWLBuffer> buffer, uint32_t format) : m_pHLBuffer(buffer), m_uDrmFormat(format) {
+ auto dma = buffer->dmabuf();
+
+ m_iImage = g_pHyprOpenGL->createEGLImage(dma);
+ if (m_iImage == EGL_NO_IMAGE_KHR)
+ throw std::runtime_error("createEGLImage failed");
+
+ glGenRenderbuffers(1, &m_iRBO);
+ glBindRenderbuffer(GL_RENDERBUFFER, m_iRBO);
+ g_pHyprOpenGL->m_sProc.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, (GLeglImageOES)m_iImage);
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
+
+ glGenFramebuffers(1, &m_sFramebuffer.m_iFb);
+ m_sFramebuffer.m_vSize = buffer->size;
+ m_sFramebuffer.bind();
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_iRBO);
+
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ throw std::runtime_error("rbo: glCheckFramebufferStatus failed");
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+}
+
void CRenderbuffer::bind() {
glBindRenderbuffer(GL_RENDERBUFFER, m_iRBO);
bindFB();
diff --git a/src/render/Renderbuffer.hpp b/src/render/Renderbuffer.hpp
index 2a8bf250..ed7050c5 100644
--- a/src/render/Renderbuffer.hpp
+++ b/src/render/Renderbuffer.hpp
@@ -3,10 +3,12 @@
#include "Framebuffer.hpp"
class CMonitor;
+class IWLBuffer;
class CRenderbuffer {
public:
CRenderbuffer(wlr_buffer* buffer, uint32_t format);
+ CRenderbuffer(SP<IWLBuffer> buffer, uint32_t format);
~CRenderbuffer();
void bind();
@@ -16,6 +18,7 @@ class CRenderbuffer {
uint32_t getFormat();
wlr_buffer* m_pWlrBuffer = nullptr;
+ WP<IWLBuffer> m_pHLBuffer = {};
DYNLISTENER(destroyBuffer);
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index 40ae953e..2a6cbb3b 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -1,6 +1,5 @@
#include "Renderer.hpp"
#include "../Compositor.hpp"
-#include "linux-dmabuf-unstable-v1-protocol.h"
#include "../helpers/Region.hpp"
#include <algorithm>
#include "../config/ConfigValue.hpp"
@@ -13,6 +12,7 @@
#include "../protocols/XDGShell.hpp"
#include "../protocols/PresentationTime.hpp"
#include "../protocols/core/DataDevice.hpp"
+#include "../protocols/core/Compositor.hpp"
extern "C" {
#include <xf86drm.h>
@@ -90,19 +90,24 @@ 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);
- const auto RDATA = (SRenderData*)data;
- const auto INTERACTIVERESIZEINPROGRESS = RDATA->pWindow && g_pInputManager->currentlyDraggedWindow.lock() == RDATA->pWindow && g_pInputManager->dragMode == MBIND_RESIZE;
+static void renderSurface(SP<CWLSurfaceResource> surface, int x, int y, void* data) {
+ if (!surface->current.buffer || !surface->current.buffer->texture)
+ 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)
+ // this is bad, probably has been logged elsewhere. Means the texture failed
+ // uploading to the GPU.
+ if (!TEXTURE->m_iTexID)
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 +145,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;
@@ -155,15 +160,23 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data)
windowBox.height = RDATA->h - y;
}
- if (windowBox.width <= 1 || windowBox.height <= 1)
+ if (windowBox.width <= 1 || windowBox.height <= 1) {
+ if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) {
+ surface->frame(RDATA->when);
+ auto FEEDBACK = makeShared<CQueuedPresentationData>(surface);
+ FEEDBACK->attachMonitor(RDATA->pMonitor);
+ FEEDBACK->discarded();
+ PROTO::presentation->queueData(FEEDBACK);
+ }
return; // invisible
+ }
windowBox.scale(RDATA->pMonitor->scale);
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 +196,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 +208,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<CQueuedPresentationData>(surface);
FEEDBACK->attachMonitor(RDATA->pMonitor);
FEEDBACK->presented();
@@ -506,7 +519,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 +589,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 +597,8 @@ 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<CWLSurfaceResource> s, const Vector2D& offset, void* data) { renderSurface(s, offset.x, offset.y, data); },
+ &renderdata);
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false;
@@ -641,14 +655,15 @@ 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<CWLSurfaceResource> s, const Vector2D& offset, void* data) { renderSurface(s, offset.x, offset.y, data); },
+ data);
rd->x = oldPos.x;
rd->y = oldPos.y;
},
@@ -698,7 +713,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 +732,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<CWLSurfaceResource> s, const Vector2D& offset, void* data) { renderSurface(s, offset.x, offset.y, data); }, &renderdata);
renderdata.squishOversized = false; // don't squish popups
renderdata.dontRound = true;
@@ -726,11 +741,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 +761,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<CWLSurfaceResource> s, const Vector2D& offset, void* data) { renderSurface(s, offset.x, offset.y, data); }, &renderdata);
}
void CHyprRenderer::renderSessionLockSurface(SSessionLockSurface* pSurface, CMonitor* pMonitor, timespec* time) {
@@ -766,7 +781,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<CWLSurfaceResource> s, const Vector2D& offset, void* data) { renderSurface(s, offset.x, offset.y, data); }, &renderdata);
}
void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* time, const Vector2D& translate, const float& scale) {
@@ -966,17 +981,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<CWLSurfaceResource> 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 +1004,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 +1026,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 +1038,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 +1061,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<CQueuedPresentationData>(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<CQueuedPresentationData>(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 +1441,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<CWLSurfaceResource> r, const Vector2D& offset, 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<CWLSurfaceResource> r, const Vector2D& offset, 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 +1672,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<CWLSurfaceResource> 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 +1845,6 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
pMonitor->onDisconnect();
pMonitor->events.modeChanged.emit();
- pMonitor->updateGlobal();
return true;
}
@@ -2242,12 +2250,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<CWLSurface> surf, int hotspotX, int hotspotY, bool force) {
m_bCursorHasSurface = surf;
m_sLastCursorData.name = "";
@@ -2464,8 +2471,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())
@@ -2544,6 +2551,15 @@ CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(wlr_buffer* buffer, uint32
return m_vRenderbuffers.emplace_back(std::make_unique<CRenderbuffer>(buffer, fmt)).get();
}
+CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(SP<IWLBuffer> buffer, uint32_t fmt) {
+ auto it = std::find_if(m_vRenderbuffers.begin(), m_vRenderbuffers.end(), [&](const auto& other) { return other->m_pHLBuffer == buffer; });
+
+ if (it != m_vRenderbuffers.end())
+ return it->get();
+
+ return m_vRenderbuffers.emplace_back(std::make_unique<CRenderbuffer>(buffer, fmt)).get();
+}
+
void CHyprRenderer::makeEGLCurrent() {
if (!g_pCompositor)
return;
@@ -2556,7 +2572,7 @@ void CHyprRenderer::unsetEGL() {
eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
-bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode, wlr_buffer* buffer, CFramebuffer* fb, bool simple) {
+bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode, SP<IWLBuffer> buffer, CFramebuffer* fb, bool simple) {
makeEGLCurrent();
@@ -2586,10 +2602,13 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode
return false;
}
} else
- m_pCurrentWlrBuffer = wlr_buffer_lock(buffer);
+ m_pCurrentHLBuffer = buffer;
try {
- m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentWlrBuffer, pMonitor->drmFormat);
+ if (m_pCurrentWlrBuffer)
+ m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentWlrBuffer, pMonitor->drmFormat);
+ else
+ m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentHLBuffer.lock(), pMonitor->drmFormat);
} catch (std::exception& e) {
Debug::log(ERR, "getOrCreateRenderbuffer failed for {}", pMonitor->szName);
wlr_buffer_unlock(m_pCurrentWlrBuffer);
diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp
index da38fed2..f88bfebf 100644
--- a/src/render/Renderer.hpp
+++ b/src/render/Renderer.hpp
@@ -12,6 +12,7 @@ struct SMonitorRule;
class CWorkspace;
class CWindow;
class CInputPopup;
+class IWLBuffer;
// TODO: add fuller damage tracking for updating only parts of a window
enum DAMAGETRACKINGMODES {
@@ -44,7 +45,7 @@ class CHyprRenderer {
void renderMonitor(CMonitor* pMonitor);
void arrangeLayersForMonitor(const int&);
- void damageSurface(wlr_surface*, double, double, double scale = 1.0);
+ void damageSurface(SP<CWLSurfaceResource>, 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 +58,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<CWLSurfaceResource>, bool main = false, const Vector2D& projSize = {}, bool fixMisalignedFSV1 = false);
std::tuple<float, float, float> 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<CWLSurface> surf, int hotspotX, int hotspotY, bool force = false);
void setCursorFromName(const std::string& name, bool force = false);
void onRenderbufferDestroy(CRenderbuffer* rb);
CRenderbuffer* getCurrentRBO();
@@ -74,7 +75,7 @@ class CHyprRenderer {
// if RENDER_MODE_NORMAL, provided damage will be written to.
// otherwise, it will be the one used.
- bool beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, wlr_buffer* buffer = nullptr, CFramebuffer* fb = nullptr, bool simple = false);
+ bool beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, SP<IWLBuffer> buffer = {}, CFramebuffer* fb = nullptr, bool simple = false);
void endRender();
bool m_bBlockSurfaceFeedback = false;
@@ -98,10 +99,10 @@ class CHyprRenderer {
CTimer m_tRenderTimer;
struct {
- int hotspotX;
- int hotspotY;
- std::optional<CWLSurface*> surf = nullptr;
- std::string name;
+ int hotspotX;
+ int hotspotY;
+ std::optional<SP<CWLSurface>> surf;
+ std::string name;
} m_sLastCursorData;
private:
@@ -121,6 +122,7 @@ class CHyprRenderer {
bool m_bCursorHasSurface = false;
CRenderbuffer* m_pCurrentRenderbuffer = nullptr;
wlr_buffer* m_pCurrentWlrBuffer = nullptr;
+ WP<IWLBuffer> m_pCurrentHLBuffer = {};
eRenderMode m_eRenderMode = RENDER_MODE_NORMAL;
bool m_bNvidia = false;
@@ -132,6 +134,7 @@ class CHyprRenderer {
} m_sCursorHiddenConditions;
CRenderbuffer* getOrCreateRenderbuffer(wlr_buffer* buffer, uint32_t fmt);
+ CRenderbuffer* getOrCreateRenderbuffer(SP<IWLBuffer> buffer, uint32_t fmt);
std::vector<std::unique_ptr<CRenderbuffer>> m_vRenderbuffers;
friend class CHyprOpenGLImpl;
diff --git a/src/render/Texture.cpp b/src/render/Texture.cpp
index 1820d0fb..aef8e4ac 100644
--- a/src/render/Texture.cpp
+++ b/src/render/Texture.cpp
@@ -1,16 +1,54 @@
#include "Texture.hpp"
+#include "Renderer.hpp"
+#include "../Compositor.hpp"
+#include "../protocols/types/Buffer.hpp"
+#include "../helpers/Format.hpp"
CTexture::CTexture() {
// naffin'
}
+CTexture::~CTexture() {
+ if (m_bNonOwning)
+ return;
+
+ g_pHyprRenderer->makeEGLCurrent();
+ destroyTexture();
+}
+
+CTexture::CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size_) {
+ g_pHyprRenderer->makeEGLCurrent();
+
+ const auto format = FormatUtils::getPixelFormatFromDRM(drmFormat);
+ ASSERT(format);
+
+ m_iType = format->withAlpha ? TEXTURE_RGBA : TEXTURE_RGBX;
+ m_vSize = size_;
+ allocate();
+
+ GLCALL(glBindTexture(GL_TEXTURE_2D, m_iTexID));
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+#ifndef GLES2
+ if (format->flipRB) {
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE));
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED));
+ }
+#endif
+ GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / format->bytesPerBlock));
+ GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, format->glInternalFormat ? format->glInternalFormat : format->glFormat, size_.x, size_.y, 0, format->glFormat, format->glType, pixels));
+ GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0));
+ GLCALL(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;
wlr_gles2_texture_get_attribs(tex, &attrs);
- m_iTarget = attrs.target;
- m_iTexID = attrs.tex;
+ m_iTarget = attrs.target;
+ m_iTexID = attrs.tex;
+ m_bNonOwning = true;
if (m_iTarget == GL_TEXTURE_2D)
m_iType = attrs.has_alpha ? TEXTURE_RGBA : TEXTURE_RGBX;
@@ -20,14 +58,72 @@ CTexture::CTexture(wlr_texture* tex) {
m_vSize = Vector2D(tex->width, tex->height);
}
+CTexture::CTexture(const SDMABUFAttrs& attrs, void* image) {
+ if (!g_pHyprOpenGL->m_sProc.glEGLImageTargetTexture2DOES) {
+ Debug::log(ERR, "Cannot create a dmabuf texture: no glEGLImageTargetTexture2DOES");
+ return;
+ }
+
+ m_iTarget = GL_TEXTURE_2D;
+ m_iType = TEXTURE_RGBA;
+ m_vSize = attrs.size;
+ m_iType = FormatUtils::isFormatOpaque(attrs.format) ? TEXTURE_RGBX : TEXTURE_RGBA;
+ allocate();
+ m_pEglImage = image;
+
+ GLCALL(glBindTexture(GL_TEXTURE_2D, m_iTexID));
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+ GLCALL(g_pHyprOpenGL->m_sProc.glEGLImageTargetTexture2DOES(m_iTarget, image));
+ GLCALL(glBindTexture(GL_TEXTURE_2D, 0));
+}
+
+void CTexture::update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const CRegion& damage) {
+ g_pHyprRenderer->makeEGLCurrent();
+
+ const auto format = FormatUtils::getPixelFormatFromDRM(drmFormat);
+ ASSERT(format);
+
+ glBindTexture(GL_TEXTURE_2D, m_iTexID);
+
+ auto rects = damage.copy().intersect(CBox{{}, m_vSize}).getRects();
+
+#ifndef GLES2
+ if (format->flipRB) {
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE));
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED));
+ }
+#endif
+
+ for (auto& rect : rects) {
+ GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / format->bytesPerBlock));
+ GLCALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, rect.x1));
+ GLCALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, rect.y1));
+
+ int width = rect.x2 - rect.x1;
+ int height = rect.y2 - rect.y1;
+ GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x1, rect.y1, width, height, format->glFormat, format->glType, pixels));
+ }
+
+ GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0));
+ GLCALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0));
+ GLCALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0));
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+}
+
void CTexture::destroyTexture() {
if (m_iTexID) {
- glDeleteTextures(1, &m_iTexID);
+ GLCALL(glDeleteTextures(1, &m_iTexID));
m_iTexID = 0;
}
+
+ if (m_pEglImage)
+ g_pHyprOpenGL->m_sProc.eglDestroyImageKHR(wlr_egl_get_display(g_pCompositor->m_sWLREGL), m_pEglImage);
+ m_pEglImage = nullptr;
}
void CTexture::allocate() {
if (!m_iTexID)
- glGenTextures(1, &m_iTexID);
-} \ No newline at end of file
+ GLCALL(glGenTextures(1, &m_iTexID));
+}
diff --git a/src/render/Texture.hpp b/src/render/Texture.hpp
index 93a6aa5f..fa1ca4fe 100644
--- a/src/render/Texture.hpp
+++ b/src/render/Texture.hpp
@@ -2,6 +2,10 @@
#include "../defines.hpp"
+class IWLBuffer;
+struct SDMABUFAttrs;
+class CRegion;
+
enum TEXTURETYPE {
TEXTURE_INVALID, // Invalid
TEXTURE_RGBA, // 4 channels
@@ -12,13 +16,27 @@ enum TEXTURETYPE {
class CTexture {
public:
CTexture();
+
+ CTexture(CTexture&) = delete;
+ CTexture(CTexture&&) = delete;
+ CTexture(const CTexture&&) = delete;
+ CTexture(const CTexture&) = delete;
+
+ CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size);
CTexture(wlr_texture*);
+ // this ctor takes ownership of the eglImage.
+ CTexture(const SDMABUFAttrs&, void* image);
+ ~CTexture();
+
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;
GLuint m_iTexID = 0;
Vector2D m_vSize;
+ void* m_pEglImage = nullptr;
+ bool m_bNonOwning = false; // wlr
}; \ No newline at end of file
diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp
index 04f69aaa..d96f2c3c 100644
--- a/src/render/decorations/CHyprGroupBarDecoration.cpp
+++ b/src/render/decorations/CHyprGroupBarDecoration.cpp
@@ -6,23 +6,23 @@
#include <pango/pangocairo.h>
// shared things to conserve VRAM
-static CTexture m_tGradientActive;
-static CTexture m_tGradientInactive;
-static CTexture m_tGradientLockedActive;
-static CTexture m_tGradientLockedInactive;
+static SP<CTexture> m_tGradientActive = makeShared<CTexture>();
+static SP<CTexture> m_tGradientInactive = makeShared<CTexture>();
+static SP<CTexture> m_tGradientLockedActive = makeShared<CTexture>();
+static SP<CTexture> m_tGradientLockedInactive = makeShared<CTexture>();
-constexpr int BAR_INDICATOR_HEIGHT = 3;
-constexpr int BAR_PADDING_OUTER_VERT = 2;
-constexpr int BAR_PADDING_OUTER_HORZ = 2;
-constexpr int BAR_TEXT_PAD = 2;
-constexpr int BAR_HORIZONTAL_PADDING = 2;
+constexpr int BAR_INDICATOR_HEIGHT = 3;
+constexpr int BAR_PADDING_OUTER_VERT = 2;
+constexpr int BAR_PADDING_OUTER_HORZ = 2;
+constexpr int BAR_TEXT_PAD = 2;
+constexpr int BAR_HORIZONTAL_PADDING = 2;
CHyprGroupBarDecoration::CHyprGroupBarDecoration(PHLWINDOW pWindow) : IHyprWindowDecoration(pWindow) {
static auto PGRADIENTS = CConfigValue<Hyprlang::INT>("group:groupbar:enabled");
static auto PENABLED = CConfigValue<Hyprlang::INT>("group:groupbar:gradients");
m_pWindow = pWindow;
- if (m_tGradientActive.m_iTexID == 0 && *PENABLED && *PGRADIENTS)
+ if (m_tGradientActive->m_iTexID == 0 && *PENABLED && *PGRADIENTS)
refreshGroupBarGradients();
}
@@ -157,10 +157,9 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a) {
rect.scale(pMonitor->scale);
if (*PGRADIENTS) {
- const auto& GRADIENTTEX =
- (m_dwGroupMembers[WINDOWINDEX].lock() == g_pCompositor->m_pLastWindow.lock() ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) :
- (GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive));
- if (GRADIENTTEX.m_iTexID != 0)
+ const auto GRADIENTTEX = (m_dwGroupMembers[WINDOWINDEX] == g_pCompositor->m_pLastWindow ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) :
+ (GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive));
+ if (GRADIENTTEX->m_iTexID != 0)
g_pHyprOpenGL->renderTexture(GRADIENTTEX, &rect, 1.0);
}
@@ -204,6 +203,7 @@ void CHyprGroupBarDecoration::invalidateTextures() {
}
CTitleTex::CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float monitorScale) {
+ tex = makeShared<CTexture>();
szContent = pWindow->m_szTitle;
pWindowOwner = pWindow;
const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, bufferSize.x, bufferSize.y);
@@ -254,8 +254,8 @@ CTitleTex::CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float
// copy the data to an OpenGL texture we have
const auto DATA = cairo_image_surface_get_data(CAIROSURFACE);
- tex.allocate();
- glBindTexture(GL_TEXTURE_2D, tex.m_iTexID);
+ tex->allocate();
+ glBindTexture(GL_TEXTURE_2D, tex->m_iTexID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -272,10 +272,10 @@ CTitleTex::CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float
}
CTitleTex::~CTitleTex() {
- tex.destroyTexture();
+ tex->destroyTexture();
}
-void renderGradientTo(CTexture& tex, CGradientValueData* grad) {
+void renderGradientTo(SP<CTexture> tex, CGradientValueData* grad) {
if (!g_pCompositor->m_pLastMonitor)
return;
@@ -308,8 +308,8 @@ void renderGradientTo(CTexture& tex, CGradientValueData* grad) {
// copy the data to an OpenGL texture we have
const auto DATA = cairo_image_surface_get_data(CAIROSURFACE);
- tex.allocate();
- glBindTexture(GL_TEXTURE_2D, tex.m_iTexID);
+ tex->allocate();
+ glBindTexture(GL_TEXTURE_2D, tex->m_iTexID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -340,11 +340,11 @@ void refreshGroupBarGradients() {
g_pHyprRenderer->makeEGLCurrent();
- if (m_tGradientActive.m_iTexID != 0) {
- m_tGradientActive.destroyTexture();
- m_tGradientInactive.destroyTexture();
- m_tGradientLockedActive.destroyTexture();
- m_tGradientLockedInactive.destroyTexture();
+ if (m_tGradientActive->m_iTexID != 0) {
+ m_tGradientActive->destroyTexture();
+ m_tGradientInactive->destroyTexture();
+ m_tGradientLockedActive->destroyTexture();
+ m_tGradientLockedInactive->destroyTexture();
}
if (!*PENABLED || !*PGRADIENTS)
diff --git a/src/render/decorations/CHyprGroupBarDecoration.hpp b/src/render/decorations/CHyprGroupBarDecoration.hpp
index e3f553c5..64870d45 100644
--- a/src/render/decorations/CHyprGroupBarDecoration.hpp
+++ b/src/render/decorations/CHyprGroupBarDecoration.hpp
@@ -12,7 +12,7 @@ class CTitleTex {
CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float monitorScale);
~CTitleTex();
- CTexture tex;
+ SP<CTexture> tex;
std::string szContent;
PHLWINDOWREF pWindowOwner;
};
diff --git a/src/xwayland/XSurface.cpp b/src/xwayland/XSurface.cpp
index 8994e975..07cac832 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 73cb89a5..0cdac1d5 100644
--- a/src/xwayland/XSurface.hpp
+++ b/src/xwayland/XSurface.hpp
@@ -5,7 +5,7 @@
#include "../helpers/Box.hpp"
#include <vector>
-struct wlr_surface;
+class CWLSurfaceResource;
class CXWaylandSurfaceResource;
#ifdef NO_XWAYLAND
@@ -39,7 +39,7 @@ typedef struct {
class CXWaylandSurface {
public:
- wlr_surface* surface = nullptr;
+ WP<CWLSurfaceResource> surface;
WP<CXWaylandSurfaceResource> 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 5dfd4839..7af1d506 100644
--- a/src/xwayland/XWM.cpp
+++ b/src/xwayland/XWM.cpp
@@ -6,6 +6,7 @@
#include <unordered_map>
#include "../Compositor.hpp"
#include "../protocols/XWaylandShell.hpp"
+#include "../protocols/core/Compositor.hpp"
#include "../managers/SeatManager.hpp"
#include "../protocols/core/Seat.hpp"
#include <ranges>
@@ -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<SP<CWLSurfaceResource>>(d)); });
listeners.newXShellSurface = PROTO::xwaylandShell->events.newSurface.registerListener([this](std::any d) { onNewResource(std::any_cast<SP<CXWaylandSurfaceResource>>(d)); });
createWMWindow();
@@ -903,13 +902,13 @@ void CXWM::sendState(SP<CXWaylandSurface> 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<CWLSurfaceResource> 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)
@@ -932,7 +931,7 @@ void CXWM::onNewResource(SP<CXWaylandSurfaceResource> resource) {
if (surf->resource || surf->wlSerial != resource->serial)
continue;
- associate(surf, resource->surface);
+ associate(surf, resource->surface.lock());
break;
}
}
@@ -955,7 +954,7 @@ void CXWM::readWindowData(SP<CXWaylandSurface> surf) {
}
}
-void CXWM::associate(SP<CXWaylandSurface> surf, wlr_surface* wlSurf) {
+void CXWM::associate(SP<CXWaylandSurface> surf, SP<CWLSurfaceResource> wlSurf) {
if (surf->surface)
return;
@@ -981,7 +980,7 @@ void CXWM::dissociate(SP<CXWaylandSurface> 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 1d695a15..bdf4fac2 100644
--- a/src/xwayland/XWM.hpp
+++ b/src/xwayland/XWM.hpp
@@ -73,7 +73,7 @@ class CXWM {
void createWMWindow();
void initSelection();
- void onNewSurface(wlr_surface* surf);
+ void onNewSurface(SP<CWLSurfaceResource> surf);
void onNewResource(SP<CXWaylandSurfaceResource> resource);
void setActiveWindow(xcb_window_t window);
@@ -87,7 +87,7 @@ class CXWM {
SP<CXWaylandSurface> windowForXID(xcb_window_t wid);
void readWindowData(SP<CXWaylandSurface> surf);
- void associate(SP<CXWaylandSurface> surf, wlr_surface* wlSurf);
+ void associate(SP<CXWaylandSurface> surf, SP<CWLSurfaceResource> wlSurf);
void dissociate(SP<CXWaylandSurface> surf);
void updateClientList();
@@ -147,9 +147,8 @@ class CXWM {
SXSelection clipboard;
- DYNLISTENER(newSurface);
-
struct {
+ CHyprSignalListener newWLSurface;
CHyprSignalListener newXShellSurface;
} listeners;