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 | |
parent | 47874f09f4d14703fe0c483a46b345c7be601ace (diff) | |
download | Hyprland-44da1b75f03b2042a9923f3657e2fcd2bc3a1045.tar.gz Hyprland-44da1b75f03b2042a9923f3657e2fcd2bc3a1045.zip |
wl_seat: move to hyprland impl
31 files changed, 1462 insertions, 416 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index cfcaa686..608ccc62 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,6 +71,7 @@ pkg_get_variable(WaylandScanner wayland-scanner wayland_scanner) message(STATUS "Found WaylandScanner at ${WaylandScanner}") pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir) message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}") +pkg_get_variable(WAYLAND_SERVER_DIR wayland-server pkgdatadir) if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) message(STATUS "Configuring Hyprland in Debug with CMake") @@ -239,6 +240,13 @@ function(protocolNew protoPath protoName external) target_sources(Hyprland PRIVATE protocols/${protoName}.cpp) endif() endfunction() +function(protocolWayland) + execute_process( + COMMAND hyprwayland-scanner --wayland-enums ${WAYLAND_SERVER_DIR}/wayland.xml ${CMAKE_SOURCE_DIR}/protocols/ + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + ) + target_sources(Hyprland PRIVATE protocols/wayland.cpp) +endfunction() target_link_libraries(Hyprland ${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland/build/libwlroots.a @@ -285,6 +293,8 @@ protocolNew("staging/ext-session-lock/ext-session-lock-v1.xml" "ext-session-lock protocolNew("stable/tablet/tablet-v2.xml" "tablet-v2" false) protocolNew("stable/presentation-time/presentation-time.xml" "presentation-time" false) +protocolWayland() + # tools add_subdirectory(hyprctl) add_subdirectory(hyprpm) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index c532f958..efc02a5f 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -4,6 +4,7 @@ #include "managers/CursorManager.hpp" #include "managers/TokenManager.hpp" #include "managers/PointerManager.hpp" +#include "managers/SeatManager.hpp" #include "managers/eventLoop/EventLoopManager.hpp" #include <random> #include <unordered_set> @@ -222,16 +223,14 @@ void CCompositor::initServer() { m_sWLRCompositor = wlr_compositor_create(m_sWLDisplay, 6, m_sWLRRenderer); m_sWLRSubCompositor = wlr_subcompositor_create(m_sWLDisplay); - m_sWLRDataDevMgr = wlr_data_device_manager_create(m_sWLDisplay); + // m_sWLRDataDevMgr = wlr_data_device_manager_create(m_sWLDisplay); - wlr_data_control_manager_v1_create(m_sWLDisplay); - wlr_primary_selection_v1_device_manager_create(m_sWLDisplay); + // wlr_data_control_manager_v1_create(m_sWLDisplay); + // wlr_primary_selection_v1_device_manager_create(m_sWLDisplay); wlr_viewporter_create(m_sWLDisplay); m_sWLRXDGShell = wlr_xdg_shell_create(m_sWLDisplay, 6); - m_sSeat.seat = wlr_seat_create(m_sWLDisplay, "seat0"); - m_sWRLDRMLeaseMgr = wlr_drm_lease_v1_manager_create(m_sWLDisplay, m_sWLRBackend); if (!m_sWRLDRMLeaseMgr) { Debug::log(INFO, "Failed to create wlr_drm_lease_v1_manager"); @@ -256,12 +255,11 @@ void CCompositor::initAllSignals() { addWLSignal(&m_sWLRBackend->events.new_output, &Events::listen_newOutput, m_sWLRBackend, "Backend"); addWLSignal(&m_sWLRXDGShell->events.new_toplevel, &Events::listen_newXDGToplevel, m_sWLRXDGShell, "XDG Shell"); addWLSignal(&m_sWLRBackend->events.new_input, &Events::listen_newInput, m_sWLRBackend, "Backend"); - addWLSignal(&m_sSeat.seat->events.request_set_cursor, &Events::listen_requestMouse, &m_sSeat, "Seat"); - addWLSignal(&m_sSeat.seat->events.request_set_selection, &Events::listen_requestSetSel, &m_sSeat, "Seat"); - addWLSignal(&m_sSeat.seat->events.request_start_drag, &Events::listen_requestDrag, &m_sSeat, "Seat"); - addWLSignal(&m_sSeat.seat->events.start_drag, &Events::listen_startDrag, &m_sSeat, "Seat"); - addWLSignal(&m_sSeat.seat->events.request_set_selection, &Events::listen_requestSetSel, &m_sSeat, "Seat"); - addWLSignal(&m_sSeat.seat->events.request_set_primary_selection, &Events::listen_requestSetPrimarySel, &m_sSeat, "Seat"); + // addWLSignal(&m_sSeat.seat->events.request_set_selection, &Events::listen_requestSetSel, &m_sSeat, "Seat"); + // addWLSignal(&m_sSeat.seat->events.request_start_drag, &Events::listen_requestDrag, &m_sSeat, "Seat"); + // addWLSignal(&m_sSeat.seat->events.start_drag, &Events::listen_startDrag, &m_sSeat, "Seat"); + // addWLSignal(&m_sSeat.seat->events.request_set_selection, &Events::listen_requestSetSel, &m_sSeat, "Seat"); + // addWLSignal(&m_sSeat.seat->events.request_set_primary_selection, &Events::listen_requestSetPrimarySel, &m_sSeat, "Seat"); addWLSignal(&m_sWLRRenderer->events.destroy, &Events::listen_RendererDestroy, m_sWLRRenderer, "WLRRenderer"); if (m_sWRLDRMLeaseMgr) @@ -275,7 +273,6 @@ void CCompositor::removeAllSignals() { removeWLSignal(&Events::listen_newOutput); removeWLSignal(&Events::listen_newXDGToplevel); removeWLSignal(&Events::listen_newInput); - removeWLSignal(&Events::listen_requestMouse); removeWLSignal(&Events::listen_requestSetSel); removeWLSignal(&Events::listen_requestDrag); removeWLSignal(&Events::listen_startDrag); @@ -379,9 +376,8 @@ void CCompositor::cleanup() { g_pHookSystem.reset(); g_pWatchdog.reset(); g_pXWaylandManager.reset(); - - if (m_sSeat.seat) - wlr_seat_destroy(m_sSeat.seat); + g_pPointerManager.reset(); + g_pSeatManager.reset(); if (m_sWLRRenderer) wlr_renderer_destroy(m_sWLRRenderer); @@ -412,6 +408,9 @@ void CCompositor::initManagers(eManagersInitStage stage) { Debug::log(LOG, "Creating the ProtocolManager!"); g_pProtocolManager = std::make_unique<CProtocolManager>(); + Debug::log(LOG, "Creating the SeatManager!"); + g_pSeatManager = std::make_unique<CSeatManager>(); + Debug::log(LOG, "Creating the KeybindManager!"); g_pKeybindManager = std::make_unique<CKeybindManager>(); @@ -890,8 +889,8 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, wlr_surface* pSurface) { static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse"); static auto PSPECIALFALLTHROUGH = CConfigValue<Hyprlang::INT>("input:special_fallthrough"); - if (g_pCompositor->m_sSeat.exclusiveClient) { - Debug::log(LOG, "Disallowing setting focus to a window due to there being an active input inhibitor layer."); + if (g_pSessionLockManager->isSessionLocked()) { + Debug::log(LOG, "Refusing a keyboard focus to a window because of a sessionlock"); return; } @@ -919,7 +918,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, wlr_surface* pSurface) { g_pXWaylandManager->activateWindow(PLASTWINDOW, false); } - wlr_seat_keyboard_notify_clear_focus(m_sSeat.seat); + g_pSeatManager->setKeyboardFocus(nullptr); g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","}); g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", ""}); @@ -939,7 +938,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, wlr_surface* pSurface) { return; } - if (m_pLastWindow.lock() == pWindow && m_sSeat.seat->keyboard_state.focused_surface == pSurface) + if (m_pLastWindow.lock() == pWindow && g_pSeatManager->state.keyboardFocus == pSurface) return; if (pWindow->m_bPinned) @@ -1017,7 +1016,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, wlr_surface* pSurface) { void CCompositor::focusSurface(wlr_surface* pSurface, PHLWINDOW pWindowOwner) { - if (m_sSeat.seat->keyboard_state.focused_surface == pSurface || (pWindowOwner && m_sSeat.seat->keyboard_state.focused_surface == pWindowOwner->m_pWLSurface.wlr())) + if (g_pSeatManager->state.keyboardFocus == pSurface || (pWindowOwner && g_pSeatManager->state.keyboardFocus == pWindowOwner->m_pWLSurface.wlr())) return; // Don't focus when already focused on this. if (g_pSessionLockManager->isSessionLocked() && !g_pSessionLockManager->isSurfaceSessionLock(pSurface)) @@ -1030,7 +1029,7 @@ void CCompositor::focusSurface(wlr_surface* pSurface, PHLWINDOW pWindowOwner) { g_pXWaylandManager->activateSurface(m_pLastFocus, false); if (!pSurface) { - wlr_seat_keyboard_clear_focus(m_sSeat.seat); + g_pSeatManager->setKeyboardFocus(nullptr); g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","}); // unfocused g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", ""}); EMIT_HOOK_EVENT("keyboardFocus", (wlr_surface*)nullptr); @@ -1038,17 +1037,8 @@ void CCompositor::focusSurface(wlr_surface* pSurface, PHLWINDOW pWindowOwner) { return; } - if (const auto KEYBOARD = wlr_seat_get_keyboard(m_sSeat.seat); KEYBOARD) { - uint32_t keycodes[WLR_KEYBOARD_KEYS_CAP] = {0}; // TODO: maybe send valid, non-keybind codes? - wlr_seat_keyboard_notify_enter(m_sSeat.seat, pSurface, keycodes, 0, &KEYBOARD->modifiers); - - wlr_seat_keyboard_focus_change_event event = { - .seat = m_sSeat.seat, - .old_surface = m_pLastFocus, - .new_surface = pSurface, - }; - wl_signal_emit_mutable(&m_sSeat.seat->keyboard_state.events.focus_change, &event); - } + if (g_pSeatManager->keyboard) + g_pSeatManager->setKeyboardFocus(pSurface); if (pWindowOwner) Debug::log(LOG, "Set keyboard focus to surface {:x}, with {}", (uintptr_t)pSurface, pWindowOwner); @@ -1245,27 +1235,6 @@ PHLWINDOW CCompositor::getTopLeftWindowOnWorkspace(const int& id) { return nullptr; } -bool CCompositor::doesSeatAcceptInput(wlr_surface* surface) { - if (g_pSessionLockManager->isSessionLocked()) { - if (g_pSessionLockManager->isSurfaceSessionLock(surface)) - return true; - - if (surface && m_sSeat.exclusiveClient == wl_resource_get_client(surface->resource)) - return true; - - return false; - } - - if (m_sSeat.exclusiveClient) { - if (surface && m_sSeat.exclusiveClient == wl_resource_get_client(surface->resource)) - return true; - - return false; - } - - return true; -} - bool CCompositor::isWindowActive(PHLWINDOW pWindow) { if (m_pLastWindow.expired() && !m_pLastFocus) return false; diff --git a/src/Compositor.hpp b/src/Compositor.hpp index c8bb8743..eedcea56 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -48,7 +48,6 @@ class CCompositor { wlr_allocator* m_sWLRAllocator; wlr_compositor* m_sWLRCompositor; wlr_subcompositor* m_sWLRSubCompositor; - wlr_data_device_manager* m_sWLRDataDevMgr; wlr_drm* m_sWRLDRM; wlr_drm_lease_v1_manager* m_sWRLDRMLeaseMgr; wlr_xdg_shell* m_sWLRXDGShell; @@ -87,8 +86,6 @@ class CCompositor { std::vector<PHLWINDOWREF> m_vWindowFocusHistory; // first element is the most recently focused. - SSeat m_sSeat; - bool m_bReadyToProcess = false; bool m_bSessionActive = true; bool m_bDPMSStateON = true; @@ -132,7 +129,6 @@ class CCompositor { PHLWINDOW getFirstWindowOnWorkspace(const int&); PHLWINDOW getTopLeftWindowOnWorkspace(const int&); PHLWINDOW getFullscreenWindowOnWorkspace(const int&); - bool doesSeatAcceptInput(wlr_surface*); bool isWindowActive(PHLWINDOW); void changeWindowZOrder(PHLWINDOW, bool); void cleanupFadingOut(const int& monid); diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 2312de72..cb10079c 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -2,6 +2,7 @@ #include "../Compositor.hpp" #include "../events/Events.hpp" #include "../protocols/LayerShell.hpp" +#include "../managers/SeatManager.hpp" PHLLS CLayerSurface::create(SP<CLayerShellResource> resource) { PHLLS pLS = SP<CLayerSurface>(new CLayerSurface(resource)); @@ -132,15 +133,14 @@ void CLayerSurface::onMap() { const bool GRABSFOCUS = layerSurface->current.interactivity != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE && // don't focus if constrained - (g_pCompositor->m_sSeat.mouse.expired() || !g_pInputManager->isConstrained()); + (g_pSeatManager->mouse.expired() || !g_pInputManager->isConstrained()); if (GRABSFOCUS) { g_pInputManager->releaseAllMouseButtons(); g_pCompositor->focusSurface(surface.wlr()); const auto LOCAL = g_pInputManager->getMouseCoordsInternal() - Vector2D(geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y); - wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, surface.wlr(), LOCAL.x, LOCAL.y); - wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, 0, LOCAL.x, LOCAL.y); + g_pSeatManager->setPointerFocus(surface.wlr(), LOCAL); g_pInputManager->m_bEmptyFocusCursorSet = false; } @@ -304,15 +304,14 @@ void CLayerSurface::onCommit() { realSize.setValueAndWarp(geometry.size()); } - if (layerSurface->current.interactivity && (g_pCompositor->m_sSeat.mouse.expired() || !g_pInputManager->isConstrained()) // don't focus if constrained + if (layerSurface->current.interactivity && (g_pSeatManager->mouse.expired() || !g_pInputManager->isConstrained()) // don't focus if constrained && !keyboardExclusive && mapped) { g_pCompositor->focusSurface(layerSurface->surface); const auto LOCAL = g_pInputManager->getMouseCoordsInternal() - Vector2D(geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y); - wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, layerSurface->surface, LOCAL.x, LOCAL.y); - wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, 0, LOCAL.x, LOCAL.y); + g_pSeatManager->setPointerFocus(layerSurface->surface, LOCAL); g_pInputManager->m_bEmptyFocusCursorSet = false; - } else if (!layerSurface->current.interactivity && (g_pCompositor->m_sSeat.mouse.expired() || !g_pInputManager->isConstrained()) && keyboardExclusive) { + } else if (!layerSurface->current.interactivity && (g_pSeatManager->mouse.expired() || !g_pInputManager->isConstrained()) && keyboardExclusive) { g_pInputManager->refocus(); } diff --git a/src/desktop/WLSurface.cpp b/src/desktop/WLSurface.cpp index c09d8fda..78b50d45 100644 --- a/src/desktop/WLSurface.cpp +++ b/src/desktop/WLSurface.cpp @@ -120,8 +120,6 @@ void CWLSurface::destroy() { if (g_pCompositor && g_pCompositor->m_pLastFocus == m_pWLRSurface) g_pCompositor->m_pLastFocus = nullptr; - if (g_pInputManager && g_pInputManager->m_pLastMouseSurface == m_pWLRSurface) - g_pInputManager->m_pLastMouseSurface = nullptr; if (g_pHyprRenderer && g_pHyprRenderer->m_sLastCursorData.surf == this) g_pHyprRenderer->m_sLastCursorData.surf.reset(); diff --git a/src/events/Devices.cpp b/src/events/Devices.cpp index 16a64559..fedc844e 100644 --- a/src/events/Devices.cpp +++ b/src/events/Devices.cpp @@ -15,12 +15,6 @@ // // // ---------------------------------------------------- // -void Events::listener_requestMouse(wl_listener* listener, void* data) { - const auto EVENT = (wlr_seat_pointer_request_set_cursor_event*)data; - - g_pInputManager->processMouseRequest(EVENT); -} - void Events::listener_newInput(wl_listener* listener, void* data) { const auto DEVICE = (wlr_input_device*)data; diff --git a/src/events/Events.hpp b/src/events/Events.hpp index 69da2d09..2e627d39 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -46,7 +46,6 @@ namespace Events { LISTENER(newVirtPtr); // Various - LISTENER(requestMouse); LISTENER(requestSetSel); LISTENER(requestSetPrimarySel); diff --git a/src/events/Misc.cpp b/src/events/Misc.cpp index a67a6753..703dba6a 100644 --- a/src/events/Misc.cpp +++ b/src/events/Misc.cpp @@ -26,13 +26,13 @@ void Events::listener_leaseRequest(wl_listener* listener, void* data) { } void Events::listener_requestSetPrimarySel(wl_listener* listener, void* data) { - const auto EVENT = (wlr_seat_request_set_primary_selection_event*)data; - wlr_seat_set_primary_selection(g_pCompositor->m_sSeat.seat, EVENT->source, EVENT->serial); + // const auto EVENT = (wlr_seat_request_set_primary_selection_event*)data; + // wlr_seat_set_primary_selection(g_pCompositor->m_sSeat.seat, EVENT->source, EVENT->serial); } void Events::listener_requestSetSel(wl_listener* listener, void* data) { - const auto EVENT = (wlr_seat_request_set_selection_event*)data; - wlr_seat_set_selection(g_pCompositor->m_sSeat.seat, EVENT->source, EVENT->serial); + // const auto EVENT = (wlr_seat_request_set_selection_event*)data; + // wlr_seat_set_selection(g_pCompositor->m_sSeat.seat, EVENT->source, EVENT->serial); } void Events::listener_readyXWayland(wl_listener* listener, void* data) { @@ -58,7 +58,7 @@ void Events::listener_readyXWayland(wl_listener* listener, void* data) { free(reply); } - wlr_xwayland_set_seat(g_pXWaylandManager->m_sWLRXWayland, g_pCompositor->m_sSeat.seat); + //wlr_xwayland_set_seat(g_pXWaylandManager->m_sWLRXWayland, g_pCompositor->m_sSeat.seat); g_pCursorManager->setXWaylandCursor(g_pXWaylandManager->m_sWLRXWayland); @@ -80,15 +80,15 @@ void Events::listener_readyXWayland(wl_listener* listener, void* data) { } void Events::listener_requestDrag(wl_listener* listener, void* data) { - const auto E = (wlr_seat_request_start_drag_event*)data; + // const auto E = (wlr_seat_request_start_drag_event*)data; - if (!wlr_seat_validate_pointer_grab_serial(g_pCompositor->m_sSeat.seat, E->origin, E->serial)) { - Debug::log(LOG, "Ignoring drag and drop request: serial mismatch."); - wlr_data_source_destroy(E->drag->source); - return; - } + // if (!wlr_seat_validate_pointer_grab_serial(g_pCompositor->m_sSeat.seat, E->origin, E->serial)) { + // Debug::log(LOG, "Ignoring drag and drop request: serial mismatch."); + // wlr_data_source_destroy(E->drag->source); + // return; + // } - wlr_seat_start_pointer_drag(g_pCompositor->m_sSeat.seat, E->drag, E->serial); + // wlr_seat_start_pointer_drag(g_pCompositor->m_sSeat.seat, E->drag, E->serial); } void Events::listener_startDrag(wl_listener* listener, void* data) { diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 4ccf8e41..fe24cc7e 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -4,6 +4,7 @@ #include "../helpers/WLClasses.hpp" #include "../managers/input/InputManager.hpp" #include "../managers/TokenManager.hpp" +#include "../managers/SeatManager.hpp" #include "../render/Renderer.hpp" #include "../config/ConfigValue.hpp" #include "../protocols/LayerShell.hpp" @@ -668,7 +669,7 @@ void Events::listener_mapWindow(void* owner, void* data) { g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->scale); g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->transform); - if (g_pCompositor->m_sSeat.mouse.expired() || !g_pInputManager->isConstrained()) + if (g_pSeatManager->mouse.expired() || !g_pInputManager->isConstrained()) g_pInputManager->sendMotionEventsToFocused(); // fix some xwayland apps that don't behave nicely diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index bc07f6ba..7b24de7d 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -58,14 +58,6 @@ struct SExtensionFindingData { wlr_surface** found; }; -struct SSeat { - wlr_seat* seat = nullptr; - wl_client* exclusiveClient = nullptr; - - WP<IPointer> mouse; - WP<IKeyboard> keyboard; -}; - struct SDrag { wlr_drag* drag = nullptr; diff --git a/src/includes.hpp b/src/includes.hpp index 844a9173..c75796b9 100644 --- a/src/includes.hpp +++ b/src/includes.hpp @@ -51,7 +51,6 @@ extern "C" { #include <wlr/types/wlr_pointer.h> #include <wlr/types/wlr_primary_selection.h> #include <wlr/types/wlr_primary_selection_v1.h> -#include <wlr/types/wlr_seat.h> #include <wlr/types/wlr_viewporter.h> #include <wlr/types/wlr_xdg_output_v1.h> #include <wlr/types/wlr_xdg_shell.h> diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index c5d7067d..ead83fa8 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -6,6 +6,7 @@ #include "TokenManager.hpp" #include "../protocols/ShortcutsInhibit.hpp" #include "../devices/IKeyboard.hpp" +#include "../managers/SeatManager.hpp" #include <regex> #include <tuple> @@ -522,7 +523,7 @@ void CKeybindManager::onSwitchOffEvent(const std::string& switchName) { int repeatKeyHandler(void* data) { SKeybind** ppActiveKeybind = (SKeybind**)data; - if (!*ppActiveKeybind || g_pCompositor->m_sSeat.keyboard.expired()) + if (!*ppActiveKeybind || g_pSeatManager->keyboard.expired()) return 0; const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find((*ppActiveKeybind)->handler); @@ -530,16 +531,13 @@ int repeatKeyHandler(void* data) { Debug::log(LOG, "Keybind repeat triggered, calling dispatcher."); DISPATCHER->second((*ppActiveKeybind)->arg); - wl_event_source_timer_update(g_pKeybindManager->m_pActiveKeybindEventSource, 1000 / g_pCompositor->m_sSeat.keyboard->repeatRate); + wl_event_source_timer_update(g_pKeybindManager->m_pActiveKeybindEventSource, 1000 / g_pSeatManager->keyboard->wlr()->repeat_info.rate); return 0; } bool CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWithMods& key, bool pressed) { - bool found = false; - - if (g_pCompositor->m_sSeat.exclusiveClient) - Debug::log(LOG, "Keybind handling only locked (inhibitor)"); + bool found = false; static auto PDISABLEINHIBIT = CConfigValue<Hyprlang::INT>("binds:disable_keybind_grabbing"); @@ -558,8 +556,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWi if (!k.locked && g_pSessionLockManager->isSessionLocked()) continue; - if (!IGNORECONDITIONS && - ((modmask != k.modmask && !k.ignoreMods) || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || k.shadowed)) + if (!IGNORECONDITIONS && ((modmask != k.modmask && !k.ignoreMods) || k.submap != m_szCurrentSelectedSubmap || k.shadowed)) continue; if (!key.keyName.empty()) { @@ -653,7 +650,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWi m_pActiveKeybind = &k; m_pActiveKeybindEventSource = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, repeatKeyHandler, &m_pActiveKeybind); - const auto PACTIVEKEEB = g_pCompositor->m_sSeat.keyboard.lock(); + const auto PACTIVEKEEB = g_pSeatManager->keyboard.lock(); wl_event_source_timer_update(m_pActiveKeybindEventSource, PACTIVEKEEB->repeatDelay); } @@ -1901,47 +1898,42 @@ void CKeybindManager::pass(std::string regexp) { return; } - const auto KEYBOARD = wlr_seat_get_keyboard(g_pCompositor->m_sSeat.seat); - - if (!KEYBOARD) { + if (!g_pSeatManager->keyboard) { Debug::log(ERR, "No kb in pass?"); return; } - const auto XWTOXW = PWINDOW->m_bIsX11 && g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bIsX11; - const auto SL = Vector2D(g_pCompositor->m_sSeat.seat->pointer_state.sx, g_pCompositor->m_sSeat.seat->pointer_state.sy); - uint32_t keycodes[32] = {0}; - const auto LASTSRF = g_pCompositor->m_pLastFocus; + const auto XWTOXW = PWINDOW->m_bIsX11 && g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bIsX11; + const auto LASTSRF = g_pCompositor->m_pLastFocus; // pass all mf shit if (!XWTOXW) { if (g_pKeybindManager->m_uLastCode != 0) - wlr_seat_keyboard_enter(g_pCompositor->m_sSeat.seat, PWINDOW->m_pWLSurface.wlr(), keycodes, 0, &KEYBOARD->modifiers); + g_pSeatManager->setKeyboardFocus(PWINDOW->m_pWLSurface.wlr()); else - wlr_seat_pointer_enter(g_pCompositor->m_sSeat.seat, PWINDOW->m_pWLSurface.wlr(), 1, 1); + g_pSeatManager->setPointerFocus(PWINDOW->m_pWLSurface.wlr(), {1, 1}); } - wlr_keyboard_modifiers kbmods = {g_pInputManager->accumulateModsFromAllKBs(), 0, 0, 0}; - wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &kbmods); + g_pSeatManager->sendKeyboardMods(g_pInputManager->accumulateModsFromAllKBs(), 0, 0, 0); if (g_pKeybindManager->m_iPassPressed == 1) { if (g_pKeybindManager->m_uLastCode != 0) - wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastCode - 8, WLR_BUTTON_PRESSED); + g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastCode - 8, WL_KEYBOARD_KEY_STATE_PRESSED); else - wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastMouseCode, WL_POINTER_BUTTON_STATE_PRESSED); + g_pSeatManager->sendPointerButton(g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastMouseCode, WL_POINTER_BUTTON_STATE_PRESSED); } else if (g_pKeybindManager->m_iPassPressed == 0) if (g_pKeybindManager->m_uLastCode != 0) - wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastCode - 8, WLR_BUTTON_RELEASED); + g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastCode - 8, WL_KEYBOARD_KEY_STATE_RELEASED); else - wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastMouseCode, WL_POINTER_BUTTON_STATE_RELEASED); + g_pSeatManager->sendPointerButton(g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastMouseCode, WL_POINTER_BUTTON_STATE_RELEASED); else { // dynamic call of the dispatcher if (g_pKeybindManager->m_uLastCode != 0) { - wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastCode - 8, WLR_BUTTON_PRESSED); - wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastCode - 8, WLR_BUTTON_RELEASED); + g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastCode - 8, WL_KEYBOARD_KEY_STATE_PRESSED); + g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastCode - 8, WL_KEYBOARD_KEY_STATE_RELEASED); } else { - wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastMouseCode, WL_POINTER_BUTTON_STATE_PRESSED); - wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastMouseCode, WL_POINTER_BUTTON_STATE_RELEASED); + g_pSeatManager->sendPointerButton(g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastMouseCode, WL_POINTER_BUTTON_STATE_PRESSED); + g_pSeatManager->sendPointerButton(g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastMouseCode, WL_POINTER_BUTTON_STATE_RELEASED); } } @@ -1949,22 +1941,24 @@ void CKeybindManager::pass(std::string regexp) { return; // Massive hack: - // this will make wlroots NOT send the leave event to XWayland apps, provided we are not on an XWayland window already. + // this will make g_pSeatManager NOT send the leave event to XWayland apps, provided we are not on an XWayland window already. // please kill me if (PWINDOW->m_bIsX11) { if (g_pKeybindManager->m_uLastCode != 0) { - g_pCompositor->m_sSeat.seat->keyboard_state.focused_client = nullptr; - g_pCompositor->m_sSeat.seat->keyboard_state.focused_surface = nullptr; + g_pSeatManager->state.keyboardFocus = nullptr; + g_pSeatManager->state.keyboardFocusResource.reset(); } else { - g_pCompositor->m_sSeat.seat->pointer_state.focused_client = nullptr; - g_pCompositor->m_sSeat.seat->pointer_state.focused_surface = nullptr; + g_pSeatManager->state.pointerFocus = nullptr; + g_pSeatManager->state.pointerFocusResource.reset(); } } + const auto SL = PWINDOW->m_vRealPosition.goal() - g_pInputManager->getMouseCoordsInternal(); + if (g_pKeybindManager->m_uLastCode != 0) - wlr_seat_keyboard_enter(g_pCompositor->m_sSeat.seat, LASTSRF, KEYBOARD->keycodes, KEYBOARD->num_keycodes, &KEYBOARD->modifiers); + g_pSeatManager->setKeyboardFocus(LASTSRF); else - wlr_seat_pointer_enter(g_pCompositor->m_sSeat.seat, PWINDOW->m_pWLSurface.wlr(), SL.x, SL.y); + g_pSeatManager->setPointerFocus(PWINDOW->m_pWLSurface.wlr(), SL); } void CKeybindManager::layoutmsg(std::string msg) { diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 663456f8..8b02e3e8 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -3,6 +3,7 @@ #include "../config/ConfigValue.hpp" #include "../protocols/PointerGestures.hpp" #include "../protocols/FractionalScale.hpp" +#include "SeatManager.hpp" #include <wlr/interfaces/wlr_output.h> #include <wlr/render/interface.h> #include <wlr/render/wlr_renderer.h> @@ -774,7 +775,7 @@ void CPointerManager::attachPointer(SP<IPointer> pointer) { }); listener->frame = pointer->pointerEvents.frame.registerListener([this] (std::any e) { - wlr_seat_pointer_notify_frame(g_pCompositor->m_sSeat.seat); + g_pSeatManager->sendPointerFrame(); }); listener->swipeBegin = pointer->pointerEvents.swipeBegin.registerListener([this] (std::any e) { @@ -865,7 +866,7 @@ void CPointerManager::attachTouch(SP<ITouch> touch) { }); listener->frame = touch->touchEvents.frame.registerListener([this] (std::any e) { - wlr_seat_touch_notify_frame(g_pCompositor->m_sSeat.seat); + g_pSeatManager->sendTouchFrame(); }); // clang-format on diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 2904ed53..f853e16f 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -28,9 +28,14 @@ #include "../protocols/Tablet.hpp" #include "../protocols/LayerShell.hpp" #include "../protocols/PresentationTime.hpp" +#include "../protocols/core/Seat.hpp" CProtocolManager::CProtocolManager() { + // Core + PROTO::seat = std::make_unique<CWLSeatProtocol>(&wl_seat_interface, 9, "WLSeat"); + + // Extensions PROTO::tearing = std::make_unique<CTearingControlProtocol>(&wp_tearing_control_manager_v1_interface, 1, "TearingControl"); PROTO::fractional = std::make_unique<CFractionalScaleProtocol>(&wp_fractional_scale_manager_v1_interface, 1, "FractionalScale"); PROTO::xdgOutput = std::make_unique<CXDGOutputProtocol>(&zxdg_output_manager_v1_interface, 3, "XDGOutput"); 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); +} diff --git a/src/managers/SeatManager.hpp b/src/managers/SeatManager.hpp new file mode 100644 index 00000000..ef114024 --- /dev/null +++ b/src/managers/SeatManager.hpp @@ -0,0 +1,106 @@ +#pragma once + +#include <wayland-server-protocol.h> +#include "../helpers/WLListener.hpp" +#include "../macros.hpp" +#include "../helpers/signal/Signal.hpp" +#include "../helpers/Vector2D.hpp" +#include <vector> + +constexpr size_t MAX_SERIAL_STORE_LEN = 100; + +struct wlr_surface; +class CWLSeatResource; +class IPointer; +class IKeyboard; + +class CSeatManager { + public: + CSeatManager(); + + void updateCapabilities(uint32_t capabilities); // in IHID caps + + void setMouse(SP<IPointer> mouse); + void setKeyboard(SP<IKeyboard> keeb); + + void setKeyboardFocus(wlr_surface* surf); + void sendKeyboardKey(uint32_t timeMs, uint32_t key, wl_keyboard_key_state state); + void sendKeyboardMods(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); + + void setPointerFocus(wlr_surface* surf, const Vector2D& local); + void sendPointerMotion(uint32_t timeMs, const Vector2D& local); + void sendPointerButton(uint32_t timeMs, uint32_t key, wl_pointer_button_state state); + void sendPointerFrame(); + void sendPointerAxis(uint32_t timeMs, wl_pointer_axis axis, double value, int32_t discrete, wl_pointer_axis_source source, wl_pointer_axis_relative_direction relative); + + void sendTouchDown(wlr_surface* surf, uint32_t timeMs, int32_t id, const Vector2D& local); + void sendTouchUp(uint32_t timeMs, int32_t id); + void sendTouchMotion(uint32_t timeMs, int32_t id, const Vector2D& local); + void sendTouchFrame(); + void sendTouchCancel(); + void sendTouchShape(int32_t id, const Vector2D& shape); + void sendTouchOrientation(int32_t id, double angle); + + uint32_t nextSerial(SP<CWLSeatResource> seatResource); + // pops the serial if it was valid, meaning it is consumed. + bool serialValid(SP<CWLSeatResource> seatResource, uint32_t serial); + + void onSetCursor(SP<CWLSeatResource> seatResource, uint32_t serial, wlr_surface* surf, const Vector2D& hotspot); + + SP<CWLSeatResource> seatResourceForClient(wl_client* client); + + struct { + wlr_surface* keyboardFocus = nullptr; + WP<CWLSeatResource> keyboardFocusResource; + + wlr_surface* pointerFocus = nullptr; + WP<CWLSeatResource> pointerFocusResource; + + wlr_surface* touchFocus = nullptr; + WP<CWLSeatResource> touchFocusResource; + } state; + + struct SSetCursorEvent { + wlr_surface* surf = nullptr; + Vector2D hotspot; + }; + + struct { + CSignal keyboardFocusChange; + CSignal pointerFocusChange; + CSignal touchFocusChange; + CSignal setCursor; // SSetCursorEvent + } events; + + // do not write to directly, use set... + WP<IPointer> mouse; + WP<IKeyboard> keyboard; + + private: + struct SSeatResourceContainer { + SSeatResourceContainer(SP<CWLSeatResource>); + + WP<CWLSeatResource> resource; + std::vector<uint32_t> serials; // old -> new + + struct { + CHyprSignalListener destroy; + } listeners; + }; + + std::vector<SP<SSeatResourceContainer>> seatResources; + void onNewSeatResource(SP<CWLSeatResource> resource); + SP<SSeatResourceContainer> containerForResource(SP<CWLSeatResource> seatResource); + + struct { + CHyprSignalListener newSeatResource; + } listeners; + + DYNLISTENER(keyboardSurfaceDestroy); + DYNLISTENER(pointerSurfaceDestroy); + DYNLISTENER(touchSurfaceDestroy); + + friend struct SSeatResourceContainer; +}; + +inline UP<CSeatManager> g_pSeatManager; diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 1d09dbb9..14fd6a79 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -14,6 +14,7 @@ #include "../../protocols/VirtualKeyboard.hpp" #include "../../protocols/VirtualPointer.hpp" #include "../../protocols/LayerShell.hpp" +#include "../../protocols/core/Seat.hpp" #include "../../devices/Mouse.hpp" #include "../../devices/VirtualPointer.hpp" @@ -22,6 +23,7 @@ #include "../../devices/TouchDevice.hpp" #include "../../managers/PointerManager.hpp" +#include "../../managers/SeatManager.hpp" CInputManager::CInputManager() { m_sListeners.setCursorShape = PROTO::cursorShape->events.setShape.registerListener([this](std::any data) { @@ -30,10 +32,10 @@ CInputManager::CInputManager() { auto event = std::any_cast<CCursorShapeProtocol::SSetShapeEvent>(data); - if (!g_pCompositor->m_sSeat.seat->pointer_state.focused_client) + if (!g_pSeatManager->state.pointerFocusResource) return; - if (wl_resource_get_client(event.pMgr->resource()) != g_pCompositor->m_sSeat.seat->pointer_state.focused_client->client) + if (wl_resource_get_client(event.pMgr->resource()) != g_pSeatManager->state.pointerFocusResource->client()) return; Debug::log(LOG, "cursorImage request: shape {} -> {}", (uint32_t)event.shape, event.shapeName); @@ -52,6 +54,7 @@ CInputManager::CInputManager() { PROTO::virtualKeyboard->events.newKeyboard.registerListener([this](std::any data) { this->newVirtualKeyboard(std::any_cast<SP<CVirtualKeyboardV1Resource>>(data)); }); m_sListeners.newVirtualMouse = PROTO::virtualPointer->events.newPointer.registerListener([this](std::any data) { this->newVirtualMouse(std::any_cast<SP<CVirtualPointerV1Resource>>(data)); }); + m_sListeners.setCursor = g_pSeatManager->events.setCursor.registerListener([this](std::any d) { this->processMouseRequest(d); }); } CInputManager::~CInputManager() { @@ -119,8 +122,7 @@ void CInputManager::sendMotionEventsToFocused() { m_bEmptyFocusCursorSet = false; - wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, g_pCompositor->m_pLastFocus, LOCAL.x, LOCAL.y); - wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, now.tv_sec * 1000 + now.tv_nsec / 10000000, LOCAL.x, LOCAL.y); + g_pSeatManager->setPointerFocus(g_pCompositor->m_pLastFocus, LOCAL); } void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { @@ -190,7 +192,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { } // constraints - if (!g_pCompositor->m_sSeat.mouse.expired() && isConstrained()) { + if (!g_pSeatManager->mouse.expired() && isConstrained()) { const auto SURF = CWLSurface::surfaceFromWlr(g_pCompositor->m_pLastFocus); const auto CONSTRAINT = SURF->constraint(); @@ -205,7 +207,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { const auto CLOSESTLOCAL = (CLOSEST - (BOX.has_value() ? BOX->pos() : Vector2D{})) * (SURF->getWindow() ? SURF->getWindow()->m_fX11SurfaceScaledBy : 1.0); g_pCompositor->warpCursorTo(CLOSEST, true); - wlr_seat_pointer_send_motion(g_pCompositor->m_sSeat.seat, time, CLOSESTLOCAL.x, CLOSESTLOCAL.y); + g_pSeatManager->sendPointerMotion(time, CLOSESTLOCAL); PROTO::relativePointer->sendRelativeMotion((uint64_t)time * 1000, {}, {}); } @@ -218,8 +220,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { // update stuff updateDragIcon(); - if (!m_sDrag.drag && !m_lCurrentlyHeldButtons.empty() && g_pCompositor->m_pLastFocus && m_pLastMouseSurface) { - foundSurface = m_pLastMouseSurface; + if (!m_sDrag.drag && !m_lCurrentlyHeldButtons.empty() && g_pCompositor->m_pLastFocus && g_pSeatManager->state.pointerFocus) { + foundSurface = g_pSeatManager->state.pointerFocus; pFoundLayerSurface = g_pCompositor->getLayerSurfaceFromSurface(foundSurface); if (pFoundLayerSurface) { surfacePos = pFoundLayerSurface->position; @@ -232,7 +234,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { m_bFocusHeldByButtons = true; m_bRefocusHeldByButtons = refocus; } else if (!g_pCompositor->m_pLastWindow.expired()) { - foundSurface = m_pLastMouseSurface; + foundSurface = g_pSeatManager->state.pointerFocus; pFoundWindow = g_pCompositor->m_pLastWindow.lock(); surfaceCoords = g_pCompositor->vectorToSurfaceLocal(mouseCoords, pFoundWindow, foundSurface); @@ -371,8 +373,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { m_bEmptyFocusCursorSet = true; } - wlr_seat_pointer_clear_focus(g_pCompositor->m_sSeat.seat); - m_pLastMouseSurface = nullptr; + g_pSeatManager->setPointerFocus(nullptr, {}); if (refocus || g_pCompositor->m_pLastWindow.expired()) // if we are forcing a refocus, and we don't find a surface, clear the kb focus too! g_pCompositor->focusWindow(nullptr); @@ -412,8 +413,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { } if (currentlyDraggedWindow.lock() && pFoundWindow != currentlyDraggedWindow) { - wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y); - wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, time, surfaceLocal.x, surfaceLocal.y); + g_pSeatManager->setPointerFocus(foundSurface, surfaceLocal); return; } @@ -441,20 +441,15 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { // enter if change floating style if (FOLLOWMOUSE != 3 && allowKeyboardRefocus) g_pCompositor->focusWindow(pFoundWindow, foundSurface); - m_pLastMouseSurface = foundSurface; - wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y); - } else if (FOLLOWMOUSE == 2 || FOLLOWMOUSE == 3) { - m_pLastMouseSurface = foundSurface; - wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y); - } + g_pSeatManager->setPointerFocus(foundSurface, surfaceLocal); + } else if (FOLLOWMOUSE == 2 || FOLLOWMOUSE == 3) + g_pSeatManager->setPointerFocus(foundSurface, surfaceLocal); - if (pFoundWindow == g_pCompositor->m_pLastWindow) { - m_pLastMouseSurface = foundSurface; - wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y); - } + if (pFoundWindow == g_pCompositor->m_pLastWindow) + g_pSeatManager->setPointerFocus(foundSurface, surfaceLocal); if (FOLLOWMOUSE != 0 || pFoundWindow == g_pCompositor->m_pLastWindow) - wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, time, surfaceLocal.x, surfaceLocal.y); + g_pSeatManager->setPointerFocus(foundSurface, surfaceLocal); m_bLastFocusOnLS = false; return; // don't enter any new surfaces @@ -489,9 +484,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { m_bLastFocusOnLS = true; } - m_pLastMouseSurface = foundSurface; - wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y); - wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, time, surfaceLocal.x, surfaceLocal.y); + g_pSeatManager->setPointerFocus(foundSurface, surfaceLocal); + g_pSeatManager->sendPointerMotion(time, surfaceLocal); } void CInputManager::onMouseButton(IPointer::SButtonEvent e) { @@ -526,34 +520,33 @@ void CInputManager::onMouseButton(IPointer::SButtonEvent e) { } } -void CInputManager::processMouseRequest(wlr_seat_pointer_request_set_cursor_event* e) { +void CInputManager::processMouseRequest(std::any E) { if (!cursorImageUnlocked()) return; - Debug::log(LOG, "cursorImage request: surface {:x}", (uintptr_t)e->surface); + auto e = std::any_cast<CSeatManager::SSetCursorEvent>(E); - if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) { + Debug::log(LOG, "cursorImage request: surface {:x}", (uintptr_t)e.surf); - if (e->surface != m_sCursorSurfaceInfo.wlSurface.wlr()) { - m_sCursorSurfaceInfo.wlSurface.unassign(); + if (e.surf != m_sCursorSurfaceInfo.wlSurface.wlr()) { + m_sCursorSurfaceInfo.wlSurface.unassign(); - if (e->surface) - m_sCursorSurfaceInfo.wlSurface.assign(e->surface); - } + if (e.surf) + m_sCursorSurfaceInfo.wlSurface.assign(e.surf); + } - if (e->surface) { - m_sCursorSurfaceInfo.vHotspot = {e->hotspot_x, e->hotspot_y}; - m_sCursorSurfaceInfo.hidden = false; - } else { - m_sCursorSurfaceInfo.vHotspot = {}; - m_sCursorSurfaceInfo.hidden = true; - } + if (e.surf) { + m_sCursorSurfaceInfo.vHotspot = e.hotspot; + m_sCursorSurfaceInfo.hidden = false; + } else { + m_sCursorSurfaceInfo.vHotspot = {}; + m_sCursorSurfaceInfo.hidden = true; + } - m_sCursorSurfaceInfo.name = ""; + m_sCursorSurfaceInfo.name = ""; - m_sCursorSurfaceInfo.inUse = true; - g_pHyprRenderer->setCursorSurface(&m_sCursorSurfaceInfo.wlSurface, e->hotspot_x, e->hotspot_y); - } + m_sCursorSurfaceInfo.inUse = true; + g_pHyprRenderer->setCursorSurface(&m_sCursorSurfaceInfo.wlSurface, e.hotspot.x, e.hotspot.y); } void CInputManager::restoreCursorIconToApp() { @@ -659,7 +652,7 @@ void CInputManager::processMouseDownNormal(const IPointer::SButtonEvent& e) { if (*PFOLLOWMOUSE == 3) // don't refocus on full loose break; - if ((g_pCompositor->m_sSeat.mouse.expired() || !isConstrained()) /* No constraints */ + if ((g_pSeatManager->mouse.expired() || !isConstrained()) /* No constraints */ && (w && g_pCompositor->m_pLastWindow.lock() != w) /* window should change */) { // a bit hacky // if we only pressed one button, allow us to refocus. m_lCurrentlyHeldButtons.size() > 0 will stick the focus @@ -681,8 +674,7 @@ void CInputManager::processMouseDownNormal(const IPointer::SButtonEvent& e) { } // notify app if we didnt handle it - if (g_pCompositor->doesSeatAcceptInput(g_pCompositor->m_pLastFocus)) - wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, e.timeMs, e.button, e.state); + g_pSeatManager->sendPointerButton(e.timeMs, e.button, e.state); if (const auto PMON = g_pCompositor->getMonitorFromVector(mouseCoords); PMON != g_pCompositor->m_pLastMonitor.get() && PMON) g_pCompositor->setActiveMonitor(PMON); @@ -747,14 +739,13 @@ void CInputManager::onMouseWheel(IPointer::SAxisEvent e) { if (*POFFWINDOWAXIS == 3) g_pCompositor->warpCursorTo({TEMPCURX, TEMPCURY}, true); - wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, e.timeMs, TEMPCURX - BOX.x, TEMPCURY - BOX.y); - wlr_seat_pointer_notify_frame(g_pCompositor->m_sSeat.seat); + g_pSeatManager->sendPointerMotion(e.timeMs, Vector2D{TEMPCURX, TEMPCURY} - BOX.pos()); + g_pSeatManager->sendPointerFrame(); } } } - wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, e.timeMs, e.axis, factor * e.delta, std::round(factor * e.deltaDiscrete), e.source, - WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL); + g_pSeatManager->sendPointerAxis(e.timeMs, e.axis, factor * e.delta, std::round(factor * e.deltaDiscrete), e.source, WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL); } Vector2D CInputManager::getMouseCoordsInternal() { @@ -826,13 +817,9 @@ void CInputManager::setupKeyboard(SP<IKeyboard> keeb) { disableAllKeyboards(false); - g_pCompositor->m_sSeat.keyboard = keeb; - - keeb->active = true; - applyConfigToKeyboard(keeb); - wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, keeb->wlr()); + g_pSeatManager->setKeyboard(keeb); } void CInputManager::setKeyboardLayout() { @@ -1015,7 +1002,7 @@ void CInputManager::setupMouse(SP<IPointer> mauz) { }, mauz.get()); - g_pCompositor->m_sSeat.mouse = mauz; + g_pSeatManager->setMouse(mauz); m_tmrLastCursorMovement.reset(); } @@ -1185,12 +1172,11 @@ void CInputManager::destroyKeyboard(SP<IKeyboard> pKeyboard) { std::erase_if(m_vKeyboards, [pKeyboard](const auto& other) { return other == pKeyboard; }); if (m_vKeyboards.size() > 0) { - g_pCompositor->m_sSeat.keyboard = m_vKeyboards.back(); - g_pCompositor->m_sSeat.keyboard->active = true; - wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, g_pCompositor->m_sSeat.keyboard->wlr()); + const auto PNEWKEYBOARD = m_vKeyboards.back(); + g_pSeatManager->setKeyboard(PNEWKEYBOARD); + PNEWKEYBOARD->active = true; } else { - g_pCompositor->m_sSeat.keyboard.reset(); - wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, nullptr); + g_pSeatManager->setKeyboard(nullptr); } removeFromHIDs(pKeyboard); @@ -1199,9 +1185,9 @@ void CInputManager::destroyKeyboard(SP<IKeyboard> pKeyboard) { void CInputManager::destroyPointer(SP<IPointer> mouse) { std::erase_if(m_vPointers, [mouse](const auto& other) { return other == mouse; }); - g_pCompositor->m_sSeat.mouse = m_vPointers.size() > 0 ? m_vPointers.front() : nullptr; + g_pSeatManager->setMouse(m_vPointers.size() > 0 ? m_vPointers.front() : nullptr); - if (!g_pCompositor->m_sSeat.mouse.expired()) + if (!g_pSeatManager->mouse.expired()) unconstrainMouse(); removeFromHIDs(mouse); @@ -1267,8 +1253,8 @@ void CInputManager::onKeyboardKey(std::any event, SP<IKeyboard> pKeyboard) { IME->setKeyboard(pKeyboard->wlr()); IME->sendKey(e.timeMs, e.keycode, e.state); } else { - wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, pKeyboard->wlr()); - wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, e.timeMs, e.keycode, e.state); + g_pSeatManager->setKeyboard(pKeyboard); + g_pSeatManager->sendKeyboardKey(e.timeMs, e.keycode, e.state); } for (auto& k : m_vKeyboards) { @@ -1295,8 +1281,8 @@ void CInputManager::onKeyboardMod(SP<IKeyboard> pKeyboard) { IME->setKeyboard(PWLRKB); IME->sendMods(MODS.depressed, MODS.latched, MODS.locked, MODS.group); } else { - wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, PWLRKB); - wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &MODS); + g_pSeatManager->setKeyboard(pKeyboard); + g_pSeatManager->sendKeyboardMods(MODS.depressed, MODS.latched, MODS.locked, MODS.group); } for (auto& k : m_vKeyboards) { @@ -1345,7 +1331,7 @@ void CInputManager::updateDragIcon() { } void CInputManager::unconstrainMouse() { - if (g_pCompositor->m_sSeat.mouse.expired()) + if (g_pSeatManager->mouse.expired()) return; for (auto& c : m_vConstraints) { @@ -1394,7 +1380,7 @@ void CInputManager::updateCapabilities() { caps |= WL_SEAT_CAPABILITY_TOUCH; } - wlr_seat_set_capabilities(g_pCompositor->m_sSeat.seat, caps); + g_pSeatManager->updateCapabilities(caps); m_uiCapabilities = caps; } @@ -1406,7 +1392,7 @@ uint32_t CInputManager::accumulateModsFromAllKBs() { if (kb->isVirtual() && shouldIgnoreVirtualKeyboard(kb)) continue; - if (!kb->enabled) + if (!kb->enabled || !kb->wlr()) continue; finalMask |= wlr_keyboard_get_modifiers(kb->wlr()); @@ -1641,7 +1627,7 @@ void CInputManager::releaseAllMouseButtons() { return; for (auto& mb : buttonsCopy) { - wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, 0, mb, WL_POINTER_BUTTON_STATE_RELEASED); + g_pSeatManager->sendPointerButton(0, mb, WL_POINTER_BUTTON_STATE_RELEASED); } m_lCurrentlyHeldButtons.clear(); diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 970d53c8..a1ca07d3 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -117,7 +117,7 @@ class CInputManager { void setClickMode(eClickBehaviorMode); eClickBehaviorMode getClickMode(); - void processMouseRequest(wlr_seat_pointer_request_set_cursor_event* e); + void processMouseRequest(std::any e); void onTouchDown(ITouch::SDownEvent); void onTouchUp(ITouch::SUpEvent); @@ -196,7 +196,6 @@ class CInputManager { // for tracking mouse refocus PHLWINDOWREF m_pLastMouseFocus; - wlr_surface* m_pLastMouseSurface = nullptr; // bool m_bEmptyFocusCursorSet = false; @@ -208,6 +207,7 @@ class CInputManager { CHyprSignalListener newIdleInhibitor; CHyprSignalListener newVirtualKeyboard; CHyprSignalListener newVirtualMouse; + CHyprSignalListener setCursor; } m_sListeners; bool m_bCursorImageOverridden = false; diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index cf666ec6..56e817ec 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -4,6 +4,7 @@ #include "../../protocols/Tablet.hpp" #include "../../devices/Tablet.hpp" #include "../../managers/PointerManager.hpp" +#include "../../managers/SeatManager.hpp" #include "../../protocols/PointerConstraints.hpp" static void unfocusTool(SP<CTabletTool> tool) { @@ -36,7 +37,7 @@ static void focusTool(SP<CTabletTool> tool, SP<CTablet> tablet, wlr_surface* sur } static void refocusTablet(SP<CTablet> tab, SP<CTabletTool> tool, bool motion = false) { - const auto LASTHLSURFACE = CWLSurface::surfaceFromWlr(g_pInputManager->m_pLastMouseSurface); + const auto LASTHLSURFACE = CWLSurface::surfaceFromWlr(g_pSeatManager->state.pointerFocus); if (!LASTHLSURFACE || !tool->active) { if (tool->getSurface()) @@ -56,7 +57,7 @@ static void refocusTablet(SP<CTablet> tab, SP<CTabletTool> tool, bool motion = f const auto CURSORPOS = g_pInputManager->getMouseCoordsInternal(); - focusTool(tool, tab, g_pInputManager->m_pLastMouseSurface); + focusTool(tool, tab, g_pSeatManager->state.pointerFocus); if (!motion) return; diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index 4a6484c2..7748813b 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -3,6 +3,7 @@ #include "../../config/ConfigValue.hpp" #include "../../protocols/IdleNotify.hpp" #include "../../devices/ITouch.hpp" +#include "../SeatManager.hpp" void CInputManager::onTouchDown(ITouch::SDownEvent e) { static auto PSWIPETOUCH = CConfigValue<Hyprlang::INT>("gestures:workspace_swipe_touch"); @@ -76,7 +77,7 @@ void CInputManager::onTouchDown(ITouch::SDownEvent e) { } else return; // oops, nothing found. - wlr_seat_touch_notify_down(g_pCompositor->m_sSeat.seat, m_sTouchData.touchFocusSurface, e.timeMs, e.touchID, local.x, local.y); + g_pSeatManager->sendTouchDown(m_sTouchData.touchFocusSurface, e.timeMs, e.touchID, local); PROTO::idle->onActivity(); } @@ -90,9 +91,8 @@ void CInputManager::onTouchUp(ITouch::SUpEvent e) { return; } - if (m_sTouchData.touchFocusSurface) { - wlr_seat_touch_notify_up(g_pCompositor->m_sSeat.seat, e.timeMs, e.touchID); - } + if (m_sTouchData.touchFocusSurface) + g_pSeatManager->sendTouchUp(e.timeMs, e.touchID); } void CInputManager::onTouchMove(ITouch::SMotionEvent e) { @@ -131,8 +131,7 @@ void CInputManager::onTouchMove(ITouch::SMotionEvent e) { if (m_sTouchData.touchFocusWindow->m_bIsX11) local = local * m_sTouchData.touchFocusWindow->m_fX11SurfaceScaledBy; - wlr_seat_touch_notify_motion(g_pCompositor->m_sSeat.seat, e.timeMs, e.touchID, local.x, local.y); - // wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, local.x, local.y); + g_pSeatManager->sendTouchMotion(e.timeMs, e.touchID, local); } else if (!m_sTouchData.touchFocusLS.expired()) { const auto PMONITOR = g_pCompositor->getMonitorFromID(m_sTouchData.touchFocusLS->monitorID); @@ -140,7 +139,6 @@ void CInputManager::onTouchMove(ITouch::SMotionEvent e) { const auto local = g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchSurfaceOrigin; - wlr_seat_touch_notify_motion(g_pCompositor->m_sSeat.seat, e.timeMs, e.touchID, local.x, local.y); - // wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, local.x, local.y); + g_pSeatManager->sendTouchMotion(e.timeMs, e.touchID, local); } } 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; +}; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 2574a015..3c540b8d 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2493,8 +2493,8 @@ void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) { const auto PWORKSPACE = pMonitor->activeWorkspace; - if (!PWORKSPACE || !PWORKSPACE->m_bHasFullscreenWindow || g_pInputManager->m_sDrag.drag || g_pCompositor->m_sSeat.exclusiveClient || pMonitor->activeSpecialWorkspace || - PWORKSPACE->m_fAlpha.value() != 1.f || PWORKSPACE->m_vRenderOffset.value() != Vector2D{}) + if (!PWORKSPACE || !PWORKSPACE->m_bHasFullscreenWindow || g_pInputManager->m_sDrag.drag || pMonitor->activeSpecialWorkspace || PWORKSPACE->m_fAlpha.value() != 1.f || + PWORKSPACE->m_vRenderOffset.value() != Vector2D{}) return; const auto PCANDIDATE = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); |