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.
11 #include "utils/log.h"
13 #include "platform/posix/utils/FileHandle.h"
14 #include "platform/posix/utils/Mmap.h"
21 using namespace KODI::WINDOWING::WAYLAND
;
22 using namespace std::placeholders
;
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
,
49 InstanceProviderT instanceProvider
)
51 bool hasCapability
= caps
& cap
;
53 if ((!!proxy
) != hasCapability
)
59 // The capability was added
60 CLog::Log(LOGDEBUG
, "Wayland seat {} gained capability {}", seatName
, capName
);
61 proxy
= instanceProvider();
66 // The capability was removed
67 CLog::Log(LOGDEBUG
, "Wayland seat {} lost capability {}", seatName
, capName
);
68 proxy
.proxy_release();
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
)
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]()
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
,
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
);