kodi
ButtonMapping.h
1 /*
2  * Copyright (C) 2014-2024 Team Kodi
3  * This file is part of Kodi - https://kodi.tv
4  *
5  * SPDX-License-Identifier: GPL-2.0-or-later
6  * See LICENSES/README.md for more information.
7  */
8 
9 #pragma once
10 
11 #include "input/joysticks/DriverPrimitive.h"
12 #include "input/joysticks/interfaces/IButtonMapCallback.h"
13 #include "input/joysticks/interfaces/IDriverHandler.h"
14 #include "input/keyboard/interfaces/IKeyboardDriverHandler.h"
15 #include "input/mouse/MouseTypes.h"
16 #include "input/mouse/interfaces/IMouseDriverHandler.h"
17 
18 #include <chrono>
19 #include <map>
20 #include <memory>
21 #include <stdint.h>
22 
23 namespace KODI
24 {
25 namespace KEYMAP
26 {
27 class IKeymap;
28 } // namespace KEYMAP
29 
30 namespace JOYSTICK
31 {
32 class CButtonMapping;
33 class IButtonMap;
34 class IButtonMapper;
35 
48 {
49 protected:
50  CPrimitiveDetector(CButtonMapping* buttonMapping);
51 
57  bool MapPrimitive(const CDriverPrimitive& primitive);
58 
59 private:
60  CButtonMapping* const m_buttonMapping;
61 };
62 
69 {
70 public:
71  CButtonDetector(CButtonMapping* buttonMapping, unsigned int buttonIndex);
72 
81  bool OnMotion(bool bPressed);
82 
83 private:
84  // Construction parameters
85  const unsigned int m_buttonIndex;
86 };
87 
94 {
95 public:
96  CHatDetector(CButtonMapping* buttonMapping, unsigned int hatIndex);
97 
105  bool OnMotion(HAT_STATE state);
106 
107 private:
108  // Construction parameters
109  const unsigned int m_hatIndex;
110 };
111 
113 {
114  bool bKnown = false;
115  int center = 0;
116  unsigned int range = 1;
117  bool bLateDiscovery = false;
118 };
119 
126 {
127 public:
128  CAxisDetector(CButtonMapping* buttonMapping,
129  unsigned int axisIndex,
130  const AxisConfiguration& config);
131 
139  bool OnMotion(float position);
140 
147  void ProcessMotion();
148 
154  bool IsMapping() const { return m_state == AXIS_STATE::MAPPED; }
155 
163  void SetEmitted(const CDriverPrimitive& activePrimitive);
164 
165 private:
166  enum class AXIS_STATE
167  {
171  INACTIVE,
172 
176  ACTIVATED,
177 
181  MAPPED,
182  };
183 
184  enum class AXIS_TYPE
185  {
189  UNKNOWN,
190 
203  NORMAL,
204 
214  OFFSET,
215  };
216 
217  void DetectType(float position);
218 
219  // Construction parameters
220  const unsigned int m_axisIndex;
221  AxisConfiguration m_config; // mutable
222 
223  // State variables
224  AXIS_STATE m_state = AXIS_STATE::INACTIVE;
225  CDriverPrimitive m_activatedPrimitive;
226  AXIS_TYPE m_type = AXIS_TYPE::UNKNOWN;
227  bool m_initialPositionKnown = false; // set to true on first motion
228  float m_initialPosition = 0.0f; // set to position of first motion
229  bool m_initialPositionChanged =
230  false; // set to true when position differs from the initial position
231  std::chrono::time_point<std::chrono::steady_clock>
232  m_activationTimeMs; // only used to delay anomalous trigger mapping to detect full range
233 };
234 
241 {
242 public:
243  CKeyDetector(CButtonMapping* buttonMapping, XBMCKey keycode);
244 
253  bool OnMotion(bool bPressed);
254 
255 private:
256  // Construction parameters
257  const XBMCKey m_keycode;
258 };
259 
266 {
267 public:
268  CMouseButtonDetector(CButtonMapping* buttonMapping, MOUSE::BUTTON_ID buttonIndex);
269 
278  bool OnMotion(bool bPressed);
279 
280 private:
281  // Construction parameters
282  const MOUSE::BUTTON_ID m_buttonIndex;
283 };
284 
291 {
292 public:
293  CPointerDetector(CButtonMapping* buttonMapping);
294 
304  bool OnMotion(int x, int y);
305 
306 private:
307  // Utility function
308  static INPUT::INTERCARDINAL_DIRECTION GetPointerDirection(int x, int y);
309 
310  static const unsigned int MIN_FRAME_COUNT = 10;
311 
312  // State variables
313  bool m_bStarted = false;
314  int m_startX = 0;
315  int m_startY = 0;
316  unsigned int m_frameCount = 0;
317 };
318 
334  public IButtonMapCallback
335 {
336 public:
343  CButtonMapping(IButtonMapper* buttonMapper, IButtonMap* buttonMap, KEYMAP::IKeymap* keymap);
344 
345  ~CButtonMapping() override = default;
346 
347  // implementation of IDriverHandler
348  bool OnButtonMotion(unsigned int buttonIndex, bool bPressed) override;
349  bool OnHatMotion(unsigned int hatIndex, HAT_STATE state) override;
350  bool OnAxisMotion(unsigned int axisIndex,
351  float position,
352  int center,
353  unsigned int range) override;
354  void OnInputFrame() override;
355 
356  // implementation of IKeyboardDriverHandler
357  bool OnKeyPress(const CKey& key) override;
358  void OnKeyRelease(const CKey& key) override {}
359 
360  // implementation of IMouseDriverHandler
361  bool OnPosition(int x, int y) override;
362  bool OnButtonPress(MOUSE::BUTTON_ID button) override;
363  void OnButtonRelease(MOUSE::BUTTON_ID button) override;
364 
365  // implementation of IButtonMapCallback
366  void SaveButtonMap() override;
367  void ResetIgnoredPrimitives() override;
368  void RevertButtonMap() override;
369 
381  bool MapPrimitive(const CDriverPrimitive& primitive);
382 
383 private:
384  bool IsMapping() const;
385 
386  void OnLateDiscovery(unsigned int axisIndex);
387 
388  CButtonDetector& GetButton(unsigned int buttonIndex);
389  CHatDetector& GetHat(unsigned int hatIndex);
390  CAxisDetector& GetAxis(unsigned int axisIndex,
391  float position,
392  const AxisConfiguration& initialConfig = AxisConfiguration());
393  CKeyDetector& GetKey(XBMCKey keycode);
394  CMouseButtonDetector& GetMouseButton(MOUSE::BUTTON_ID buttonIndex);
395  CPointerDetector& GetPointer();
396 
397  // Construction parameters
398  IButtonMapper* const m_buttonMapper;
399  IButtonMap* const m_buttonMap;
400  KEYMAP::IKeymap* const m_keymap;
401 
402  std::map<unsigned int, CButtonDetector> m_buttons;
403  std::map<unsigned int, CHatDetector> m_hats;
404  std::map<unsigned int, CAxisDetector> m_axes;
405  std::map<XBMCKey, CKeyDetector> m_keys;
406  std::map<MOUSE::BUTTON_ID, CMouseButtonDetector> m_mouseButtons;
407  std::unique_ptr<CPointerDetector> m_pointer;
408  std::chrono::time_point<std::chrono::steady_clock> m_lastAction;
409  uint64_t m_frameCount = 0;
410 };
411 } // namespace JOYSTICK
412 } // namespace KODI
Definition: ButtonMapping.h:112
Detects when a button should be mapped.
Definition: ButtonMapping.h:68
Definition: deflate.c:123
void OnKeyRelease(const CKey &key) override
A key has been released.
Definition: ButtonMapping.h:358
BUTTON_ID
Buttons on a mouse.
Definition: MouseTypes.h:26
Interface defining methods to handle joystick events for raw driver elements (buttons, hats, axes)
Definition: IDriverHandler.h:23
Detects and dispatches mapping events.
Definition: ButtonMapping.h:47
Button map interface to translate between the driver&#39;s raw button/hat/axis elements and physical joys...
Definition: IButtonMap.h:29
Detects when a D-pad direction should be mapped.
Definition: ButtonMapping.h:93
Detects when a keyboard key should be mapped.
Definition: ButtonMapping.h:240
Detects when a mouse button should be mapped.
Definition: ButtonMapping.h:265
bool IsMapping() const
Check if the axis was mapped and is still in motion.
Definition: ButtonMapping.h:154
Definition: AudioDecoder.h:18
Generic implementation of a class that provides button mapping by translating driver events to button...
Definition: ButtonMapping.h:331
Interface for handling mouse driver events.
Definition: IMouseDriverHandler.h:22
Basic driver element associated with input events.
Definition: DriverPrimitive.h:70
Detects when a mouse button should be mapped.
Definition: ButtonMapping.h:290
Detects when an axis should be mapped.
Definition: ButtonMapping.h:125
Button mapper interface to assign the driver&#39;s raw button/hat/axis elements to physical joystick feat...
Definition: IButtonMapper.h:37
Interface for handling keyboard events.
Definition: IKeyboardDriverHandler.h:22
Interface for handling button maps.
Definition: IButtonMapCallback.h:20
Definition: Key.h:17
Interface for mapping buttons to Kodi actions.
Definition: IKeymap.h:28