mirror of
https://github.com/hyprwm/xdg-desktop-portal-hyprland.git
synced 2024-12-27 03:49:48 +01:00
remotedesktop: implement remotedesktop portal
This commit is contained in:
parent
7c381c7cab
commit
ebb343a884
11 changed files with 736 additions and 18 deletions
|
@ -84,11 +84,12 @@ else()
|
||||||
set(HYPRLAND_PROTOCOLS "${CMAKE_SOURCE_DIR}/subprojects/hyprland-protocols")
|
set(HYPRLAND_PROTOCOLS "${CMAKE_SOURCE_DIR}/subprojects/hyprland-protocols")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
pkg_search_module(UUID REQUIRED uuid)
|
||||||
file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
|
file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
|
||||||
add_executable(xdg-desktop-portal-hyprland ${SRCFILES})
|
add_executable(xdg-desktop-portal-hyprland ${SRCFILES})
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
xdg-desktop-portal-hyprland PRIVATE rt PkgConfig::SDBUS Threads::Threads
|
xdg-desktop-portal-hyprland PRIVATE rt PkgConfig::SDBUS Threads::Threads
|
||||||
PkgConfig::deps)
|
PkgConfig::deps ${UUID_LIBRARIES})
|
||||||
|
|
||||||
# protocols
|
# protocols
|
||||||
pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
|
pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
|
||||||
|
@ -127,6 +128,8 @@ protocolwayland()
|
||||||
protocolnew("${CMAKE_SOURCE_DIR}/protocols"
|
protocolnew("${CMAKE_SOURCE_DIR}/protocols"
|
||||||
"wlr-foreign-toplevel-management-unstable-v1" true)
|
"wlr-foreign-toplevel-management-unstable-v1" true)
|
||||||
protocolnew("${CMAKE_SOURCE_DIR}/protocols" "wlr-screencopy-unstable-v1" true)
|
protocolnew("${CMAKE_SOURCE_DIR}/protocols" "wlr-screencopy-unstable-v1" true)
|
||||||
|
protocolnew("${CMAKE_SOURCE_DIR}/protocols" "wlr-virtual-pointer-unstable-v1" true)
|
||||||
|
protocolnew("${CMAKE_SOURCE_DIR}/protocols" "virtual-keyboard-unstable-v1" true)
|
||||||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-global-shortcuts-v1"
|
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-global-shortcuts-v1"
|
||||||
true)
|
true)
|
||||||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-toplevel-export-v1"
|
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-toplevel-export-v1"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[portal]
|
[portal]
|
||||||
DBusName=org.freedesktop.impl.portal.desktop.hyprland
|
DBusName=org.freedesktop.impl.portal.desktop.hyprland
|
||||||
Interfaces=org.freedesktop.impl.portal.Screenshot;org.freedesktop.impl.portal.ScreenCast;org.freedesktop.impl.portal.GlobalShortcuts;org.freedesktop.impl.portal.InputCapture;
|
Interfaces=org.freedesktop.impl.portal.Screenshot;org.freedesktop.impl.portal.ScreenCast;org.freedesktop.impl.portal.GlobalShortcuts;org.freedesktop.impl.portal.InputCapture;org.freedesktop.impl.portal.RemoteDesktop;
|
||||||
UseIn=wlroots;Hyprland;sway;Wayfire;river;
|
UseIn=wlroots;Hyprland;sway;Wayfire;river;
|
||||||
|
|
113
protocols/virtual-keyboard-unstable-v1.xml
Normal file
113
protocols/virtual-keyboard-unstable-v1.xml
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<protocol name="virtual_keyboard_unstable_v1">
|
||||||
|
<copyright>
|
||||||
|
Copyright © 2008-2011 Kristian Høgsberg
|
||||||
|
Copyright © 2010-2013 Intel Corporation
|
||||||
|
Copyright © 2012-2013 Collabora, Ltd.
|
||||||
|
Copyright © 2018 Purism SPC
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice (including the next
|
||||||
|
paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
</copyright>
|
||||||
|
|
||||||
|
<interface name="zwp_virtual_keyboard_v1" version="1">
|
||||||
|
<description summary="virtual keyboard">
|
||||||
|
The virtual keyboard provides an application with requests which emulate
|
||||||
|
the behaviour of a physical keyboard.
|
||||||
|
|
||||||
|
This interface can be used by clients on its own to provide raw input
|
||||||
|
events, or it can accompany the input method protocol.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<request name="keymap">
|
||||||
|
<description summary="keyboard mapping">
|
||||||
|
Provide a file descriptor to the compositor which can be
|
||||||
|
memory-mapped to provide a keyboard mapping description.
|
||||||
|
|
||||||
|
Format carries a value from the keymap_format enumeration.
|
||||||
|
</description>
|
||||||
|
<arg name="format" type="uint" summary="keymap format"/>
|
||||||
|
<arg name="fd" type="fd" summary="keymap file descriptor"/>
|
||||||
|
<arg name="size" type="uint" summary="keymap size, in bytes"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<enum name="error">
|
||||||
|
<entry name="no_keymap" value="0" summary="No keymap was set"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<request name="key">
|
||||||
|
<description summary="key event">
|
||||||
|
A key was pressed or released.
|
||||||
|
The time argument is a timestamp with millisecond granularity, with an
|
||||||
|
undefined base. All requests regarding a single object must share the
|
||||||
|
same clock.
|
||||||
|
|
||||||
|
Keymap must be set before issuing this request.
|
||||||
|
|
||||||
|
State carries a value from the key_state enumeration.
|
||||||
|
</description>
|
||||||
|
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||||
|
<arg name="key" type="uint" summary="key that produced the event"/>
|
||||||
|
<arg name="state" type="uint" summary="physical state of the key"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="modifiers">
|
||||||
|
<description summary="modifier and group state">
|
||||||
|
Notifies the compositor that the modifier and/or group state has
|
||||||
|
changed, and it should update state.
|
||||||
|
|
||||||
|
The client should use wl_keyboard.modifiers event to synchronize its
|
||||||
|
internal state with seat state.
|
||||||
|
|
||||||
|
Keymap must be set before issuing this request.
|
||||||
|
</description>
|
||||||
|
<arg name="mods_depressed" type="uint" summary="depressed modifiers"/>
|
||||||
|
<arg name="mods_latched" type="uint" summary="latched modifiers"/>
|
||||||
|
<arg name="mods_locked" type="uint" summary="locked modifiers"/>
|
||||||
|
<arg name="group" type="uint" summary="keyboard layout"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor" since="1">
|
||||||
|
<description summary="destroy the virtual keyboard keyboard object"/>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<interface name="zwp_virtual_keyboard_manager_v1" version="1">
|
||||||
|
<description summary="virtual keyboard manager">
|
||||||
|
A virtual keyboard manager allows an application to provide keyboard
|
||||||
|
input events as if they came from a physical keyboard.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<enum name="error">
|
||||||
|
<entry name="unauthorized" value="0" summary="client not authorized to use the interface"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<request name="create_virtual_keyboard">
|
||||||
|
<description summary="Create a new virtual keyboard">
|
||||||
|
Creates a new virtual keyboard associated to a seat.
|
||||||
|
|
||||||
|
If the compositor enables a keyboard to perform arbitrary actions, it
|
||||||
|
should present an error when an untrusted client requests a new
|
||||||
|
keyboard.
|
||||||
|
</description>
|
||||||
|
<arg name="seat" type="object" interface="wl_seat"/>
|
||||||
|
<arg name="id" type="new_id" interface="zwp_virtual_keyboard_v1"/>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
</protocol>
|
152
protocols/wlr-virtual-pointer-unstable-v1.xml
Normal file
152
protocols/wlr-virtual-pointer-unstable-v1.xml
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<protocol name="wlr_virtual_pointer_unstable_v1">
|
||||||
|
<copyright>
|
||||||
|
Copyright © 2019 Josef Gajdusek
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice (including the next
|
||||||
|
paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
</copyright>
|
||||||
|
|
||||||
|
<interface name="zwlr_virtual_pointer_v1" version="2">
|
||||||
|
<description summary="virtual pointer">
|
||||||
|
This protocol allows clients to emulate a physical pointer device. The
|
||||||
|
requests are mostly mirror opposites of those specified in wl_pointer.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<enum name="error">
|
||||||
|
<entry name="invalid_axis" value="0"
|
||||||
|
summary="client sent invalid axis enumeration value" />
|
||||||
|
<entry name="invalid_axis_source" value="1"
|
||||||
|
summary="client sent invalid axis source enumeration value" />
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<request name="motion">
|
||||||
|
<description summary="pointer relative motion event">
|
||||||
|
The pointer has moved by a relative amount to the previous request.
|
||||||
|
|
||||||
|
Values are in the global compositor space.
|
||||||
|
</description>
|
||||||
|
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||||
|
<arg name="dx" type="fixed" summary="displacement on the x-axis"/>
|
||||||
|
<arg name="dy" type="fixed" summary="displacement on the y-axis"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="motion_absolute">
|
||||||
|
<description summary="pointer absolute motion event">
|
||||||
|
The pointer has moved in an absolute coordinate frame.
|
||||||
|
|
||||||
|
Value of x can range from 0 to x_extent, value of y can range from 0
|
||||||
|
to y_extent.
|
||||||
|
</description>
|
||||||
|
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||||
|
<arg name="x" type="uint" summary="position on the x-axis"/>
|
||||||
|
<arg name="y" type="uint" summary="position on the y-axis"/>
|
||||||
|
<arg name="x_extent" type="uint" summary="extent of the x-axis"/>
|
||||||
|
<arg name="y_extent" type="uint" summary="extent of the y-axis"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="button">
|
||||||
|
<description summary="button event">
|
||||||
|
A button was pressed or released.
|
||||||
|
</description>
|
||||||
|
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||||
|
<arg name="button" type="uint" summary="button that produced the event"/>
|
||||||
|
<arg name="state" type="uint" enum="wl_pointer.button_state" summary="physical state of the button"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="axis">
|
||||||
|
<description summary="axis event">
|
||||||
|
Scroll and other axis requests.
|
||||||
|
</description>
|
||||||
|
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||||
|
<arg name="axis" type="uint" enum="wl_pointer.axis" summary="axis type"/>
|
||||||
|
<arg name="value" type="fixed" summary="length of vector in touchpad coordinates"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="frame">
|
||||||
|
<description summary="end of a pointer event sequence">
|
||||||
|
Indicates the set of events that logically belong together.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="axis_source">
|
||||||
|
<description summary="axis source event">
|
||||||
|
Source information for scroll and other axis.
|
||||||
|
</description>
|
||||||
|
<arg name="axis_source" type="uint" enum="wl_pointer.axis_source" summary="source of the axis event"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="axis_stop">
|
||||||
|
<description summary="axis stop event">
|
||||||
|
Stop notification for scroll and other axes.
|
||||||
|
</description>
|
||||||
|
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||||
|
<arg name="axis" type="uint" enum="wl_pointer.axis" summary="the axis stopped with this event"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="axis_discrete">
|
||||||
|
<description summary="axis click event">
|
||||||
|
Discrete step information for scroll and other axes.
|
||||||
|
|
||||||
|
This event allows the client to extend data normally sent using the axis
|
||||||
|
event with discrete value.
|
||||||
|
</description>
|
||||||
|
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||||
|
<arg name="axis" type="uint" enum="wl_pointer.axis" summary="axis type"/>
|
||||||
|
<arg name="value" type="fixed" summary="length of vector in touchpad coordinates"/>
|
||||||
|
<arg name="discrete" type="int" summary="number of steps"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor" since="1">
|
||||||
|
<description summary="destroy the virtual pointer object"/>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<interface name="zwlr_virtual_pointer_manager_v1" version="2">
|
||||||
|
<description summary="virtual pointer manager">
|
||||||
|
This object allows clients to create individual virtual pointer objects.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<request name="create_virtual_pointer">
|
||||||
|
<description summary="Create a new virtual pointer">
|
||||||
|
Creates a new virtual pointer. The optional seat is a suggestion to the
|
||||||
|
compositor.
|
||||||
|
</description>
|
||||||
|
<arg name="seat" type="object" interface="wl_seat" allow-null="true"/>
|
||||||
|
<arg name="id" type="new_id" interface="zwlr_virtual_pointer_v1"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor" since="1">
|
||||||
|
<description summary="destroy the virtual pointer manager"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<!-- Version 2 additions -->
|
||||||
|
<request name="create_virtual_pointer_with_output" since="2">
|
||||||
|
<description summary="Create a new virtual pointer">
|
||||||
|
Creates a new virtual pointer. The seat and the output arguments are
|
||||||
|
optional. If the seat argument is set, the compositor should assign the
|
||||||
|
input device to the requested seat. If the output argument is set, the
|
||||||
|
compositor should map the input device to the requested output.
|
||||||
|
</description>
|
||||||
|
<arg name="seat" type="object" interface="wl_seat" allow-null="true"/>
|
||||||
|
<arg name="output" type="object" interface="wl_output" allow-null="true"/>
|
||||||
|
<arg name="id" type="new_id" interface="zwlr_virtual_pointer_v1"/>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
</protocol>
|
|
@ -31,7 +31,7 @@ SOutput::SOutput(SP<CCWlOutput> output_) : output(output_) {
|
||||||
y = y_;
|
y = y_;
|
||||||
});
|
});
|
||||||
output->setScale([this](CCWlOutput* r, uint32_t factor_) { scale = factor_; });
|
output->setScale([this](CCWlOutput* r, uint32_t factor_) { scale = factor_; });
|
||||||
output->setDone([](CCWlOutput* r) { g_pPortalManager->m_sPortals.inputCapture->zonesChanged(); });
|
output->setDone([](CCWlOutput* r) {});
|
||||||
}
|
}
|
||||||
|
|
||||||
CPortalManager::CPortalManager() {
|
CPortalManager::CPortalManager() {
|
||||||
|
@ -60,6 +60,7 @@ void CPortalManager::onGlobal(uint32_t name, const char* interface, uint32_t ver
|
||||||
|
|
||||||
Debug::log(LOG, " | Got interface: {} (ver {})", INTERFACE, version);
|
Debug::log(LOG, " | Got interface: {} (ver {})", INTERFACE, version);
|
||||||
|
|
||||||
|
|
||||||
if (INTERFACE == zwlr_screencopy_manager_v1_interface.name && m_sPipewire.loop) {
|
if (INTERFACE == zwlr_screencopy_manager_v1_interface.name && m_sPipewire.loop) {
|
||||||
m_sPortals.screencopy = std::make_unique<CScreencopyPortal>(makeShared<CCZwlrScreencopyManagerV1>(
|
m_sPortals.screencopy = std::make_unique<CScreencopyPortal>(makeShared<CCZwlrScreencopyManagerV1>(
|
||||||
(wl_proxy*)wl_registry_bind((wl_registry*)m_sWaylandConnection.registry->resource(), name, &zwlr_screencopy_manager_v1_interface, version)));
|
(wl_proxy*)wl_registry_bind((wl_registry*)m_sWaylandConnection.registry->resource(), name, &zwlr_screencopy_manager_v1_interface, version)));
|
||||||
|
@ -69,9 +70,23 @@ void CPortalManager::onGlobal(uint32_t name, const char* interface, uint32_t ver
|
||||||
m_sPortals.globalShortcuts = std::make_unique<CGlobalShortcutsPortal>(makeShared<CCHyprlandGlobalShortcutsManagerV1>(
|
m_sPortals.globalShortcuts = std::make_unique<CGlobalShortcutsPortal>(makeShared<CCHyprlandGlobalShortcutsManagerV1>(
|
||||||
(wl_proxy*)wl_registry_bind((wl_registry*)m_sWaylandConnection.registry->resource(), name, &hyprland_global_shortcuts_manager_v1_interface, version)));
|
(wl_proxy*)wl_registry_bind((wl_registry*)m_sWaylandConnection.registry->resource(), name, &hyprland_global_shortcuts_manager_v1_interface, version)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_sPortals.remoteDesktop == nullptr)
|
||||||
|
m_sPortals.remoteDesktop = std::make_unique<CRemoteDesktopPortal>();
|
||||||
|
|
||||||
if (INTERFACE == hyprland_input_capture_manager_v1_interface.name)
|
if (INTERFACE == hyprland_input_capture_manager_v1_interface.name)
|
||||||
m_sPortals.inputCapture = std::make_unique<CInputCapturePortal>(makeShared<CCHyprlandInputCaptureManagerV1>(
|
m_sPortals.inputCapture = std::make_unique<CInputCapturePortal>(makeShared<CCHyprlandInputCaptureManagerV1>(
|
||||||
(wl_proxy*)wl_registry_bind((wl_registry*)m_sWaylandConnection.registry->resource(), name, &hyprland_input_capture_manager_v1_interface, version)));
|
(wl_proxy*)wl_registry_bind((wl_registry*)m_sWaylandConnection.registry->resource(), name, &hyprland_input_capture_manager_v1_interface, version)));
|
||||||
|
|
||||||
|
if (INTERFACE == zwlr_virtual_pointer_manager_v1_interface.name)
|
||||||
|
m_sPortals.remoteDesktop->registerPointer(makeShared<CCZwlrVirtualPointerManagerV1>(
|
||||||
|
(wl_proxy*)wl_registry_bind((wl_registry*)m_sWaylandConnection.registry->resource(), name, &zwlr_virtual_pointer_manager_v1_interface, version)));
|
||||||
|
|
||||||
|
if (INTERFACE == zwp_virtual_keyboard_manager_v1_interface.name)
|
||||||
|
m_sPortals.remoteDesktop->registerKeyboard(makeShared<CCZwpVirtualKeyboardManagerV1>(
|
||||||
|
(wl_proxy*)wl_registry_bind((wl_registry*)m_sWaylandConnection.registry->resource(), name, &zwp_virtual_keyboard_manager_v1_interface, version)));
|
||||||
|
|
||||||
|
|
||||||
else if (INTERFACE == hyprland_toplevel_export_manager_v1_interface.name) {
|
else if (INTERFACE == hyprland_toplevel_export_manager_v1_interface.name) {
|
||||||
m_sWaylandConnection.hyprlandToplevelMgr = makeShared<CCHyprlandToplevelExportManagerV1>(
|
m_sWaylandConnection.hyprlandToplevelMgr = makeShared<CCHyprlandToplevelExportManagerV1>(
|
||||||
(wl_proxy*)wl_registry_bind((wl_registry*)m_sWaylandConnection.registry->resource(), name, &hyprland_toplevel_export_manager_v1_interface, version));
|
(wl_proxy*)wl_registry_bind((wl_registry*)m_sWaylandConnection.registry->resource(), name, &hyprland_toplevel_export_manager_v1_interface, version));
|
||||||
|
@ -85,6 +100,20 @@ void CPortalManager::onGlobal(uint32_t name, const char* interface, uint32_t ver
|
||||||
POUTPUT->id = name;
|
POUTPUT->id = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (INTERFACE == wl_seat_interface.name) {
|
||||||
|
m_sWaylandConnection.seat = makeShared<CCWlSeat>((wl_proxy*)wl_registry_bind((wl_registry*)m_sWaylandConnection.registry->resource(), name, &wl_seat_interface, version));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
else if (INTERFACE == wl_keyboard_interface.name) {
|
||||||
|
const auto PKEYBOARD = m_vKeyboards
|
||||||
|
.emplace_back(std::make_unique<SKeyboard>(makeShared<CCWlKeyboard>(
|
||||||
|
(wl_proxy*)wl_registry_bind((wl_registry*)m_sWaylandConnection.registry->resource(), name, &wl_keyboard_interface, version))))
|
||||||
|
.get();
|
||||||
|
PKEYBOARD->id = name;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
else if (INTERFACE == zwp_linux_dmabuf_v1_interface.name) {
|
else if (INTERFACE == zwp_linux_dmabuf_v1_interface.name) {
|
||||||
if (version < 4) {
|
if (version < 4) {
|
||||||
Debug::log(ERR, "cannot use linux_dmabuf with ver < 4");
|
Debug::log(ERR, "cannot use linux_dmabuf with ver < 4");
|
||||||
|
@ -419,8 +448,9 @@ void CPortalManager::startEventLoop() {
|
||||||
m_sPortals.globalShortcuts.reset();
|
m_sPortals.globalShortcuts.reset();
|
||||||
m_sPortals.screencopy.reset();
|
m_sPortals.screencopy.reset();
|
||||||
m_sPortals.screenshot.reset();
|
m_sPortals.screenshot.reset();
|
||||||
m_sHelpers.toplevel.reset();
|
|
||||||
m_sPortals.inputCapture.reset();
|
m_sPortals.inputCapture.reset();
|
||||||
|
m_sPortals.remoteDesktop.reset();
|
||||||
|
m_sHelpers.toplevel.reset();
|
||||||
|
|
||||||
m_pConnection.reset();
|
m_pConnection.reset();
|
||||||
pw_loop_destroy(m_sPipewire.loop);
|
pw_loop_destroy(m_sPipewire.loop);
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "../portals/Screenshot.hpp"
|
#include "../portals/Screenshot.hpp"
|
||||||
#include "../portals/GlobalShortcuts.hpp"
|
#include "../portals/GlobalShortcuts.hpp"
|
||||||
#include "../portals/InputCapture.hpp"
|
#include "../portals/InputCapture.hpp"
|
||||||
|
#include "../portals/RemoteDesktop.hpp"
|
||||||
#include "../helpers/Timer.hpp"
|
#include "../helpers/Timer.hpp"
|
||||||
#include "../shared/ToplevelManager.hpp"
|
#include "../shared/ToplevelManager.hpp"
|
||||||
#include <gbm.h>
|
#include <gbm.h>
|
||||||
|
@ -20,6 +21,9 @@
|
||||||
#include "linux-dmabuf-v1.hpp"
|
#include "linux-dmabuf-v1.hpp"
|
||||||
#include "wlr-foreign-toplevel-management-unstable-v1.hpp"
|
#include "wlr-foreign-toplevel-management-unstable-v1.hpp"
|
||||||
#include "wlr-screencopy-unstable-v1.hpp"
|
#include "wlr-screencopy-unstable-v1.hpp"
|
||||||
|
#include "hyprland-input-capture-v1.hpp"
|
||||||
|
#include "wlr-virtual-pointer-unstable-v1.hpp"
|
||||||
|
#include "virtual-keyboard-unstable-v1.hpp"
|
||||||
|
|
||||||
#include "../includes.hpp"
|
#include "../includes.hpp"
|
||||||
#include "../dbusDefines.hpp"
|
#include "../dbusDefines.hpp"
|
||||||
|
@ -60,6 +64,12 @@ class CPortalManager {
|
||||||
SOutput* getOutputFromName(const std::string& name);
|
SOutput* getOutputFromName(const std::string& name);
|
||||||
std::vector<std::unique_ptr<SOutput>> const& getAllOutputs();
|
std::vector<std::unique_ptr<SOutput>> const& getAllOutputs();
|
||||||
|
|
||||||
|
struct {
|
||||||
|
enum wl_keyboard_keymap_format format;
|
||||||
|
int32_t fd;
|
||||||
|
uint32_t size;
|
||||||
|
} m_sKeymap;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
pw_loop* loop = nullptr;
|
pw_loop* loop = nullptr;
|
||||||
} m_sPipewire;
|
} m_sPipewire;
|
||||||
|
@ -69,6 +79,7 @@ class CPortalManager {
|
||||||
std::unique_ptr<CScreenshotPortal> screenshot;
|
std::unique_ptr<CScreenshotPortal> screenshot;
|
||||||
std::unique_ptr<CGlobalShortcutsPortal> globalShortcuts;
|
std::unique_ptr<CGlobalShortcutsPortal> globalShortcuts;
|
||||||
std::unique_ptr<CInputCapturePortal> inputCapture;
|
std::unique_ptr<CInputCapturePortal> inputCapture;
|
||||||
|
std::unique_ptr<CRemoteDesktopPortal> remoteDesktop;
|
||||||
} m_sPortals;
|
} m_sPortals;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -77,6 +88,7 @@ class CPortalManager {
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
wl_display* display = nullptr;
|
wl_display* display = nullptr;
|
||||||
|
SP<CCWlSeat> seat;
|
||||||
SP<CCWlRegistry> registry;
|
SP<CCWlRegistry> registry;
|
||||||
SP<CCHyprlandToplevelExportManagerV1> hyprlandToplevelMgr;
|
SP<CCHyprlandToplevelExportManagerV1> hyprlandToplevelMgr;
|
||||||
SP<CCZwpLinuxDmabufV1> linuxDmabuf;
|
SP<CCZwpLinuxDmabufV1> linuxDmabuf;
|
||||||
|
@ -130,8 +142,8 @@ class CPortalManager {
|
||||||
std::unique_ptr<std::thread> thread;
|
std::unique_ptr<std::thread> thread;
|
||||||
} m_sTimersThread;
|
} m_sTimersThread;
|
||||||
|
|
||||||
std::unique_ptr<sdbus::IConnection> m_pConnection;
|
std::unique_ptr<sdbus::IConnection> m_pConnection;
|
||||||
std::vector<std::unique_ptr<SOutput>> m_vOutputs;
|
std::vector<std::unique_ptr<SOutput>> m_vOutputs;
|
||||||
|
|
||||||
std::mutex m_mEventLock;
|
std::mutex m_mEventLock;
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,7 +25,11 @@ CInputCapturePortal::CInputCapturePortal(SP<CCHyprlandInputCaptureManagerV1> mgr
|
||||||
});
|
});
|
||||||
|
|
||||||
mgr->setKeymap([this](CCHyprlandInputCaptureManagerV1* r, hyprlandInputCaptureManagerV1KeymapFormat format, int32_t fd, uint32_t size) {
|
mgr->setKeymap([this](CCHyprlandInputCaptureManagerV1* r, hyprlandInputCaptureManagerV1KeymapFormat format, int32_t fd, uint32_t size) {
|
||||||
|
Debug::log(LOG, "[input-capture] got keymap");
|
||||||
onKeymap(format == HYPRLAND_INPUT_CAPTURE_MANAGER_V1_KEYMAP_FORMAT_XKB_V1 ? fd : 0, size);
|
onKeymap(format == HYPRLAND_INPUT_CAPTURE_MANAGER_V1_KEYMAP_FORMAT_XKB_V1 ? fd : 0, size);
|
||||||
|
g_pPortalManager->m_sKeymap.format = wl_keyboard_keymap_format(format);
|
||||||
|
g_pPortalManager->m_sKeymap.fd = fd;
|
||||||
|
g_pPortalManager->m_sKeymap.size = size;
|
||||||
});
|
});
|
||||||
|
|
||||||
mgr->setModifiers([this](CCHyprlandInputCaptureManagerV1* r, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) {
|
mgr->setModifiers([this](CCHyprlandInputCaptureManagerV1* r, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) {
|
||||||
|
@ -128,7 +132,8 @@ dbUasv CInputCapturePortal::onCreateSession(sdbus::ObjectPath requestHandle, sdb
|
||||||
session->request = createDBusRequest(requestHandle);
|
session->request = createDBusRequest(requestHandle);
|
||||||
session->request->onDestroy = [session]() { session->request.release(); };
|
session->request->onDestroy = [session]() { session->request.release(); };
|
||||||
|
|
||||||
session->eis = std::make_unique<EmulatedInputServer>("eis-" + sessionId, keymap);
|
session->eis = std::make_unique<EmulatedInputServer>("eis-" + sessionId);
|
||||||
|
session->eis->setKeymap(keymap);
|
||||||
|
|
||||||
sessions.emplace(sessionHandle, session);
|
sessions.emplace(sessionHandle, session);
|
||||||
|
|
||||||
|
|
207
src/portals/RemoteDesktop.cpp
Normal file
207
src/portals/RemoteDesktop.cpp
Normal file
|
@ -0,0 +1,207 @@
|
||||||
|
#include "RemoteDesktop.hpp"
|
||||||
|
#include "../core/PortalManager.hpp"
|
||||||
|
#include "../helpers/Log.hpp"
|
||||||
|
#include "../helpers/MiscFunctions.hpp"
|
||||||
|
|
||||||
|
void CRemoteDesktopPortal::registerPointer(SP<CCZwlrVirtualPointerManagerV1> mgr) {
|
||||||
|
m_sState.pointerMgr = mgr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRemoteDesktopPortal::registerKeyboard(SP<CCZwpVirtualKeyboardManagerV1> mgr) {
|
||||||
|
m_sState.keyboardMgr = mgr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CRemoteDesktopPortal::CRemoteDesktopPortal() {
|
||||||
|
Debug::log(LOG, "[remotedesktop] initializing remote desktop portal");
|
||||||
|
m_pObject = sdbus::createObject(*g_pPortalManager->getConnection(), OBJECT_PATH);
|
||||||
|
m_pObject
|
||||||
|
->addVTable(
|
||||||
|
sdbus::registerMethod("CreateSession")
|
||||||
|
.implementedAs([this](sdbus::ObjectPath o1, sdbus::ObjectPath o2, std::string s, std::unordered_map<std::string, sdbus::Variant> m) {
|
||||||
|
return onCreateSession(o1, o2, s, m);
|
||||||
|
}),
|
||||||
|
sdbus::registerMethod("SelectDevices")
|
||||||
|
.implementedAs([this](sdbus::ObjectPath o1, sdbus::ObjectPath o2, std::string s, std::unordered_map<std::string, sdbus::Variant> m) {
|
||||||
|
return onSelectDevices(o1, o2, s, m);
|
||||||
|
}),
|
||||||
|
sdbus::registerMethod("Start")
|
||||||
|
.implementedAs([this](sdbus::ObjectPath o1, sdbus::ObjectPath o2, std::string s1, std::string s2, std::unordered_map<std::string, sdbus::Variant> m) {
|
||||||
|
return onStart(o1, o2, s1, s2, m);
|
||||||
|
}),
|
||||||
|
sdbus::registerMethod("NotifyPointerMotion")
|
||||||
|
.implementedAs([this](sdbus::ObjectPath o, double d1, double d2, std::unordered_map<std::string, sdbus::Variant> m) {
|
||||||
|
return onNotifyPointerMotion(o, d1, d2, m);
|
||||||
|
}),
|
||||||
|
sdbus::registerMethod("NotifyPointerMotionAbsolute")
|
||||||
|
.implementedAs([this](sdbus::ObjectPath o, unsigned int u, double d1, double d2, std::unordered_map<std::string, sdbus::Variant> m) {
|
||||||
|
return onNotifyPointerMotionAbsolute(o, u, d1, d2, m);
|
||||||
|
}),
|
||||||
|
sdbus::registerMethod("NotifyPointerButton")
|
||||||
|
.implementedAs([this](sdbus::ObjectPath o, int i, unsigned int u, std::unordered_map<std::string, sdbus::Variant> m) {
|
||||||
|
return onNotifyPointerButton(o, i, u, m);
|
||||||
|
}),
|
||||||
|
sdbus::registerMethod("NotifyPointerAxis")
|
||||||
|
.implementedAs([this](sdbus::ObjectPath o, double d1, double d2, std::unordered_map<std::string, sdbus::Variant> m) {
|
||||||
|
return onNotifyPointerAxis(o, d1, d2, m);
|
||||||
|
}),
|
||||||
|
sdbus::registerMethod("NotifyPointerAxisDiscrete")
|
||||||
|
.implementedAs([this](sdbus::ObjectPath o, unsigned int u, int i, std::unordered_map<std::string, sdbus::Variant> m) {
|
||||||
|
return onNotifyPointerAxisDiscrete(o, u, i, m);
|
||||||
|
}),
|
||||||
|
sdbus::registerMethod("NotifyKeyboardKeycode")
|
||||||
|
.implementedAs([this](sdbus::ObjectPath o, int i, unsigned int u, std::unordered_map<std::string, sdbus::Variant> m) {
|
||||||
|
return onNotifyKeyboardKeycode(o, i, u, m);
|
||||||
|
}),
|
||||||
|
sdbus::registerMethod("NotifyKeyboardKeysym")
|
||||||
|
.implementedAs([this](sdbus::ObjectPath o, int i, unsigned int u, std::unordered_map<std::string, sdbus::Variant> m) {
|
||||||
|
return onNotifyKeyboardKeysym(o, i, u, m);
|
||||||
|
}),
|
||||||
|
sdbus::registerMethod("NotifyTouchDown")
|
||||||
|
.implementedAs([this](sdbus::ObjectPath o, unsigned int u1, unsigned int u2, double d1, double d2, std::unordered_map<std::string, sdbus::Variant> m) {
|
||||||
|
return onNotifyTouchDown(o, u1, u2, d1, d2, m);
|
||||||
|
}),
|
||||||
|
sdbus::registerMethod("NotifyTouchMotion")
|
||||||
|
.implementedAs([this](sdbus::ObjectPath o, unsigned int u1, unsigned int u2, double d1, double d2, std::unordered_map<std::string, sdbus::Variant> m) {
|
||||||
|
return onNotifyTouchMotion(o, u1, u2, d1, d2, m);
|
||||||
|
}),
|
||||||
|
sdbus::registerMethod("NotifyTouchUp")
|
||||||
|
.implementedAs([this](sdbus::ObjectPath o, unsigned int u, std::unordered_map<std::string, sdbus::Variant> m) {
|
||||||
|
return onNotifyTouchUp(o, u, m);
|
||||||
|
}),
|
||||||
|
sdbus::registerMethod("ConnectToEIS").implementedAs([this](sdbus::ObjectPath o, std::string s, std::unordered_map<std::string, sdbus::Variant> m) {
|
||||||
|
return onConnectToEIS(o, s, m);
|
||||||
|
}),
|
||||||
|
sdbus::registerProperty("AvailableDeviceTypes").withGetter([] { return (uint32_t)(1 | 2); }),
|
||||||
|
sdbus::registerProperty("version").withGetter([] { return (uint32_t)(1); }))
|
||||||
|
.forInterface(INTERFACE_NAME);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUasv CRemoteDesktopPortal::onCreateSession(sdbus::ObjectPath requestHandle, sdbus::ObjectPath sessionHandle, std::string appID,
|
||||||
|
std::unordered_map<std::string, sdbus::Variant> opts) {
|
||||||
|
Debug::log(LOG, "[remotedesktop] New session:");
|
||||||
|
Debug::log(LOG, "[remotedesktop] | {}", requestHandle.c_str());
|
||||||
|
Debug::log(LOG, "[remotedesktop] | {}", sessionHandle.c_str());
|
||||||
|
Debug::log(LOG, "[remotedesktop] | appid: {}", appID);
|
||||||
|
|
||||||
|
std::shared_ptr<SSession> PSESSION = std::make_shared<SSession>(appID, requestHandle, sessionHandle);
|
||||||
|
|
||||||
|
// create objects
|
||||||
|
PSESSION->session = createDBusSession(sessionHandle);
|
||||||
|
PSESSION->sessionHandle = sessionHandle;
|
||||||
|
PSESSION->session->onDestroy = [PSESSION, this]() {
|
||||||
|
PSESSION->eis->stopServer();
|
||||||
|
PSESSION->eis.reset();
|
||||||
|
Debug::log(LOG, "[remotedesktop] Session {} destroyed", PSESSION->sessionHandle.c_str());
|
||||||
|
PSESSION->session.release();
|
||||||
|
m_mSessions.erase(PSESSION->sessionHandle);
|
||||||
|
};
|
||||||
|
|
||||||
|
PSESSION->request = createDBusRequest(requestHandle);
|
||||||
|
PSESSION->requestHandle = requestHandle;
|
||||||
|
PSESSION->request->onDestroy = [PSESSION]() { PSESSION->request.release(); };
|
||||||
|
|
||||||
|
PSESSION->pointer = makeShared<CCZwlrVirtualPointerV1>(m_sState.pointerMgr->sendCreateVirtualPointer(g_pPortalManager->m_sWaylandConnection.seat->resource()));
|
||||||
|
PSESSION->keyboard = makeShared<CCZwpVirtualKeyboardV1>(m_sState.keyboardMgr->sendCreateVirtualKeyboard(g_pPortalManager->m_sWaylandConnection.seat->resource()));
|
||||||
|
|
||||||
|
const auto& keymap = g_pPortalManager->m_sKeymap;
|
||||||
|
PSESSION->keyboard->sendKeymap(keymap.format, keymap.fd, keymap.size);
|
||||||
|
|
||||||
|
PSESSION->eis = std::make_unique<EmulatedInputServer>("eisr-" + std::to_string(m_uSessionCounter++));
|
||||||
|
PSESSION->eis->setVirtualPointer(PSESSION->pointer);
|
||||||
|
PSESSION->eis->setVirtualKeyboard(PSESSION->keyboard);
|
||||||
|
|
||||||
|
m_mSessions.emplace(sessionHandle, PSESSION);
|
||||||
|
|
||||||
|
return {0, {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUasv CRemoteDesktopPortal::onSelectDevices(sdbus::ObjectPath requestHandle, sdbus::ObjectPath sessionHandle, std::string appID,
|
||||||
|
std::unordered_map<std::string, sdbus::Variant> opts) {
|
||||||
|
return {0, {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUasv CRemoteDesktopPortal::onStart(sdbus::ObjectPath requestHandle, sdbus::ObjectPath sessionHandle, std::string appID, std::string parentWindow,
|
||||||
|
std::unordered_map<std::string, sdbus::Variant> opts) {
|
||||||
|
Debug::log(LOG, "[remotedesktop] start request");
|
||||||
|
|
||||||
|
std::unordered_map<std::string, sdbus::Variant> results;
|
||||||
|
results["devices"] = sdbus::Variant{uint32_t{1 | 2}};
|
||||||
|
results["clipboard_enabled"] = sdbus::Variant{bool(true)};
|
||||||
|
|
||||||
|
std::unordered_map<std::string, sdbus::Variant> restoreData;
|
||||||
|
results["restore_data"] = sdbus::Variant{sdbus::Struct<std::string, uint32_t, sdbus::Variant>{"hyprland", 1, sdbus::Variant{restoreData}}};
|
||||||
|
results["persist_mode"] = sdbus::Variant{uint32_t{2}};
|
||||||
|
|
||||||
|
return {0, results};
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUasv CRemoteDesktopPortal::onNotifyPointerMotion(sdbus::ObjectPath sessionHandle, double dx, double dy, std::unordered_map<std::string, sdbus::Variant> opts) {
|
||||||
|
const auto PSESSION = m_mSessions[sessionHandle];
|
||||||
|
PSESSION->pointer->sendMotion(0, dx, dy);
|
||||||
|
return {0, {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUasv CRemoteDesktopPortal::onNotifyPointerMotionAbsolute(sdbus::ObjectPath sessionHandle, unsigned int stream, double x, double y, std::unordered_map<std::string, sdbus::Variant> opts) {
|
||||||
|
const auto PSESSION = m_mSessions[sessionHandle];
|
||||||
|
PSESSION->pointer->sendMotionAbsolute(0, x, y, 1920, 1080);
|
||||||
|
return {0, {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUasv CRemoteDesktopPortal::onNotifyPointerButton(sdbus::ObjectPath sessionHandle, int button, unsigned int state, std::unordered_map<std::string, sdbus::Variant> opts) {
|
||||||
|
const auto PSESSION = m_mSessions[sessionHandle];
|
||||||
|
PSESSION->pointer->sendButton(0, button, state);
|
||||||
|
return {0, {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUasv CRemoteDesktopPortal::onNotifyPointerAxis(sdbus::ObjectPath sessionHandle, double dx, double dy, std::unordered_map<std::string, sdbus::Variant> opts) {
|
||||||
|
const auto PSESSION = m_mSessions[sessionHandle];
|
||||||
|
PSESSION->pointer->sendAxis(0, 0, dy);
|
||||||
|
PSESSION->pointer->sendAxis(0, 1, dx);
|
||||||
|
return {0, {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUasv CRemoteDesktopPortal::onNotifyPointerAxisDiscrete(sdbus::ObjectPath sessionHandle, unsigned int axis, int steps, std::unordered_map<std::string, sdbus::Variant> opts) {
|
||||||
|
const auto PSESSION = m_mSessions[sessionHandle];
|
||||||
|
PSESSION->pointer->sendAxisDiscrete(1, 0, axis, steps);
|
||||||
|
return {0, {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUasv CRemoteDesktopPortal::onNotifyKeyboardKeycode(sdbus::ObjectPath sessionHandle, int keycode, unsigned int state, std::unordered_map<std::string, sdbus::Variant> opts) {
|
||||||
|
const auto PSESSION = m_mSessions[sessionHandle];
|
||||||
|
PSESSION->keyboard->sendKey(1, keycode, state);
|
||||||
|
return {0, {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUasv CRemoteDesktopPortal::onNotifyKeyboardKeysym(sdbus::ObjectPath sessionHandle, int keysym, unsigned int state, std::unordered_map<std::string, sdbus::Variant> opts) {
|
||||||
|
const auto PSESSION = m_mSessions[sessionHandle];
|
||||||
|
return {0, {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUasv CRemoteDesktopPortal::onNotifyTouchDown(sdbus::ObjectPath sessionHandle, unsigned int stream, unsigned int slot, double x, double y,
|
||||||
|
std::unordered_map<std::string, sdbus::Variant> opts) {
|
||||||
|
const auto PSESSION = m_mSessions[sessionHandle];
|
||||||
|
return {0, {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUasv CRemoteDesktopPortal::onNotifyTouchMotion(sdbus::ObjectPath sessionHandle, unsigned int stream, unsigned int slot, double x, double y,
|
||||||
|
std::unordered_map<std::string, sdbus::Variant> opts) {
|
||||||
|
const auto PSESSION = m_mSessions[sessionHandle];
|
||||||
|
return {0, {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUasv CRemoteDesktopPortal::onNotifyTouchUp(sdbus::ObjectPath sessionHandle, unsigned int slot, std::unordered_map<std::string, sdbus::Variant> opts) {
|
||||||
|
const auto PSESSION = m_mSessions[sessionHandle];
|
||||||
|
return {0, {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
sdbus::UnixFd CRemoteDesktopPortal::onConnectToEIS(sdbus::ObjectPath sessionHandle, std::string appID, std::unordered_map<std::string, sdbus::Variant> opts) {
|
||||||
|
Debug::log(LOG, "[remotedesktop] New ConnectToEIS request: {}:", sessionHandle.c_str());
|
||||||
|
const auto PSESSION = m_mSessions[sessionHandle];
|
||||||
|
if (!PSESSION) return (sdbus::UnixFd)0;
|
||||||
|
|
||||||
|
int sockfd = PSESSION->eis->getFileDescriptor();
|
||||||
|
|
||||||
|
Debug::log(LOG, "[remotedesktop] Connected to the socket. File descriptor: {}", sockfd);
|
||||||
|
return (sdbus::UnixFd)sockfd;
|
||||||
|
}
|
64
src/portals/RemoteDesktop.hpp
Normal file
64
src/portals/RemoteDesktop.hpp
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <sdbus-c++/sdbus-c++.h>
|
||||||
|
#include "wlr-virtual-pointer-unstable-v1.hpp"
|
||||||
|
#include "virtual-keyboard-unstable-v1.hpp"
|
||||||
|
#include "../shared/Session.hpp"
|
||||||
|
#include "../shared/Eis.hpp"
|
||||||
|
#include "../dbusDefines.hpp"
|
||||||
|
#include <libei-1.0/libeis.h>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
class CRemoteDesktopPortal {
|
||||||
|
public:
|
||||||
|
CRemoteDesktopPortal();
|
||||||
|
void registerPointer(SP<CCZwlrVirtualPointerManagerV1> mgr);
|
||||||
|
void registerKeyboard(SP<CCZwpVirtualKeyboardManagerV1> mgr);
|
||||||
|
|
||||||
|
dbUasv onCreateSession(sdbus::ObjectPath requestHandle, sdbus::ObjectPath sessionHandle, std::string appID,
|
||||||
|
std::unordered_map<std::string, sdbus::Variant> opts);
|
||||||
|
dbUasv onSelectDevices(sdbus::ObjectPath requestHandle, sdbus::ObjectPath sessionHandle, std::string appID,
|
||||||
|
std::unordered_map<std::string, sdbus::Variant> opts);
|
||||||
|
dbUasv onStart(sdbus::ObjectPath requestHandle, sdbus::ObjectPath sessionHandle, std::string appID, std::string parentWindow,
|
||||||
|
std::unordered_map<std::string, sdbus::Variant> opts);
|
||||||
|
dbUasv onNotifyPointerMotion(sdbus::ObjectPath sessionHandle, double dx, double dy, std::unordered_map<std::string, sdbus::Variant> opts);
|
||||||
|
dbUasv onNotifyPointerMotionAbsolute(sdbus::ObjectPath sessionHandle, unsigned int stream, double x, double y, std::unordered_map<std::string, sdbus::Variant> opts);
|
||||||
|
dbUasv onNotifyPointerButton(sdbus::ObjectPath sessionHandle, int button, unsigned int state, std::unordered_map<std::string, sdbus::Variant> opts);
|
||||||
|
dbUasv onNotifyPointerAxis(sdbus::ObjectPath sessionHandle, double dx, double dy, std::unordered_map<std::string, sdbus::Variant> opts);
|
||||||
|
dbUasv onNotifyPointerAxisDiscrete(sdbus::ObjectPath sessionHandle, unsigned int axis, int steps, std::unordered_map<std::string, sdbus::Variant> opts);
|
||||||
|
dbUasv onNotifyKeyboardKeycode(sdbus::ObjectPath sessionHandle, int keycode, unsigned int state, std::unordered_map<std::string, sdbus::Variant> opts);
|
||||||
|
dbUasv onNotifyKeyboardKeysym(sdbus::ObjectPath sessionHandle, int keysym, unsigned int state, std::unordered_map<std::string, sdbus::Variant> opts);
|
||||||
|
dbUasv onNotifyTouchDown(sdbus::ObjectPath sessionHandle, unsigned int stream, unsigned int slot, double x, double y,
|
||||||
|
std::unordered_map<std::string, sdbus::Variant> opts);
|
||||||
|
dbUasv onNotifyTouchMotion(sdbus::ObjectPath sessionHandle, unsigned int stream, unsigned int slot, double x, double y,
|
||||||
|
std::unordered_map<std::string, sdbus::Variant> opts);
|
||||||
|
dbUasv onNotifyTouchUp(sdbus::ObjectPath sessionHandle, unsigned int slot, std::unordered_map<std::string, sdbus::Variant> opts);
|
||||||
|
sdbus::UnixFd onConnectToEIS(sdbus::ObjectPath sessionHandle, std::string appID, std::unordered_map<std::string, sdbus::Variant> opts);
|
||||||
|
|
||||||
|
struct SSession {
|
||||||
|
std::string appid;
|
||||||
|
sdbus::ObjectPath requestHandle, sessionHandle;
|
||||||
|
std::unique_ptr<SDBusRequest> request;
|
||||||
|
std::unique_ptr<SDBusSession> session;
|
||||||
|
|
||||||
|
SP<CCZwlrVirtualPointerV1> pointer;
|
||||||
|
SP<CCZwpVirtualKeyboardV1> keyboard;
|
||||||
|
std::unique_ptr<EmulatedInputServer> eis;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unordered_map<std::string, std::shared_ptr<SSession>> m_mSessions;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::priority_queue<int, std::vector<int>, std::greater<int>> m_pqFreeIds;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
SP<CCZwlrVirtualPointerManagerV1> pointerMgr;
|
||||||
|
SP<CCZwpVirtualKeyboardManagerV1> keyboardMgr;
|
||||||
|
} m_sState;
|
||||||
|
|
||||||
|
std::unique_ptr<sdbus::IObject> m_pObject;
|
||||||
|
uint m_uSessionCounter = 0;
|
||||||
|
|
||||||
|
const sdbus::InterfaceName INTERFACE_NAME = sdbus::InterfaceName{"org.freedesktop.impl.portal.RemoteDesktop"};
|
||||||
|
const sdbus::ObjectPath OBJECT_PATH = sdbus::ObjectPath{"/org/freedesktop/portal/desktop"};
|
||||||
|
};
|
|
@ -6,12 +6,11 @@
|
||||||
#include <libeis.h>
|
#include <libeis.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <linux/input-event-codes.h>
|
||||||
|
|
||||||
EmulatedInputServer::EmulatedInputServer(std::string socketName, Keymap _keymap) {
|
EmulatedInputServer::EmulatedInputServer(std::string socketName) {
|
||||||
Debug::log(LOG, "[EIS] Init socket: {}", socketName);
|
Debug::log(LOG, "[EIS] Init socket: {}", socketName);
|
||||||
|
|
||||||
keymap = _keymap;
|
|
||||||
|
|
||||||
const char* xdg = getenv("XDG_RUNTIME_DIR");
|
const char* xdg = getenv("XDG_RUNTIME_DIR");
|
||||||
if (xdg)
|
if (xdg)
|
||||||
socketPath = std::string(xdg) + "/" + socketName;
|
socketPath = std::string(xdg) + "/" + socketName;
|
||||||
|
@ -61,12 +60,6 @@ int EmulatedInputServer::onEvent(eis_event* e) {
|
||||||
eisClient = eis_event_get_client(e);
|
eisClient = eis_event_get_client(e);
|
||||||
Debug::log(LOG, "[EIS] {} client connected: {}", eis_client_is_sender(eisClient) ? "Sender" : "Receiver", eis_client_get_name(eisClient));
|
Debug::log(LOG, "[EIS] {} client connected: {}", eis_client_is_sender(eisClient) ? "Sender" : "Receiver", eis_client_get_name(eisClient));
|
||||||
|
|
||||||
if (eis_client_is_sender(eisClient)) {
|
|
||||||
Debug::log(WARN, "[EIS] Unexpected sender client {} connected to input capture session", eis_client_get_name(eisClient));
|
|
||||||
eis_client_disconnect(eisClient);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (client.handle) {
|
if (client.handle) {
|
||||||
Debug::log(WARN, "[EIS] Unexpected additional client {} connected to input capture session", eis_client_get_name(eisClient));
|
Debug::log(WARN, "[EIS] Unexpected additional client {} connected to input capture session", eis_client_get_name(eisClient));
|
||||||
eis_client_disconnect(eisClient);
|
eis_client_disconnect(eisClient);
|
||||||
|
@ -80,6 +73,7 @@ int EmulatedInputServer::onEvent(eis_event* e) {
|
||||||
seat = eis_client_new_seat(eisClient, "default");
|
seat = eis_client_new_seat(eisClient, "default");
|
||||||
|
|
||||||
eis_seat_configure_capability(seat, EIS_DEVICE_CAP_POINTER);
|
eis_seat_configure_capability(seat, EIS_DEVICE_CAP_POINTER);
|
||||||
|
eis_seat_configure_capability(seat, EIS_DEVICE_CAP_POINTER_ABSOLUTE);
|
||||||
eis_seat_configure_capability(seat, EIS_DEVICE_CAP_BUTTON);
|
eis_seat_configure_capability(seat, EIS_DEVICE_CAP_BUTTON);
|
||||||
eis_seat_configure_capability(seat, EIS_DEVICE_CAP_SCROLL);
|
eis_seat_configure_capability(seat, EIS_DEVICE_CAP_SCROLL);
|
||||||
eis_seat_configure_capability(seat, EIS_DEVICE_CAP_KEYBOARD);
|
eis_seat_configure_capability(seat, EIS_DEVICE_CAP_KEYBOARD);
|
||||||
|
@ -120,6 +114,121 @@ int EmulatedInputServer::onEvent(eis_event* e) {
|
||||||
} else
|
} else
|
||||||
Debug::log(WARN, "[EIS] Unknown device to close");
|
Debug::log(WARN, "[EIS] Unknown device to close");
|
||||||
break;
|
break;
|
||||||
|
case EIS_EVENT_FRAME:
|
||||||
|
if (virtualPointer != nullptr) {
|
||||||
|
virtualPointer->sendFrame();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EIS_EVENT_DEVICE_START_EMULATING:
|
||||||
|
device = eis_event_get_device(e);
|
||||||
|
Debug::log(LOG, "[EIS] Device {} is ready to send events", eis_device_get_name(device));
|
||||||
|
break;
|
||||||
|
case EIS_EVENT_DEVICE_STOP_EMULATING:
|
||||||
|
device = eis_event_get_device(e);
|
||||||
|
Debug::log(LOG, "[EIS] Device {} will no longer send events", eis_device_get_name(device));
|
||||||
|
break;
|
||||||
|
case EIS_EVENT_POINTER_MOTION:
|
||||||
|
if (virtualPointer != nullptr) {
|
||||||
|
virtualPointer->sendMotion(0, eis_event_pointer_get_dx(e), eis_event_pointer_get_dy(e));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EIS_EVENT_POINTER_MOTION_ABSOLUTE:
|
||||||
|
if (virtualPointer != nullptr) {
|
||||||
|
virtualPointer->sendMotionAbsolute(0, eis_event_pointer_get_absolute_x(e), eis_event_pointer_get_absolute_y(e), screenWidth, screenHeight);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EIS_EVENT_BUTTON_BUTTON:
|
||||||
|
if (virtualPointer != nullptr) {
|
||||||
|
virtualPointer->sendButton(0, eis_event_button_get_button(e), eis_event_button_get_is_press(e));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EIS_EVENT_SCROLL_DELTA:
|
||||||
|
if (virtualPointer != nullptr) {
|
||||||
|
virtualPointer->sendAxis(0, 0, eis_event_scroll_get_dy(e));
|
||||||
|
virtualPointer->sendAxis(0, 1, eis_event_scroll_get_dx(e));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EIS_EVENT_SCROLL_STOP:
|
||||||
|
if (virtualPointer != nullptr) {
|
||||||
|
if (eis_event_scroll_get_stop_x(e))
|
||||||
|
virtualPointer->sendAxisStop(0, 1);
|
||||||
|
if (eis_event_scroll_get_stop_y(e))
|
||||||
|
virtualPointer->sendAxisStop(0, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EIS_EVENT_SCROLL_DISCRETE:
|
||||||
|
if (virtualPointer != nullptr) {
|
||||||
|
virtualPointer->sendAxisDiscrete(1, 0, 1, eis_event_scroll_get_discrete_dy(e));
|
||||||
|
virtualPointer->sendAxisDiscrete(1, 1, 1, eis_event_scroll_get_discrete_dx(e));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EIS_EVENT_KEYBOARD_KEY:
|
||||||
|
{
|
||||||
|
if (virtualKeyboard != nullptr) {
|
||||||
|
uint32_t keycode = eis_event_keyboard_get_key(e);
|
||||||
|
bool pressed = eis_event_keyboard_get_key_is_press(e);
|
||||||
|
switch (keycode) {
|
||||||
|
case KEY_LEFTSHIFT:
|
||||||
|
case KEY_RIGHTSHIFT:
|
||||||
|
if (pressed)
|
||||||
|
depressed |= 1;
|
||||||
|
else
|
||||||
|
depressed &= ~(1);
|
||||||
|
break;
|
||||||
|
case KEY_CAPSLOCK:
|
||||||
|
if (pressed) {
|
||||||
|
if (locked & (1 << 1))
|
||||||
|
locked &= ~(1 << 1);
|
||||||
|
else
|
||||||
|
locked |= 1 << 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_LEFTCTRL:
|
||||||
|
case KEY_RIGHTCTRL:
|
||||||
|
if (pressed)
|
||||||
|
depressed |= 1 << 2;
|
||||||
|
else
|
||||||
|
depressed &= ~(1 << 2);
|
||||||
|
break;
|
||||||
|
case KEY_LEFTALT:
|
||||||
|
case KEY_RIGHTALT:
|
||||||
|
if (pressed)
|
||||||
|
depressed |= 1 << 3;
|
||||||
|
else
|
||||||
|
depressed &= ~(1 << 3);
|
||||||
|
break;
|
||||||
|
case KEY_NUMLOCK:
|
||||||
|
if (pressed) {
|
||||||
|
if (locked & (1 << 4))
|
||||||
|
locked &= ~(1 << 4);
|
||||||
|
else
|
||||||
|
locked |= 1 << 4;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_LEFTMETA:
|
||||||
|
case KEY_RIGHTMETA:
|
||||||
|
if (pressed)
|
||||||
|
depressed |= 1 << 6;
|
||||||
|
else
|
||||||
|
depressed &= ~(1 << 6);
|
||||||
|
break;
|
||||||
|
case KEY_SCROLLLOCK:
|
||||||
|
if (pressed) {
|
||||||
|
if (locked & (1 << 7))
|
||||||
|
locked &= ~(1 << 7);
|
||||||
|
else
|
||||||
|
locked |= 1 << 7;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
virtualKeyboard->sendModifiers(depressed, latched, locked, 3);
|
||||||
|
virtualKeyboard->sendKey(1, keycode, pressed);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default: return 0;
|
default: return 0;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -132,6 +241,7 @@ void EmulatedInputServer::ensurePointer(eis_event* event) {
|
||||||
eis_device* pointer = eis_seat_new_device(client.seat);
|
eis_device* pointer = eis_seat_new_device(client.seat);
|
||||||
eis_device_configure_name(pointer, "captured relative pointer");
|
eis_device_configure_name(pointer, "captured relative pointer");
|
||||||
eis_device_configure_capability(pointer, EIS_DEVICE_CAP_POINTER);
|
eis_device_configure_capability(pointer, EIS_DEVICE_CAP_POINTER);
|
||||||
|
eis_device_configure_capability(pointer, EIS_DEVICE_CAP_POINTER_ABSOLUTE);
|
||||||
eis_device_configure_capability(pointer, EIS_DEVICE_CAP_BUTTON);
|
eis_device_configure_capability(pointer, EIS_DEVICE_CAP_BUTTON);
|
||||||
eis_device_configure_capability(pointer, EIS_DEVICE_CAP_SCROLL);
|
eis_device_configure_capability(pointer, EIS_DEVICE_CAP_SCROLL);
|
||||||
|
|
||||||
|
@ -140,9 +250,15 @@ void EmulatedInputServer::ensurePointer(eis_event* event) {
|
||||||
|
|
||||||
eis_region_set_offset(r, o->x, o->y);
|
eis_region_set_offset(r, o->x, o->y);
|
||||||
eis_region_set_size(r, o->width, o->height);
|
eis_region_set_size(r, o->width, o->height);
|
||||||
|
Debug::log(LOG, "[EIS] REGION TME {} {}", o->width, o->height);
|
||||||
eis_region_set_physical_scale(r, o->scale);
|
eis_region_set_physical_scale(r, o->scale);
|
||||||
eis_region_add(r);
|
eis_region_add(r);
|
||||||
eis_region_unref(r);
|
eis_region_unref(r);
|
||||||
|
|
||||||
|
//#FIXME: #TODO: this doesn't work if there are multiple outputs in getAllOutPuts()
|
||||||
|
screenWidth = o->width;
|
||||||
|
screenHeight = o->height;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
eis_device_add(pointer);
|
eis_device_add(pointer);
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <libeis.h>
|
#include <libei-1.0/libeis.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include "wlr-virtual-pointer-unstable-v1.hpp"
|
||||||
|
#include "virtual-keyboard-unstable-v1.hpp"
|
||||||
|
#include <memory>
|
||||||
|
#include "../includes.hpp"
|
||||||
|
|
||||||
struct Keymap {
|
struct Keymap {
|
||||||
int32_t fd = 0;
|
int32_t fd = 0;
|
||||||
|
@ -13,7 +17,7 @@ struct Keymap {
|
||||||
*/
|
*/
|
||||||
class EmulatedInputServer {
|
class EmulatedInputServer {
|
||||||
public:
|
public:
|
||||||
EmulatedInputServer(std::string socketPath, Keymap keymap);
|
EmulatedInputServer(std::string socketPath);
|
||||||
std::string socketPath;
|
std::string socketPath;
|
||||||
|
|
||||||
void startEmulating(int activationId);
|
void startEmulating(int activationId);
|
||||||
|
@ -32,6 +36,9 @@ class EmulatedInputServer {
|
||||||
|
|
||||||
int getFileDescriptor();
|
int getFileDescriptor();
|
||||||
|
|
||||||
|
void setVirtualPointer(SP<CCZwlrVirtualPointerV1> ptr) {virtualPointer = ptr;}
|
||||||
|
void setVirtualKeyboard(SP<CCZwpVirtualKeyboardV1> kb) {virtualKeyboard = kb; }
|
||||||
|
|
||||||
void stopServer();
|
void stopServer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -46,6 +53,15 @@ class EmulatedInputServer {
|
||||||
eis_device* keyboard = nullptr;
|
eis_device* keyboard = nullptr;
|
||||||
} client;
|
} client;
|
||||||
|
|
||||||
|
SP<CCZwlrVirtualPointerV1> virtualPointer = nullptr;
|
||||||
|
SP<CCZwpVirtualKeyboardV1> virtualKeyboard = nullptr;
|
||||||
|
uint32_t screenWidth = 0;
|
||||||
|
uint32_t screenHeight = 0;
|
||||||
|
|
||||||
|
uint32_t depressed = 0;
|
||||||
|
uint32_t latched = 0;
|
||||||
|
uint32_t locked = 0;
|
||||||
|
|
||||||
Keymap keymap;
|
Keymap keymap;
|
||||||
|
|
||||||
int onEvent(eis_event* e);
|
int onEvent(eis_event* e);
|
||||||
|
|
Loading…
Reference in a new issue