From 121d3a72137d4780602cf245704615f63357ea22 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 10 May 2024 18:27:57 +0100 Subject: wl_seat: move to hyprland impl --- src/managers/SeatManager.cpp | 391 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 391 insertions(+) create mode 100644 src/managers/SeatManager.cpp (limited to 'src/managers/SeatManager.cpp') 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 + +CSeatManager::CSeatManager() { + listeners.newSeatResource = PROTO::seat->events.newSeatResource.registerListener([this](std::any res) { onNewSeatResource(std::any_cast>(res)); }); +} + +CSeatManager::SSeatResourceContainer::SSeatResourceContainer(SP 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 resource) { + seatResources.emplace_back(makeShared(resource)); +} + +SP CSeatManager::containerForResource(SP seatResource) { + for (auto& c : seatResources) { + if (c->resource == seatResource) + return c; + } + + return nullptr; +} + +uint32_t CSeatManager::nextSerial(SP 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 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 MAUZ) { + if (mouse == MAUZ) + return; + + mouse = MAUZ; +} + +void CSeatManager::setKeyboard(SP 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 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 CSeatManager::seatResourceForClient(wl_client* client) { + return PROTO::seat->seatResourceForClient(client); +} -- cgit v1.2.3