summaryrefslogtreecommitdiffstats
path: root/xbmc/input/InputManager.h
blob: 52ad4591b38a1e9f0a7d9e91aa0e3b24425a085a (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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
/*
 *  Copyright (C) 2005-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 "input/KeyboardStat.h"
#include "input/actions/Action.h"
#include "input/button/ButtonStat.h"
#include "input/mouse/MouseStat.h"
#include "input/mouse/interfaces/IMouseInputProvider.h"
#include "interfaces/IActionListener.h"
#include "settings/lib/ISettingCallback.h"
#include "threads/CriticalSection.h"
#include "utils/Observer.h"
#include "windowing/XBMC_events.h"

#include <map>
#include <memory>
#include <string>
#include <vector>

class CButtonTranslator;
class CCustomControllerTranslator;
class CJoystickMapper;
class CKey;
class CProfileManager;
class CTouchTranslator;
class IKeymapEnvironment;
class IWindowKeymap;

namespace KODI
{

namespace KEYBOARD
{
class IKeyboardDriverHandler;
}

namespace MOUSE
{
class IMouseDriverHandler;
}
} // namespace KODI

/// \addtogroup input
/// \{

/*!
 * \ingroup input keyboard mouse touch joystick
 * \brief Main input processing class.
 *
 * This class consolidates all input generated from different sources such as
 * mouse, keyboard, joystick or touch (in \ref OnEvent).
 *
 * \copydoc keyboard
 * \copydoc mouse
 */
class CInputManager : public ISettingCallback, public IActionListener, public Observable
{
public:
  CInputManager();
  CInputManager(const CInputManager&) = delete;
  CInputManager const& operator=(CInputManager const&) = delete;
  ~CInputManager() override;

  /*! \brief decode a mouse event and reset idle timers.
   *
   * \param windowId Currently active window
   * \return true if event is handled, false otherwise
   */
  bool ProcessMouse(int windowId);

  /*! \brief decode an event from the event service, this can be mouse, key, joystick, reset idle
   * timers.
   *
   * \param windowId Currently active window
   * \param frameTime Time in seconds since last call
   * \return true if event is handled, false otherwise
   */
  bool ProcessEventServer(int windowId, float frameTime);

  /*! \brief decode an event from peripherals.
   *
   * \param frameTime Time in seconds since last call
   * \return true if event is handled, false otherwise
   */
  bool ProcessPeripherals(float frameTime);

  /*! \brief Process all inputs
   *
   * \param windowId Currently active window
   * \param frameTime Time in seconds since last call
   * \return true on success, false otherwise
   */
  bool Process(int windowId, float frameTime);

  /*!
   * \brief Call once during application startup to initialize peripherals that need it
   */
  void InitializeInputs();

  /*!
   * \brief Deinitialize input and keymaps
   */
  void Deinitialize();

  /*! \brief Handle an input event
   *
   * \param newEvent event details
   * \return true on successfully handled event
   * \sa XBMC_Event
   */
  bool OnEvent(XBMC_Event& newEvent);

  /*! \brief Control if the mouse is actively used or not
   *
   * \param[in] active sets mouse active or inactive
   */
  void SetMouseActive(bool active = true);

  /*! \brief Control if we should use a mouse or not
   *
   * \param[in] mouseEnabled sets mouse enabled or disabled
   */
  void SetMouseEnabled(bool mouseEnabled = true);

  /*! \brief Set the current state of the mouse such as click, drag operation
   *
   * \param[in] mouseState which state the mouse should be set to
   * \sa MOUSE_STATE
   */
  void SetMouseState(MOUSE_STATE mouseState);

  /*! \brief Check if the mouse is currently active
   *
   * \return true if active, false otherwise
   */
  bool IsMouseActive();

  /*! \brief Get the current state of the mouse, such as click or drag operation
   *
   * \return the current state of the mouse as a value from MOUSE_STATE
   * \sa MOUSE_STATE
   */
  MOUSE_STATE GetMouseState();

  /*! \brief Get the current mouse positions x and y coordinates
   *
   * \return a struct containing the x and y coordinates
   * \sa MousePosition
   */
  MousePosition GetMousePosition();

  /*! \brief Set the current screen resolution and pointer speed
   *
   * \param[in] maxX    screen width
   * \param[in] maxY    screen height
   * \param[in] speedX  mouse speed in x dimension
   * \param[in] speedY  mouse speed in y dimension
   * \return
   */
  void SetMouseResolution(int maxX, int maxY, float speedX, float speedY);

  /*! \brief Get the status of the controller-enable setting
   * \return True if controller input is enabled for the UI, false otherwise
   */
  bool IsControllerEnabled() const;

  /*! \brief Returns whether or not we can handle a given built-in command.
   *
   */
  bool HasBuiltin(const std::string& command);

  /*! \brief Parse a builtin command and execute any input action
   *  currently only LIRC commands implemented
   *
   * \param[in] execute Command to execute
   * \param[in] params  parameters that was passed to the command
   * \return 0 on success, -1 on failure
   */
  int ExecuteBuiltin(const std::string& execute, const std::vector<std::string>& params);

  // Button translation
  bool LoadKeymaps();
  bool ReloadKeymaps();
  void ClearKeymaps();
  void AddKeymap(const std::string& keymap);
  void RemoveKeymap(const std::string& keymap);

  const IKeymapEnvironment* KeymapEnvironment() const { return m_keymapEnvironment.get(); }

  /*! \brief Obtain the action configured for a given window and key
   *
   * \param window the window id
   * \param key the key to query the action for
   * \param fallback if no action is directly configured for the given window, obtain the action
   * from fallback window, if exists or from global config as last resort
   *
   * \return the action matching the key
   */
  CAction GetAction(int window, const CKey& key, bool fallback = true);

  bool TranslateCustomControllerString(int windowId,
                                       const std::string& controllerName,
                                       int buttonId,
                                       int& action,
                                       std::string& strAction);

  bool TranslateTouchAction(
      int windowId, int touchAction, int touchPointers, int& action, std::string& actionString);

  std::vector<std::shared_ptr<const IWindowKeymap>> GetJoystickKeymaps() const;

  /*!
   * \brief Queue an action to be processed on the next call to Process()
   */
  void QueueAction(const CAction& action);

  // implementation of ISettingCallback
  void OnSettingChanged(const std::shared_ptr<const CSetting>& setting) override;

  // implementation of IActionListener
  bool OnAction(const CAction& action) override;

  void RegisterKeyboardDriverHandler(KODI::KEYBOARD::IKeyboardDriverHandler* handler);
  void UnregisterKeyboardDriverHandler(KODI::KEYBOARD::IKeyboardDriverHandler* handler);

  virtual void RegisterMouseDriverHandler(KODI::MOUSE::IMouseDriverHandler* handler);
  virtual void UnregisterMouseDriverHandler(KODI::MOUSE::IMouseDriverHandler* handler);

private:
  /*! \brief Process keyboard event and translate into an action
   *
   * \param key keypress details
   * \return true on successfully handled event
   * \sa CKey
   */
  bool OnKey(const CKey& key);

  /*! \brief Process key up event
   *
   * \param key details of released key
   * \sa CKey
   */
  void OnKeyUp(const CKey& key);

  /*! \brief Handle keypress
   *
   * \param key keypress details
   * \return true on successfully handled event
   */
  bool HandleKey(const CKey& key);

  /*! \brief Determine if an action should be processed or just
   *   cancel the screensaver
   *
   * \param action Action that is about to be processed
   * \return true on any poweractions such as shutdown/reboot/sleep/suspend, false otherwise
   * \sa CAction
   */
  bool AlwaysProcess(const CAction& action);

  /*! \brief Send the Action to CApplication for further handling,
   *   play a sound before or after sending the action.
   *
   * \param action Action to send to CApplication
   * \return result from CApplication::OnAction
   * \sa CAction
   */
  bool ExecuteInputAction(const CAction& action);

  /*! \brief Dispatch actions queued since the last call to Process()
   */
  void ProcessQueuedActions();

  CKeyboardStat m_Keyboard;
  KODI::INPUT::CButtonStat m_buttonStat;
  CMouseStat m_Mouse;
  CKey m_LastKey;

  std::map<std::string, std::map<int, float>> m_lastAxisMap;

  std::vector<CAction> m_queuedActions;
  CCriticalSection m_actionMutex;

  // Button translation
  std::unique_ptr<IKeymapEnvironment> m_keymapEnvironment;
  std::unique_ptr<CButtonTranslator> m_buttonTranslator;
  std::unique_ptr<CCustomControllerTranslator> m_customControllerTranslator;
  std::unique_ptr<CTouchTranslator> m_touchTranslator;
  std::unique_ptr<CJoystickMapper> m_joystickTranslator;

  std::vector<KODI::KEYBOARD::IKeyboardDriverHandler*> m_keyboardHandlers;
  std::vector<KODI::MOUSE::IMouseDriverHandler*> m_mouseHandlers;

  std::unique_ptr<KODI::KEYBOARD::IKeyboardDriverHandler> m_keyboardEasterEgg;

  // Input state
  bool m_enableController = true;

  // Settings
  static const std::string SETTING_INPUT_ENABLE_CONTROLLER;
};

/// \}