summaryrefslogtreecommitdiff
path: root/src/managers/SeatManager.cpp
diff options
context:
space:
mode:
authorVaxry <vaxry@vaxry.net>2024-05-10 18:27:57 +0100
committerVaxry <43317083+vaxerski@users.noreply.github.com>2024-05-14 23:02:24 +0100
commit121d3a72137d4780602cf245704615f63357ea22 (patch)
treeb25c8a3ee7b239006281f0e00110d1c324b8cedc /src/managers/SeatManager.cpp
parent4cdddcfe466cb21db81af0ac39e51cc15f574da9 (diff)
wl_seat: move to hyprland impl
Diffstat (limited to 'src/managers/SeatManager.cpp')
-rw-r--r--src/managers/SeatManager.cpp391
1 files changed, 391 insertions, 0 deletions
diff --git a/src/managers/SeatManager.cpp b/src/managers/SeatManager.cpp
new file mode 100644
index 00000000..f9d394b5
--- /dev/null
+++ b/src/managers/SeatManager.cpp
@@ -0,0 +1,391 @@
+#include "SeatManager.hpp"
+#include "../protocols/core/Seat.hpp"
+#include "../Compositor.hpp"
+#include "../devices/IKeyboard.hpp"
+#include <algorithm>
+
+CSeatManager::CSeatManager() {
+ listeners.newSeatResource = PROTO::seat->events.newSeatResource.registerListener([this](std::any res) { onNewSeatResource(std::any_cast<SP<CWLSeatResource>>(res)); });
+}
+
+CSeatManager::SSeatResourceContainer::SSeatResourceContainer(SP<CWLSeatResource> res) {
+ resource = res;
+ listeners.destroy = res->events.destroy.registerListener(
+ [this](std::any data) { std::erase_if(g_pSeatManager->seatResources, [this](const auto& e) { return e->resource.expired() || e->resource == resource; }); });
+}
+
+void CSeatManager::onNewSeatResource(SP<CWLSeatResource> resource) {
+ seatResources.emplace_back(makeShared<SSeatResourceContainer>(resource));
+}
+
+SP<CSeatManager::SSeatResourceContainer> CSeatManager::containerForResource(SP<CWLSeatResource> seatResource) {
+ for (auto& c : seatResources) {
+ if (c->resource == seatResource)
+ return c;
+ }
+
+ return nullptr;
+}
+
+uint32_t CSeatManager::nextSerial(SP<CWLSeatResource> seatResource) {
+ if (!seatResource)
+ return 0;
+
+ auto container = containerForResource(seatResource);
+
+ ASSERT(container);
+
+ auto serial = wl_display_next_serial(g_pCompositor->m_sWLDisplay);
+
+ container->serials.emplace_back(serial);
+
+ if (container->serials.size() > MAX_SERIAL_STORE_LEN)
+ container->serials.erase(container->serials.begin());
+
+ return serial;
+}
+
+bool CSeatManager::serialValid(SP<CWLSeatResource> seatResource, uint32_t serial) {
+ if (!seatResource)
+ return false;
+
+ auto container = containerForResource(seatResource);
+
+ ASSERT(container);
+
+ for (auto it = container->serials.begin(); it != container->serials.end(); ++it) {
+ if (*it == serial) {
+ container->serials.erase(it);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void CSeatManager::updateCapabilities(uint32_t capabilities) {
+ PROTO::seat->updateCapabilities(capabilities);
+}
+
+void CSeatManager::setMouse(SP<IPointer> MAUZ) {
+ if (mouse == MAUZ)
+ return;
+
+ mouse = MAUZ;
+}
+
+void CSeatManager::setKeyboard(SP<IKeyboard> KEEB) {
+ if (keyboard == KEEB)
+ return;
+
+ if (keyboard)
+ keyboard->active = false;
+ keyboard = KEEB;
+
+ if (KEEB) {
+ KEEB->active = true;
+ PROTO::seat->updateRepeatInfo(KEEB->wlr()->repeat_info.rate, KEEB->wlr()->repeat_info.delay);
+ }
+ PROTO::seat->updateKeymap();
+}
+
+void CSeatManager::setKeyboardFocus(wlr_surface* surf) {
+ if (state.keyboardFocus == surf)
+ return;
+
+ if (!keyboard || !keyboard->wlr()) {
+ Debug::log(ERR, "BUG THIS: setKeyboardFocus without a valid keyboard set");
+ return;
+ }
+
+ hyprListener_keyboardSurfaceDestroy.removeCallback();
+
+ if (state.keyboardFocusResource) {
+ for (auto& k : state.keyboardFocusResource->keyboards) {
+ if (!k)
+ continue;
+
+ k->sendLeave();
+ }
+ }
+
+ state.keyboardFocusResource.reset();
+ state.keyboardFocus = surf;
+
+ if (!surf) {
+ events.keyboardFocusChange.emit();
+ return;
+ }
+
+ auto client = wl_resource_get_client(surf->resource);
+ for (auto& r : seatResources) {
+ if (r->resource->client() == client) {
+ state.keyboardFocusResource = r->resource;
+ for (auto& k : state.keyboardFocusResource->keyboards) {
+ if (!k)
+ continue;
+
+ k->sendEnter(surf);
+ k->sendMods(keyboard->wlr()->modifiers.depressed, keyboard->wlr()->modifiers.latched, keyboard->wlr()->modifiers.locked, keyboard->wlr()->modifiers.group);
+ }
+
+ break;
+ }
+ }
+
+ hyprListener_keyboardSurfaceDestroy.initCallback(
+ &surf->events.destroy, [this](void* owner, void* data) { setKeyboardFocus(nullptr); }, nullptr, "CSeatManager");
+
+ events.keyboardFocusChange.emit();
+}
+
+void CSeatManager::sendKeyboardKey(uint32_t timeMs, uint32_t key, wl_keyboard_key_state state_) {
+ if (!state.keyboardFocusResource)
+ return;
+
+ for (auto& k : state.keyboardFocusResource->keyboards) {
+ if (!k)
+ continue;
+
+ k->sendKey(timeMs, key, state_);
+ }
+}
+
+void CSeatManager::sendKeyboardMods(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) {
+ if (!state.keyboardFocusResource)
+ return;
+
+ for (auto& k : state.keyboardFocusResource->keyboards) {
+ if (!k)
+ continue;
+
+ k->sendMods(depressed, latched, locked, group);
+ }
+}
+
+void CSeatManager::setPointerFocus(wlr_surface* surf, const Vector2D& local) {
+ if (state.pointerFocus == surf)
+ return;
+
+ if (!mouse || !mouse->wlr()) {
+ Debug::log(ERR, "BUG THIS: setPointerFocus without a valid mouse set");
+ return;
+ }
+
+ hyprListener_pointerSurfaceDestroy.removeCallback();
+
+ if (state.pointerFocusResource) {
+ for (auto& p : state.pointerFocusResource->pointers) {
+ if (!p)
+ continue;
+
+ p->sendLeave();
+ }
+ }
+
+ state.pointerFocusResource.reset();
+ state.pointerFocus = surf;
+
+ if (!surf) {
+ events.pointerFocusChange.emit();
+ return;
+ }
+
+ auto client = wl_resource_get_client(surf->resource);
+ for (auto& r : seatResources) {
+ if (r->resource->client() == client) {
+ state.pointerFocusResource = r->resource;
+ for (auto& p : state.pointerFocusResource->pointers) {
+ if (!p)
+ continue;
+
+ p->sendEnter(surf, local);
+ }
+
+ break;
+ }
+ }
+
+ hyprListener_pointerSurfaceDestroy.initCallback(
+ &surf->events.destroy, [this](void* owner, void* data) { setPointerFocus(nullptr, {}); }, nullptr, "CSeatManager");
+
+ events.pointerFocusChange.emit();
+}
+
+void CSeatManager::sendPointerMotion(uint32_t timeMs, const Vector2D& local) {
+ if (!state.pointerFocusResource)
+ return;
+
+ for (auto& p : state.pointerFocusResource->pointers) {
+ if (!p)
+ continue;
+
+ p->sendMotion(timeMs, local);
+ }
+}
+
+void CSeatManager::sendPointerButton(uint32_t timeMs, uint32_t key, wl_pointer_button_state state_) {
+ if (!state.pointerFocusResource)
+ return;
+
+ for (auto& p : state.pointerFocusResource->pointers) {
+ if (!p)
+ continue;
+
+ p->sendButton(timeMs, key, state_);
+ }
+}
+
+void CSeatManager::sendPointerFrame() {
+ if (!state.pointerFocusResource)
+ return;
+
+ for (auto& p : state.pointerFocusResource->pointers) {
+ if (!p)
+ continue;
+
+ p->sendFrame();
+ }
+}
+
+void CSeatManager::sendPointerAxis(uint32_t timeMs, wl_pointer_axis axis, double value, int32_t discrete, wl_pointer_axis_source source,
+ wl_pointer_axis_relative_direction relative) {
+ if (!state.pointerFocusResource)
+ return;
+
+ for (auto& p : state.pointerFocusResource->pointers) {
+ if (!p)
+ continue;
+
+ p->sendAxis(timeMs, axis, value);
+ p->sendAxisSource(source);
+ p->sendAxisRelativeDirection(axis, relative);
+ }
+}
+
+void CSeatManager::sendTouchDown(wlr_surface* surf, uint32_t timeMs, int32_t id, const Vector2D& local) {
+ if (state.touchFocus == surf)
+ return;
+
+ hyprListener_touchSurfaceDestroy.removeCallback();
+
+ if (state.touchFocusResource) {
+ for (auto& t : state.touchFocusResource->touches) {
+ if (!t)
+ continue;
+
+ t->sendUp(timeMs, id);
+ }
+ }
+
+ state.touchFocusResource.reset();
+ state.touchFocus = surf;
+
+ if (!surf) {
+ events.touchFocusChange.emit();
+ return;
+ }
+
+ auto client = wl_resource_get_client(surf->resource);
+ for (auto& r : seatResources) {
+ if (r->resource->client() == client) {
+ state.touchFocusResource = r->resource;
+ for (auto& t : state.touchFocusResource->touches) {
+ if (!t)
+ continue;
+
+ t->sendDown(surf, timeMs, id, local);
+ }
+
+ break;
+ }
+ }
+
+ hyprListener_touchSurfaceDestroy.initCallback(
+ &surf->events.destroy, [this, timeMs, id](void* owner, void* data) { sendTouchUp(timeMs + 10, id); }, nullptr, "CSeatManager");
+
+ events.touchFocusChange.emit();
+}
+
+void CSeatManager::sendTouchUp(uint32_t timeMs, int32_t id) {
+ sendTouchDown(nullptr, timeMs, id, {});
+}
+
+void CSeatManager::sendTouchMotion(uint32_t timeMs, int32_t id, const Vector2D& local) {
+ if (!state.touchFocusResource)
+ return;
+
+ for (auto& t : state.touchFocusResource->touches) {
+ if (!t)
+ continue;
+
+ t->sendMotion(timeMs, id, local);
+ }
+}
+
+void CSeatManager::sendTouchFrame() {
+ if (!state.touchFocusResource)
+ return;
+
+ for (auto& t : state.touchFocusResource->touches) {
+ if (!t)
+ continue;
+
+ t->sendFrame();
+ }
+}
+
+void CSeatManager::sendTouchCancel() {
+ if (!state.touchFocusResource)
+ return;
+
+ for (auto& t : state.touchFocusResource->touches) {
+ if (!t)
+ continue;
+
+ t->sendCancel();
+ }
+}
+
+void CSeatManager::sendTouchShape(int32_t id, const Vector2D& shape) {
+ if (!state.touchFocusResource)
+ return;
+
+ for (auto& t : state.touchFocusResource->touches) {
+ if (!t)
+ continue;
+
+ t->sendShape(id, shape);
+ }
+}
+
+void CSeatManager::sendTouchOrientation(int32_t id, double angle) {
+ if (!state.touchFocusResource)
+ return;
+
+ for (auto& t : state.touchFocusResource->touches) {
+ if (!t)
+ continue;
+
+ t->sendOrientation(id, angle);
+ }
+}
+
+void CSeatManager::onSetCursor(SP<CWLSeatResource> seatResource, uint32_t serial, wlr_surface* 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;
+ }
+
+ // TODO: fix this. Probably should be done in the CWlPointer as the serial could be lost by us.
+ // if (!serialValid(seatResource, serial)) {
+ // Debug::log(LOG, "[seatmgr] Rejecting a setCursor because the serial is invalid");
+ // return;
+ // }
+
+ events.setCursor.emit(SSetCursorEvent{surf, hotspot});
+}
+
+SP<CWLSeatResource> CSeatManager::seatResourceForClient(wl_client* client) {
+ return PROTO::seat->seatResourceForClient(client);
+}