summaryrefslogtreecommitdiffstats
path: root/xbmc/windowing/wayland/Seat.h
blob: 095f18dd89cab707f59ee0a64bb85b9108c45d36 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/*
 *  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.
 */

#pragma once

#include "SeatSelection.h"

#include <cstdint>
#include <set>

#include <wayland-client-protocol.hpp>

namespace KODI
{
namespace WINDOWING
{
namespace WAYLAND
{

class CSeat;

/**
 * Handler for raw wl_keyboard events
 *
 * All functions are identical to wl_keyboard, except for the keymap which is
 * retrieved from its fd and put into a string
 */
class IRawInputHandlerKeyboard
{
public:
  virtual void OnKeyboardKeymap(CSeat* seat, wayland::keyboard_keymap_format format, std::string const& keymap) {}
  virtual void OnKeyboardEnter(CSeat* seat,
                               std::uint32_t serial,
                               const wayland::surface_t& surface,
                               const wayland::array_t& keys)
  {
  }
  virtual void OnKeyboardLeave(CSeat* seat, std::uint32_t serial, const wayland::surface_t& surface)
  {
  }
  virtual void OnKeyboardKey(CSeat* seat, std::uint32_t serial, std::uint32_t time, std::uint32_t key, wayland::keyboard_key_state state) {}
  virtual void OnKeyboardModifiers(CSeat* seat, std::uint32_t serial, std::uint32_t modsDepressed, std::uint32_t modsLatched, std::uint32_t modsLocked, std::uint32_t group) {}
  virtual void OnKeyboardRepeatInfo(CSeat* seat, std::int32_t rate, std::int32_t delay) {}
protected:
  ~IRawInputHandlerKeyboard() = default;
};

/**
 * Handler for raw wl_pointer events
 *
 * All functions are identical to wl_pointer
 */
class IRawInputHandlerPointer
{
public:
  virtual void OnPointerEnter(CSeat* seat,
                              std::uint32_t serial,
                              const wayland::surface_t& surface,
                              double surfaceX,
                              double surfaceY)
  {
  }
  virtual void OnPointerLeave(CSeat* seat, std::uint32_t serial, const wayland::surface_t& surface)
  {
  }
  virtual void OnPointerMotion(CSeat* seat, std::uint32_t time, double surfaceX, double surfaceY) {}
  virtual void OnPointerButton(CSeat* seat, std::uint32_t serial, std::uint32_t time, std::uint32_t button, wayland::pointer_button_state state) {}
  virtual void OnPointerAxis(CSeat* seat, std::uint32_t time, wayland::pointer_axis axis, double value) {}
protected:
  ~IRawInputHandlerPointer() = default;
};

/**
 * Handler for raw wl_touch events
 *
 * All functions are identical to wl_touch
 */
class IRawInputHandlerTouch
{
public:
  virtual void OnTouchDown(CSeat* seat,
                           std::uint32_t serial,
                           std::uint32_t time,
                           const wayland::surface_t& surface,
                           std::int32_t id,
                           double x,
                           double y)
  {
  }
  virtual void OnTouchUp(CSeat* seat, std::uint32_t serial, std::uint32_t time, std::int32_t id) {}
  virtual void OnTouchMotion(CSeat* seat, std::uint32_t time, std::int32_t id, double x, double y) {}
  virtual void OnTouchCancel(CSeat* seat) {}
  virtual void OnTouchShape(CSeat* seat, std::int32_t id, double major, double minor) {}
protected:
  ~IRawInputHandlerTouch() = default;
};

/**
 * Handle all events and requests related to one seat (including input and selection)
 *
 * The primary purpose of this class is to act as entry point of Wayland events into
 * the Kodi world and distribute them further as necessary.
 * Input events are forwarded to (potentially multiple) handlers. As the Wayland
 * protocol is not very specific on having multiple wl_seat/wl_pointer instances
 * and how they interact, having one central instance and then handling everything
 * in Kodi with multiple handlers is better than each handler having its own
 * protocol object instance.
 */
class CSeat
{
public:
  /**
   * Construct seat handler
   * \param globalName Wayland numeric global name of the seat
   * \param seat bound seat_t instance
   * \param connection connection for retrieving additional globals
   */
  CSeat(std::uint32_t globalName, wayland::seat_t const& seat, CConnection& connection);
  ~CSeat() noexcept;

  void AddRawInputHandlerKeyboard(IRawInputHandlerKeyboard* rawKeyboardHandler);
  void RemoveRawInputHandlerKeyboard(IRawInputHandlerKeyboard* rawKeyboardHandler);
  void AddRawInputHandlerPointer(IRawInputHandlerPointer* rawPointerHandler);
  void RemoveRawInputHandlerPointer(IRawInputHandlerPointer* rawPointerHandler);
  void AddRawInputHandlerTouch(IRawInputHandlerTouch* rawTouchHandler);
  void RemoveRawInputHandlerTouch(IRawInputHandlerTouch* rawTouchHandler);

  std::uint32_t GetGlobalName() const
  {
    return m_globalName;
  }
  std::string const& GetName() const
  {
    return m_name;
  }
  bool HasPointerCapability() const
  {
    return !!m_pointer;
  }
  bool HasKeyboardCapability() const
  {
    return !!m_keyboard;
  }
  bool HasTouchCapability() const
  {
    return !!m_touch;
  }
  std::string GetSelectionText() const
  {
    return m_selection.GetSelectionText();
  }
  /**
   * Get the wl_seat underlying this seat
   *
   * The wl_seat should only be used when strictly necessary, e.g. when
   * starting a move operation with shell interfaces.
   * It may not be used to derive further wl_pointer etc. instances.
   */
  wayland::seat_t const& GetWlSeat()
  {
    return m_seat;
  }

  /**
   * Set the cursor of the pointer of this seat
   *
   * Parameters are identical wo wl_pointer.set_cursor().
   * If the seat does not currently have the pointer capability, this is a no-op.
   */
  void SetCursor(std::uint32_t serial, wayland::surface_t const& surface, std::int32_t hotspotX, std::int32_t hotspotY);

private:
  CSeat(CSeat const& other) = delete;
  CSeat& operator=(CSeat const& other) = delete;

  void HandleOnCapabilities(const wayland::seat_capability& caps);
  void HandlePointerCapability();
  void HandleKeyboardCapability();
  void HandleTouchCapability();

  std::uint32_t m_globalName;
  std::string m_name{"<unknown>"};

  wayland::seat_t m_seat;
  wayland::pointer_t m_pointer;
  wayland::keyboard_t m_keyboard;
  wayland::touch_t m_touch;

  std::set<IRawInputHandlerKeyboard*> m_rawKeyboardHandlers;
  std::set<IRawInputHandlerPointer*> m_rawPointerHandlers;
  std::set<IRawInputHandlerTouch*> m_rawTouchHandlers;

  CSeatSelection m_selection;
};

}
}
}