1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef GLK_EVENTS_H
24 #define GLK_EVENTS_H
25 
26 #include "common/events.h"
27 #include "graphics/surface.h"
28 #include "glk/utils.h"
29 
30 namespace Glk {
31 
32 #define GAME_FRAME_RATE 100
33 #define GAME_FRAME_TIME (1000 / GAME_FRAME_RATE)
34 
35 class Window;
36 
37 /**
38  * Event types
39  */
40 enum EvType {
41 	evtype_None         = 0,
42 	evtype_Timer        = 1,
43 	evtype_CharInput    = 2,
44 	evtype_LineInput    = 3,
45 	evtype_MouseInput   = 4,
46 	evtype_Arrange      = 5,
47 	evtype_Redraw       = 6,
48 	evtype_SoundNotify  = 7,
49 	evtype_Hyperlink    = 8,
50 	evtype_VolumeNotify = 9,
51 
52 	// ScummVM custom events
53 	evtype_Quit         = 99
54 };
55 
56 /**
57  * Keycodes
58  */
59 enum Keycode {
60 	keycode_Unknown  = 0xffffffffU,
61 	keycode_Left     = 0xfffffffeU,
62 	keycode_Right    = 0xfffffffdU,
63 	keycode_Up       = 0xfffffffcU,
64 	keycode_Down     = 0xfffffffbU,
65 	keycode_Return   = 0xfffffffaU,
66 	keycode_Delete   = 0xfffffff9U,
67 	keycode_Escape   = 0xfffffff8U,
68 	keycode_Tab      = 0xfffffff7U,
69 	keycode_PageUp   = 0xfffffff6U,
70 	keycode_PageDown = 0xfffffff5U,
71 	keycode_Home     = 0xfffffff4U,
72 	keycode_End      = 0xfffffff3U,
73 	keycode_Func1    = 0xffffffefU,
74 	keycode_Func2    = 0xffffffeeU,
75 	keycode_Func3    = 0xffffffedU,
76 	keycode_Func4    = 0xffffffecU,
77 	keycode_Func5    = 0xffffffebU,
78 	keycode_Func6    = 0xffffffeaU,
79 	keycode_Func7    = 0xffffffe9U,
80 	keycode_Func8    = 0xffffffe8U,
81 	keycode_Func9    = 0xffffffe7U,
82 	keycode_Func10   = 0xffffffe6U,
83 	keycode_Func11   = 0xffffffe5U,
84 	keycode_Func12   = 0xffffffe4U,
85 
86 	// non standard keycodes
87 	keycode_Erase          = 0xffffef7fU,
88 	keycode_MouseWheelUp   = 0xffffeffeU,
89 	keycode_MouseWheelDown = 0xffffefffU,
90 	keycode_SkipWordLeft   = 0xfffff000U,
91 	keycode_SkipWordRight  = 0xfffff001U,
92 
93 	// The last keycode is always = 0x100000000 - keycode_MAXVAL)
94 	keycode_MAXVAL = 28U
95 };
96 
97 /**
98  * List of cursors
99  */
100 enum CursorId {
101 	CURSOR_NONE = 0,
102 	CURSOR_ARROW = 1,
103 	CURSOR_IBEAM = 2,
104 	CURSOR_HAND = 3
105 };
106 
107 /**
108  * Event structure
109  */
110 struct Event {
111 	EvType type;
112 	Window *window;
113 	uint val1, val2;
114 
115 	/**
116 	 * Constructor
117 	 */
EventEvent118 	Event() {
119 		clear();
120 	}
121 
122 	/**
123 	 * Constructor
124 	 */
EventEvent125 	Event(EvType evType, Window *evWindow, uint evVal1, uint evVal2) {
126 		type = evType;
127 		window = evWindow;
128 		val1 = evVal1;
129 		val2 = evVal2;
130 	}
131 
132 	/**
133 	 * Clear
134 	 */
clearEvent135 	void clear() {
136 		type = evtype_None;
137 		window = nullptr;
138 		val1 = val2 = 0;
139 	}
140 
141 	/**
142 	 * Boolean cast to allow checking whether event is filled out
143 	 */
144 	operator bool() const {
145 		return type != evtype_None;
146 	}
147 };
148 typedef Event event_t;
149 
150 class EventQueue : public Common::Queue<Event> {
151 public:
152 	/**
153 	 * Retrieve a pending event, if any
154 	 */
retrieve()155 	Event retrieve() {
156 		return empty() ? Event() : pop();
157 	}
158 };
159 
160 /**
161  * Events manager
162  */
163 class Events {
164 	struct Surface : public Graphics::Surface {
165 		Common::Point _hotspot;
166 	};
167 private:
168 	EventQueue _eventsPolled;       ///< User generated events
169 	EventQueue _eventsLogged;       ///< Custom events generated by game code
170 	Event *_currentEvent;           ///< Event pointer passed during event retrieval
171 	uint32 _priorFrameTime;         ///< Time of prior game frame
172 	uint32 _frameCounter;           ///< Frame counter
173 	bool _redraw;                   ///< Screen needed redrawing
174 	CursorId _cursorId;             ///< Current cursor Id
175 	Surface _cursors[4];            ///< Cursor pixel data
176 	uint _timerMilli;               ///< Time in milliseconds between timer events
177 	uint _timerTimeExpiry;          ///< When to trigger next timer event
178 private:
179 	/**
180 	 * Initialize the cursor graphics
181 	 */
182 	void initializeCursors();
183 
184 	/**
185 	 * Checks for whether it's time for the next game frame
186 	 */
187 	void checkForNextFrameCounter();
188 
189 	/**
190 	 * Dispatches an event
191 	 */
192 	void dispatchEvent(Event &ev, bool polled);
193 
194 	/**
195 	 * Poll for user events
196 	 */
197 	void pollEvents();
198 
199 	/**
200 	 * Handle a key down event
201 	 */
202 	void handleKeyDown(const Common::KeyState &ks);
203 
204 	/**
205 	 * Handle scroll events
206 	 */
207 	void handleScroll(bool wheelUp);
208 
209 	/**
210 	 * Handle mouse move events
211 	 */
212 	void handleMouseMove(const Point &pos);
213 
214 	/**
215 	 * Handle mouse down events
216 	 */
217 	void handleButtonDown(bool isLeft, const Point &pos);
218 
219 	/**
220 	 * Handle mouse up events
221 	 */
222 	void handleButtonUp(bool isLeft, const Point &pos);
223 
224 	/**
225 	 * Returns true if the passed keycode is for the Ctrl or Alt keys
226 	 */
227 	bool isModifierKey(const Common::KeyCode &keycode) const;
228 public:
229 	bool _forceClick;
230 public:
231 	/**
232 	 * Constructor
233 	 */
234 	Events();
235 
236 	/**
237 	 * Destructor
238 	 */
239 	~Events();
240 
241 	/**
242 	  * Get any pending event
243 	  */
244 	void getEvent(event_t *event, bool polled);
245 
246 	/**
247 	 * Store an event for retrieval
248 	 */
249 	void store(EvType type, Window *win, uint val1 = 0, uint val2 = 0);
250 
251 	/**
252 	 * Wait for a keypress
253 	 */
254 	uint getKeypress();
255 
256 	/**
257 	 * Wait for a keyboard or mouse press
258 	 */
259 	void waitForPress();
260 
261 	/**
262 	 * Get the total number of frames played
263 	 */
getTotalPlayTicks()264 	uint32 getTotalPlayTicks() const {
265 		return _frameCounter;
266 	}
267 
268 	/**
269 	 * Set the total number of frames played
270 	 */
setTotalPlayTicks(uint frames)271 	void setTotalPlayTicks(uint frames) {
272 		_frameCounter = frames;
273 	}
274 
275 	/**
276 	 * Flags the screen for redrawing
277 	 */
redraw()278 	void redraw() {
279 		_redraw = true;
280 	}
281 
282 	/**
283 	 * Sets the current cursor
284 	 */
285 	void setCursor(CursorId cursorId);
286 
287 	/**
288 	 * Sets whether the mouse cursor is visible
289 	 * @remarks Normally the cursor is visible for all games, even for those that didn't have mouse originally,
290 	 * so as to allow for common Glk functionality for selecting ranges of text
291 	 */
292 	void showMouseCursor(bool visible);
293 
294 	/**
295 	 * Set a timer interval
296 	 * @param   milli       Time in millieseconds for intervals, or 0 for off
297 	 */
298 	void setTimerInterval(uint milli);
299 
300 	/**
301 	 * Returns true if it's time for a timer event
302 	 */
303 	bool isTimerExpired() const;
304 };
305 
306 } // End of namespace Glk
307 
308 #endif
309