mirror of
https://github.com/hyprwm/Hyprland.git
synced 2024-12-27 01:34:24 +03:00
wayland/core: move to new impl (#6268)
* wayland/core/dmabuf: move to new impl it's the final countdown
This commit is contained in:
parent
c31d9ef417
commit
6967a31450
@ -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()
|
||||
|
||||
|
18
flake.lock
18
flake.lock
@ -13,11 +13,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1716576411,
|
||||
"narHash": "sha256-FIN1wMoyePBTtibCbaeJaoKNLuAYIGwLCWAYC1DJanw=",
|
||||
"lastModified": 1717181720,
|
||||
"narHash": "sha256-yv+QZWsusu/NWjydkxixHC2g+tIJ9v+xkE2EiVpJj6g=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprcursor",
|
||||
"rev": "57298fc4f13c807e50ada2c986a3114b7fc2e621",
|
||||
"rev": "9e27a2c2ceb1e0b85bd55b0afefad196056fe87c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -84,11 +84,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1716058375,
|
||||
"narHash": "sha256-CwjWoVnBZE5SBpRx9dgSQGCr4Goxyfcyv3zZbOhVqzk=",
|
||||
"lastModified": 1717784906,
|
||||
"narHash": "sha256-YxmfxHfWed1fosaa7fC1u7XoKp1anEZU+7Lh/ojRKoM=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprwayland-scanner",
|
||||
"rev": "3afed4364790aebe0426077631af1e164a9650cc",
|
||||
"rev": "0f30f9eca6e404130988554accbb64d1c9ec877d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -99,11 +99,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1716330097,
|
||||
"narHash": "sha256-8BO3B7e3BiyIDsaKA0tY8O88rClYRTjvAp66y+VBUeU=",
|
||||
"lastModified": 1717602782,
|
||||
"narHash": "sha256-pL9jeus5QpX5R+9rsp3hhZ+uplVHscNJh8n8VpqscM0=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "5710852ba686cc1fd0d3b8e22b3117d43ba374c2",
|
||||
"rev": "e8057b67ebf307f01bdcc8fba94d94f75039d1f6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -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
189
protocols/wayland-drm.xml
Normal 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>
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
|
@ -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() {
|
||||
|
@ -36,7 +36,7 @@ class CLayerSurface {
|
||||
|
||||
bool keyboardExclusive = false;
|
||||
|
||||
CWLSurface surface;
|
||||
SP<CWLSurface> surface;
|
||||
|
||||
bool mapped = false;
|
||||
uint32_t layer = 0;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -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();
|
||||
};
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
@ -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
271
src/helpers/Format.cpp
Normal 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
37
src/helpers/Format.hpp
Normal 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);
|
||||
};
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -172,7 +172,6 @@ class CMonitor {
|
||||
int64_t activeWorkspaceID();
|
||||
int64_t activeSpecialWorkspaceID();
|
||||
CBox logicalBox();
|
||||
void updateGlobal();
|
||||
|
||||
bool m_bEnabled = false;
|
||||
bool m_bRenderingInitPassed = false;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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_);
|
||||
}
|
||||
};
|
||||
|
@ -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_);
|
||||
}
|
||||
};
|
||||
|
@ -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(); });
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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?
|
||||
|
@ -89,4 +89,14 @@
|
||||
}
|
||||
#else
|
||||
#define UNREACHABLE() std::unreachable();
|
||||
#endif
|
||||
#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); \
|
||||
} \
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
||||
|
@ -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*);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
};
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -5,23 +5,28 @@
|
||||
#include <unordered_map>
|
||||
#include "WaylandProtocol.hpp"
|
||||
#include "alpha-modifier-v1.hpp"
|
||||
#include "../helpers/signal/Listener.hpp"
|
||||
|
||||
class CWLSurfaceResource;
|
||||
|
||||
class CAlphaModifier {
|
||||
public:
|
||||
CAlphaModifier(SP<CWpAlphaModifierSurfaceV1> resource_, wlr_surface* surface);
|
||||
CAlphaModifier(SP<CWpAlphaModifierSurfaceV1> resource_, SP<CWLSurfaceResource> surface);
|
||||
~CAlphaModifier();
|
||||
|
||||
bool good();
|
||||
wlr_surface* getSurface();
|
||||
void onSurfaceDestroy();
|
||||
bool good();
|
||||
SP<CWLSurfaceResource> getSurface();
|
||||
void onSurfaceDestroy();
|
||||
|
||||
private:
|
||||
SP<CWpAlphaModifierSurfaceV1> resource;
|
||||
wlr_surface* pSurface = nullptr;
|
||||
WP<CWLSurfaceResource> pSurface;
|
||||
|
||||
void setSurfaceAlpha(float a);
|
||||
|
||||
DYNLISTENER(surfaceDestroy);
|
||||
struct {
|
||||
CHyprSignalListener destroySurface;
|
||||
} listeners;
|
||||
};
|
||||
|
||||
class CAlphaModifierProtocol : public IWaylandProtocol {
|
||||
@ -33,15 +38,15 @@ class CAlphaModifierProtocol : public IWaylandProtocol {
|
||||
private:
|
||||
void onManagerResourceDestroy(wl_resource* res);
|
||||
void destroyModifier(CAlphaModifier* decoration);
|
||||
void onGetSurface(CWpAlphaModifierV1* pMgr, uint32_t id, wlr_surface* surface);
|
||||
void onGetSurface(CWpAlphaModifierV1* pMgr, uint32_t id, SP<CWLSurfaceResource> surface);
|
||||
|
||||
//
|
||||
std::vector<UP<CWpAlphaModifierV1>> m_vManagers;
|
||||
std::unordered_map<wlr_surface*, UP<CAlphaModifier>> m_mAlphaModifiers; // xdg_toplevel -> deco
|
||||
std::vector<UP<CWpAlphaModifierV1>> m_vManagers;
|
||||
std::unordered_map<WP<CWLSurfaceResource>, UP<CAlphaModifier>> m_mAlphaModifiers; // xdg_toplevel -> deco
|
||||
|
||||
friend class CAlphaModifier;
|
||||
};
|
||||
|
||||
namespace PROTO {
|
||||
inline UP<CAlphaModifierProtocol> alphaModifier;
|
||||
};
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
@ -6,19 +6,20 @@
|
||||
#include "fractional-scale-v1.hpp"
|
||||
|
||||
class CFractionalScaleProtocol;
|
||||
class CWLSurfaceResource;
|
||||
|
||||
class CFractionalScaleAddon {
|
||||
public:
|
||||
CFractionalScaleAddon(SP<CWpFractionalScaleV1> resource_, wlr_surface* surf_);
|
||||
CFractionalScaleAddon(SP<CWpFractionalScaleV1> resource_, SP<CWLSurfaceResource> surf_);
|
||||
|
||||
void setScale(const float& scale);
|
||||
void onSurfaceDestroy();
|
||||
void setScale(const float& scale);
|
||||
void onSurfaceDestroy();
|
||||
|
||||
bool good();
|
||||
bool good();
|
||||
|
||||
wlr_surface* surf();
|
||||
SP<CWLSurfaceResource> surf();
|
||||
|
||||
bool operator==(const wl_resource* other) const {
|
||||
bool operator==(const wl_resource* other) const {
|
||||
return other == resource->resource();
|
||||
}
|
||||
|
||||
@ -28,42 +29,36 @@ class CFractionalScaleAddon {
|
||||
|
||||
private:
|
||||
SP<CWpFractionalScaleV1> resource;
|
||||
float scale = 1.F;
|
||||
wlr_surface* surface = nullptr;
|
||||
float scale = 1.F;
|
||||
WP<CWLSurfaceResource> surface;
|
||||
bool surfaceGone = false;
|
||||
|
||||
friend class CFractionalScaleProtocol;
|
||||
};
|
||||
|
||||
struct SSurfaceListener {
|
||||
DYNLISTENER(surfaceDestroy);
|
||||
};
|
||||
|
||||
class CFractionalScaleProtocol : public IWaylandProtocol {
|
||||
public:
|
||||
CFractionalScaleProtocol(const wl_interface* iface, const int& ver, const std::string& name);
|
||||
|
||||
virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
|
||||
|
||||
void onSurfaceDestroy(wlr_surface* surf);
|
||||
void sendScale(wlr_surface* surf, const float& scale);
|
||||
void onSurfaceDestroy(SP<CWLSurfaceResource> surf);
|
||||
void sendScale(SP<CWLSurfaceResource> surf, const float& scale);
|
||||
|
||||
private:
|
||||
void removeAddon(CFractionalScaleAddon*);
|
||||
void registerSurface(wlr_surface*);
|
||||
void onManagerResourceDestroy(wl_resource* res);
|
||||
void onGetFractionalScale(CWpFractionalScaleManagerV1* pMgr, uint32_t id, wlr_surface* surface);
|
||||
void onGetFractionalScale(CWpFractionalScaleManagerV1* pMgr, uint32_t id, SP<CWLSurfaceResource> surface);
|
||||
|
||||
//
|
||||
std::unordered_map<wlr_surface*, SSurfaceListener> m_mSurfaceDestroyListeners;
|
||||
|
||||
std::unordered_map<wlr_surface*, float> m_mSurfaceScales;
|
||||
std::unordered_map<wlr_surface*, UP<CFractionalScaleAddon>> m_mAddons;
|
||||
std::vector<UP<CWpFractionalScaleManagerV1>> m_vManagers;
|
||||
std::unordered_map<WP<CWLSurfaceResource>, float> m_mSurfaceScales;
|
||||
std::unordered_map<WP<CWLSurfaceResource>, UP<CFractionalScaleAddon>> m_mAddons;
|
||||
std::vector<UP<CWpFractionalScaleManagerV1>> m_vManagers;
|
||||
|
||||
friend class CFractionalScaleAddon;
|
||||
};
|
||||
|
||||
namespace PROTO {
|
||||
inline UP<CFractionalScaleProtocol> fractional;
|
||||
};
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
||||
|
@ -7,22 +7,23 @@
|
||||
#include "../helpers/signal/Signal.hpp"
|
||||
|
||||
class CIdleInhibitorResource;
|
||||
class CWLSurfaceResource;
|
||||
|
||||
class CIdleInhibitor {
|
||||
public:
|
||||
CIdleInhibitor(SP<CIdleInhibitorResource> resource_, wlr_surface* surf_);
|
||||
CIdleInhibitor(SP<CIdleInhibitorResource> resource_, SP<CWLSurfaceResource> surf_);
|
||||
|
||||
struct {
|
||||
CHyprSignalListener destroy;
|
||||
} listeners;
|
||||
|
||||
WP<CIdleInhibitorResource> resource;
|
||||
wlr_surface* surface = nullptr;
|
||||
WP<CWLSurfaceResource> surface;
|
||||
};
|
||||
|
||||
class CIdleInhibitorResource {
|
||||
public:
|
||||
CIdleInhibitorResource(SP<CZwpIdleInhibitorV1> resource_, wlr_surface* surface_);
|
||||
CIdleInhibitorResource(SP<CZwpIdleInhibitorV1> resource_, SP<CWLSurfaceResource> surface_);
|
||||
~CIdleInhibitorResource();
|
||||
|
||||
SP<CIdleInhibitor> inhibitor;
|
||||
@ -33,10 +34,12 @@ class CIdleInhibitorResource {
|
||||
|
||||
private:
|
||||
SP<CZwpIdleInhibitorV1> resource;
|
||||
wlr_surface* surface = nullptr;
|
||||
WP<CWLSurfaceResource> surface;
|
||||
bool destroySent = false;
|
||||
|
||||
DYNLISTENER(surfaceDestroy);
|
||||
struct {
|
||||
CHyprSignalListener destroySurface;
|
||||
} listeners;
|
||||
};
|
||||
|
||||
class CIdleInhibitProtocol : public IWaylandProtocol {
|
||||
@ -51,7 +54,7 @@ class CIdleInhibitProtocol : public IWaylandProtocol {
|
||||
|
||||
private:
|
||||
void onManagerResourceDestroy(wl_resource* res);
|
||||
void onCreateInhibitor(CZwpIdleInhibitManagerV1* pMgr, uint32_t id, wlr_surface* surface);
|
||||
void onCreateInhibitor(CZwpIdleInhibitManagerV1* pMgr, uint32_t id, SP<CWLSurfaceResource> surface);
|
||||
|
||||
void removeInhibitor(CIdleInhibitorResource*);
|
||||
|
||||
@ -64,4 +67,4 @@ class CIdleInhibitProtocol : public IWaylandProtocol {
|
||||
|
||||
namespace PROTO {
|
||||
inline UP<CIdleInhibitProtocol> idleInhibit;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
||||
|
454
src/protocols/LinuxDMABUF.cpp
Normal file
454
src/protocols/LinuxDMABUF.cpp
Normal 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; });
|
||||
}
|
138
src/protocols/LinuxDMABUF.hpp
Normal file
138
src/protocols/LinuxDMABUF.hpp
Normal 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
133
src/protocols/MesaDRM.cpp
Normal 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
60
src/protocols/MesaDRM.hpp
Normal 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;
|
||||
};
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
//
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user