[Windows] Fix driver version detection of AMD RDNA+ GPU on Windows 10
[xbmc.git] / xbmc / windowing / wayland / Seat.cpp
blob770c274ed6ff693b7d372d4d2d9bfa2a9946595a
1 /*
2 * Copyright (C) 2017-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "Seat.h"
11 #include "utils/log.h"
13 #include "platform/posix/utils/FileHandle.h"
14 #include "platform/posix/utils/Mmap.h"
16 #include <cassert>
17 #include <utility>
19 #include <unistd.h>
21 using namespace KODI::WINDOWING::WAYLAND;
22 using namespace std::placeholders;
24 namespace
27 /**
28 * Handle change of availability of a wl_seat input capability
30 * This checks whether the capability is currently available with the wl_seat
31 * and whether it was bound to a protocol object. If there is a mismatch between
32 * these two, the protocol proxy is released if a capability was removed or bound
33 * if a capability was added.
35 * \param caps new capabilities
36 * \param cap capability to check for
37 * \param seatName human-readable name of the seat for log messages
38 * \param capName human-readable name of the capability for log messages
39 * \param proxy proxy object that should be filled with a new instance or reset
40 * \param instanceProvider function that functions as factory for the Wayland
41 * protocol instance if the capability has been added
43 template<typename T, typename InstanceProviderT>
44 bool HandleCapabilityChange(const wayland::seat_capability& caps,
45 const wayland::seat_capability& cap,
46 std::string const& seatName,
47 std::string const& capName,
48 T& proxy,
49 InstanceProviderT instanceProvider)
51 bool hasCapability = caps & cap;
53 if ((!!proxy) != hasCapability)
55 // Capability changed
57 if (hasCapability)
59 // The capability was added
60 CLog::Log(LOGDEBUG, "Wayland seat {} gained capability {}", seatName, capName);
61 proxy = instanceProvider();
62 return true;
64 else
66 // The capability was removed
67 CLog::Log(LOGDEBUG, "Wayland seat {} lost capability {}", seatName, capName);
68 proxy.proxy_release();
72 return false;
77 CSeat::CSeat(std::uint32_t globalName, wayland::seat_t const& seat, CConnection& connection)
78 : m_globalName{globalName}, m_seat{seat}, m_selection{connection, seat}
80 m_seat.on_name() = [this](std::string name) { m_name = std::move(name); };
81 m_seat.on_capabilities() = std::bind(&CSeat::HandleOnCapabilities, this, std::placeholders::_1);
84 CSeat::~CSeat() noexcept = default;
86 void CSeat::AddRawInputHandlerKeyboard(KODI::WINDOWING::WAYLAND::IRawInputHandlerKeyboard *rawKeyboardHandler)
88 assert(rawKeyboardHandler);
89 m_rawKeyboardHandlers.emplace(rawKeyboardHandler);
92 void CSeat::RemoveRawInputHandlerKeyboard(KODI::WINDOWING::WAYLAND::IRawInputHandlerKeyboard *rawKeyboardHandler)
94 m_rawKeyboardHandlers.erase(rawKeyboardHandler);
97 void CSeat::AddRawInputHandlerPointer(IRawInputHandlerPointer* rawPointerHandler)
99 assert(rawPointerHandler);
100 m_rawPointerHandlers.emplace(rawPointerHandler);
103 void CSeat::RemoveRawInputHandlerPointer(KODI::WINDOWING::WAYLAND::IRawInputHandlerPointer *rawPointerHandler)
105 m_rawPointerHandlers.erase(rawPointerHandler);
108 void CSeat::AddRawInputHandlerTouch(IRawInputHandlerTouch* rawTouchHandler)
110 assert(rawTouchHandler);
111 m_rawTouchHandlers.emplace(rawTouchHandler);
114 void CSeat::RemoveRawInputHandlerTouch(KODI::WINDOWING::WAYLAND::IRawInputHandlerTouch *rawTouchHandler)
116 m_rawTouchHandlers.erase(rawTouchHandler);
119 void CSeat::HandleOnCapabilities(const wayland::seat_capability& caps)
121 if (HandleCapabilityChange(caps, wayland::seat_capability::keyboard, GetName(), "keyboard", m_keyboard, std::bind(&wayland::seat_t::get_keyboard, m_seat)))
123 HandleKeyboardCapability();
125 if (HandleCapabilityChange(caps, wayland::seat_capability::pointer, GetName(), "pointer", m_pointer, std::bind(&wayland::seat_t::get_pointer, m_seat)))
127 HandlePointerCapability();
129 if (HandleCapabilityChange(caps, wayland::seat_capability::touch, GetName(), "touch", m_touch, std::bind(&wayland::seat_t::get_touch, m_seat)))
131 HandleTouchCapability();
135 void CSeat::SetCursor(std::uint32_t serial, wayland::surface_t const &surface, std::int32_t hotspotX, std::int32_t hotspotY)
137 if (m_pointer)
139 m_pointer.set_cursor(serial, surface, hotspotX, hotspotY);
143 void CSeat::HandleKeyboardCapability()
145 m_keyboard.on_keymap() = [this](wayland::keyboard_keymap_format format, int fd, std::uint32_t size)
147 KODI::UTILS::POSIX::CFileHandle fdGuard{fd};
148 KODI::UTILS::POSIX::CMmap mmap{nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0};
149 std::string keymap{static_cast<const char*> (mmap.Data()), size};
150 for (auto handler : m_rawKeyboardHandlers)
152 handler->OnKeyboardKeymap(this, format, keymap);
155 m_keyboard.on_enter() = [this](std::uint32_t serial, const wayland::surface_t& surface,
156 const wayland::array_t& keys) {
157 for (auto handler : m_rawKeyboardHandlers)
159 handler->OnKeyboardEnter(this, serial, surface, keys);
162 m_keyboard.on_leave() = [this](std::uint32_t serial, const wayland::surface_t& surface) {
163 for (auto handler : m_rawKeyboardHandlers)
165 handler->OnKeyboardLeave(this, serial, surface);
168 m_keyboard.on_key() = [this](std::uint32_t serial, std::uint32_t time, std::uint32_t key, wayland::keyboard_key_state state)
170 for (auto handler : m_rawKeyboardHandlers)
172 handler->OnKeyboardKey(this, serial, time, key, state);
175 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)
177 for (auto handler : m_rawKeyboardHandlers)
179 handler->OnKeyboardModifiers(this, serial, modsDepressed, modsLatched, modsLocked, group);
182 InstallKeyboardRepeatInfo();
185 void CSeat::InstallKeyboardRepeatInfo()
187 m_keyboard.on_repeat_info() = [this](std::int32_t rate, std::int32_t delay)
189 for (auto handler : m_rawKeyboardHandlers)
191 handler->OnKeyboardRepeatInfo(this, rate, delay);
196 void CSeat::HandlePointerCapability()
198 m_pointer.on_enter() = [this](std::uint32_t serial, const wayland::surface_t& surface,
199 double surfaceX, double surfaceY) {
200 for (auto handler : m_rawPointerHandlers)
202 handler->OnPointerEnter(this, serial, surface, surfaceX, surfaceY);
205 m_pointer.on_leave() = [this](std::uint32_t serial, const wayland::surface_t& surface) {
206 for (auto handler : m_rawPointerHandlers)
208 handler->OnPointerLeave(this, serial, surface);
211 m_pointer.on_motion() = [this](std::uint32_t time, double surfaceX, double surfaceY)
213 for (auto handler : m_rawPointerHandlers)
215 handler->OnPointerMotion(this, time, surfaceX, surfaceY);
218 m_pointer.on_button() = [this](std::uint32_t serial, std::uint32_t time, std::uint32_t button, wayland::pointer_button_state state)
220 for (auto handler : m_rawPointerHandlers)
222 handler->OnPointerButton(this, serial, time, button, state);
225 m_pointer.on_axis() = [this](std::uint32_t time, wayland::pointer_axis axis, double value)
227 for (auto handler : m_rawPointerHandlers)
229 handler->OnPointerAxis(this, time, axis, value);
232 // Wayland groups pointer events, but right now there is no benefit in
233 // treating them in groups. The main use case for doing so seems to be
234 // multi-axis (i.e. diagonal) scrolling, but we do not support this anyway.
235 /*m_pointer.on_frame() = [this]()
238 };*/
241 void CSeat::HandleTouchCapability()
243 m_touch.on_down() = [this](std::uint32_t serial, std::uint32_t time,
244 const wayland::surface_t& surface, std::int32_t id, double x,
245 double y) {
246 for (auto handler : m_rawTouchHandlers)
248 handler->OnTouchDown(this, serial, time, surface, id, x, y);
251 m_touch.on_up() = [this](std::uint32_t serial, std::uint32_t time, std::int32_t id)
253 for (auto handler : m_rawTouchHandlers)
255 handler->OnTouchUp(this, serial, time, id);
258 m_touch.on_motion() = [this](std::uint32_t time, std::int32_t id, double x, double y)
260 for (auto handler : m_rawTouchHandlers)
262 handler->OnTouchMotion(this, time, id, x, y);
265 m_touch.on_cancel() = [this]()
267 for (auto handler : m_rawTouchHandlers)
269 handler->OnTouchCancel(this);
272 m_touch.on_shape() = [this](std::int32_t id, double major, double minor)
274 for (auto handler : m_rawTouchHandlers)
276 handler->OnTouchShape(this, id, major, minor);