1 /* GemRB - Infinity Engine Emulator
2  * Copyright (C) 2003 The GemRB Project
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13 
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  *
19  */
20 
21 /**
22  * @file EventMgr.h
23  * Declares EventMgr, class distributing events from input devices to GUI windows
24  * @author The GemRB Project
25  */
26 
27 
28 #ifndef EVENTMGR_H
29 #define EVENTMGR_H
30 
31 #include "exports.h"
32 #include "ie_types.h"
33 
34 #include "Callback.h"
35 #include "Region.h"
36 #include "System/String.h"
37 
38 #include <bitset>
39 #include <climits>
40 #include <cstdint>
41 #include <list>
42 #include <map>
43 #include <vector>
44 
45 namespace GemRB {
46 
47 class Control;
48 class Window;
49 
50 #define GEM_LEFT		0x81
51 #define GEM_RIGHT		0x82
52 #define GEM_UP			0x83
53 #define GEM_DOWN		0x84
54 #define GEM_DELETE		0x85
55 #define GEM_RETURN		0x86
56 #define GEM_BACKSP		0x87
57 #define GEM_TAB			0x88
58 #define GEM_ALT			0x89
59 #define GEM_HOME		0x8a
60 #define GEM_END			0x8b
61 #define GEM_ESCAPE		0x8c
62 #define GEM_PGUP		0x8d
63 #define GEM_PGDOWN		0x8e
64 #define GEM_GRAB		0x8f
65 
66 // 0x90 - 0x9f reserved for function keys (1-16)
67 #define GEM_FUNCTIONX(x) \
68 	(0x8F + x)
69 
70 #define GEM_MOD_SHIFT           1
71 #define GEM_MOD_CTRL            2
72 #define GEM_MOD_ALT             4
73 
74 // Mouse buttons
75 #define GEM_MB_ACTION           1
76 #define GEM_MB_MIDDLE           2
77 #define GEM_MB_MENU             4
78 
79 #define FINGER_MAX 5
80 
81 enum InputAxis : int8_t {
82 	AXIS_INVALID = -1,
83 	AXIS_LEFT_X,
84 	AXIS_LEFT_Y,
85 	AXIS_RIGHT_X,
86 	AXIS_RIGHT_Y
87 };
88 
89 enum ControllerButton : int8_t {
90 	CONTROLLER_INVALID = -1,
91 	CONTROLLER_BUTTON_A,
92 	CONTROLLER_BUTTON_B,
93 	CONTROLLER_BUTTON_X,
94 	CONTROLLER_BUTTON_Y,
95 	CONTROLLER_BUTTON_BACK,
96 	CONTROLLER_BUTTON_GUIDE,
97 	CONTROLLER_BUTTON_START,
98 	CONTROLLER_BUTTON_LEFTSTICK,
99 	CONTROLLER_BUTTON_RIGHTSTICK,
100 	CONTROLLER_BUTTON_LEFTSHOULDER,
101 	CONTROLLER_BUTTON_RIGHTSHOULDER,
102 	CONTROLLER_BUTTON_DPAD_UP,
103 	CONTROLLER_BUTTON_DPAD_DOWN,
104 	CONTROLLER_BUTTON_DPAD_LEFT,
105 	CONTROLLER_BUTTON_DPAD_RIGHT
106 };
107 
108 typedef unsigned char EventButton;
109 typedef unsigned short KeyboardKey;
110 typedef unsigned short ButtonMask;
111 
112 struct EventBase {
113 	unsigned short repeats; // number of times this event has been repeated (within the repeat time interval)
114 };
115 
116 struct ScreenEvent : public EventBase {
117 	// cant use Point due to non trival constructor
118 	int x,y; // mouse position at time of event
119 	int deltaX, deltaY; // the vector of motion/scroll
120 
PosScreenEvent121 	Point Pos() const { return Point(x,y); }
DeltaScreenEvent122 	Point Delta() const { return Point(deltaX, deltaY); }
123 };
124 
125 struct GEM_EXPORT MouseEvent : public ScreenEvent {
126 	ButtonMask buttonStates;
127 	EventButton button;
128 
ButtonStateMouseEvent129 	bool ButtonState(unsigned short btn) const {
130 		return buttonStates & btn;
131 	}
132 };
133 
134 struct GEM_EXPORT KeyboardEvent : public EventBase {
135 	KeyboardKey keycode; // raw keycode
136 	KeyboardKey character; // the translated character
137 };
138 
139 struct GEM_EXPORT TextEvent : public EventBase {
140 	String text; // activate the soft keyboard and disable hot keys until next (non TextEvent) event
141 };
142 
143 struct GEM_EXPORT ControllerEvent : public EventBase {
144 	InputAxis axis;
145 	float axisPct;
146 	int axisDelta;
147 	ButtonMask buttonStates;
148 	EventButton button;
149 };
150 
151 struct GEM_EXPORT TouchEvent : public ScreenEvent {
152 	struct Finger : public ScreenEvent {
153 		uint64_t id;
154 	};
155 
156 	Finger fingers[FINGER_MAX];
157 
158 	int numFingers;
159 	float pressure;
160 };
161 
162 struct GEM_EXPORT GestureEvent : public TouchEvent {
163 	float dTheta;
164 	float dDist;
165 };
166 
167 struct GEM_EXPORT Event {
168 	enum EventType {
169 		MouseMove = 0,
170 		MouseUp,
171 		MouseDown,
172 		MouseScroll,
173 
174 		KeyUp,
175 		KeyDown,
176 
177 		TouchGesture,
178 		TouchUp,
179 		TouchDown,
180 
181 		TextInput, // clipboard or faux event sent to signal the soft keyboard+temp disable hotkeys
182 
183 		ControllerAxis,
184 		ControllerButtonUp,
185 		ControllerButtonDown
186 
187 		// leaving off types for unused events
188 	};
189 
190 	enum EventTypeMask {
191 		NoEventsMask = 0U,
192 
193 		MouseMoveMask = 1 << MouseMove,
194 		MouseUpMask = 1 << MouseUp,
195 		MouseDownMask = 1 << MouseDown,
196 		MouseScrollMask = 1 << MouseScroll,
197 
198 		AllMouseMask = MouseMoveMask | MouseUpMask | MouseDownMask | MouseScrollMask,
199 
200 		KeyUpMask = 1 << KeyUp,
201 		KeyDownMask = 1 << KeyDown,
202 
203 		AllKeyMask = KeyUpMask | KeyDownMask,
204 
205 		TouchGestureMask = 1 << TouchGesture,
206 		TouchUpMask = 1 << TouchUp,
207 		TouchDownMask = 1 << TouchDown,
208 
209 		AllTouchMask = TouchGestureMask | TouchUpMask | TouchDownMask,
210 
211 		TextInputMask = 1 << TextInput,
212 
213 		ControllerAxisMask = 1 << ControllerAxis,
214 		ControllerButtonUpMask = 1 << ControllerButtonUp,
215 		ControllerButtonDownMask = 1 << ControllerButtonDown,
216 
217 		AllControllerMask = ControllerAxisMask | ControllerButtonUpMask | ControllerButtonDownMask,
218 
219 		AllEventsMask = 0xffffffffU
220 	};
221 
EventMaskFromTypeEvent222 	static EventTypeMask EventMaskFromType (EventType type) { return static_cast<EventTypeMask>(1U << type); };
223 
224 	union {
225 		MouseEvent mouse;
226 		ControllerEvent controller;
227 		KeyboardEvent keyboard;
228 		TouchEvent touch;
229 		GestureEvent gesture;
230 	};
231 
232 	TextEvent text; // text is nontrivial so it stands alone (until C++11 is allowed)
233 
234     typedef unsigned short EventMods;
235 
236 	EventType type;
237 	unsigned long time;
238 	EventMods mod; // modifier keys held during the event
239 	bool isScreen; // event coresponsds to location on screen
240 };
241 
242 MouseEvent MouseEventFromTouch(const TouchEvent& te, bool down);
243 MouseEvent MouseEventFromController(const ControllerEvent& ce, bool down);
244 KeyboardEvent KeyEventFromController(const ControllerEvent& ce);
245 
246 /**
247  * @class EventMgr
248  * Class distributing events from input devices to GUI windows.
249  * The events are pumped into instance of this class from a Video driver plugin
250  */
251 
252 class GEM_EXPORT EventMgr {
253 public:
254 	typedef std::bitset<sizeof(short) * CHAR_BIT> buttonbits;
255 	using EventCallback = Callback<bool, const Event&>;
256 	typedef size_t TapMonitorId;
257 
258 	static constexpr int mouseClickRadius = 5; // radius for reapeat click events
259 	static constexpr int mouseDragRadius = 10; // radius for drag events
260 
261 	static unsigned long DCDelay;
262 	static unsigned long DPDelay;
263 	static bool TouchInputEnabled;
264 
265 	static Event CreateMouseBtnEvent(const Point& pos, EventButton btn, bool down, int mod = 0);
266 	static Event CreateMouseMotionEvent(const Point& pos, int mod = 0);
267 	static Event CreateMouseWheelEvent(const Point& vec, int mod = 0);
268 
269 	static Event CreateKeyEvent(KeyboardKey key, bool down, int mod = 0);
270 
271 	static Event CreateTouchEvent(const TouchEvent::Finger fingers[], int numFingers, bool down, float pressure = 0.0);
272 	static Event CreateTouchGesture(const TouchEvent& touch, float rotation, float pinch);
273 
274 	static Event CreateTextEvent(const char* text);
275 	static Event CreateTextEvent(const String& text);
276 
277 	static Event CreateControllerAxisEvent(InputAxis axis, int delta, float pct);
278 	static Event CreateControllerButtonEvent(EventButton btn, bool down);
279 
280 	static bool RegisterHotKeyCallback(EventCallback, KeyboardKey key, short mod = 0);
281 	static void UnRegisterHotKeyCallback(EventCallback, KeyboardKey key, short mod = 0);
282 	static TapMonitorId RegisterEventMonitor(EventCallback, Event::EventTypeMask mask = Event::AllEventsMask);
283 	static void UnRegisterEventMonitor(TapMonitorId monitor);
284 
285 private:
286 	// FIXME: this shouldnt really be static... but im not sure we want direct access to the EventMgr instance...
287 	// currently the delays are static so it makes sense for now that the HotKeys are...
288 	// map combination of keyboard key and modifier keys to a callback
289 	typedef std::map<TapMonitorId, std::pair<Event::EventTypeMask, EventCallback> > EventTaps;
290 	typedef std::map<int, std::list<EventCallback> > KeyMap;
291 
292 	static EventTaps Taps;
293 	static KeyMap HotKeys;
294 
295 	static buttonbits mouseButtonFlags;
296 	static buttonbits modKeys;
297 	static Point mousePos;
298 
299 	static std::map<uint64_t, TouchEvent::Finger> fingerStates;
300 
301 	static buttonbits controllerButtonStates;
302 
303 public:
304 	void DispatchEvent(Event&& e);
305 
306 	static bool ModState(unsigned short mod);
307 
308 	static bool MouseButtonState(EventButton btn);
309 	static bool MouseDown();
MousePos()310 	static Point MousePos() { return mousePos; }
311 
FingerState(uint64_t id)312 	static const TouchEvent::Finger* FingerState(uint64_t id) { return (fingerStates.count(id)) ? &fingerStates[id] : NULL; };
313 	static bool FingerDown();
NumFingersDown()314 	static ieByte NumFingersDown() { return fingerStates.size(); };
315 
316 	static bool ControllerButtonState(EventButton btn);
317 };
318 
319 }
320 
321 #endif // ! EVENTMGR_H
322