1 /***************************************************************************
2  *   Copyright (C) 2005-2019 by the FIFE team                              *
3  *   http://www.fifengine.net                                              *
4  *   This file is part of FIFE.                                            *
5  *                                                                         *
6  *   FIFE is free software; you can redistribute it and/or                 *
7  *   modify it under the terms of the GNU Lesser General Public            *
8  *   License as published by the Free Software Foundation; either          *
9  *   version 2.1 of the License, or (at your option) any later version.    *
10  *                                                                         *
11  *   This library is distributed in the hope that it will be useful,       *
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
14  *   Lesser General Public License for more details.                       *
15  *                                                                         *
16  *   You should have received a copy of the GNU Lesser General Public      *
17  *   License along with this library; if not, write to the                 *
18  *   Free Software Foundation, Inc.,                                       *
19  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
20  ***************************************************************************/
21 
22 // Standard C++ library includes
23 #include <iostream>
24 
25 // 3rd party library includes
26 
27 // FIFE includes
28 // These includes are split up in two parts, separated by one empty line
29 // First block: files included from the FIFE root src directory
30 // Second block: files included from the same folder
31 #include "util/base/exception.h"
32 #include "util/log/logger.h"
33 #include "util/math/fife_math.h"
34 #include "eventchannel/joystick/joystickmanager.h"
35 #include "eventchannel/key/key.h"
36 #include "eventchannel/key/keyevent.h"
37 #include "eventchannel/key/ikeyfilter.h"
38 #include "eventchannel/mouse/mouseevent.h"
39 #include "eventchannel/command/command.h"
40 #include "video/renderbackend.h"
41 
42 #include "eventmanager.h"
43 
44 namespace FIFE {
45 	static Logger _log(LM_EVTCHANNEL);
46 
EventManager()47 	EventManager::EventManager():
48 		m_commandListeners(),
49 		m_keyListeners(),
50 		m_textListeners(),
51 		m_mouseListeners(),
52 		m_sdleventListeners(),
53 		m_keystatemap(),
54 		m_keyfilter(0),
55 		m_mousestate(0),
56 		m_mostrecentbtn(MouseEvent::EMPTY),
57 		m_mouseSensitivity(0.0),
58 		m_acceleration(false),
59 		m_warp(false),
60 		m_enter(false),
61 		m_oldX(0),
62 		m_oldY(0),
63 		m_lastTicks(0),
64 		m_oldVelocity(0.0),
65 		m_joystickManager(NULL) {
66 	}
67 
~EventManager()68 	EventManager::~EventManager() {
69 		delete m_joystickManager;
70 	}
71 
72 	template<typename T>
addListener(std::deque<T> & vec,T & listener)73 	void addListener(std::deque<T>& vec, T& listener) {
74 		if (!listener->isActive()) {
75 			listener->setActive(true);
76 			vec.push_back(listener);
77 		}
78 	}
79 
80 	template<typename T>
addListenerFront(std::deque<T> & vec,T & listener)81 	void addListenerFront(std::deque<T>& vec, T& listener) {
82 		if (!listener->isActive()) {
83 			listener->setActive(true);
84 			vec.push_front(listener);
85 		}
86 	}
87 
88 	template<typename T>
removeListener(std::deque<T> & vec,T & listener)89 	void removeListener(std::deque<T>& vec, T& listener) {
90 		if (listener->isActive()) {
91 			listener->setActive(false);
92 			for (typename std::deque<T>::iterator it = vec.begin(); it != vec.end(); ++it) {
93 				if (*it == listener) {
94 					vec.erase(it);
95 					break;
96 				}
97 			}
98 		}
99 	}
100 
addCommandListener(ICommandListener * listener)101 	void EventManager::addCommandListener(ICommandListener* listener) {
102 		addListener<ICommandListener*>(m_commandListeners, listener);
103 	}
104 
addCommandListenerFront(ICommandListener * listener)105 	void EventManager::addCommandListenerFront(ICommandListener* listener) {
106 		addListenerFront<ICommandListener*>(m_commandListeners, listener);
107 	}
108 
removeCommandListener(ICommandListener * listener)109 	void EventManager::removeCommandListener(ICommandListener* listener) {
110 		removeListener<ICommandListener*>(m_commandListeners, listener);
111 	}
112 
addKeyListener(IKeyListener * listener)113 	void EventManager::addKeyListener(IKeyListener* listener) {
114 		addListener<IKeyListener*>(m_keyListeners, listener);
115 	}
116 
addKeyListenerFront(IKeyListener * listener)117 	void EventManager::addKeyListenerFront(IKeyListener* listener) {
118 		addListenerFront<IKeyListener*>(m_keyListeners, listener);
119 	}
120 
removeKeyListener(IKeyListener * listener)121 	void EventManager::removeKeyListener(IKeyListener* listener) {
122 		removeListener<IKeyListener*>(m_keyListeners, listener);
123 	}
124 
addTextListener(ITextListener * listener)125 	void EventManager::addTextListener(ITextListener* listener) {
126 		addListener<ITextListener*>(m_textListeners, listener);
127 	}
128 
addTextListenerFront(ITextListener * listener)129 	void EventManager::addTextListenerFront(ITextListener* listener) {
130 		addListenerFront<ITextListener*>(m_textListeners, listener);
131 	}
132 
removeTextListener(ITextListener * listener)133 	void EventManager::removeTextListener(ITextListener* listener) {
134 		removeListener<ITextListener*>(m_textListeners, listener);
135 	}
136 
addMouseListener(IMouseListener * listener)137 	void EventManager::addMouseListener(IMouseListener* listener) {
138 		addListener<IMouseListener*>(m_mouseListeners, listener);
139 	}
140 
addMouseListenerFront(IMouseListener * listener)141 	void EventManager::addMouseListenerFront(IMouseListener* listener) {
142 		addListenerFront<IMouseListener*>(m_mouseListeners, listener);
143 	}
144 
removeMouseListener(IMouseListener * listener)145 	void EventManager::removeMouseListener(IMouseListener* listener) {
146 		removeListener<IMouseListener*>(m_mouseListeners, listener);
147 	}
148 
addSdlEventListener(ISdlEventListener * listener)149 	void EventManager::addSdlEventListener(ISdlEventListener* listener) {
150 		addListener<ISdlEventListener*>(m_sdleventListeners, listener);
151 	}
152 
addSdlEventListenerFront(ISdlEventListener * listener)153 	void EventManager::addSdlEventListenerFront(ISdlEventListener* listener) {
154 		addListenerFront<ISdlEventListener*>(m_sdleventListeners, listener);
155 	}
156 
removeSdlEventListener(ISdlEventListener * listener)157 	void EventManager::removeSdlEventListener(ISdlEventListener* listener) {
158 		removeListener<ISdlEventListener*>(m_sdleventListeners, listener);
159 	}
160 
addDropListener(IDropListener * listener)161 	void EventManager::addDropListener(IDropListener* listener) {
162 		addListener<IDropListener*>(m_dropListeners, listener);
163 	}
164 
addDropListenerFront(IDropListener * listener)165 	void EventManager::addDropListenerFront(IDropListener* listener) {
166 		addListenerFront<IDropListener*>(m_dropListeners, listener);
167 	}
168 
removeDropListener(IDropListener * listener)169 	void EventManager::removeDropListener(IDropListener* listener) {
170 		removeListener<IDropListener*>(m_dropListeners, listener);
171 	}
172 
addJoystickListener(IJoystickListener * listener)173 	void EventManager::addJoystickListener(IJoystickListener* listener) {
174 		if (m_joystickManager) {
175 			m_joystickManager->addJoystickListener(listener);
176 		}
177 	}
178 
addJoystickListenerFront(IJoystickListener * listener)179 	void EventManager::addJoystickListenerFront(IJoystickListener* listener) {
180 		if (m_joystickManager) {
181 			m_joystickManager->addJoystickListenerFront(listener);
182 		}
183 	}
184 
removeJoystickListener(IJoystickListener * listener)185 	void EventManager::removeJoystickListener(IJoystickListener* listener) {
186 		if (m_joystickManager) {
187 			m_joystickManager->removeJoystickListener(listener);
188 		}
189 	}
190 
dispatchCommand(Command & command)191 	void EventManager::dispatchCommand(Command& command) {
192 		std::deque<ICommandListener*> listeners = m_commandListeners;
193 		std::deque<ICommandListener*>::iterator i = listeners.begin();
194 		for (; i != listeners.end(); ++i) {
195 			if (!(*i)->isActive()) continue;
196 			(*i)->onCommand(command);
197 			if (command.isConsumed()) {
198 				break;
199 			}
200 		}
201 	}
202 
dispatchKeyEvent(KeyEvent & evt)203 	void EventManager::dispatchKeyEvent(KeyEvent& evt) {
204 		std::deque<IKeyListener*> listeners = m_keyListeners;
205 		std::deque<IKeyListener*>::iterator i = listeners.begin();
206 		for (; i != listeners.end(); ++i) {
207 			if (!(*i)->isActive() || (evt.isConsumedByWidgets() && !(*i)->isGlobalListener())) continue;
208 			switch (evt.getType()) {
209 				case KeyEvent::PRESSED:
210 					(*i)->keyPressed(evt);
211 					break;
212 				case KeyEvent::RELEASED:
213 					(*i)->keyReleased(evt);
214 					break;
215 				default:
216 					break;
217 			}
218 			if (evt.isConsumed()) {
219 				break;
220 			}
221 		}
222 	}
223 
dispatchTextEvent(TextEvent & evt)224 	void EventManager::dispatchTextEvent(TextEvent& evt) {
225 		std::deque<ITextListener*> listeners = m_textListeners;
226 		std::deque<ITextListener*>::iterator i = listeners.begin();
227 		for (; i != listeners.end(); ++i) {
228 			if (!(*i)->isActive()) continue;
229 			switch (evt.getType()) {
230 				case TextEvent::INPUT:
231 					(*i)->textInput(evt);
232 					break;
233 				case TextEvent::EDIT:
234 					(*i)->textEdit(evt);
235 					break;
236 				default:
237 					break;
238 			}
239 			if (evt.isConsumed()) {
240 				break;
241 			}
242 		}
243 	}
244 
dispatchMouseEvent(MouseEvent & evt)245 	void EventManager::dispatchMouseEvent(MouseEvent& evt) {
246 		std::deque<IMouseListener*> listeners = m_mouseListeners;
247 		std::deque<IMouseListener*>::iterator i = listeners.begin();
248 		for (; i != listeners.end(); ++i) {
249 			if (!(*i)->isActive() || (evt.isConsumedByWidgets() && !(*i)->isGlobalListener())) continue;
250 			switch (evt.getType()) {
251 				case MouseEvent::MOVED:
252 					(*i)->mouseMoved(evt);
253 					break;
254 				case MouseEvent::PRESSED:
255 					(*i)->mousePressed(evt);
256 					break;
257 				case MouseEvent::RELEASED:
258 					(*i)->mouseReleased(evt);
259 					break;
260 				case MouseEvent::WHEEL_MOVED_DOWN:
261 					(*i)->mouseWheelMovedDown(evt);
262 					break;
263 				case MouseEvent::WHEEL_MOVED_UP:
264 					(*i)->mouseWheelMovedUp(evt);
265 					break;
266 				case MouseEvent::WHEEL_MOVED_RIGHT:
267 					(*i)->mouseWheelMovedRight(evt);
268 					break;
269 				case MouseEvent::WHEEL_MOVED_LEFT:
270 					(*i)->mouseWheelMovedLeft(evt);
271 					break;
272 				case MouseEvent::CLICKED:
273 					(*i)->mouseClicked(evt);
274 					break;
275 				case MouseEvent::ENTERED:
276 					(*i)->mouseEntered(evt);
277 					break;
278 				case MouseEvent::EXITED:
279 					(*i)->mouseExited(evt);
280 					break;
281 				case MouseEvent::DRAGGED:
282 					(*i)->mouseDragged(evt);
283 					break;
284 				default:
285 					break;
286 			}
287 			if (evt.isConsumed()) {
288 				break;
289 			}
290 		}
291 	}
292 
dispatchSdlEvent(SDL_Event & evt)293 	bool EventManager::dispatchSdlEvent(SDL_Event& evt) {
294 		bool ret = false;
295 		std::deque<ISdlEventListener*> listeners = m_sdleventListeners;
296 		std::deque<ISdlEventListener*>::iterator i = listeners.begin();
297 		for (; i != listeners.end(); ++i) {
298 			if (!(*i)->isActive()) continue;
299 			ret = ret || (*i)->onSdlEvent(evt);
300 		}
301 		return ret;
302 	}
303 
dispatchDropEvent(DropEvent & evt)304 	void EventManager::dispatchDropEvent(DropEvent& evt) {
305 		std::deque<IDropListener*> listeners = m_dropListeners;
306 		std::deque<IDropListener*>::iterator i = listeners.begin();
307 		for (; i != listeners.end(); ++i) {
308 			if (!(*i)->isActive()) continue;
309 			(*i)->fileDropped(evt);
310 			if (evt.isConsumed()) {
311 				break;
312 			}
313 		}
314 	}
315 
combineEvents(SDL_Event & event1,const SDL_Event & event2)316 	bool EventManager::combineEvents(SDL_Event& event1, const SDL_Event& event2) {
317 		if(event1.type == event2.type) {
318 			switch (event1.type) {
319 				case SDL_MOUSEMOTION:
320 					if(event1.motion.state == event2.motion.state) {
321 						event1.motion.x = event2.motion.x;
322 						event1.motion.y = event2.motion.y;
323 						event1.motion.xrel += event2.motion.xrel;
324 						event1.motion.yrel += event2.motion.yrel;
325 						return true;
326 					}
327 					return false;
328 			}
329 		}
330 		return false;
331 	}
332 
processEvents()333 	void EventManager::processEvents() {
334 		// The double SDL_PollEvent calls don't throw away events,
335 		// but try to combine (mouse motion) events.
336 		SDL_Event event, next_event;
337 		bool has_next_event = (SDL_PollEvent(&event) != 0);
338 		while (has_next_event) {
339 			has_next_event = (SDL_PollEvent(&next_event) != 0);
340 			if (has_next_event && combineEvents(event, next_event)) {
341 				continue;
342 			}
343 			switch (event.type) {
344 				case SDL_QUIT: {
345 					Command cmd;
346 					cmd.setSource(this);
347 					cmd.setCommandType(CMD_QUIT_GAME);
348 					dispatchCommand(cmd);
349 					}
350 					break;
351 
352 				case SDL_WINDOWEVENT:
353 					processWindowEvent(event);
354 					break;
355 
356 				case SDL_KEYDOWN:
357 				case SDL_KEYUP:
358 					processKeyEvent(event);
359 					break;
360 
361 				//case SDL_TEXTEDITING: // is buggy with SDL 2.0.1
362 				case SDL_TEXTINPUT:
363 					processTextEvent(event);
364 					break;
365 
366 				case SDL_MOUSEWHEEL:
367 				case SDL_MOUSEBUTTONUP:
368 				case SDL_MOUSEMOTION:
369 				case SDL_MOUSEBUTTONDOWN:
370 					processMouseEvent(event);
371 					break;
372 
373 				case SDL_DROPFILE:
374 					processDropEvent(event);
375 					break;
376 
377 				case SDL_JOYBUTTONDOWN:
378 				case SDL_JOYBUTTONUP:
379 				case SDL_JOYAXISMOTION:
380 				case SDL_JOYHATMOTION:
381 				case SDL_JOYDEVICEADDED:
382 				case SDL_JOYDEVICEREMOVED: {
383 					if (m_joystickManager) {
384 						m_joystickManager->processJoystickEvent(event);
385 					}
386 					break;
387 				}
388 				case SDL_CONTROLLERBUTTONDOWN:
389 				case SDL_CONTROLLERBUTTONUP:
390 				case SDL_CONTROLLERAXISMOTION: {
391 					if (m_joystickManager) {
392 						m_joystickManager->processControllerEvent(event);
393 					}
394 					break;
395 				}
396 
397 			}
398 			if (has_next_event) {
399 				event = next_event;
400 			}
401 		}
402 	}
403 
processWindowEvent(SDL_Event event)404 	void EventManager::processWindowEvent(SDL_Event event) {
405 		if (dispatchSdlEvent(event)) {
406 			return;
407 		}
408 
409 		CommandType ct = CMD_UNKNOWN;
410 		switch (event.window.event) {
411 			case SDL_WINDOWEVENT_CLOSE:
412 				ct = CMD_QUIT_GAME;
413 				break;
414 
415 			case SDL_WINDOWEVENT_ENTER:
416 				ct = CMD_MOUSE_FOCUS_GAINED;
417 				break;
418 
419 			case SDL_WINDOWEVENT_LEAVE:
420 				ct = CMD_MOUSE_FOCUS_LOST;
421 				break;
422 
423 			case SDL_WINDOWEVENT_FOCUS_GAINED:
424 				ct = CMD_INPUT_FOCUS_GAINED;
425 				break;
426 
427 			case SDL_WINDOWEVENT_FOCUS_LOST:
428 				ct = CMD_INPUT_FOCUS_LOST;
429 				break;
430 
431 			case SDL_WINDOWEVENT_SHOWN:
432 				ct = CMD_APP_RESTORED;
433 				break;
434 
435 			case SDL_WINDOWEVENT_MINIMIZED:
436 			case SDL_WINDOWEVENT_HIDDEN:
437 				ct = CMD_APP_ICONIFIED;
438 				break;
439 
440 			default:
441 				ct = CMD_UNKNOWN;
442 		}
443 		if (ct != CMD_UNKNOWN) {
444 			Command cmd;
445 			cmd.setCommandType(ct);
446 			dispatchCommand(cmd);
447 		}
448 	}
449 
processKeyEvent(SDL_Event event)450 	void EventManager::processKeyEvent(SDL_Event event) {
451 		KeyEvent keyevt;
452 		keyevt.setSource(this);
453 		fillKeyEvent(event, keyevt);
454 		m_keystatemap[keyevt.getKey().getValue()] = (keyevt.getType() == KeyEvent::PRESSED);
455 		// if event is not filtered it gets dispatched, even it is a function key
456 		if (!m_keyfilter || !m_keyfilter->isFiltered(keyevt)) {
457 			if (dispatchSdlEvent(event))
458 				keyevt.consumedByWidgets();
459 		}
460 
461 		dispatchKeyEvent(keyevt);
462 	}
463 
processTextEvent(SDL_Event event)464 	void EventManager::processTextEvent(SDL_Event event) {
465 		if (dispatchSdlEvent(event)) {
466 			return;
467 		}
468 
469 		TextEvent txtevt;
470 		txtevt.setSource(this);
471 		fillTextEvent(event, txtevt);
472 		dispatchTextEvent(txtevt);
473 	}
474 
processMouseEvent(SDL_Event event)475 	void EventManager::processMouseEvent(SDL_Event event) {
476 		if (event.type == SDL_MOUSEMOTION && (!Mathf::Equal(m_mouseSensitivity, 0.0) || m_acceleration)) {
477 			uint16_t tmp_x = event.motion.x;
478 			uint16_t tmp_y = event.motion.y;
479 			if (m_enter) {
480 				m_oldX = tmp_x;
481 				m_oldY = tmp_y;
482 				m_oldVelocity = 0.0;
483 				m_enter = false;
484 			}
485 
486 			float modifier;
487 			if (m_acceleration) {
488 				uint32_t ticks = SDL_GetTicks();
489 				float difference = static_cast<float>((ticks - m_lastTicks) + 1);
490 				m_lastTicks = ticks;
491 				float dx = static_cast<float>(tmp_x - m_oldX);
492 				float dy = static_cast<float>(tmp_y - m_oldY);
493 				float distance = Mathf::Sqrt(dx * dx + dy * dy);
494 				float acceleration = static_cast<float>((distance / difference) / difference);
495 				float velocity = (m_oldVelocity + acceleration * difference)/2;
496 				if (velocity > m_mouseSensitivity+1) {
497 					velocity = m_mouseSensitivity+1;
498 				}
499 				m_oldVelocity = velocity;
500 				modifier = velocity;
501 			} else {
502 				modifier = m_mouseSensitivity;
503 			}
504 
505 			int16_t tmp_xrel = static_cast<int16_t>(tmp_x - m_oldX);
506 			int16_t tmp_yrel = static_cast<int16_t>(tmp_y - m_oldY);
507 			if ((tmp_xrel != 0) || (tmp_yrel != 0)) {
508 				Rect screen = RenderBackend::instance()->getArea();
509 				int16_t x_fact = static_cast<int16_t>(round(static_cast<float>(tmp_xrel * modifier)));
510 				int16_t y_fact = static_cast<int16_t>(round(static_cast<float>(tmp_yrel * modifier)));
511 				if ((tmp_x + x_fact) > screen.w) {
512 					tmp_x = screen.w;
513 				} else if ((tmp_x + x_fact) < screen.x) {
514 					tmp_x = screen.x;
515 				} else {
516 					tmp_x += x_fact;
517 				}
518 
519 				if (tmp_y + y_fact > screen.h) {
520 					tmp_y = screen.h;
521 				} else if ((tmp_y + y_fact) < screen.y) {
522 					tmp_y = screen.y;
523 				} else {
524 					tmp_y += y_fact;
525 				}
526 				m_oldX = tmp_x;
527 				m_oldY = tmp_y;
528 				event.motion.x = tmp_x;
529 				event.motion.y = tmp_y;
530 				m_warp = true; //don't trigger an event handler when warping
531 				SDL_WarpMouseInWindow(RenderBackend::instance()->getWindow(), tmp_x, tmp_y);
532 				m_warp = false;
533 			}
534 		}
535 
536 		MouseEvent mouseevt;
537 		mouseevt.setSource(this);
538 		fillMouseEvent(event, mouseevt);
539 		fillModifiers(mouseevt);
540 		if (event.type == SDL_MOUSEBUTTONDOWN) {
541 			m_mousestate |= static_cast<int32_t>(mouseevt.getButton());
542 			m_mostrecentbtn = mouseevt.getButton();
543 		} else if (event.type == SDL_MOUSEBUTTONUP) {
544 			m_mousestate &= ~static_cast<int32_t>(mouseevt.getButton());
545 		}
546 
547 		if (dispatchSdlEvent(event))
548 			mouseevt.consumedByWidgets();
549 
550 		dispatchMouseEvent(mouseevt);
551 	}
552 
processDropEvent(SDL_Event event)553 	void EventManager::processDropEvent(SDL_Event event) {
554 		// only dispatched as DropEvent
555 		//if (dispatchSdlEvent(event)) {
556 		//	return;
557 		//}
558 
559 		char* tmp = event.drop.file;
560 		std::string path(tmp);
561 		SDL_free(tmp);
562 
563 		DropEvent drop;
564 		drop.setPath(path);
565 		drop.setSource(this);
566 		dispatchDropEvent(drop);
567 	}
568 
fillMouseEvent(const SDL_Event & sdlevt,MouseEvent & mouseevt)569 	void EventManager::fillMouseEvent(const SDL_Event& sdlevt, MouseEvent& mouseevt) {
570 		if (m_warp) {
571 			return;
572 		}
573 
574 		mouseevt.setX(sdlevt.button.x);
575 		mouseevt.setY(sdlevt.button.y);
576 
577 		mouseevt.setButton(MouseEvent::EMPTY);
578 		mouseevt.setType(MouseEvent::MOVED);
579 		if ((sdlevt.type == SDL_MOUSEBUTTONUP) || (sdlevt.type == SDL_MOUSEBUTTONDOWN)) {
580 			switch (sdlevt.button.button) {
581 				case SDL_BUTTON_LEFT:
582 					mouseevt.setButton(MouseEvent::LEFT);
583 					break;
584 				case SDL_BUTTON_RIGHT:
585 					mouseevt.setButton(MouseEvent::RIGHT);
586 					break;
587 				case SDL_BUTTON_MIDDLE:
588 					mouseevt.setButton(MouseEvent::MIDDLE);
589 					break;
590 				case SDL_BUTTON_X1:
591 					mouseevt.setButton(MouseEvent::X1);
592 					break;
593 				case SDL_BUTTON_X2:
594 					mouseevt.setButton(MouseEvent::X2);
595 					break;
596 				default:
597 					mouseevt.setButton(MouseEvent::UNKNOWN_BUTTON);
598 					break;
599 			}
600 
601 			if (sdlevt.button.state == SDL_RELEASED) {
602 				mouseevt.setType(MouseEvent::RELEASED);
603 			} else {
604 				mouseevt.setType(MouseEvent::PRESSED);
605 			}
606 		}
607 		if (sdlevt.type == SDL_MOUSEWHEEL) {
608 #if SDL_VERSION_ATLEAST(2,0,4)
609 			if (sdlevt.wheel.y > 0 || (sdlevt.wheel.direction == SDL_MOUSEWHEEL_FLIPPED && sdlevt.wheel.y < 0)) {
610 				mouseevt.setType(MouseEvent::WHEEL_MOVED_UP);
611 			} else if (sdlevt.wheel.y < 0 || (sdlevt.wheel.direction == SDL_MOUSEWHEEL_FLIPPED && sdlevt.wheel.y > 0)) {
612 				mouseevt.setType(MouseEvent::WHEEL_MOVED_DOWN);
613 			}
614 			if (sdlevt.wheel.x > 0 || (sdlevt.wheel.direction == SDL_MOUSEWHEEL_FLIPPED && sdlevt.wheel.x < 0)) {
615 				mouseevt.setType(MouseEvent::WHEEL_MOVED_RIGHT);
616 			} else if (sdlevt.wheel.x < 0 || (sdlevt.wheel.direction == SDL_MOUSEWHEEL_FLIPPED && sdlevt.wheel.x > 0)) {
617 				mouseevt.setType(MouseEvent::WHEEL_MOVED_LEFT);
618 			}
619 #else
620 			if (sdlevt.wheel.y > 0) {
621 				mouseevt.setType(MouseEvent::WHEEL_MOVED_UP);
622 			} else if (sdlevt.wheel.y < 0) {
623 				mouseevt.setType(MouseEvent::WHEEL_MOVED_DOWN);
624 			}
625 			if (sdlevt.wheel.x > 0) {
626 				mouseevt.setType(MouseEvent::WHEEL_MOVED_RIGHT);
627 			} else if (sdlevt.wheel.x < 0) {
628 				mouseevt.setType(MouseEvent::WHEEL_MOVED_LEFT);
629 			}
630 #endif
631 		}
632 
633 		if ((mouseevt.getType() == MouseEvent::MOVED) && ((m_mousestate & m_mostrecentbtn) != 0)) {
634 			mouseevt.setType(MouseEvent::DRAGGED);
635 			mouseevt.setButton(m_mostrecentbtn);
636 		}
637 	}
638 
fillKeyEvent(const SDL_Event & sdlevt,KeyEvent & keyevt)639 	void EventManager::fillKeyEvent(const SDL_Event& sdlevt, KeyEvent& keyevt) {
640 		if (sdlevt.type == SDL_KEYDOWN) {
641 			keyevt.setType(KeyEvent::PRESSED);
642 		} else if (sdlevt.type == SDL_KEYUP) {
643 			keyevt.setType(KeyEvent::RELEASED);
644 		} else {
645 			FL_WARN(_log, LMsg("fillKeyEvent()")
646 				<< " Invalid key event type of " << sdlevt.type << ".  Ignoring event.");
647 			return;
648 		}
649 
650 		SDL_Keysym keysym = sdlevt.key.keysym;
651 		keyevt.setShiftPressed((keysym.mod & KMOD_SHIFT) != 0);
652 		keyevt.setControlPressed((keysym.mod & KMOD_CTRL) != 0);
653 		keyevt.setAltPressed((keysym.mod & KMOD_ALT) != 0);
654 		keyevt.setMetaPressed((keysym.mod & KMOD_GUI) != 0); // currently gui/super keys
655 		keyevt.setNumericPad((keysym.mod & KMOD_NUM) != 0);
656 		keyevt.setKey(Key(static_cast<Key::KeyType>(keysym.sym)));
657 	}
658 
fillTextEvent(const SDL_Event & sdlevt,TextEvent & txtevt)659 	void EventManager::fillTextEvent(const SDL_Event& sdlevt, TextEvent& txtevt) {
660 		if (sdlevt.type == SDL_TEXTINPUT) {
661 			txtevt.setType(TextEvent::INPUT);
662 			Text t(sdlevt.text.text);
663 			txtevt.setText(t);
664 		} else if (sdlevt.type == SDL_TEXTEDITING) {
665 			txtevt.setType(TextEvent::EDIT);
666 			Text t(sdlevt.edit.text, sdlevt.edit.start, sdlevt.edit.length);
667 			txtevt.setText(t);
668 		} else {
669 			FL_WARN(_log, LMsg("fillTextEvent()")
670 				<< " Invalid text event type of " << sdlevt.type << ".  Ignoring event.");
671 		}
672 	}
673 
fillModifiers(InputEvent & evt)674 	void EventManager::fillModifiers(InputEvent& evt) {
675 		evt.setAltPressed(m_keystatemap[Key::ALT_GR] |
676 			m_keystatemap[Key::LEFT_ALT] |
677 			m_keystatemap[Key::RIGHT_ALT]);
678 		evt.setControlPressed(m_keystatemap[Key::LEFT_CONTROL] |
679 			m_keystatemap[Key::RIGHT_CONTROL]);
680 		evt.setShiftPressed(m_keystatemap[Key::LEFT_SHIFT] |
681 			m_keystatemap[Key::RIGHT_SHIFT]);
682 	}
683 
getEventSourceType()684 	EventSourceType EventManager::getEventSourceType() {
685 		return ES_ENGINE;
686 	}
687 
setKeyFilter(IKeyFilter * keyFilter)688 	void EventManager::setKeyFilter(IKeyFilter* keyFilter) {
689 		m_keyfilter = keyFilter;
690 	}
691 
setMouseSensitivity(float sensitivity)692 	void EventManager::setMouseSensitivity(float sensitivity) {
693 		if (sensitivity < -0.99) {
694 			sensitivity = -0.99;
695 		} else if (sensitivity > 10.0) {
696 			sensitivity = 10.0;
697 		}
698 		m_mouseSensitivity = sensitivity;
699 	}
700 
getMouseSensitivity() const701 	float EventManager::getMouseSensitivity() const {
702 		return m_mouseSensitivity;
703 	}
704 
setMouseAccelerationEnabled(bool acceleration)705 	void EventManager::setMouseAccelerationEnabled(bool acceleration) {
706 		m_acceleration = acceleration;
707 	}
708 
isMouseAccelerationEnabled() const709 	bool EventManager::isMouseAccelerationEnabled() const {
710 		return m_acceleration;
711 	}
712 
isClipboardText() const713 	bool EventManager::isClipboardText() const {
714 		return SDL_HasClipboardText();
715 	}
716 
getClipboardText() const717 	std::string EventManager::getClipboardText() const {
718 		std::string text;
719 		if (SDL_HasClipboardText()) {
720 			text = std::string(SDL_GetClipboardText());
721 		}
722 		return text;
723 	}
724 
setClipboardText(const std::string & text)725 	void EventManager::setClipboardText(const std::string& text) {
726 		SDL_SetClipboardText(text.c_str());
727 	}
728 
setJoystickSupport(bool support)729 	void EventManager::setJoystickSupport(bool support) {
730 		if (support && !m_joystickManager) {
731 			m_joystickManager = new JoystickManager();
732 		} else if (!support && m_joystickManager) {
733 			delete m_joystickManager;
734 			m_joystickManager = NULL;
735 		}
736 	}
737 
getJoystick(int32_t instanceId)738 	Joystick* EventManager::getJoystick(int32_t instanceId) {
739 		if (m_joystickManager) {
740 			return m_joystickManager->getJoystick(instanceId);
741 		}
742 		return NULL;
743 	}
744 
getJoystickCount() const745 	uint8_t EventManager::getJoystickCount() const {
746 		if (m_joystickManager) {
747 			return m_joystickManager->getJoystickCount();
748 		}
749 		return 0;
750 	}
751 
loadGamepadMapping(const std::string & file)752 	void EventManager::loadGamepadMapping(const std::string& file) {
753 		if (m_joystickManager) {
754 			m_joystickManager->loadMapping(file);
755 		}
756 	}
757 
saveGamepadMapping(const std::string guid,const std::string & file)758 	void EventManager::saveGamepadMapping(const std::string guid, const std::string& file) {
759 		if (m_joystickManager) {
760 			m_joystickManager->saveMapping(guid, file);
761 		}
762 	}
763 
saveGamepadMappings(const std::string & file)764 	void EventManager::saveGamepadMappings(const std::string& file) {
765 		if (m_joystickManager) {
766 			m_joystickManager->saveMappings(file);
767 		}
768 	}
769 
getGamepadStringMapping(const std::string & guid)770 	std::string EventManager::getGamepadStringMapping(const std::string& guid) {
771 		std::string mapping;
772 		if (m_joystickManager) {
773 			mapping = m_joystickManager->getStringMapping(guid);
774 		}
775 		return mapping;
776 	}
777 
setGamepadStringMapping(const std::string & mapping)778 	void EventManager::setGamepadStringMapping(const std::string& mapping) {
779 		if (m_joystickManager) {
780 			m_joystickManager->setStringMapping(mapping);
781 		}
782 	}
783 }
784