wayland/core: move to new impl (#6268)

* wayland/core/dmabuf: move to new impl

it's the final countdown
This commit is contained in:
Vaxry 2024-06-08 10:07:59 +02:00 committed by GitHub
parent c31d9ef417
commit 6967a31450
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
147 changed files with 5388 additions and 2226 deletions

View file

@ -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()

View file

@ -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": {

View file

@ -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 = []

189
protocols/wayland-drm.xml Normal file
View file

@ -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>

View file

@ -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;
}

View file

@ -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*);
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;
std::string explicitConfigPath;
private:
void initAllSignals();

View file

@ -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);
}

View file

@ -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;

View file

@ -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() {

View file

@ -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;

View file

@ -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() {

View file

@ -36,7 +36,7 @@ class CLayerSurface {
bool keyboardExclusive = false;
CWLSurface surface;
SP<CWLSurface> surface;
bool mapped = false;
uint32_t layer = 0;

View file

@ -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;
}

View file

@ -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

View file

@ -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() {

View file

@ -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();
};

View file

@ -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();
}

View file

@ -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;
wlr_surface* m_pWLRSurface = nullptr;
bool m_bInert = true;
PHLWINDOWREF m_pWindowOwner;
PHLLSREF m_pLayerOwner;
CPopup* m_pPopupOwner = nullptr;
CSubsurface* m_pSubsurfaceOwner = nullptr;
WP<CWLSurfaceResource> m_pResource;
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;
};

View file

@ -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)
if (!m_pWLSurface->resource() || !m_pWLSurface->resource()->current.buffer)
return false;
// 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;
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)
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) {

View file

@ -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();

View file

@ -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();
});
}
}

View file

@ -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;
};

View file

@ -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 = {};

271
src/helpers/Format.cpp Normal file
View file

@ -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;
}

37
src/helpers/Format.hpp Normal file
View file

@ -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);
};

View file

@ -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;
}

View file

@ -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) {

View file

@ -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);

View file

@ -172,7 +172,6 @@ class CMonitor {
int64_t activeWorkspaceID();
int64_t activeSpecialWorkspaceID();
CBox logicalBox();
void updateGlobal();
bool m_bEnabled = false;
bool m_bRenderingInitPassed = false;

View file

@ -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);
}

View file

@ -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;

View file

@ -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;

View file

@ -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_);
}
};

View file

@ -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_);
}
};

View file

@ -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(); });
}

View file

@ -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() {

View file

@ -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};

View file

@ -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?

View file

@ -90,3 +90,13 @@
#else
#define UNREACHABLE() std::unreachable();
#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); \
} \
}

View file

@ -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);

View file

@ -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);

View file

@ -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();
}
}

View file

@ -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) {

View file

@ -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 {

View file

@ -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.

View file

@ -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();

View file

@ -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;
};

View file

@ -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

View file

@ -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*);

View file

@ -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)

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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();
}

View file

@ -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;

View file

@ -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();
}

View file

@ -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;
};

View file

@ -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;

View file

@ -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");
listeners.surfaceUnmap = pSurface->events.unmap.registerListener([this](std::any d) {
Debug::log(LOG, "Unmap TI owner1");
if (enterLocks)
enterLocks--;
pFocusedSurface = nullptr;
hyprListener_surfaceUnmapped.removeCallback();
hyprListener_surfaceDestroyed.removeCallback();
},
this, "CTextInput");
if (enterLocks)
enterLocks--;
pFocusedSurface.reset();
listeners.surfaceUnmap.reset();
listeners.surfaceDestroy.reset();
});
hyprListener_surfaceDestroyed.initCallback(
&pSurface->events.destroy,
[this](void* owner, void* data) {
Debug::log(LOG, "destroy TI owner1");
listeners.surfaceDestroy = pSurface->events.destroy.registerListener([this](std::any d) {
Debug::log(LOG, "Destroy TI owner1");
if (enterLocks)
enterLocks--;
pFocusedSurface = nullptr;
hyprListener_surfaceUnmapped.removeCallback();
hyprListener_surfaceDestroyed.removeCallback();
},
this, "CTextInput");
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() {

View file

@ -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;
};

View file

@ -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();
}

View file

@ -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;

View file

@ -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,11 +38,11 @@ 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;
};

View file

@ -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;
}

View file

@ -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);

View file

@ -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[surface]);
registerSurface(surface);
PADDON->setScale(m_mSurfaceScales.at(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();
}

View file

@ -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,38 +29,32 @@ 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;
};

View file

@ -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);

View file

@ -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));

View file

@ -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*);

View file

@ -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();

View file

@ -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 {

View file

@ -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");
listeners.destroySurface = surf_->events.destroy.registerListener([this](std::any d) {
events.destroy.emit();
PROTO::layerShell->destroyResource(this);
});
hyprListener_commitSurface.initCallback(
&surf_->events.commit,
[this](void* owner, void* data) {
current = pending;
pending.committed = 0;
listeners.commitSurface = surf_->events.commit.registerListener([this](std::any d) {
current = pending;
pending.committed = 0;
bool attachedBuffer = surface->pending.buffer_width > 0 && surface->pending.buffer_height > 0;
bool attachedBuffer = surface->current.buffer;
if (attachedBuffer && !configured) {
wlr_surface_reject_pending(surface, resource->resource(), -1, "layerSurface was not configured, but a buffer was attached");
return;
}
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;
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.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) {
wlr_surface_reject_pending(surface, resource->resource(), -1, "y == 0 but anchor doesn't have top and bottom");
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;
wlr_surface_map(surface);
events.map.emit();
return;
}
if (attachedBuffer && !mapped) {
mapped = true;
surface->map();
events.map.emit();
return;
}
if (!attachedBuffer && mapped) {
mapped = false;
wlr_surface_unmap(surface);
events.unmap.emit();
return;
}
if (!attachedBuffer && mapped) {
mapped = false;
surface->unmap();
events.unmap.emit();
configured = false;
return;
}
events.commit.emit();
},
this, "CLayerShellResource");
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();

View file

@ -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;

View file

@ -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; });
}

View file

@ -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;
};

133
src/protocols/MesaDRM.cpp Normal file
View file

@ -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; });
}

60
src/protocols/MesaDRM.hpp Normal file
View file

@ -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;
};

View file

@ -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();

View file

@ -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);
}

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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) {

View file

@ -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;
};

View file

@ -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);

View file

@ -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;

View file

@ -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();

View file

@ -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();

View file

@ -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;
}
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 (!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");
if (committed)
events.commit.emit();
else {
pSurface->map();
events.map.emit();
}
committed = true;
});
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();
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();
if (g_pCompositor->m_pLastFocus == pSurface)
g_pCompositor->m_pLastFocus = nullptr;
pSurface = nullptr;
},
this, "SessionLockSurface");
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) {

View file

@ -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;
};

View file

@ -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)

View file

@ -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 {

View file

@ -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();
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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);
//

View file

@ -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) {

View file

@ -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) {

View file

@ -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);

Some files were not shown because too many files have changed in this diff Show more