diff options
| author | Vaxry <vaxry@vaxry.net> | 2024-05-10 18:27:57 +0100 |
|---|---|---|
| committer | Vaxry <43317083+vaxerski@users.noreply.github.com> | 2024-05-14 23:02:24 +0100 |
| commit | 121d3a72137d4780602cf245704615f63357ea22 (patch) | |
| tree | b25c8a3ee7b239006281f0e00110d1c324b8cedc /src/managers/SeatManager.cpp | |
| parent | 4cdddcfe466cb21db81af0ac39e51cc15f574da9 (diff) | |
wl_seat: move to hyprland impl
Diffstat (limited to 'src/managers/SeatManager.cpp')
| -rw-r--r-- | src/managers/SeatManager.cpp | 391 |
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); +} |
