1 /*
2  *  Copyright (C) 2005-2018 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/KeyboardStat.h"
12 #include "input/actions/Action.h"
13 #include "input/button/ButtonStat.h"
14 #include "input/mouse/MouseStat.h"
15 #include "input/mouse/interfaces/IMouseInputProvider.h"
16 #include "interfaces/IActionListener.h"
17 #include "settings/lib/ISettingCallback.h"
18 #include "threads/CriticalSection.h"
19 #include "utils/Observer.h"
20 #include "windowing/XBMC_events.h"
21 
22 #include <map>
23 #include <memory>
24 #include <string>
25 #include <vector>
26 
27 class CAppParamParser;
28 class CButtonTranslator;
29 class CCustomControllerTranslator;
30 class CJoystickMapper;
31 class CKey;
32 class CProfileManager;
33 class CTouchTranslator;
34 class IKeymapEnvironment;
35 class IWindowKeymap;
36 
37 namespace KODI
38 {
39 
40 namespace KEYBOARD
41 {
42 class IKeyboardDriverHandler;
43 }
44 
45 namespace MOUSE
46 {
47 class IMouseDriverHandler;
48 }
49 } // namespace KODI
50 
51 /// \addtogroup input
52 /// \{
53 
54 /*!
55  * \ingroup input keyboard mouse touch joystick
56  * \brief Main input processing class.
57  *
58  * This class consolidates all input generated from different sources such as
59  * mouse, keyboard, joystick or touch (in \ref OnEvent).
60  *
61  * \copydoc keyboard
62  * \copydoc mouse
63  */
64 class CInputManager : public ISettingCallback, public IActionListener, public Observable
65 {
66 public:
67   explicit CInputManager(const CAppParamParser& params);
68   CInputManager(const CInputManager&) = delete;
69   CInputManager const& operator=(CInputManager const&) = delete;
70   ~CInputManager() override;
71 
72   /*! \brief decode a mouse event and reset idle timers.
73    *
74    * \param windowId Currently active window
75    * \return true if event is handled, false otherwise
76    */
77   bool ProcessMouse(int windowId);
78 
79   /*! \brief decode an event from the event service, this can be mouse, key, joystick, reset idle
80    * timers.
81    *
82    * \param windowId Currently active window
83    * \param frameTime Time in seconds since last call
84    * \return true if event is handled, false otherwise
85    */
86   bool ProcessEventServer(int windowId, float frameTime);
87 
88   /*! \brief decode an event from peripherals.
89    *
90    * \param frameTime Time in seconds since last call
91    * \return true if event is handled, false otherwise
92    */
93   bool ProcessPeripherals(float frameTime);
94 
95   /*! \brief Process all inputs
96    *
97    * \param windowId Currently active window
98    * \param frameTime Time in seconds since last call
99    * \return true on success, false otherwise
100    */
101   bool Process(int windowId, float frameTime);
102 
103   /*!
104    * \brief Call once during application startup to initialize peripherals that need it
105    */
106   void InitializeInputs();
107 
108   /*!
109    * \brief Deinitialize input and keymaps
110    */
111   void Deinitialize();
112 
113   /*! \brief Handle an input event
114    *
115    * \param newEvent event details
116    * \return true on successfully handled event
117    * \sa XBMC_Event
118    */
119   bool OnEvent(XBMC_Event& newEvent);
120 
121   /*! \brief Control if the mouse is actively used or not
122    *
123    * \param[in] active sets mouse active or inactive
124    */
125   void SetMouseActive(bool active = true);
126 
127   /*! \brief Control if we should use a mouse or not
128    *
129    * \param[in] mouseEnabled sets mouse enabled or disabled
130    */
131   void SetMouseEnabled(bool mouseEnabled = true);
132 
133   /*! \brief Set the current state of the mouse such as click, drag operation
134    *
135    * \param[in] mouseState which state the mouse should be set to
136    * \sa MOUSE_STATE
137    */
138   void SetMouseState(MOUSE_STATE mouseState);
139 
140   /*! \brief Check if the mouse is currently active
141    *
142    * \return true if active, false otherwise
143    */
144   bool IsMouseActive();
145 
146   /*! \brief Get the current state of the mouse, such as click or drag operation
147    *
148    * \return the current state of the mouse as a value from MOUSE_STATE
149    * \sa MOUSE_STATE
150    */
151   MOUSE_STATE GetMouseState();
152 
153   /*! \brief Get the current mouse positions x and y coordinates
154    *
155    * \return a struct containing the x and y coordinates
156    * \sa MousePosition
157    */
158   MousePosition GetMousePosition();
159 
160   /*! \brief Set the current screen resolution and pointer speed
161    *
162    * \param[in] maxX    screen width
163    * \param[in] maxY    screen height
164    * \param[in] speedX  mouse speed in x dimension
165    * \param[in] speedY  mouse speed in y dimension
166    * \return
167    */
168   void SetMouseResolution(int maxX, int maxY, float speedX, float speedY);
169 
170   /*! \brief Get the status of the controller-enable setting
171    * \return True if controller input is enabled for the UI, false otherwise
172    */
173   bool IsControllerEnabled() const;
174 
175   /*! \brief Returns whether or not we can handle a given built-in command.
176    *
177    */
178   bool HasBuiltin(const std::string& command);
179 
180   /*! \brief Parse a builtin command and execute any input action
181    *  currently only LIRC commands implemented
182    *
183    * \param[in] execute Command to execute
184    * \param[in] params  parameters that was passed to the command
185    * \return 0 on success, -1 on failure
186    */
187   int ExecuteBuiltin(const std::string& execute, const std::vector<std::string>& params);
188 
189   // Button translation
190   bool LoadKeymaps();
191   bool ReloadKeymaps();
192   void ClearKeymaps();
193   void AddKeymap(const std::string& keymap);
194   void RemoveKeymap(const std::string& keymap);
195 
KeymapEnvironment()196   const IKeymapEnvironment* KeymapEnvironment() const { return m_keymapEnvironment.get(); }
197 
198   /*! \brief Obtain the action configured for a given window and key
199    *
200    * \param window the window id
201    * \param key the key to query the action for
202    * \param fallback if no action is directly configured for the given window, obtain the action
203    * from fallback window, if exists or from global config as last resort
204    *
205    * \return the action matching the key
206    */
207   CAction GetAction(int window, const CKey& key, bool fallback = true);
208 
209   bool TranslateCustomControllerString(int windowId,
210                                        const std::string& controllerName,
211                                        int buttonId,
212                                        int& action,
213                                        std::string& strAction);
214 
215   bool TranslateTouchAction(
216       int windowId, int touchAction, int touchPointers, int& action, std::string& actionString);
217 
218   std::vector<std::shared_ptr<const IWindowKeymap>> GetJoystickKeymaps() const;
219 
220   /*!
221    * \brief Queue an action to be processed on the next call to Process()
222    */
223   void QueueAction(const CAction& action);
224 
225   // implementation of ISettingCallback
226   void OnSettingChanged(const std::shared_ptr<const CSetting>& setting) override;
227 
228   // implementation of IActionListener
229   bool OnAction(const CAction& action) override;
230 
231   void RegisterKeyboardDriverHandler(KODI::KEYBOARD::IKeyboardDriverHandler* handler);
232   void UnregisterKeyboardDriverHandler(KODI::KEYBOARD::IKeyboardDriverHandler* handler);
233 
234   virtual void RegisterMouseDriverHandler(KODI::MOUSE::IMouseDriverHandler* handler);
235   virtual void UnregisterMouseDriverHandler(KODI::MOUSE::IMouseDriverHandler* handler);
236 
237 private:
238   /*! \brief Process keyboard event and translate into an action
239    *
240    * \param key keypress details
241    * \return true on successfully handled event
242    * \sa CKey
243    */
244   bool OnKey(const CKey& key);
245 
246   /*! \brief Process key up event
247    *
248    * \param key details of released key
249    * \sa CKey
250    */
251   void OnKeyUp(const CKey& key);
252 
253   /*! \brief Handle keypress
254    *
255    * \param key keypress details
256    * \return true on successfully handled event
257    */
258   bool HandleKey(const CKey& key);
259 
260   /*! \brief Determine if an action should be processed or just
261    *   cancel the screensaver
262    *
263    * \param action Action that is about to be processed
264    * \return true on any poweractions such as shutdown/reboot/sleep/suspend, false otherwise
265    * \sa CAction
266    */
267   bool AlwaysProcess(const CAction& action);
268 
269   /*! \brief Send the Action to CApplication for further handling,
270    *   play a sound before or after sending the action.
271    *
272    * \param action Action to send to CApplication
273    * \return result from CApplication::OnAction
274    * \sa CAction
275    */
276   bool ExecuteInputAction(const CAction& action);
277 
278   /*! \brief Dispatch actions queued since the last call to Process()
279    */
280   void ProcessQueuedActions();
281 
282   CKeyboardStat m_Keyboard;
283   KODI::INPUT::CButtonStat m_buttonStat;
284   CMouseStat m_Mouse;
285   CKey m_LastKey;
286 
287   std::map<std::string, std::map<int, float>> m_lastAxisMap;
288 
289   std::vector<CAction> m_queuedActions;
290   CCriticalSection m_actionMutex;
291 
292   // Button translation
293   std::unique_ptr<IKeymapEnvironment> m_keymapEnvironment;
294   std::unique_ptr<CButtonTranslator> m_buttonTranslator;
295   std::unique_ptr<CCustomControllerTranslator> m_customControllerTranslator;
296   std::unique_ptr<CTouchTranslator> m_touchTranslator;
297   std::unique_ptr<CJoystickMapper> m_joystickTranslator;
298 
299   std::vector<KODI::KEYBOARD::IKeyboardDriverHandler*> m_keyboardHandlers;
300   std::vector<KODI::MOUSE::IMouseDriverHandler*> m_mouseHandlers;
301 
302   std::unique_ptr<KODI::KEYBOARD::IKeyboardDriverHandler> m_keyboardEasterEgg;
303 
304   // Input state
305   bool m_enableController = true;
306 
307   // Settings
308   static const std::string SETTING_INPUT_ENABLE_CONTROLLER;
309 };
310 
311 /// \}
312