virtual-pointer: move to new impl

This commit is contained in:
Vaxry 2024-05-03 01:27:59 +01:00
parent 7d49819b5e
commit 2755297670
13 changed files with 428 additions and 21 deletions

View file

@ -262,6 +262,7 @@ protocolNew("protocols/wlr-gamma-control-unstable-v1.xml" "wlr-gamma-control-uns
protocolNew("protocols/wlr-foreign-toplevel-management-unstable-v1.xml" "wlr-foreign-toplevel-management-unstable-v1" true) protocolNew("protocols/wlr-foreign-toplevel-management-unstable-v1.xml" "wlr-foreign-toplevel-management-unstable-v1" true)
protocolNew("protocols/wlr-output-power-management-unstable-v1.xml" "wlr-output-power-management-unstable-v1" true) protocolNew("protocols/wlr-output-power-management-unstable-v1.xml" "wlr-output-power-management-unstable-v1" true)
protocolNew("protocols/virtual-keyboard-unstable-v1.xml" "virtual-keyboard-unstable-v1" true) protocolNew("protocols/virtual-keyboard-unstable-v1.xml" "virtual-keyboard-unstable-v1" true)
protocolNew("protocols/wlr-virtual-pointer-unstable-v1.xml" "wlr-virtual-pointer-unstable-v1" true)
protocolNew("protocols/input-method-unstable-v2.xml" "input-method-unstable-v2" true) protocolNew("protocols/input-method-unstable-v2.xml" "input-method-unstable-v2" true)
protocolNew("staging/tearing-control/tearing-control-v1.xml" "tearing-control-v1" false) protocolNew("staging/tearing-control/tearing-control-v1.xml" "tearing-control-v1" false)
protocolNew("staging/fractional-scale/fractional-scale-v1.xml" "fractional-scale-v1" false) protocolNew("staging/fractional-scale/fractional-scale-v1.xml" "fractional-scale-v1" false)

View file

@ -40,6 +40,7 @@ new_protocols = [
['wlr-output-power-management-unstable-v1.xml'], ['wlr-output-power-management-unstable-v1.xml'],
['input-method-unstable-v2.xml'], ['input-method-unstable-v2.xml'],
['virtual-keyboard-unstable-v1.xml'], ['virtual-keyboard-unstable-v1.xml'],
['wlr-virtual-pointer-unstable-v1.xml'],
[wl_protocol_dir, 'staging/tearing-control/tearing-control-v1.xml'], [wl_protocol_dir, 'staging/tearing-control/tearing-control-v1.xml'],
[wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml'], [wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml'],
[wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'], [wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],

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

View file

@ -245,8 +245,6 @@ void CCompositor::initServer() {
m_sWLROutputMgr = wlr_output_manager_v1_create(m_sWLDisplay); m_sWLROutputMgr = wlr_output_manager_v1_create(m_sWLDisplay);
m_sWLRVirtPtrMgr = wlr_virtual_pointer_manager_v1_create(m_sWLDisplay);
m_sWRLDRMLeaseMgr = wlr_drm_lease_v1_manager_create(m_sWLDisplay, m_sWLRBackend); m_sWRLDRMLeaseMgr = wlr_drm_lease_v1_manager_create(m_sWLDisplay, m_sWLRBackend);
if (!m_sWRLDRMLeaseMgr) { if (!m_sWRLDRMLeaseMgr) {
Debug::log(INFO, "Failed to create wlr_drm_lease_v1_manager"); Debug::log(INFO, "Failed to create wlr_drm_lease_v1_manager");
@ -305,7 +303,6 @@ void CCompositor::initAllSignals() {
addWLSignal(&m_sWLROutputLayout->events.change, &Events::listen_change, m_sWLROutputLayout, "OutputLayout"); addWLSignal(&m_sWLROutputLayout->events.change, &Events::listen_change, m_sWLROutputLayout, "OutputLayout");
addWLSignal(&m_sWLROutputMgr->events.apply, &Events::listen_outputMgrApply, m_sWLROutputMgr, "OutputMgr"); addWLSignal(&m_sWLROutputMgr->events.apply, &Events::listen_outputMgrApply, m_sWLROutputMgr, "OutputMgr");
addWLSignal(&m_sWLROutputMgr->events.test, &Events::listen_outputMgrTest, m_sWLROutputMgr, "OutputMgr"); addWLSignal(&m_sWLROutputMgr->events.test, &Events::listen_outputMgrTest, m_sWLROutputMgr, "OutputMgr");
addWLSignal(&m_sWLRVirtPtrMgr->events.new_virtual_pointer, &Events::listen_newVirtPtr, m_sWLRVirtPtrMgr, "VirtPtrMgr");
addWLSignal(&m_sWLRRenderer->events.destroy, &Events::listen_RendererDestroy, m_sWLRRenderer, "WLRRenderer"); addWLSignal(&m_sWLRRenderer->events.destroy, &Events::listen_RendererDestroy, m_sWLRRenderer, "WLRRenderer");
if (m_sWRLDRMLeaseMgr) if (m_sWRLDRMLeaseMgr)
@ -346,7 +343,6 @@ void CCompositor::removeAllSignals() {
removeWLSignal(&Events::listen_change); removeWLSignal(&Events::listen_change);
removeWLSignal(&Events::listen_outputMgrApply); removeWLSignal(&Events::listen_outputMgrApply);
removeWLSignal(&Events::listen_outputMgrTest); removeWLSignal(&Events::listen_outputMgrTest);
removeWLSignal(&Events::listen_newVirtPtr);
removeWLSignal(&Events::listen_RendererDestroy); removeWLSignal(&Events::listen_RendererDestroy);
if (m_sWRLDRMLeaseMgr) if (m_sWRLDRMLeaseMgr)

View file

@ -60,7 +60,6 @@ class CCompositor {
wlr_egl* m_sWLREGL; wlr_egl* m_sWLREGL;
int m_iDRMFD; int m_iDRMFD;
wlr_server_decoration_manager* m_sWLRServerDecoMgr; wlr_server_decoration_manager* m_sWLRServerDecoMgr;
wlr_virtual_pointer_manager_v1* m_sWLRVirtPtrMgr;
wlr_tablet_manager_v2* m_sWLRTabletManager; wlr_tablet_manager_v2* m_sWLRTabletManager;
wlr_xdg_foreign_registry* m_sWLRForeignRegistry; wlr_xdg_foreign_registry* m_sWLRForeignRegistry;
wlr_linux_dmabuf_v1* m_sWLRLinuxDMABuf; wlr_linux_dmabuf_v1* m_sWLRLinuxDMABuf;

View file

@ -93,14 +93,6 @@ void Events::listener_newInput(wl_listener* listener, void* data) {
g_pInputManager->updateCapabilities(); g_pInputManager->updateCapabilities();
} }
void Events::listener_newVirtPtr(wl_listener* listener, void* data) {
const auto EV = (wlr_virtual_pointer_v1_new_pointer_event*)data;
const auto POINTER = EV->new_pointer;
const auto DEVICE = &POINTER->pointer.base;
g_pInputManager->newMouse(DEVICE, true);
}
void Events::listener_destroyMouse(void* owner, void* data) { void Events::listener_destroyMouse(void* owner, void* data) {
const auto PMOUSE = (SMouse*)owner; const auto PMOUSE = (SMouse*)owner;

View file

@ -12,6 +12,7 @@
class CMonitor; class CMonitor;
class CVirtualKeyboard; class CVirtualKeyboard;
class CVirtualPointer;
struct SRenderData { struct SRenderData {
CMonitor* pMonitor; CMonitor* pMonitor;
@ -112,6 +113,12 @@ struct SMouse {
bool connected = false; // means connected to the cursor bool connected = false; // means connected to the cursor
WP<CVirtualPointer> virtualPointer;
struct {
CHyprSignalListener destroyMouse;
} listeners;
DYNLISTENER(destroyMouse); DYNLISTENER(destroyMouse);
bool operator==(const SMouse& b) const { bool operator==(const SMouse& b) const {

View file

@ -67,7 +67,6 @@ extern "C" {
#include <wlr/types/wlr_subcompositor.h> #include <wlr/types/wlr_subcompositor.h>
#include <wlr/types/wlr_damage_ring.h> #include <wlr/types/wlr_damage_ring.h>
#include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h> #include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h>
#include <wlr/types/wlr_virtual_pointer_v1.h>
#include <wlr/util/log.h> #include <wlr/util/log.h>
#include <wlr/util/region.h> #include <wlr/util/region.h>
#include <wlr/util/edges.h> #include <wlr/util/edges.h>
@ -79,6 +78,7 @@ extern "C" {
#include <wlr/render/gles2.h> #include <wlr/render/gles2.h>
#include <wlr/render/wlr_texture.h> #include <wlr/render/wlr_texture.h>
#include <wlr/interfaces/wlr_keyboard.h> #include <wlr/interfaces/wlr_keyboard.h>
#include <wlr/interfaces/wlr_pointer.h>
#include <wlr/types/wlr_xdg_foreign_registry.h> #include <wlr/types/wlr_xdg_foreign_registry.h>
#include <wlr/types/wlr_xdg_foreign_v1.h> #include <wlr/types/wlr_xdg_foreign_v1.h>
#include <wlr/types/wlr_xdg_foreign_v2.h> #include <wlr/types/wlr_xdg_foreign_v2.h>

View file

@ -21,6 +21,7 @@
#include "../protocols/SessionLock.hpp" #include "../protocols/SessionLock.hpp"
#include "../protocols/InputMethodV2.hpp" #include "../protocols/InputMethodV2.hpp"
#include "../protocols/VirtualKeyboard.hpp" #include "../protocols/VirtualKeyboard.hpp"
#include "../protocols/VirtualPointer.hpp"
CProtocolManager::CProtocolManager() { CProtocolManager::CProtocolManager() {
@ -45,6 +46,7 @@ CProtocolManager::CProtocolManager() {
PROTO::sessionLock = std::make_unique<CSessionLockProtocol>(&ext_session_lock_manager_v1_interface, 1, "SessionLock"); PROTO::sessionLock = std::make_unique<CSessionLockProtocol>(&ext_session_lock_manager_v1_interface, 1, "SessionLock");
PROTO::ime = std::make_unique<CInputMethodV2Protocol>(&zwp_input_method_manager_v2_interface, 1, "IMEv2"); PROTO::ime = std::make_unique<CInputMethodV2Protocol>(&zwp_input_method_manager_v2_interface, 1, "IMEv2");
PROTO::virtualKeyboard = std::make_unique<CVirtualKeyboardProtocol>(&zwp_virtual_keyboard_manager_v1_interface, 1, "VirtualKeyboard"); PROTO::virtualKeyboard = std::make_unique<CVirtualKeyboardProtocol>(&zwp_virtual_keyboard_manager_v1_interface, 1, "VirtualKeyboard");
PROTO::virtualPointer = std::make_unique<CVirtualPointerProtocol>(&zwlr_virtual_pointer_manager_v1_interface, 2, "VirtualPointer");
// Old protocol implementations. // Old protocol implementations.
// TODO: rewrite them to use hyprwayland-scanner. // TODO: rewrite them to use hyprwayland-scanner.

View file

@ -12,6 +12,7 @@
#include "../../protocols/SessionLock.hpp" #include "../../protocols/SessionLock.hpp"
#include "../../protocols/InputMethodV2.hpp" #include "../../protocols/InputMethodV2.hpp"
#include "../../protocols/VirtualKeyboard.hpp" #include "../../protocols/VirtualKeyboard.hpp"
#include "../../protocols/VirtualPointer.hpp"
CInputManager::CInputManager() { CInputManager::CInputManager() {
m_sListeners.setCursorShape = PROTO::cursorShape->events.setShape.registerListener([this](std::any data) { m_sListeners.setCursorShape = PROTO::cursorShape->events.setShape.registerListener([this](std::any data) {
@ -40,6 +41,8 @@ CInputManager::CInputManager() {
m_sListeners.newIdleInhibitor = PROTO::idleInhibit->events.newIdleInhibitor.registerListener([this](std::any data) { this->newIdleInhibitor(data); }); m_sListeners.newIdleInhibitor = PROTO::idleInhibit->events.newIdleInhibitor.registerListener([this](std::any data) { this->newIdleInhibitor(data); });
m_sListeners.newVirtualKeyboard = m_sListeners.newVirtualKeyboard =
PROTO::virtualKeyboard->events.newKeyboard.registerListener([this](std::any data) { this->newVirtualKeyboard(std::any_cast<SP<CVirtualKeyboard>>(data)); }); PROTO::virtualKeyboard->events.newKeyboard.registerListener([this](std::any data) { this->newVirtualKeyboard(std::any_cast<SP<CVirtualKeyboard>>(data)); });
m_sListeners.newVirtualMouse =
PROTO::virtualPointer->events.newPointer.registerListener([this](std::any data) { this->newVirtualMouse(std::any_cast<SP<CVirtualPointer>>(data)); });
} }
CInputManager::~CInputManager() { CInputManager::~CInputManager() {
@ -968,12 +971,41 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
pKeyboard->keyboard->name); pKeyboard->keyboard->name);
} }
void CInputManager::newMouse(wlr_input_device* mouse, bool virt) { void CInputManager::newVirtualMouse(SP<CVirtualPointer> mouse) {
const auto PMOUSE = &m_lMice.emplace_back();
PMOUSE->mouse = &mouse->wlr()->base;
PMOUSE->virtualPointer = mouse;
PMOUSE->virt = true;
try {
PMOUSE->name = getNameForNewDevice(mouse->wlr()->base.name);
} catch (std::exception& e) {
Debug::log(ERR, "Mouse had no name???"); // logic error
}
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, &mouse->wlr()->base);
PMOUSE->connected = true;
setPointerConfigs();
PMOUSE->hyprListener_destroyMouse.initCallback(&mouse->wlr()->base.events.destroy, &Events::listener_destroyMouse, PMOUSE, "Mouse");
// TODO: this pointer pass sucks.
PMOUSE->listeners.destroyMouse = mouse->events.destroy.registerListener([this, PMOUSE](std::any data) { destroyMouse(PMOUSE->mouse); });
g_pCompositor->m_sSeat.mouse = PMOUSE;
m_tmrLastCursorMovement.reset();
Debug::log(LOG, "New virtual mouse created, pointer WLR: {:x}", (uintptr_t)mouse->wlr());
}
void CInputManager::newMouse(wlr_input_device* mouse) {
m_lMice.emplace_back(); m_lMice.emplace_back();
const auto PMOUSE = &m_lMice.back(); const auto PMOUSE = &m_lMice.back();
PMOUSE->mouse = mouse; PMOUSE->mouse = mouse;
PMOUSE->virt = virt;
try { try {
PMOUSE->name = getNameForNewDevice(mouse->name); PMOUSE->name = getNameForNewDevice(mouse->name);
} catch (std::exception& e) { } catch (std::exception& e) {

View file

@ -12,6 +12,7 @@ class CPointerConstraint;
class CWindow; class CWindow;
class CIdleInhibitor; class CIdleInhibitor;
class CVirtualKeyboard; class CVirtualKeyboard;
class CVirtualPointer;
enum eClickBehaviorMode { enum eClickBehaviorMode {
CLICKMODE_DEFAULT = 0, CLICKMODE_DEFAULT = 0,
@ -79,7 +80,8 @@ class CInputManager {
void newKeyboard(wlr_input_device*); void newKeyboard(wlr_input_device*);
void newVirtualKeyboard(SP<CVirtualKeyboard>); void newVirtualKeyboard(SP<CVirtualKeyboard>);
void newMouse(wlr_input_device*, bool virt = false); void newMouse(wlr_input_device*);
void newVirtualMouse(SP<CVirtualPointer>);
void newTouchDevice(wlr_input_device*); void newTouchDevice(wlr_input_device*);
void newSwitch(wlr_input_device*); void newSwitch(wlr_input_device*);
void destroyTouchDevice(STouchDevice*); void destroyTouchDevice(STouchDevice*);
@ -201,6 +203,7 @@ class CInputManager {
CHyprSignalListener setCursorShape; CHyprSignalListener setCursorShape;
CHyprSignalListener newIdleInhibitor; CHyprSignalListener newIdleInhibitor;
CHyprSignalListener newVirtualKeyboard; CHyprSignalListener newVirtualKeyboard;
CHyprSignalListener newVirtualMouse;
} m_sListeners; } m_sListeners;
bool m_bCursorImageOverridden = false; bool m_bCursorImageOverridden = false;

View file

@ -0,0 +1,165 @@
#include "VirtualPointer.hpp"
#define LOGM PROTO::virtualPointer->protoLog
static const wlr_pointer_impl pointerImpl = {
.name = "virtual-pointer-v1",
};
CVirtualPointer::CVirtualPointer(SP<CZwlrVirtualPointerV1> resource_) : resource(resource_) {
if (!good())
return;
resource->setDestroy([this](CZwlrVirtualPointerV1* r) {
events.destroy.emit();
PROTO::virtualPointer->destroyResource(this);
});
resource->setOnDestroy([this](CZwlrVirtualPointerV1* r) {
events.destroy.emit();
PROTO::virtualPointer->destroyResource(this);
});
wlr_pointer_init(&pointer, &pointerImpl, "CVirtualPointer");
resource->setMotion([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, wl_fixed_t dx, wl_fixed_t dy) {
wlr_pointer_motion_event event = {
.pointer = &pointer,
.time_msec = timeMs,
.delta_x = wl_fixed_to_double(dx),
.delta_y = wl_fixed_to_double(dy),
.unaccel_dx = wl_fixed_to_double(dx),
.unaccel_dy = wl_fixed_to_double(dy),
};
wl_signal_emit_mutable(&pointer.events.motion, &event);
});
resource->setMotionAbsolute([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t x, uint32_t y, uint32_t xExtent, uint32_t yExtent) {
if (!xExtent || !yExtent)
return;
wlr_pointer_motion_absolute_event event = {
.pointer = &pointer,
.time_msec = timeMs,
.x = (double)x / xExtent,
.y = (double)y / yExtent,
};
wl_signal_emit_mutable(&pointer.events.motion_absolute, &event);
});
resource->setButton([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t button, uint32_t state) {
struct wlr_pointer_button_event event = {
.pointer = &pointer,
.time_msec = timeMs,
.button = button,
.state = (wl_pointer_button_state)state,
};
wl_signal_emit_mutable(&pointer.events.button, &event);
});
resource->setAxis([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t axis_, wl_fixed_t value) {
if (axis > WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
r->error(ZWLR_VIRTUAL_POINTER_V1_ERROR_INVALID_AXIS, "Invalid axis");
return;
}
axis = axis_;
axisEvents[axis] = wlr_pointer_axis_event{.pointer = &pointer, .time_msec = timeMs, .orientation = (wl_pointer_axis)axis, .delta = wl_fixed_to_double(value)};
});
resource->setFrame([this](CZwlrVirtualPointerV1* r) {
for (auto& e : axisEvents) {
if (!e.pointer)
continue;
wl_signal_emit_mutable(&pointer.events.axis, &e);
e.pointer = nullptr;
}
wl_signal_emit_mutable(&pointer.events.frame, &pointer);
});
resource->setAxisSource([this](CZwlrVirtualPointerV1* r, uint32_t source) { axisEvents[axis].source = (wl_pointer_axis_source)source; });
resource->setAxisStop([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t axis_) {
if (axis > WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
r->error(ZWLR_VIRTUAL_POINTER_V1_ERROR_INVALID_AXIS, "Invalid axis");
return;
}
axis = axis_;
axisEvents[axis].pointer = &pointer;
axisEvents[axis].time_msec = timeMs;
axisEvents[axis].orientation = (wl_pointer_axis)axis;
axisEvents[axis].delta = 0;
axisEvents[axis].delta_discrete = 0;
});
resource->setAxisDiscrete([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t axis_, wl_fixed_t value, int32_t discrete) {
if (axis > WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
r->error(ZWLR_VIRTUAL_POINTER_V1_ERROR_INVALID_AXIS, "Invalid axis");
return;
}
axis = axis_;
axisEvents[axis].pointer = &pointer;
axisEvents[axis].time_msec = timeMs;
axisEvents[axis].orientation = (wl_pointer_axis)axis;
axisEvents[axis].delta = wl_fixed_to_double(value);
axisEvents[axis].delta_discrete = discrete * 120;
});
}
CVirtualPointer::~CVirtualPointer() {
wlr_pointer_finish(&pointer);
events.destroy.emit();
}
bool CVirtualPointer::good() {
return resource->resource();
}
wlr_pointer* CVirtualPointer::wlr() {
return &pointer;
}
wl_client* CVirtualPointer::client() {
return resource->client();
}
CVirtualPointerProtocol::CVirtualPointerProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
;
}
void CVirtualPointerProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
const auto RESOURCE = m_vManagers.emplace_back(std::make_unique<CZwlrVirtualPointerManagerV1>(client, ver, id)).get();
RESOURCE->setOnDestroy([this](CZwlrVirtualPointerManagerV1* p) { this->onManagerResourceDestroy(p->resource()); });
RESOURCE->setDestroy([this](CZwlrVirtualPointerManagerV1* p) { this->onManagerResourceDestroy(p->resource()); });
RESOURCE->setCreateVirtualPointer([this](CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, uint32_t id) { this->onCreatePointer(pMgr, seat, id); });
RESOURCE->setCreateVirtualPointerWithOutput([this](CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, wl_resource* output, uint32_t id) {
LOGM(WARN, "TODO: CreateWithOutput is not supported yet. Ignoring for now.");
this->onCreatePointer(pMgr, seat, id);
});
}
void CVirtualPointerProtocol::onManagerResourceDestroy(wl_resource* res) {
std::erase_if(m_vManagers, [&](const auto& other) { return other->resource() == res; });
}
void CVirtualPointerProtocol::destroyResource(CVirtualPointer* pointer) {
std::erase_if(m_vPointers, [&](const auto& other) { return other.get() == pointer; });
}
void CVirtualPointerProtocol::onCreatePointer(CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, uint32_t id) {
const auto RESOURCE = m_vPointers.emplace_back(std::make_shared<CVirtualPointer>(std::make_shared<CZwlrVirtualPointerV1>(pMgr->client(), pMgr->version(), id)));
if (!RESOURCE->good()) {
pMgr->noMemory();
m_vPointers.pop_back();
return;
}
LOGM(LOG, "New VPointer at id {}", id);
events.newPointer.emit(RESOURCE);
}

View file

@ -0,0 +1,57 @@
#pragma once
#include <memory>
#include <vector>
#include <cstdint>
#include <array>
#include "WaylandProtocol.hpp"
#include "wlr-virtual-pointer-unstable-v1.hpp"
#include "../helpers/signal/Signal.hpp"
class CVirtualPointer {
public:
CVirtualPointer(SP<CZwlrVirtualPointerV1> resource_);
~CVirtualPointer();
struct {
CSignal destroy;
} events;
bool good();
wlr_pointer* wlr();
wl_client* client();
private:
SP<CZwlrVirtualPointerV1> resource;
wlr_pointer pointer;
uint32_t axis = 0;
std::array<wlr_pointer_axis_event, 2> axisEvents;
};
class CVirtualPointerProtocol : public IWaylandProtocol {
public:
CVirtualPointerProtocol(const wl_interface* iface, const int& ver, const std::string& name);
virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
struct {
CSignal newPointer; // SP<CVirtualPointer>
} events;
private:
void onManagerResourceDestroy(wl_resource* res);
void destroyResource(CVirtualPointer* pointer);
void onCreatePointer(CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, uint32_t id);
//
std::vector<UP<CZwlrVirtualPointerManagerV1>> m_vManagers;
std::vector<SP<CVirtualPointer>> m_vPointers;
friend class CVirtualPointer;
};
namespace PROTO {
inline UP<CVirtualPointerProtocol> virtualPointer;
};