summaryrefslogtreecommitdiff
path: root/src/protocols/VirtualPointer.cpp
diff options
context:
space:
mode:
authorVaxry <vaxry@vaxry.net>2024-05-03 01:27:59 +0100
committerVaxry <vaxry@vaxry.net>2024-05-03 01:52:05 +0100
commit27552976705e416ce481ca74d377578bcbc134e0 (patch)
treef878f05a1bffead708cdc7dc480e0b199860f163 /src/protocols/VirtualPointer.cpp
parent7d49819b5ecb4cb69d3db405a658ba44c17fc8e6 (diff)
virtual-pointer: move to new impl
Diffstat (limited to 'src/protocols/VirtualPointer.cpp')
-rw-r--r--src/protocols/VirtualPointer.cpp165
1 files changed, 165 insertions, 0 deletions
diff --git a/src/protocols/VirtualPointer.cpp b/src/protocols/VirtualPointer.cpp
new file mode 100644
index 00000000..287e7bad
--- /dev/null
+++ b/src/protocols/VirtualPointer.cpp
@@ -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);
+} \ No newline at end of file