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
|
/*
* 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;
};
|