diff options
Diffstat (limited to 'xbmc/input/mouse/MouseStat.h')
-rw-r--r-- | xbmc/input/mouse/MouseStat.h | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/xbmc/input/mouse/MouseStat.h b/xbmc/input/mouse/MouseStat.h new file mode 100644 index 0000000..354d1c3 --- /dev/null +++ b/xbmc/input/mouse/MouseStat.h @@ -0,0 +1,227 @@ +/* + * 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 "windowing/XBMC_events.h" + +#define XBMC_BUTTON(X) (1 << ((X)-1)) +#define XBMC_BUTTON_LEFT 1 +#define XBMC_BUTTON_MIDDLE 2 +#define XBMC_BUTTON_RIGHT 3 +#define XBMC_BUTTON_WHEELUP 4 +#define XBMC_BUTTON_WHEELDOWN 5 +#define XBMC_BUTTON_X1 6 +#define XBMC_BUTTON_X2 7 +#define XBMC_BUTTON_X3 8 +#define XBMC_BUTTON_X4 9 +#define XBMC_BUTTON_LMASK XBMC_BUTTON(XBMC_BUTTON_LEFT) +#define XBMC_BUTTON_MMASK XBMC_BUTTON(XBMC_BUTTON_MIDDLE) +#define XBMC_BUTTON_RMASK XBMC_BUTTON(XBMC_BUTTON_RIGHT) +#define XBMC_BUTTON_X1MASK XBMC_BUTTON(XBMC_BUTTON_X1) +#define XBMC_BUTTON_X2MASK XBMC_BUTTON(XBMC_BUTTON_X2) +#define XBMC_BUTTON_X3MASK XBMC_BUTTON(XBMC_BUTTON_X3) +#define XBMC_BUTTON_X4MASK XBMC_BUTTON(XBMC_BUTTON_X4) + +#define MOUSE_MINIMUM_MOVEMENT 2 +#define MOUSE_DOUBLE_CLICK_LENGTH 500L +#define MOUSE_ACTIVE_LENGTH 5000L + +#define MOUSE_MAX_BUTTON 7 + +enum MOUSE_STATE +{ + /*! Normal state */ + MOUSE_STATE_NORMAL = 1, + /*! Control below the mouse is currently in focus */ + MOUSE_STATE_FOCUS, + /*! A drag operation is being performed */ + MOUSE_STATE_DRAG, + /*! A mousebutton is being clicked */ + MOUSE_STATE_CLICK +}; + +enum MOUSE_BUTTON +{ + MOUSE_LEFT_BUTTON = 0, + MOUSE_RIGHT_BUTTON, + MOUSE_MIDDLE_BUTTON, + MOUSE_EXTRA_BUTTON1, + MOUSE_EXTRA_BUTTON2, + MOUSE_EXTRA_BUTTON3, + MOUSE_EXTRA_BUTTON4 +}; + +enum class HoldAction +{ + /*! No action should occur */ + NONE, + /*! A drag action has started */ + DRAG_START, + /*! A drag action is in progress */ + DRAG, + /*! A drag action has finished */ + DRAG_END +}; + +//! Holds everything we know about the current state of the mouse +struct MouseState +{ + /*! X location */ + int x; + /*! Y location */ + int y; + /*! Change in x */ + int16_t dx; + /*! Change in y */ + int16_t dy; + /*! Change in z (wheel) */ + int8_t dz; + /*! Current state of the buttons */ + bool button[MOUSE_MAX_BUTTON]; + /*! True if the mouse is active */ + bool active; +}; + +struct MousePosition +{ + int x; + int y; +}; + +class CAction; + +class CMouseStat +{ +public: + CMouseStat(); + virtual ~CMouseStat(); + + void Initialize(); + void HandleEvent(const XBMC_Event& newEvent); + void SetResolution(int maxX, int maxY, float speedX, float speedY); + bool IsActive(); + bool IsEnabled() const; + + void SetActive(bool active = true); + void SetState(MOUSE_STATE state) { m_pointerState = state; } + void SetEnabled(bool enabled = true); + MOUSE_STATE GetState() const { return m_pointerState; } + uint32_t GetKey() const; + + HoldAction GetHold(int ButtonID) const; + inline int GetX(void) const { return m_mouseState.x; } + inline int GetY(void) const { return m_mouseState.y; } + inline int GetDX(void) const { return m_mouseState.dx; } + inline int GetDY(void) const { return m_mouseState.dy; } + MousePosition GetPosition() { return MousePosition{m_mouseState.x, m_mouseState.y}; } + +private: + /*! \brief Holds information regarding a particular mouse button state + + The CButtonState class is used to track where in a button event the mouse currently is. + There is effectively 5 BUTTON_STATE's available, and transitioning between those states + is handled by the Update() function. + + The actions we detect are: + * short clicks - down/up press of the mouse within short_click_time ms, where the pointer stays + within click_confines pixels + * long clicks - down/up press of the mouse greater than short_click_time ms, where the pointers + stays within click_confines pixels + * double clicks - a further down press of the mouse within double_click_time of the up press of + a short click, where the pointer stays within click_confines pixels + * drag - the mouse is down and has been moved more than click_confines pixels + + \sa CMouseStat + */ + class CButtonState + { + public: + /*! \brief enum for the actions to perform as a result of an Update function + */ + enum BUTTON_ACTION + { + MB_NONE = 0, ///< no action should occur + MB_SHORT_CLICK, ///< a short click has occurred (a double click may be in process) + MB_LONG_CLICK, ///< a long click has occurred + MB_DOUBLE_CLICK, ///< a double click has occurred + MB_DRAG_START, ///< a drag action has started + MB_DRAG, ///< a drag action is in progress + MB_DRAG_END + }; ///< a drag action has finished + + CButtonState(); + + /*! \brief Update the button state, with where the mouse is, and whether the button is down or + not + + \param time frame time in ms + \param x horizontal coordinate of the mouse + \param y vertical coordinate of the mouse + \param down true if the button is down + \return action that should be performed + */ + BUTTON_ACTION Update(unsigned int time, int x, int y, bool down); + + private: + //! number of pixels that the pointer may move while the button is down to + //! trigger a click + static const unsigned int click_confines = 5; + + //! Time for mouse down/up to trigger a short click rather than a long click + static const unsigned int short_click_time = 1000; + + //! Time for mouse down following a short click to trigger a double click + static const unsigned int double_click_time = 500; + + bool InClickRange(int x, int y) const; + + enum BUTTON_STATE + { + STATE_RELEASED = 0, ///< mouse button is released, no events pending + STATE_IN_CLICK, ///< mouse button is down, a click is pending + STATE_IN_DOUBLE_CLICK, ///< mouse button is released, pending double click + STATE_IN_DOUBLE_IGNORE, ///< mouse button is down following double click + STATE_IN_DRAG + }; ///< mouse button is down during a drag + + BUTTON_STATE m_state; + unsigned int m_time; + int m_x; + int m_y; + }; + + /*! \brief detect whether the mouse has moved + + Uses a trigger threshold of 2 pixels to detect mouse movement + + \return whether the mouse has moved past the trigger threshold. + */ + bool MovedPastThreshold() const; + + // state of the mouse + MOUSE_STATE m_pointerState{MOUSE_STATE_NORMAL}; + MouseState m_mouseState{}; + bool m_mouseEnabled; + CButtonState m_buttonState[MOUSE_MAX_BUTTON]; + + int m_maxX{0}; + int m_maxY{0}; + float m_speedX{0.0f}; + float m_speedY{0.0f}; + + // active/click timers + unsigned int m_lastActiveTime; + + bool bClick[MOUSE_MAX_BUTTON]{}; + bool bDoubleClick[MOUSE_MAX_BUTTON]{}; + HoldAction m_hold[MOUSE_MAX_BUTTON]{}; + bool bLongClick[MOUSE_MAX_BUTTON]{}; + + uint32_t m_Key; +}; |