diff options
author | Vaxry <[email protected]> | 2024-05-10 18:27:57 +0100 |
---|---|---|
committer | Vaxry <[email protected]> | 2024-05-14 15:28:41 +0100 |
commit | 44da1b75f03b2042a9923f3657e2fcd2bc3a1045 (patch) | |
tree | 9f2c1a6f4f8c5caaf7cd3e30be0ea9dd84242422 /src/protocols | |
parent | 47874f09f4d14703fe0c483a46b345c7be601ace (diff) | |
download | Hyprland-44da1b75f03b2042a9923f3657e2fcd2bc3a1045.tar.gz Hyprland-44da1b75f03b2042a9923f3657e2fcd2bc3a1045.zip |
wl_seat: move to hyprland impl
Diffstat (limited to 'src/protocols')
-rw-r--r-- | src/protocols/FocusGrab.cpp | 291 | ||||
-rw-r--r-- | src/protocols/FocusGrab.hpp | 8 | ||||
-rw-r--r-- | src/protocols/InputMethodV2.cpp | 12 | ||||
-rw-r--r-- | src/protocols/PointerConstraints.cpp | 5 | ||||
-rw-r--r-- | src/protocols/PointerGestures.cpp | 52 | ||||
-rw-r--r-- | src/protocols/RelativePointer.cpp | 8 | ||||
-rw-r--r-- | src/protocols/SessionLock.cpp | 3 | ||||
-rw-r--r-- | src/protocols/Tablet.cpp | 20 | ||||
-rw-r--r-- | src/protocols/core/Seat.cpp | 437 | ||||
-rw-r--r-- | src/protocols/core/Seat.hpp | 163 |
10 files changed, 803 insertions, 196 deletions
diff --git a/src/protocols/FocusGrab.cpp b/src/protocols/FocusGrab.cpp index 1ab4d4a6..4189ed6e 100644 --- a/src/protocols/FocusGrab.cpp +++ b/src/protocols/FocusGrab.cpp @@ -1,124 +1,125 @@ #include "FocusGrab.hpp" #include "Compositor.hpp" #include <hyprland-focus-grab-v1.hpp> -#include <managers/input/InputManager.hpp> +#include "../managers/input/InputManager.hpp" +#include "../managers/SeatManager.hpp" #include <cstdint> #include <memory> #include <wayland-server.h> -static void focus_grab_pointer_enter(wlr_seat_pointer_grab* grab, wlr_surface* surface, double sx, double sy) { - if (static_cast<CFocusGrab*>(grab->data)->isSurfaceComitted(surface)) - wlr_seat_pointer_enter(grab->seat, surface, sx, sy); - else - wlr_seat_pointer_clear_focus(grab->seat); -} - -static void focus_grab_pointer_clear_focus(wlr_seat_pointer_grab* grab) { - wlr_seat_pointer_clear_focus(grab->seat); -} - -static void focus_grab_pointer_motion(wlr_seat_pointer_grab* grab, uint32_t time, double sx, double sy) { - wlr_seat_pointer_send_motion(grab->seat, time, sx, sy); -} - -static uint32_t focus_grab_pointer_button(wlr_seat_pointer_grab* grab, uint32_t time, uint32_t button, wl_pointer_button_state state) { - uint32_t serial = wlr_seat_pointer_send_button(grab->seat, time, button, state); - - if (serial) - return serial; - else { - static_cast<CFocusGrab*>(grab->data)->finish(true); - return 0; - } -} - -static void focus_grab_pointer_axis(wlr_seat_pointer_grab* grab, uint32_t time, enum wl_pointer_axis orientation, double value, int32_t value_discrete, - enum wl_pointer_axis_source source, enum wl_pointer_axis_relative_direction relative_direction) { - wlr_seat_pointer_send_axis(grab->seat, time, orientation, value, value_discrete, source, relative_direction); -} - -static void focus_grab_pointer_frame(wlr_seat_pointer_grab* grab) { - wlr_seat_pointer_send_frame(grab->seat); -} - -static void focus_grab_pointer_cancel(wlr_seat_pointer_grab* grab) { - static_cast<CFocusGrab*>(grab->data)->finish(true); -} - -static const wlr_pointer_grab_interface focus_grab_pointer_impl = { - .enter = focus_grab_pointer_enter, - .clear_focus = focus_grab_pointer_clear_focus, - .motion = focus_grab_pointer_motion, - .button = focus_grab_pointer_button, - .axis = focus_grab_pointer_axis, - .frame = focus_grab_pointer_frame, - .cancel = focus_grab_pointer_cancel, -}; - -static void focus_grab_keyboard_enter(wlr_seat_keyboard_grab* grab, wlr_surface* surface, const uint32_t keycodes[], size_t num_keycodes, const wlr_keyboard_modifiers* modifiers) { - if (static_cast<CFocusGrab*>(grab->data)->isSurfaceComitted(surface)) - wlr_seat_keyboard_enter(grab->seat, surface, keycodes, num_keycodes, modifiers); - - // otherwise the last grabbed window should retain keyboard focus. -} - -static void focus_grab_keyboard_clear_focus(wlr_seat_keyboard_grab* grab) { - static_cast<CFocusGrab*>(grab->data)->finish(true); -} - -static void focus_grab_keyboard_key(wlr_seat_keyboard_grab* grab, uint32_t time, uint32_t key, uint32_t state) { - wlr_seat_keyboard_send_key(grab->seat, time, key, state); -} - -static void focus_grab_keyboard_modifiers(wlr_seat_keyboard_grab* grab, const wlr_keyboard_modifiers* modifiers) { - wlr_seat_keyboard_send_modifiers(grab->seat, modifiers); -} - -static void focus_grab_keyboard_cancel(wlr_seat_keyboard_grab* grab) { - static_cast<CFocusGrab*>(grab->data)->finish(true); -} - -static const wlr_keyboard_grab_interface focus_grab_keyboard_impl = { - .enter = focus_grab_keyboard_enter, - .clear_focus = focus_grab_keyboard_clear_focus, - .key = focus_grab_keyboard_key, - .modifiers = focus_grab_keyboard_modifiers, - .cancel = focus_grab_keyboard_cancel, -}; - -static uint32_t focus_grab_touch_down(wlr_seat_touch_grab* grab, uint32_t time, wlr_touch_point* point) { - if (!static_cast<CFocusGrab*>(grab->data)->isSurfaceComitted(point->surface)) - return 0; - - return wlr_seat_touch_send_down(grab->seat, point->surface, time, point->touch_id, point->sx, point->sy); -} - -static void focus_grab_touch_up(wlr_seat_touch_grab* grab, uint32_t time, wlr_touch_point* point) { - wlr_seat_touch_send_up(grab->seat, time, point->touch_id); -} - -static void focus_grab_touch_motion(wlr_seat_touch_grab* grab, uint32_t time, wlr_touch_point* point) { - wlr_seat_touch_send_motion(grab->seat, time, point->touch_id, point->sx, point->sy); -} - -static void focus_grab_touch_enter(wlr_seat_touch_grab* grab, uint32_t time, wlr_touch_point* point) {} - -static void focus_grab_touch_frame(wlr_seat_touch_grab* grab) { - wlr_seat_touch_send_frame(grab->seat); -} - -static void focus_grab_touch_cancel(wlr_seat_touch_grab* grab) { - static_cast<CFocusGrab*>(grab->data)->finish(true); -} - -static const wlr_touch_grab_interface focus_grab_touch_impl = { - .down = focus_grab_touch_down, - .up = focus_grab_touch_up, - .motion = focus_grab_touch_motion, - .enter = focus_grab_touch_enter, - .frame = focus_grab_touch_frame, - .cancel = focus_grab_touch_cancel, -}; +// static void focus_grab_pointer_enter(wlr_seat_pointer_grab* grab, wlr_surface* surface, double sx, double sy) { +// if (static_cast<CFocusGrab*>(grab->data)->isSurfaceComitted(surface)) +// wlr_seat_pointer_enter(grab->seat, surface, sx, sy); +// else +// wlr_seat_pointer_clear_focus(grab->seat); +// } + +// static void focus_grab_pointer_clear_focus(wlr_seat_pointer_grab* grab) { +// wlr_seat_pointer_clear_focus(grab->seat); +// } + +// static void focus_grab_pointer_motion(wlr_seat_pointer_grab* grab, uint32_t time, double sx, double sy) { +// wlr_seat_pointer_send_motion(grab->seat, time, sx, sy); +// } + +// static uint32_t focus_grab_pointer_button(wlr_seat_pointer_grab* grab, uint32_t time, uint32_t button, wl_pointer_button_state state) { +// uint32_t serial = wlr_seat_pointer_send_button(grab->seat, time, button, state); + +// if (serial) +// return serial; +// else { +// static_cast<CFocusGrab*>(grab->data)->finish(true); +// return 0; +// } +// } + +// static void focus_grab_pointer_axis(wlr_seat_pointer_grab* grab, uint32_t time, enum wl_pointer_axis orientation, double value, int32_t value_discrete, +// enum wl_pointer_axis_source source, enum wl_pointer_axis_relative_direction relative_direction) { +// wlr_seat_pointer_send_axis(grab->seat, time, orientation, value, value_discrete, source, relative_direction); +// } + +// static void focus_grab_pointer_frame(wlr_seat_pointer_grab* grab) { +// wlr_seat_pointer_send_frame(grab->seat); +// } + +// static void focus_grab_pointer_cancel(wlr_seat_pointer_grab* grab) { +// static_cast<CFocusGrab*>(grab->data)->finish(true); +// } + +// static const wlr_pointer_grab_interface focus_grab_pointer_impl = { +// .enter = focus_grab_pointer_enter, +// .clear_focus = focus_grab_pointer_clear_focus, +// .motion = focus_grab_pointer_motion, +// .button = focus_grab_pointer_button, +// .axis = focus_grab_pointer_axis, +// .frame = focus_grab_pointer_frame, +// .cancel = focus_grab_pointer_cancel, +// }; + +// static void focus_grab_keyboard_enter(wlr_seat_keyboard_grab* grab, wlr_surface* surface, const uint32_t keycodes[], size_t num_keycodes, const wlr_keyboard_modifiers* modifiers) { +// if (static_cast<CFocusGrab*>(grab->data)->isSurfaceComitted(surface)) +// wlr_seat_keyboard_enter(grab->seat, surface, keycodes, num_keycodes, modifiers); + +// // otherwise the last grabbed window should retain keyboard focus. +// } + +// static void focus_grab_keyboard_clear_focus(wlr_seat_keyboard_grab* grab) { +// static_cast<CFocusGrab*>(grab->data)->finish(true); +// } + +// static void focus_grab_keyboard_key(wlr_seat_keyboard_grab* grab, uint32_t time, uint32_t key, uint32_t state) { +// wlr_seat_keyboard_send_key(grab->seat, time, key, state); +// } + +// static void focus_grab_keyboard_modifiers(wlr_seat_keyboard_grab* grab, const wlr_keyboard_modifiers* modifiers) { +// wlr_seat_keyboard_send_modifiers(grab->seat, modifiers); +// } + +// static void focus_grab_keyboard_cancel(wlr_seat_keyboard_grab* grab) { +// static_cast<CFocusGrab*>(grab->data)->finish(true); +// } + +// static const wlr_keyboard_grab_interface focus_grab_keyboard_impl = { +// .enter = focus_grab_keyboard_enter, +// .clear_focus = focus_grab_keyboard_clear_focus, +// .key = focus_grab_keyboard_key, +// .modifiers = focus_grab_keyboard_modifiers, +// .cancel = focus_grab_keyboard_cancel, +// }; + +// static uint32_t focus_grab_touch_down(wlr_seat_touch_grab* grab, uint32_t time, wlr_touch_point* point) { +// if (!static_cast<CFocusGrab*>(grab->data)->isSurfaceComitted(point->surface)) +// return 0; + +// return wlr_seat_touch_send_down(grab->seat, point->surface, time, point->touch_id, point->sx, point->sy); +// } + +// static void focus_grab_touch_up(wlr_seat_touch_grab* grab, uint32_t time, wlr_touch_point* point) { +// wlr_seat_touch_send_up(grab->seat, time, point->touch_id); +// } + +// static void focus_grab_touch_motion(wlr_seat_touch_grab* grab, uint32_t time, wlr_touch_point* point) { +// wlr_seat_touch_send_motion(grab->seat, time, point->touch_id, point->sx, point->sy); +// } + +// static void focus_grab_touch_enter(wlr_seat_touch_grab* grab, uint32_t time, wlr_touch_point* point) {} + +// static void focus_grab_touch_frame(wlr_seat_touch_grab* grab) { +// wlr_seat_touch_send_frame(grab->seat); +// } + +// static void focus_grab_touch_cancel(wlr_seat_touch_grab* grab) { +// static_cast<CFocusGrab*>(grab->data)->finish(true); +// } + +// static const wlr_touch_grab_interface focus_grab_touch_impl = { +// .down = focus_grab_touch_down, +// .up = focus_grab_touch_up, +// .motion = focus_grab_touch_motion, +// .enter = focus_grab_touch_enter, +// .frame = focus_grab_touch_frame, +// .cancel = focus_grab_touch_cancel, +// }; CFocusGrabSurfaceState::CFocusGrabSurfaceState(CFocusGrab* grab, wlr_surface* surface) { hyprListener_surfaceDestroy.initCallback( @@ -133,14 +134,14 @@ CFocusGrab::CFocusGrab(SP<CHyprlandFocusGrabV1> resource_) : resource(resource_) if (!resource->resource()) return; - m_sPointerGrab.interface = &focus_grab_pointer_impl; - m_sPointerGrab.data = this; + // m_sPointerGrab.interface = &focus_grab_pointer_impl; + // m_sPointerGrab.data = this; - m_sKeyboardGrab.interface = &focus_grab_keyboard_impl; - m_sKeyboardGrab.data = this; + // m_sKeyboardGrab.interface = &focus_grab_keyboard_impl; + // m_sKeyboardGrab.data = this; - m_sTouchGrab.interface = &focus_grab_touch_impl; - m_sTouchGrab.data = this; + // m_sTouchGrab.interface = &focus_grab_touch_impl; + // m_sTouchGrab.data = this; resource->setDestroy([this](CHyprlandFocusGrabV1* pMgr) { PROTO::focusGrab->destroyGrab(this); }); resource->setOnDestroy([this](CHyprlandFocusGrabV1* pMgr) { PROTO::focusGrab->destroyGrab(this); }); @@ -167,21 +168,21 @@ bool CFocusGrab::isSurfaceComitted(wlr_surface* surface) { void CFocusGrab::start() { if (!m_bGrabActive) { - wlr_seat_pointer_start_grab(g_pCompositor->m_sSeat.seat, &m_sPointerGrab); - wlr_seat_keyboard_start_grab(g_pCompositor->m_sSeat.seat, &m_sKeyboardGrab); - wlr_seat_touch_start_grab(g_pCompositor->m_sSeat.seat, &m_sTouchGrab); + // wlr_seat_pointer_start_grab(g_pCompositor->m_sSeat.seat, &m_sPointerGrab); + // wlr_seat_keyboard_start_grab(g_pCompositor->m_sSeat.seat, &m_sKeyboardGrab); + // wlr_seat_touch_start_grab(g_pCompositor->m_sSeat.seat, &m_sTouchGrab); m_bGrabActive = true; // Ensure the grab ends if another grab begins, including from xdg_popup::grab. - hyprListener_pointerGrabStarted.initCallback( - &g_pCompositor->m_sSeat.seat->events.pointer_grab_begin, [this](void*, void*) { finish(true); }, this, "CFocusGrab"); + // hyprListener_pointerGrabStarted.initCallback( + // &g_pCompositor->m_sSeat.seat->events.pointer_grab_begin, [this](void*, void*) { finish(true); }, this, "CFocusGrab"); - hyprListener_keyboardGrabStarted.initCallback( - &g_pCompositor->m_sSeat.seat->events.keyboard_grab_begin, [this](void*, void*) { finish(true); }, this, "CFocusGrab"); + // hyprListener_keyboardGrabStarted.initCallback( + // &g_pCompositor->m_sSeat.seat->events.keyboard_grab_begin, [this](void*, void*) { finish(true); }, this, "CFocusGrab"); - hyprListener_touchGrabStarted.initCallback( - &g_pCompositor->m_sSeat.seat->events.touch_grab_begin, [this](void*, void*) { finish(true); }, this, "CFocusGrab"); + // hyprListener_touchGrabStarted.initCallback( + // &g_pCompositor->m_sSeat.seat->events.touch_grab_begin, [this](void*, void*) { finish(true); }, this, "CFocusGrab"); } // Ensure new surfaces are focused if under the mouse when comitted. @@ -192,28 +193,28 @@ void CFocusGrab::start() { void CFocusGrab::finish(bool sendCleared) { if (m_bGrabActive) { m_bGrabActive = false; - hyprListener_pointerGrabStarted.removeCallback(); - hyprListener_keyboardGrabStarted.removeCallback(); - hyprListener_touchGrabStarted.removeCallback(); + // hyprListener_pointerGrabStarted.removeCallback(); + // hyprListener_keyboardGrabStarted.removeCallback(); + // hyprListener_touchGrabStarted.removeCallback(); // Only clear grabs that belong to this focus grab. When superseded by another grab // or xdg_popup grab we might not own the current grab. bool hadGrab = false; - if (g_pCompositor->m_sSeat.seat->pointer_state.grab == &m_sPointerGrab) { - wlr_seat_pointer_end_grab(g_pCompositor->m_sSeat.seat); - hadGrab = true; - } + // if (g_pCompositor->m_sSeat.seat->pointer_state.grab == &m_sPointerGrab) { + // wlr_seat_pointer_end_grab(g_pCompositor->m_sSeat.seat); + // hadGrab = true; + // } - if (g_pCompositor->m_sSeat.seat->keyboard_state.grab == &m_sKeyboardGrab) { - wlr_seat_keyboard_end_grab(g_pCompositor->m_sSeat.seat); - hadGrab = true; - } + // if (g_pCompositor->m_sSeat.seat->keyboard_state.grab == &m_sKeyboardGrab) { + // wlr_seat_keyboard_end_grab(g_pCompositor->m_sSeat.seat); + // hadGrab = true; + // } - if (g_pCompositor->m_sSeat.seat->touch_state.grab == &m_sTouchGrab) { - wlr_seat_touch_end_grab(g_pCompositor->m_sSeat.seat); - hadGrab = true; - } + // if (g_pCompositor->m_sSeat.seat->touch_state.grab == &m_sTouchGrab) { + // wlr_seat_touch_end_grab(g_pCompositor->m_sSeat.seat); + // hadGrab = true; + // } m_mSurfaces.clear(); @@ -248,7 +249,7 @@ void CFocusGrab::eraseSurface(wlr_surface* surface) { } void CFocusGrab::refocusKeyboard() { - auto keyboardSurface = g_pCompositor->m_sSeat.seat->keyboard_state.focused_surface; + auto keyboardSurface = g_pSeatManager->state.keyboardFocus; if (keyboardSurface != nullptr && isSurfaceComitted(keyboardSurface)) return; diff --git a/src/protocols/FocusGrab.hpp b/src/protocols/FocusGrab.hpp index 11c26774..3e5d36ab 100644 --- a/src/protocols/FocusGrab.hpp +++ b/src/protocols/FocusGrab.hpp @@ -44,10 +44,10 @@ class CFocusGrab { SP<CHyprlandFocusGrabV1> resource; std::unordered_map<wlr_surface*, UP<CFocusGrabSurfaceState>> m_mSurfaces; - wlr_seat_pointer_grab m_sPointerGrab; - wlr_seat_keyboard_grab m_sKeyboardGrab; - wlr_seat_touch_grab m_sTouchGrab; - bool m_bGrabActive = false; + // wlr_seat_pointer_grab m_sPointerGrab; + // wlr_seat_keyboard_grab m_sKeyboardGrab; + // wlr_seat_touch_grab m_sTouchGrab; + bool m_bGrabActive = false; DYNLISTENER(pointerGrabStarted); DYNLISTENER(keyboardGrabStarted); diff --git a/src/protocols/InputMethodV2.cpp b/src/protocols/InputMethodV2.cpp index d84f6772..66d4773c 100644 --- a/src/protocols/InputMethodV2.cpp +++ b/src/protocols/InputMethodV2.cpp @@ -1,5 +1,7 @@ #include "InputMethodV2.hpp" #include "../Compositor.hpp" +#include "../managers/SeatManager.hpp" +#include "../devices/IKeyboard.hpp" #include <sys/mman.h> #define LOGM PROTO::ime->protoLog @@ -11,14 +13,12 @@ CInputMethodKeyboardGrabV2::CInputMethodKeyboardGrabV2(SP<CZwpInputMethodKeyboar resource->setRelease([this](CZwpInputMethodKeyboardGrabV2* r) { PROTO::ime->destroyResource(this); }); resource->setOnDestroy([this](CZwpInputMethodKeyboardGrabV2* r) { PROTO::ime->destroyResource(this); }); - const auto PKEYBOARD = wlr_seat_get_keyboard(g_pCompositor->m_sSeat.seat); - - if (!PKEYBOARD) { + if (!g_pSeatManager->keyboard) { LOGM(ERR, "IME called but no active keyboard???"); return; } - sendKeyboardData(PKEYBOARD); + sendKeyboardData(g_pSeatManager->keyboard->wlr()); } CInputMethodKeyboardGrabV2::~CInputMethodKeyboardGrabV2() { @@ -59,13 +59,13 @@ void CInputMethodKeyboardGrabV2::sendKeyboardData(wlr_keyboard* keyboard) { } void CInputMethodKeyboardGrabV2::sendKey(uint32_t time, uint32_t key, wl_keyboard_key_state state) { - const auto SERIAL = wlr_seat_client_next_serial(wlr_seat_client_for_wl_client(g_pCompositor->m_sSeat.seat, resource->client())); + const auto SERIAL = g_pSeatManager->nextSerial(g_pSeatManager->seatResourceForClient(resource->client())); resource->sendKey(SERIAL, time, key, (uint32_t)state); } void CInputMethodKeyboardGrabV2::sendMods(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) { - const auto SERIAL = wlr_seat_client_next_serial(wlr_seat_client_for_wl_client(g_pCompositor->m_sSeat.seat, resource->client())); + const auto SERIAL = g_pSeatManager->nextSerial(g_pSeatManager->seatResourceForClient(resource->client())); resource->sendModifiers(SERIAL, depressed, latched, locked, group); } diff --git a/src/protocols/PointerConstraints.cpp b/src/protocols/PointerConstraints.cpp index 7b5729c0..87abdcdd 100644 --- a/src/protocols/PointerConstraints.cpp +++ b/src/protocols/PointerConstraints.cpp @@ -2,6 +2,7 @@ #include "../desktop/WLSurface.hpp" #include "../Compositor.hpp" #include "../config/ConfigValue.hpp" +#include "../managers/SeatManager.hpp" #define LOGM PROTO::constraints->protoLog @@ -125,10 +126,10 @@ void CPointerConstraint::activate() { return; // TODO: hack, probably not a super duper great idea - if (g_pCompositor->m_sSeat.seat->pointer_state.focused_surface != pHLSurface->wlr()) { + if (g_pSeatManager->state.pointerFocus != pHLSurface->wlr()) { const auto SURFBOX = pHLSurface->getSurfaceBoxGlobal(); const auto LOCAL = SURFBOX.has_value() ? logicPositionHint() - SURFBOX->pos() : Vector2D{}; - wlr_seat_pointer_enter(g_pCompositor->m_sSeat.seat, pHLSurface->wlr(), LOCAL.x, LOCAL.y); + g_pSeatManager->setPointerFocus(pHLSurface->wlr(), LOCAL); } if (locked) diff --git a/src/protocols/PointerGestures.cpp b/src/protocols/PointerGestures.cpp index 5b5d1c52..2bfd74da 100644 --- a/src/protocols/PointerGestures.cpp +++ b/src/protocols/PointerGestures.cpp @@ -1,5 +1,7 @@ #include "PointerGestures.hpp" #include "../Compositor.hpp" +#include "../managers/SeatManager.hpp" +#include "core/Seat.hpp" #define LOGM PROTO::pointerGestures->protoLog @@ -103,26 +105,26 @@ void CPointerGesturesProtocol::onGetHoldGesture(CZwpPointerGesturesV1* pMgr, uin } void CPointerGesturesProtocol::swipeBegin(uint32_t timeMs, uint32_t fingers) { - if (!g_pCompositor->m_sSeat.seat->pointer_state.focused_client) + if (!g_pSeatManager->state.pointerFocusResource) return; - const auto FOCUSEDCLIENT = g_pCompositor->m_sSeat.seat->pointer_state.focused_client->client; + const auto FOCUSEDCLIENT = g_pSeatManager->state.pointerFocusResource->client(); - const auto SERIAL = wlr_seat_client_next_serial(g_pCompositor->m_sSeat.seat->pointer_state.focused_client); + const auto SERIAL = g_pSeatManager->nextSerial(g_pSeatManager->state.pointerFocusResource.lock()); for (auto& sw : m_vSwipes) { if (sw->resource->client() != FOCUSEDCLIENT) continue; - sw->resource->sendBegin(SERIAL, timeMs, g_pCompositor->m_sSeat.seat->pointer_state.focused_surface->resource, fingers); + sw->resource->sendBegin(SERIAL, timeMs, g_pSeatManager->state.pointerFocus->resource, fingers); } } void CPointerGesturesProtocol::swipeUpdate(uint32_t timeMs, const Vector2D& delta) { - if (!g_pCompositor->m_sSeat.seat->pointer_state.focused_client) + if (!g_pSeatManager->state.pointerFocusResource) return; - const auto FOCUSEDCLIENT = g_pCompositor->m_sSeat.seat->pointer_state.focused_client->client; + const auto FOCUSEDCLIENT = g_pSeatManager->state.pointerFocusResource->client(); for (auto& sw : m_vSwipes) { if (sw->resource->client() != FOCUSEDCLIENT) @@ -133,12 +135,12 @@ void CPointerGesturesProtocol::swipeUpdate(uint32_t timeMs, const Vector2D& delt } void CPointerGesturesProtocol::swipeEnd(uint32_t timeMs, bool cancelled) { - if (!g_pCompositor->m_sSeat.seat->pointer_state.focused_client) + if (!g_pSeatManager->state.pointerFocusResource) return; - const auto FOCUSEDCLIENT = g_pCompositor->m_sSeat.seat->pointer_state.focused_client->client; + const auto FOCUSEDCLIENT = g_pSeatManager->state.pointerFocusResource->client(); - const auto SERIAL = wlr_seat_client_next_serial(g_pCompositor->m_sSeat.seat->pointer_state.focused_client); + const auto SERIAL = g_pSeatManager->nextSerial(g_pSeatManager->state.pointerFocusResource.lock()); for (auto& sw : m_vSwipes) { if (sw->resource->client() != FOCUSEDCLIENT) @@ -149,26 +151,26 @@ void CPointerGesturesProtocol::swipeEnd(uint32_t timeMs, bool cancelled) { } void CPointerGesturesProtocol::pinchBegin(uint32_t timeMs, uint32_t fingers) { - if (!g_pCompositor->m_sSeat.seat->pointer_state.focused_client) + if (!g_pSeatManager->state.pointerFocusResource) return; - const auto FOCUSEDCLIENT = g_pCompositor->m_sSeat.seat->pointer_state.focused_client->client; + const auto FOCUSEDCLIENT = g_pSeatManager->state.pointerFocusResource->client(); - const auto SERIAL = wlr_seat_client_next_serial(g_pCompositor->m_sSeat.seat->pointer_state.focused_client); + const auto SERIAL = g_pSeatManager->nextSerial(g_pSeatManager->state.pointerFocusResource.lock()); for (auto& sw : m_vPinches) { if (sw->resource->client() != FOCUSEDCLIENT) continue; - sw->resource->sendBegin(SERIAL, timeMs, g_pCompositor->m_sSeat.seat->pointer_state.focused_surface->resource, fingers); + sw->resource->sendBegin(SERIAL, timeMs, g_pSeatManager->state.pointerFocus->resource, fingers); } } void CPointerGesturesProtocol::pinchUpdate(uint32_t timeMs, const Vector2D& delta, double scale, double rotation) { - if (!g_pCompositor->m_sSeat.seat->pointer_state.focused_client) + if (!g_pSeatManager->state.pointerFocusResource) return; - const auto FOCUSEDCLIENT = g_pCompositor->m_sSeat.seat->pointer_state.focused_client->client; + const auto FOCUSEDCLIENT = g_pSeatManager->state.pointerFocusResource->client(); for (auto& sw : m_vPinches) { if (sw->resource->client() != FOCUSEDCLIENT) @@ -179,12 +181,12 @@ void CPointerGesturesProtocol::pinchUpdate(uint32_t timeMs, const Vector2D& delt } void CPointerGesturesProtocol::pinchEnd(uint32_t timeMs, bool cancelled) { - if (!g_pCompositor->m_sSeat.seat->pointer_state.focused_client) + if (!g_pSeatManager->state.pointerFocusResource) return; - const auto FOCUSEDCLIENT = g_pCompositor->m_sSeat.seat->pointer_state.focused_client->client; + const auto FOCUSEDCLIENT = g_pSeatManager->state.pointerFocusResource->client(); - const auto SERIAL = wlr_seat_client_next_serial(g_pCompositor->m_sSeat.seat->pointer_state.focused_client); + const auto SERIAL = g_pSeatManager->nextSerial(g_pSeatManager->state.pointerFocusResource.lock()); for (auto& sw : m_vPinches) { if (sw->resource->client() != FOCUSEDCLIENT) @@ -195,28 +197,28 @@ void CPointerGesturesProtocol::pinchEnd(uint32_t timeMs, bool cancelled) { } void CPointerGesturesProtocol::holdBegin(uint32_t timeMs, uint32_t fingers) { - if (!g_pCompositor->m_sSeat.seat->pointer_state.focused_client) + if (!g_pSeatManager->state.pointerFocusResource) return; - const auto FOCUSEDCLIENT = g_pCompositor->m_sSeat.seat->pointer_state.focused_client->client; + const auto FOCUSEDCLIENT = g_pSeatManager->state.pointerFocusResource->client(); - const auto SERIAL = wlr_seat_client_next_serial(g_pCompositor->m_sSeat.seat->pointer_state.focused_client); + const auto SERIAL = g_pSeatManager->nextSerial(g_pSeatManager->state.pointerFocusResource.lock()); for (auto& sw : m_vHolds) { if (sw->resource->client() != FOCUSEDCLIENT) continue; - sw->resource->sendBegin(SERIAL, timeMs, g_pCompositor->m_sSeat.seat->pointer_state.focused_surface->resource, fingers); + sw->resource->sendBegin(SERIAL, timeMs, g_pSeatManager->state.pointerFocus->resource, fingers); } } void CPointerGesturesProtocol::holdEnd(uint32_t timeMs, bool cancelled) { - if (!g_pCompositor->m_sSeat.seat->pointer_state.focused_client) + if (!g_pSeatManager->state.pointerFocusResource) return; - const auto FOCUSEDCLIENT = g_pCompositor->m_sSeat.seat->pointer_state.focused_client->client; + const auto FOCUSEDCLIENT = g_pSeatManager->state.pointerFocusResource->client(); - const auto SERIAL = wlr_seat_client_next_serial(g_pCompositor->m_sSeat.seat->pointer_state.focused_client); + const auto SERIAL = g_pSeatManager->nextSerial(g_pSeatManager->state.pointerFocusResource.lock()); for (auto& sw : m_vHolds) { if (sw->resource->client() != FOCUSEDCLIENT) diff --git a/src/protocols/RelativePointer.cpp b/src/protocols/RelativePointer.cpp index c64687ee..e4818758 100644 --- a/src/protocols/RelativePointer.cpp +++ b/src/protocols/RelativePointer.cpp @@ -1,5 +1,7 @@ #include "RelativePointer.hpp" -#include "Compositor.hpp" +#include "../Compositor.hpp" +#include "../managers/SeatManager.hpp" +#include "core/Seat.hpp" #include <algorithm> CRelativePointer::CRelativePointer(SP<CZwpRelativePointerV1> resource_) : resource(resource_) { @@ -58,10 +60,10 @@ void CRelativePointerProtocol::onGetRelativePointer(CZwpRelativePointerManagerV1 void CRelativePointerProtocol::sendRelativeMotion(uint64_t time, const Vector2D& delta, const Vector2D& deltaUnaccel) { - if (!g_pCompositor->m_sSeat.seat->pointer_state.focused_client) + if (!g_pSeatManager->state.pointerFocusResource) return; - const auto FOCUSED = g_pCompositor->m_sSeat.seat->pointer_state.focused_client->client; + const auto FOCUSED = g_pSeatManager->state.pointerFocusResource->client(); for (auto& rp : m_vRelativePointers) { if (FOCUSED != rp->client()) diff --git a/src/protocols/SessionLock.cpp b/src/protocols/SessionLock.cpp index db3404be..fd803eda 100644 --- a/src/protocols/SessionLock.cpp +++ b/src/protocols/SessionLock.cpp @@ -1,5 +1,6 @@ #include "SessionLock.hpp" #include "../Compositor.hpp" +#include "../managers/SeatManager.hpp" #include "FractionalScale.hpp" #define LOGM PROTO::sessionLock->protoLog @@ -76,7 +77,7 @@ CSessionLockSurface::~CSessionLockSurface() { } void CSessionLockSurface::sendConfigure() { - const auto SERIAL = wlr_seat_client_next_serial(wlr_seat_client_for_wl_client(g_pCompositor->m_sSeat.seat, resource->client())); + const auto SERIAL = g_pSeatManager->nextSerial(g_pSeatManager->seatResourceForClient(resource->client())); resource->sendConfigure(SERIAL, pMonitor->vecSize.x, pMonitor->vecSize.y); } diff --git a/src/protocols/Tablet.cpp b/src/protocols/Tablet.cpp index b3ca76f5..7c54a116 100644 --- a/src/protocols/Tablet.cpp +++ b/src/protocols/Tablet.cpp @@ -1,6 +1,8 @@ #include "Tablet.hpp" #include "../devices/Tablet.hpp" #include "../Compositor.hpp" +#include "../managers/SeatManager.hpp" +#include "core/Seat.hpp" #include <algorithm> #define LOGM PROTO::tablet->protoLog @@ -159,12 +161,10 @@ CTabletToolV2Resource::CTabletToolV2Resource(SP<CZwpTabletToolV2> resource_, SP< resource->setOnDestroy([this](CZwpTabletToolV2* r) { PROTO::tablet->destroyResource(this); }); resource->setSetCursor([this](CZwpTabletToolV2* r, uint32_t serial, wl_resource* surf, int32_t hot_x, int32_t hot_y) { - wlr_seat_pointer_request_set_cursor_event e; - e.hotspot_x = hot_x; - e.hotspot_y = hot_y; - e.surface = surf ? wlr_surface_from_resource(surf) : nullptr; - e.serial = serial; - g_pInputManager->processMouseRequest(&e); + if (!g_pSeatManager->state.pointerFocusResource || g_pSeatManager->state.pointerFocusResource->client() != r->client()) + return; + + g_pInputManager->processMouseRequest(CSeatManager::SSetCursorEvent{wlr_surface_from_resource(surf), {hot_x, hot_y}}); }); } @@ -539,7 +539,7 @@ void CTabletV2Protocol::down(SP<CTabletTool> tool) { if (t->tool != tool || !t->current) continue; - auto serial = wlr_seat_client_next_serial(wlr_seat_client_for_wl_client(g_pCompositor->m_sSeat.seat, t->resource->client())); + auto serial = g_pSeatManager->nextSerial(g_pSeatManager->seatResourceForClient(t->resource->client())); t->resource->sendDown(serial); t->queueFrame(); } @@ -586,7 +586,7 @@ void CTabletV2Protocol::proximityIn(SP<CTabletTool> tool, SP<CTablet> tablet, wl toolResource->current = true; toolResource->lastSurf = surf; - auto serial = wlr_seat_client_next_serial(wlr_seat_client_for_wl_client(g_pCompositor->m_sSeat.seat, toolResource->resource->client())); + auto serial = g_pSeatManager->nextSerial(g_pSeatManager->seatResourceForClient(toolResource->resource->client())); toolResource->resource->sendProximityIn(serial, tabletResource->resource.get(), surf->resource); toolResource->queueFrame(); @@ -610,7 +610,7 @@ void CTabletV2Protocol::buttonTool(SP<CTabletTool> tool, uint32_t button, uint32 if (t->tool != tool || !t->current) continue; - auto serial = wlr_seat_client_next_serial(wlr_seat_client_for_wl_client(g_pCompositor->m_sSeat.seat, t->resource->client())); + auto serial = g_pSeatManager->nextSerial(g_pSeatManager->seatResourceForClient(t->resource->client())); t->resource->sendButton(serial, button, (zwpTabletToolV2ButtonState)state); t->queueFrame(); } @@ -634,7 +634,7 @@ void CTabletV2Protocol::mode(SP<CTabletPad> pad, uint32_t group, uint32_t mode, LOGM(ERR, "BUG THIS: group >= t->groups.size()"); return; } - auto serial = wlr_seat_client_next_serial(wlr_seat_client_for_wl_client(g_pCompositor->m_sSeat.seat, t->resource->client())); + auto serial = g_pSeatManager->nextSerial(g_pSeatManager->seatResourceForClient(t->resource->client())); t->groups.at(group)->resource->sendModeSwitch(timeMs, serial, mode); } } diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp new file mode 100644 index 00000000..489fced7 --- /dev/null +++ b/src/protocols/core/Seat.cpp @@ -0,0 +1,437 @@ +#include "Seat.hpp" +#include "../../devices/IKeyboard.hpp" +#include "../../managers/SeatManager.hpp" +#include "../../config/ConfigValue.hpp" +#include <algorithm> + +#include <fcntl.h> + +#define LOGM PROTO::seat->protoLog + +CWLTouchResource::CWLTouchResource(SP<CWlTouch> resource_, SP<CWLSeatResource> owner_) : owner(owner_), resource(resource_) { + if (!good()) + return; + + resource->setRelease([this](CWlTouch* r) { PROTO::seat->destroyResource(this); }); + resource->setOnDestroy([this](CWlTouch* r) { PROTO::seat->destroyResource(this); }); +} + +bool CWLTouchResource::good() { + return resource->resource(); +} + +void CWLTouchResource::sendDown(wlr_surface* surface, uint32_t timeMs, int32_t id, const Vector2D& local) { + if (!owner) + return; + + if (currentSurface) { + LOGM(WARN, "requested CWLTouchResource::sendDown without sendUp first."); + sendUp(timeMs, id); + } + + ASSERT(wl_resource_get_client(surface->resource) == owner->client()); + + currentSurface = surface; + hyprListener_surfaceDestroy.initCallback( + &surface->events.destroy, [this, id, timeMs](void* owner, void* data) { sendUp(timeMs + 10 /* hack */, id); }, this, "CWLTouchResource"); + + // FIXME: + // fix this once we get our own wlr_surface, this is horrible + resource->sendDownRaw(g_pSeatManager->nextSerial(owner.lock()), timeMs, surface->resource, id, wl_fixed_from_double(local.x), wl_fixed_from_double(local.y)); +} + +void CWLTouchResource::sendUp(uint32_t timeMs, int32_t id) { + if (!owner || !currentSurface) + return; + + resource->sendUp(g_pSeatManager->nextSerial(owner.lock()), timeMs, id); + currentSurface = nullptr; + hyprListener_surfaceDestroy.removeCallback(); +} + +void CWLTouchResource::sendMotion(uint32_t timeMs, int32_t id, const Vector2D& local) { + if (!owner || !currentSurface) + return; + + resource->sendMotion(timeMs, id, wl_fixed_from_double(local.x), wl_fixed_from_double(local.y)); +} + +void CWLTouchResource::sendFrame() { + if (!owner || !currentSurface) + return; + + resource->sendFrame(); +} + +void CWLTouchResource::sendCancel() { + if (!owner || !currentSurface) + return; + + resource->sendCancel(); +} + +void CWLTouchResource::sendShape(int32_t id, const Vector2D& shape) { + if (!owner || !currentSurface || resource->version() < 6) + return; + + resource->sendShape(id, wl_fixed_from_double(shape.x), wl_fixed_from_double(shape.y)); +} + +void CWLTouchResource::sendOrientation(int32_t id, double angle) { + if (!owner || !currentSurface || resource->version() < 6) + return; + + resource->sendOrientation(id, wl_fixed_from_double(angle)); +} + +CWLPointerResource::CWLPointerResource(SP<CWlPointer> resource_, SP<CWLSeatResource> owner_) : owner(owner_), resource(resource_) { + if (!good()) + return; + + resource->setRelease([this](CWlPointer* r) { PROTO::seat->destroyResource(this); }); + resource->setOnDestroy([this](CWlPointer* r) { PROTO::seat->destroyResource(this); }); + + resource->setSetCursor([this](CWlPointer* r, uint32_t serial, wl_resource* surf, int32_t hotX, int32_t hotY) { + if (!owner) { + LOGM(ERR, "Client bug: setCursor when seatClient is already dead"); + return; + } + + g_pSeatManager->onSetCursor(owner.lock(), serial, surf ? wlr_surface_from_resource(surf) : nullptr, {hotX, hotY}); + }); +} + +bool CWLPointerResource::good() { + return resource->resource(); +} + +void CWLPointerResource::sendEnter(wlr_surface* surface, const Vector2D& local) { + if (!owner || currentSurface == surface) + return; + + if (currentSurface) { + LOGM(WARN, "requested CWLPointerResource::sendEnter without sendLeave first."); + sendLeave(); + } + + ASSERT(wl_resource_get_client(surface->resource) == owner->client()); + + currentSurface = surface; + hyprListener_surfaceDestroy.initCallback( + &surface->events.destroy, [this](void* owner, void* data) { sendLeave(); }, this, "CWLPointerResource"); + + resource->sendEnterRaw(g_pSeatManager->nextSerial(owner.lock()), surface->resource, wl_fixed_from_double(local.x), wl_fixed_from_double(local.y)); +} + +void CWLPointerResource::sendLeave() { + if (!owner || !currentSurface) + return; + + resource->sendLeaveRaw(g_pSeatManager->nextSerial(owner.lock()), currentSurface->resource); + currentSurface = nullptr; + hyprListener_surfaceDestroy.removeCallback(); +} + +void CWLPointerResource::sendMotion(uint32_t timeMs, const Vector2D& local) { + if (!owner || !currentSurface) + return; + + resource->sendMotion(timeMs, wl_fixed_from_double(local.x), wl_fixed_from_double(local.y)); +} + +void CWLPointerResource::sendButton(uint32_t timeMs, uint32_t button, wl_pointer_button_state state) { + if (!owner || !currentSurface) + return; + + resource->sendButton(g_pSeatManager->nextSerial(owner.lock()), timeMs, button, state); +} + +void CWLPointerResource::sendAxis(uint32_t timeMs, wl_pointer_axis axis, double value) { + if (!owner || !currentSurface) + return; + + resource->sendAxis(timeMs, axis, wl_fixed_from_double(value)); +} + +void CWLPointerResource::sendFrame() { + if (!owner || resource->version() < 5) + return; + + resource->sendFrame(); +} + +void CWLPointerResource::sendAxisSource(wl_pointer_axis_source source) { + if (!owner || !currentSurface || resource->version() < 5) + return; + + resource->sendAxisSource(source); +} + +void CWLPointerResource::sendAxisStop(uint32_t timeMs, wl_pointer_axis axis) { + if (!owner || !currentSurface || resource->version() < 5) + return; + + resource->sendAxisStop(timeMs, axis); +} + +void CWLPointerResource::sendAxisDiscrete(wl_pointer_axis axis, int32_t discrete) { + if (!owner || !currentSurface || resource->version() < 5) + return; + + resource->sendAxisDiscrete(axis, discrete); +} + +void CWLPointerResource::sendAxisValue120(wl_pointer_axis axis, int32_t value120) { + if (!owner || !currentSurface || resource->version() < 8) + return; + + resource->sendAxisValue120(axis, value120); +} + +void CWLPointerResource::sendAxisRelativeDirection(wl_pointer_axis axis, wl_pointer_axis_relative_direction direction) { + if (!owner || !currentSurface || resource->version() < 9) + return; + + resource->sendAxisRelativeDirection(axis, direction); +} + +CWLKeyboardResource::CWLKeyboardResource(SP<CWlKeyboard> resource_, SP<CWLSeatResource> owner_) : owner(owner_), resource(resource_) { + if (!good()) + return; + + resource->setRelease([this](CWlKeyboard* r) { PROTO::seat->destroyResource(this); }); + resource->setOnDestroy([this](CWlKeyboard* r) { PROTO::seat->destroyResource(this); }); + + static auto REPEAT = CConfigValue<Hyprlang::INT>("input:repeat_rate"); + static auto DELAY = CConfigValue<Hyprlang::INT>("input:repeat_delay"); + sendKeymap(g_pSeatManager->keyboard.lock()); + repeatInfo(*REPEAT, *DELAY); +} + +bool CWLKeyboardResource::good() { + return resource->resource(); +} + +void CWLKeyboardResource::sendKeymap(SP<IKeyboard> keyboard) { + wl_keyboard_keymap_format format = keyboard ? WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 : WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP; + int fd; + uint32_t size; + if (keyboard) { + fd = keyboard->wlr()->keymap_fd; + size = keyboard->wlr()->keymap_size; + } else { + fd = open("/dev/null", O_RDONLY | O_CLOEXEC); + if (fd < 0) { + LOGM(ERR, "Failed to open /dev/null"); + return; + } + size = 0; + } + + resource->sendKeymap(format, fd, size); + + if (!keyboard) + close(fd); +} + +void CWLKeyboardResource::sendEnter(wlr_surface* surface) { + if (!owner || currentSurface == surface) + return; + + if (currentSurface) { + LOGM(WARN, "requested CWLKeyboardResource::sendEnter without sendLeave first."); + sendLeave(); + } + + ASSERT(wl_resource_get_client(surface->resource) == owner->client()); + + currentSurface = surface; + hyprListener_surfaceDestroy.initCallback( + &surface->events.destroy, [this](void* owner, void* data) { sendLeave(); }, this, "CWLKeyboardResource"); + + wl_array arr; + wl_array_init(&arr); + + resource->sendEnterRaw(g_pSeatManager->nextSerial(owner.lock()), surface->resource, &arr); + + wl_array_release(&arr); +} + +void CWLKeyboardResource::sendLeave() { + if (!owner || !currentSurface) + return; + + resource->sendLeaveRaw(g_pSeatManager->nextSerial(owner.lock()), currentSurface->resource); + currentSurface = nullptr; + hyprListener_surfaceDestroy.removeCallback(); +} + +void CWLKeyboardResource::sendKey(uint32_t timeMs, uint32_t key, wl_keyboard_key_state state) { + if (!owner || !currentSurface) + return; + + resource->sendKey(g_pSeatManager->nextSerial(owner.lock()), timeMs, key, state); +} + +void CWLKeyboardResource::sendMods(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) { + if (!owner || !currentSurface) + return; + + resource->sendModifiers(g_pSeatManager->nextSerial(owner.lock()), depressed, latched, locked, group); +} + +void CWLKeyboardResource::repeatInfo(uint32_t rate, uint32_t delayMs) { + if (!owner || resource->version() < 4) + return; + + resource->sendRepeatInfo(rate, delayMs); +} + +CWLSeatResource::CWLSeatResource(SP<CWlSeat> resource_) : resource(resource_) { + if (!good()) + return; + + resource->setOnDestroy([this](CWlSeat* r) { + events.destroy.emit(); + PROTO::seat->destroyResource(this); + }); + resource->setRelease([this](CWlSeat* r) { + events.destroy.emit(); + PROTO::seat->destroyResource(this); + }); + + pClient = resource->client(); + + resource->setGetKeyboard([this](CWlSeat* r, uint32_t id) { + const auto RESOURCE = PROTO::seat->m_vKeyboards.emplace_back(makeShared<CWLKeyboardResource>(makeShared<CWlKeyboard>(r->client(), r->version(), id), self.lock())); + + if (!RESOURCE->good()) { + r->noMemory(); + PROTO::seat->m_vKeyboards.pop_back(); + return; + } + + keyboards.push_back(RESOURCE); + }); + + resource->setGetPointer([this](CWlSeat* r, uint32_t id) { + const auto RESOURCE = PROTO::seat->m_vPointers.emplace_back(makeShared<CWLPointerResource>(makeShared<CWlPointer>(r->client(), r->version(), id), self.lock())); + + if (!RESOURCE->good()) { + r->noMemory(); + PROTO::seat->m_vPointers.pop_back(); + return; + } + + pointers.push_back(RESOURCE); + }); + + resource->setGetTouch([this](CWlSeat* r, uint32_t id) { + const auto RESOURCE = PROTO::seat->m_vTouches.emplace_back(makeShared<CWLTouchResource>(makeShared<CWlTouch>(r->client(), r->version(), id), self.lock())); + + if (!RESOURCE->good()) { + r->noMemory(); + PROTO::seat->m_vTouches.pop_back(); + return; + } + + touches.push_back(RESOURCE); + }); + + if (resource->version() >= 2) + resource->sendName(HL_SEAT_NAME); + + sendCapabilities(PROTO::seat->currentCaps); +} + +CWLSeatResource::~CWLSeatResource() { + events.destroy.emit(); +} + +void CWLSeatResource::sendCapabilities(uint32_t caps) { + uint32_t wlCaps = 0; + if (caps & eHIDCapabilityType::HID_INPUT_CAPABILITY_KEYBOARD) + wlCaps |= WL_SEAT_CAPABILITY_KEYBOARD; + if (caps & eHIDCapabilityType::HID_INPUT_CAPABILITY_POINTER) + wlCaps |= WL_SEAT_CAPABILITY_POINTER; + if (caps & eHIDCapabilityType::HID_INPUT_CAPABILITY_TOUCH) + wlCaps |= WL_SEAT_CAPABILITY_TOUCH; + + resource->sendCapabilities((wl_seat_capability)wlCaps); +} + +bool CWLSeatResource::good() { + return resource->resource(); +} + +wl_client* CWLSeatResource::client() { + return pClient; +} + +CWLSeatProtocol::CWLSeatProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CWLSeatProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vSeatResources.emplace_back(makeShared<CWLSeatResource>(makeShared<CWlSeat>(client, ver, id))); + + if (!RESOURCE->good()) { + wl_client_post_no_memory(client); + m_vSeatResources.pop_back(); + return; + } + + RESOURCE->self = RESOURCE; + + LOGM(LOG, "New seat resource bound at {:x}", (uintptr_t)RESOURCE.get()); + + events.newSeatResource.emit(RESOURCE); +} + +void CWLSeatProtocol::destroyResource(CWLSeatResource* seat) { + std::erase_if(m_vSeatResources, [&](const auto& other) { return other.get() == seat; }); +} + +void CWLSeatProtocol::destroyResource(CWLKeyboardResource* resource) { + std::erase_if(m_vKeyboards, [&](const auto& other) { return other.get() == resource; }); +} + +void CWLSeatProtocol::destroyResource(CWLPointerResource* resource) { + std::erase_if(m_vPointers, [&](const auto& other) { return other.get() == resource; }); +} + +void CWLSeatProtocol::destroyResource(CWLTouchResource* resource) { + std::erase_if(m_vTouches, [&](const auto& other) { return other.get() == resource; }); +} + +void CWLSeatProtocol::updateCapabilities(uint32_t caps) { + if (caps == currentCaps) + return; + + currentCaps = caps; + + for (auto& s : m_vSeatResources) { + s->sendCapabilities(caps); + } +} + +void CWLSeatProtocol::updateKeymap() { + for (auto& k : m_vKeyboards) { + k->sendKeymap(g_pSeatManager->keyboard.lock()); + } +} + +void CWLSeatProtocol::updateRepeatInfo(uint32_t rate, uint32_t delayMs) { + for (auto& k : m_vKeyboards) { + k->repeatInfo(rate, delayMs); + } +} + +SP<CWLSeatResource> CWLSeatProtocol::seatResourceForClient(wl_client* client) { + for (auto& r : m_vSeatResources) { + if (r->client() == client) + return r; + } + + return nullptr; +} diff --git a/src/protocols/core/Seat.hpp b/src/protocols/core/Seat.hpp new file mode 100644 index 00000000..4cd0d124 --- /dev/null +++ b/src/protocols/core/Seat.hpp @@ -0,0 +1,163 @@ +#pragma once + +/* + Implementations for: + - wl_seat + - wl_keyboard + - wl_pointer + - wl_touch +*/ + +#include <memory> +#include <vector> +#include <cstdint> +#include "../WaylandProtocol.hpp" +#include <wayland-server-protocol.h> +#include "wayland.hpp" +#include "../../helpers/signal/Signal.hpp" +#include "../../helpers/Vector2D.hpp" + +constexpr const char* HL_SEAT_NAME = "Hyprland"; + +class IKeyboard; + +class CWLPointerResource; +class CWLKeyboardResource; +class CWLTouchResource; +class CWLSeatResource; + +class CWLTouchResource { + public: + CWLTouchResource(SP<CWlTouch> resource_, SP<CWLSeatResource> owner_); + + bool good(); + void sendDown(wlr_surface* surface, uint32_t timeMs, int32_t id, const Vector2D& local); + void sendUp(uint32_t timeMs, int32_t id); + void sendMotion(uint32_t timeMs, int32_t id, const Vector2D& local); + void sendFrame(); + void sendCancel(); + void sendShape(int32_t id, const Vector2D& shape); + void sendOrientation(int32_t id, double angle); + + WP<CWLSeatResource> owner; + + private: + SP<CWlTouch> resource; + wlr_surface* currentSurface = nullptr; + + DYNLISTENER(surfaceDestroy); +}; + +class CWLPointerResource { + public: + CWLPointerResource(SP<CWlPointer> resource_, SP<CWLSeatResource> owner_); + + bool good(); + void sendEnter(wlr_surface* surface, const Vector2D& local); + void sendLeave(); + void sendMotion(uint32_t timeMs, const Vector2D& local); + void sendButton(uint32_t timeMs, uint32_t button, wl_pointer_button_state state); + void sendAxis(uint32_t timeMs, wl_pointer_axis axis, double value); + void sendFrame(); + void sendAxisSource(wl_pointer_axis_source source); + void sendAxisStop(uint32_t timeMs, wl_pointer_axis axis); + void sendAxisDiscrete(wl_pointer_axis axis, int32_t discrete); + void sendAxisValue120(wl_pointer_axis axis, int32_t value120); + void sendAxisRelativeDirection(wl_pointer_axis axis, wl_pointer_axis_relative_direction direction); + + WP<CWLSeatResource> owner; + + private: + SP<CWlPointer> resource; + wlr_surface* currentSurface = nullptr; + + DYNLISTENER(surfaceDestroy); +}; + +class CWLKeyboardResource { + public: + CWLKeyboardResource(SP<CWlKeyboard> resource_, SP<CWLSeatResource> owner_); + + bool good(); + void sendKeymap(SP<IKeyboard> keeb); + void sendEnter(wlr_surface* surface); + void sendLeave(); + void sendKey(uint32_t timeMs, uint32_t key, wl_keyboard_key_state state); + void sendMods(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); + void repeatInfo(uint32_t rate, uint32_t delayMs); + + WP<CWLSeatResource> owner; + + private: + SP<CWlKeyboard> resource; + wlr_surface* currentSurface = nullptr; + + DYNLISTENER(surfaceDestroy); +}; + +class CWLSeatResource { + public: + CWLSeatResource(SP<CWlSeat> resource_); + ~CWLSeatResource(); + + void sendCapabilities(uint32_t caps); // uses IHID capabilities + + bool good(); + wl_client* client(); + + std::vector<WP<CWLPointerResource>> pointers; + std::vector<WP<CWLKeyboardResource>> keyboards; + std::vector<WP<CWLTouchResource>> touches; + + WP<CWLSeatResource> self; + + struct { + CSignal destroy; + } events; + + private: + SP<CWlSeat> resource; + wl_client* pClient = nullptr; +}; + +class CWLSeatProtocol : public IWaylandProtocol { + public: + CWLSeatProtocol(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 newSeatResource; // SP<CWLSeatResource> + } events; + + private: + void updateCapabilities(uint32_t caps); // in IHID caps + void updateRepeatInfo(uint32_t rate, uint32_t delayMs); + void updateKeymap(); + + void destroyResource(CWLSeatResource* resource); + void destroyResource(CWLKeyboardResource* resource); + void destroyResource(CWLTouchResource* resource); + void destroyResource(CWLPointerResource* resource); + + // + std::vector<SP<CWLSeatResource>> m_vSeatResources; + std::vector<SP<CWLKeyboardResource>> m_vKeyboards; + std::vector<SP<CWLTouchResource>> m_vTouches; + std::vector<SP<CWLPointerResource>> m_vPointers; + + SP<CWLSeatResource> seatResourceForClient(wl_client* client); + + // + uint32_t currentCaps = 0; + + friend class CWLSeatResource; + friend class CWLKeyboardResource; + friend class CWLTouchResource; + friend class CWLPointerResource; + friend class CSeatManager; +}; + +namespace PROTO { + inline UP<CWLSeatProtocol> seat; +}; |