diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 18:07:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 18:07:22 +0000 |
commit | c04dcc2e7d834218ef2d4194331e383402495ae1 (patch) | |
tree | 7333e38d10d75386e60f336b80c2443c1166031d /xbmc/windowing/wayland/Seat.cpp | |
parent | Initial commit. (diff) | |
download | kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.tar.xz kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.zip |
Adding upstream version 2:20.4+dfsg.upstream/2%20.4+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xbmc/windowing/wayland/Seat.cpp')
-rw-r--r-- | xbmc/windowing/wayland/Seat.cpp | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/xbmc/windowing/wayland/Seat.cpp b/xbmc/windowing/wayland/Seat.cpp new file mode 100644 index 0000000..56709b3 --- /dev/null +++ b/xbmc/windowing/wayland/Seat.cpp @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "Seat.h" + +#include "utils/log.h" + +#include "platform/posix/utils/FileHandle.h" +#include "platform/posix/utils/Mmap.h" + +#include <cassert> +#include <utility> + +#include <unistd.h> + +using namespace KODI::WINDOWING::WAYLAND; +using namespace std::placeholders; + +namespace +{ + +/** + * Handle change of availability of a wl_seat input capability + * + * This checks whether the capability is currently available with the wl_seat + * and whether it was bound to a protocol object. If there is a mismatch between + * these two, the protocol proxy is released if a capability was removed or bound + * if a capability was added. + * + * \param caps new capabilities + * \param cap capability to check for + * \param seatName human-readable name of the seat for log messages + * \param capName human-readable name of the capability for log messages + * \param proxy proxy object that should be filled with a new instance or reset + * \param instanceProvider function that functions as factory for the Wayland + * protocol instance if the capability has been added + */ +template<typename T, typename InstanceProviderT> +bool HandleCapabilityChange(const wayland::seat_capability& caps, + const wayland::seat_capability& cap, + std::string const& seatName, + std::string const& capName, + T& proxy, + InstanceProviderT instanceProvider) +{ + bool hasCapability = caps & cap; + + if ((!!proxy) != hasCapability) + { + // Capability changed + + if (hasCapability) + { + // The capability was added + CLog::Log(LOGDEBUG, "Wayland seat {} gained capability {}", seatName, capName); + proxy = instanceProvider(); + return true; + } + else + { + // The capability was removed + CLog::Log(LOGDEBUG, "Wayland seat {} lost capability {}", seatName, capName); + proxy.proxy_release(); + } + } + + return false; +} + +} + +CSeat::CSeat(std::uint32_t globalName, wayland::seat_t const& seat, CConnection& connection) +: m_globalName{globalName}, m_seat{seat}, m_selection{connection, seat} +{ + m_seat.on_name() = [this](std::string name) { m_name = std::move(name); }; + m_seat.on_capabilities() = std::bind(&CSeat::HandleOnCapabilities, this, std::placeholders::_1); +} + +CSeat::~CSeat() noexcept = default; + +void CSeat::AddRawInputHandlerKeyboard(KODI::WINDOWING::WAYLAND::IRawInputHandlerKeyboard *rawKeyboardHandler) +{ + assert(rawKeyboardHandler); + m_rawKeyboardHandlers.emplace(rawKeyboardHandler); +} + +void CSeat::RemoveRawInputHandlerKeyboard(KODI::WINDOWING::WAYLAND::IRawInputHandlerKeyboard *rawKeyboardHandler) +{ + m_rawKeyboardHandlers.erase(rawKeyboardHandler); +} + +void CSeat::AddRawInputHandlerPointer(IRawInputHandlerPointer* rawPointerHandler) +{ + assert(rawPointerHandler); + m_rawPointerHandlers.emplace(rawPointerHandler); +} + +void CSeat::RemoveRawInputHandlerPointer(KODI::WINDOWING::WAYLAND::IRawInputHandlerPointer *rawPointerHandler) +{ + m_rawPointerHandlers.erase(rawPointerHandler); +} + +void CSeat::AddRawInputHandlerTouch(IRawInputHandlerTouch* rawTouchHandler) +{ + assert(rawTouchHandler); + m_rawTouchHandlers.emplace(rawTouchHandler); +} + +void CSeat::RemoveRawInputHandlerTouch(KODI::WINDOWING::WAYLAND::IRawInputHandlerTouch *rawTouchHandler) +{ + m_rawTouchHandlers.erase(rawTouchHandler); +} + +void CSeat::HandleOnCapabilities(const wayland::seat_capability& caps) +{ + if (HandleCapabilityChange(caps, wayland::seat_capability::keyboard, GetName(), "keyboard", m_keyboard, std::bind(&wayland::seat_t::get_keyboard, m_seat))) + { + HandleKeyboardCapability(); + } + if (HandleCapabilityChange(caps, wayland::seat_capability::pointer, GetName(), "pointer", m_pointer, std::bind(&wayland::seat_t::get_pointer, m_seat))) + { + HandlePointerCapability(); + } + if (HandleCapabilityChange(caps, wayland::seat_capability::touch, GetName(), "touch", m_touch, std::bind(&wayland::seat_t::get_touch, m_seat))) + { + HandleTouchCapability(); + } +} + +void CSeat::SetCursor(std::uint32_t serial, wayland::surface_t const &surface, std::int32_t hotspotX, std::int32_t hotspotY) +{ + if (m_pointer) + { + m_pointer.set_cursor(serial, surface, hotspotX, hotspotY); + } +} + +void CSeat::HandleKeyboardCapability() +{ + m_keyboard.on_keymap() = [this](wayland::keyboard_keymap_format format, int fd, std::uint32_t size) + { + KODI::UTILS::POSIX::CFileHandle fdGuard{fd}; + KODI::UTILS::POSIX::CMmap mmap{nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0}; + std::string keymap{static_cast<const char*> (mmap.Data()), size}; + for (auto handler : m_rawKeyboardHandlers) + { + handler->OnKeyboardKeymap(this, format, keymap); + } + }; + m_keyboard.on_enter() = [this](std::uint32_t serial, const wayland::surface_t& surface, + const wayland::array_t& keys) { + for (auto handler : m_rawKeyboardHandlers) + { + handler->OnKeyboardEnter(this, serial, surface, keys); + } + }; + m_keyboard.on_leave() = [this](std::uint32_t serial, const wayland::surface_t& surface) { + for (auto handler : m_rawKeyboardHandlers) + { + handler->OnKeyboardLeave(this, serial, surface); + } + }; + m_keyboard.on_key() = [this](std::uint32_t serial, std::uint32_t time, std::uint32_t key, wayland::keyboard_key_state state) + { + for (auto handler : m_rawKeyboardHandlers) + { + handler->OnKeyboardKey(this, serial, time, key, state); + } + }; + m_keyboard.on_modifiers() = [this](std::uint32_t serial, std::uint32_t modsDepressed, std::uint32_t modsLatched, std::uint32_t modsLocked, std::uint32_t group) + { + for (auto handler : m_rawKeyboardHandlers) + { + handler->OnKeyboardModifiers(this, serial, modsDepressed, modsLatched, modsLocked, group); + } + }; + m_keyboard.on_repeat_info() = [this](std::int32_t rate, std::int32_t delay) + { + for (auto handler : m_rawKeyboardHandlers) + { + handler->OnKeyboardRepeatInfo(this, rate, delay); + } + }; +} + + +void CSeat::HandlePointerCapability() +{ + m_pointer.on_enter() = [this](std::uint32_t serial, const wayland::surface_t& surface, + double surfaceX, double surfaceY) { + for (auto handler : m_rawPointerHandlers) + { + handler->OnPointerEnter(this, serial, surface, surfaceX, surfaceY); + } + }; + m_pointer.on_leave() = [this](std::uint32_t serial, const wayland::surface_t& surface) { + for (auto handler : m_rawPointerHandlers) + { + handler->OnPointerLeave(this, serial, surface); + } + }; + m_pointer.on_motion() = [this](std::uint32_t time, double surfaceX, double surfaceY) + { + for (auto handler : m_rawPointerHandlers) + { + handler->OnPointerMotion(this, time, surfaceX, surfaceY); + } + }; + m_pointer.on_button() = [this](std::uint32_t serial, std::uint32_t time, std::uint32_t button, wayland::pointer_button_state state) + { + for (auto handler : m_rawPointerHandlers) + { + handler->OnPointerButton(this, serial, time, button, state); + } + }; + m_pointer.on_axis() = [this](std::uint32_t time, wayland::pointer_axis axis, double value) + { + for (auto handler : m_rawPointerHandlers) + { + handler->OnPointerAxis(this, time, axis, value); + } + }; + // Wayland groups pointer events, but right now there is no benefit in + // treating them in groups. The main use case for doing so seems to be + // multi-axis (i.e. diagonal) scrolling, but we do not support this anyway. + /*m_pointer.on_frame() = [this]() + { + + };*/ +} + +void CSeat::HandleTouchCapability() +{ + m_touch.on_down() = [this](std::uint32_t serial, std::uint32_t time, + const wayland::surface_t& surface, std::int32_t id, double x, + double y) { + for (auto handler : m_rawTouchHandlers) + { + handler->OnTouchDown(this, serial, time, surface, id, x, y); + } + }; + m_touch.on_up() = [this](std::uint32_t serial, std::uint32_t time, std::int32_t id) + { + for (auto handler : m_rawTouchHandlers) + { + handler->OnTouchUp(this, serial, time, id); + } + }; + m_touch.on_motion() = [this](std::uint32_t time, std::int32_t id, double x, double y) + { + for (auto handler : m_rawTouchHandlers) + { + handler->OnTouchMotion(this, time, id, x, y); + } + }; + m_touch.on_cancel() = [this]() + { + for (auto handler : m_rawTouchHandlers) + { + handler->OnTouchCancel(this); + } + }; + m_touch.on_shape() = [this](std::int32_t id, double major, double minor) + { + for (auto handler : m_rawTouchHandlers) + { + handler->OnTouchShape(this, id, major, minor); + } + }; +} |