31 #include "util/base/exception.h"
32 #include "util/log/logger.h"
33 #include "util/math/fife_math.h"
34 #include "eventchannel/key/ec_key.h"
35 #include "eventchannel/key/ec_keyevent.h"
36 #include "eventchannel/key/ec_ikeyfilter.h"
37 #include "eventchannel/mouse/ec_mouseevent.h"
38 #include "eventchannel/command/ec_command.h"
39 #include "video/renderbackend.h"
41 #include "eventmanager.h"
44 static Logger _log(LM_EVTCHANNEL);
50 m_sdleventlisteners(),
55 m_mousesensitivity(0.0),
56 m_acceleration(false),
69 void removeListener(std::deque<T>& vec, T& listener) {
70 vec.push_back(listener);
74 void addListener(std::deque<T>& vec, T& listener) {
75 vec.push_back(listener);
79 addListener<ICommandListener*>(m_pending_commandlisteners, listener);
83 addListener<ICommandListener*>(m_pending_commandlisteners, listener);
87 removeListener<ICommandListener*>(m_pending_cldeletions, listener);
91 addListener<IKeyListener*>(m_pending_keylisteners, listener);
95 addListener<IKeyListener*>(m_pending_keylisteners_front, listener);
99 removeListener<IKeyListener*>(m_pending_kldeletions, listener);
103 addListener<IMouseListener*>(m_pending_mouselisteners, listener);
107 addListener<IMouseListener*>(m_pending_mouselisteners, listener);
111 removeListener<IMouseListener*>(m_pending_mldeletions, listener);
115 addListener<ISdlEventListener*>(m_pending_sdleventlisteners, listener);
119 addListener<ISdlEventListener*>(m_pending_sdleventlisteners, listener);
123 removeListener<ISdlEventListener*>(m_pending_sdldeletions, listener);
127 if(!m_pending_commandlisteners.empty()) {
128 std::deque<ICommandListener*>::iterator i = m_pending_commandlisteners.begin();
129 while (i != m_pending_commandlisteners.end()) {
130 m_commandlisteners.push_back(*i);
133 m_pending_commandlisteners.clear();
136 if(!m_pending_commandlisteners_front.empty()) {
137 std::deque<ICommandListener*>::iterator i = m_pending_commandlisteners_front.begin();
138 while (i != m_pending_commandlisteners_front.end()) {
139 m_commandlisteners.push_front(*i);
142 m_pending_commandlisteners_front.clear();
145 if (!m_pending_cldeletions.empty()) {
146 std::deque<ICommandListener*>::iterator i = m_pending_cldeletions.begin();
147 while (i != m_pending_cldeletions.end()) {
148 std::deque<ICommandListener*>::iterator j = m_commandlisteners.begin();
149 while (j != m_commandlisteners.end()) {
151 m_commandlisteners.erase(j);
158 m_pending_cldeletions.clear();
161 std::deque<ICommandListener*>::iterator i = m_commandlisteners.begin();
162 while (i != m_commandlisteners.end()) {
163 (*i)->onCommand(command);
171 void EventManager::dispatchKeyEvent(
KeyEvent& evt) {
172 if(!m_pending_keylisteners.empty()) {
173 std::deque<IKeyListener*>::iterator i = m_pending_keylisteners.begin();
174 while (i != m_pending_keylisteners.end()) {
175 m_keylisteners.push_back(*i);
178 m_pending_keylisteners.clear();
181 if(!m_pending_keylisteners_front.empty()) {
182 std::deque<IKeyListener*>::iterator i = m_pending_keylisteners_front.begin();
183 while (i != m_pending_keylisteners_front.end()) {
184 m_keylisteners.push_front(*i);
187 m_pending_keylisteners_front.clear();
190 if (!m_pending_kldeletions.empty()) {
191 std::deque<IKeyListener*>::iterator i = m_pending_kldeletions.begin();
192 while (i != m_pending_kldeletions.end()) {
193 std::deque<IKeyListener*>::iterator j = m_keylisteners.begin();
194 while (j != m_keylisteners.end()) {
196 m_keylisteners.erase(j);
203 m_pending_kldeletions.clear();
206 std::deque<IKeyListener*>::iterator i = m_keylisteners.begin();
207 while (i != m_keylisteners.end()) {
208 switch (evt.getType()) {
209 case KeyEvent::PRESSED:
210 (*i)->keyPressed(evt);
212 case KeyEvent::RELEASED:
213 (*i)->keyReleased(evt);
222 void EventManager::dispatchMouseEvent(MouseEvent& evt) {
223 if(!m_pending_mouselisteners.empty()) {
224 std::deque<IMouseListener*>::iterator i = m_pending_mouselisteners.begin();
225 while (i != m_pending_mouselisteners.end()) {
226 m_mouselisteners.push_back(*i);
229 m_pending_mouselisteners.clear();
232 if(!m_pending_mouselisteners_front.empty()) {
233 std::deque<IMouseListener*>::iterator i = m_pending_mouselisteners_front.begin();
234 while (i != m_pending_mouselisteners_front.end()) {
235 m_mouselisteners.push_front(*i);
238 m_pending_mouselisteners_front.clear();
241 if (!m_pending_mldeletions.empty()) {
242 std::deque<IMouseListener*>::iterator i = m_pending_mldeletions.begin();
243 while (i != m_pending_mldeletions.end()) {
244 std::deque<IMouseListener*>::iterator j = m_mouselisteners.begin();
245 while (j != m_mouselisteners.end()) {
247 m_mouselisteners.erase(j);
254 m_pending_mldeletions.clear();
257 std::deque<IMouseListener*>::iterator i = m_mouselisteners.begin();
258 while (i != m_mouselisteners.end()) {
259 switch (evt.getType()) {
260 case MouseEvent::MOVED:
261 (*i)->mouseMoved(evt);
263 case MouseEvent::PRESSED:
264 (*i)->mousePressed(evt);
266 case MouseEvent::RELEASED:
267 (*i)->mouseReleased(evt);
269 case MouseEvent::WHEEL_MOVED_DOWN:
270 (*i)->mouseWheelMovedDown(evt);
272 case MouseEvent::WHEEL_MOVED_UP:
273 (*i)->mouseWheelMovedUp(evt);
275 case MouseEvent::CLICKED:
276 (*i)->mouseClicked(evt);
278 case MouseEvent::ENTERED:
279 (*i)->mouseEntered(evt);
281 case MouseEvent::EXITED:
282 (*i)->mouseExited(evt);
284 case MouseEvent::DRAGGED:
285 (*i)->mouseDragged(evt);
290 if (evt.isConsumed()) {
297 bool EventManager::dispatchSdlEvent(SDL_Event& evt) {
299 if (!m_pending_sdleventlisteners.empty()) {
300 std::deque<ISdlEventListener*>::iterator i = m_pending_sdleventlisteners.begin();
301 while(i != m_pending_sdleventlisteners.end()) {
302 m_sdleventlisteners.push_back(*i);
305 m_pending_sdleventlisteners.clear();
308 if (!m_pending_sdleventlisteners_front.empty()) {
309 std::deque<ISdlEventListener*>::iterator i = m_pending_sdleventlisteners_front.begin();
310 while(i != m_pending_sdleventlisteners_front.end()) {
311 m_sdleventlisteners.push_front(*i);
314 m_pending_sdleventlisteners_front.clear();
317 if (!m_pending_sdldeletions.empty()) {
318 std::deque<ISdlEventListener*>::iterator i = m_pending_sdldeletions.begin();
319 while (i != m_pending_sdldeletions.end()) {
320 std::deque<ISdlEventListener*>::iterator j = m_sdleventlisteners.begin();
321 while (j != m_sdleventlisteners.end()) {
323 m_sdleventlisteners.erase(j);
330 m_pending_sdldeletions.clear();
333 std::deque<ISdlEventListener*>::iterator i = m_sdleventlisteners.begin();
334 while (i != m_sdleventlisteners.end()) {
335 ret = ret || (*i)->onSdlEvent(evt);
341 bool EventManager::combineEvents(SDL_Event& event1,
const SDL_Event& event2) {
342 if(event1.type == event2.type) {
343 switch (event1.type) {
344 case SDL_MOUSEMOTION:
345 if(event1.motion.state == event2.motion.state) {
346 event1.motion.x = event2.motion.x;
347 event1.motion.y = event2.motion.y;
348 event1.motion.xrel += event2.motion.xrel;
349 event1.motion.yrel += event2.motion.yrel;
361 SDL_Event event, next_event;
362 bool has_next_event = (SDL_PollEvent(&event) != 0);
363 while (has_next_event) {
364 has_next_event = (SDL_PollEvent(&next_event) != 0);
365 if(has_next_event && combineEvents(event, next_event))
368 switch (event.type) {
372 cmd.setCommandType(CMD_QUIT_GAME);
377 case SDL_ACTIVEEVENT:
378 processActiveEvent(event);
383 processKeyEvent(event);
386 case SDL_MOUSEBUTTONUP:
387 case SDL_MOUSEMOTION:
388 case SDL_MOUSEBUTTONDOWN:
389 processMouseEvent(event);
397 void EventManager::processActiveEvent(SDL_Event event) {
398 if (dispatchSdlEvent(event)) {
402 SDL_ActiveEvent actevt =
event.active;
403 std::vector<Command*> commands;
405 if (actevt.state & SDL_APPMOUSEFOCUS) {
406 Command* cmd =
new Command();
408 cmd->setCommandType(CMD_MOUSE_FOCUS_GAINED);
411 cmd->setCommandType(CMD_MOUSE_FOCUS_LOST);
413 commands.push_back(cmd);
415 if (actevt.state & SDL_APPINPUTFOCUS) {
416 Command* cmd =
new Command();
418 cmd->setCommandType(CMD_INPUT_FOCUS_GAINED);
420 cmd->setCommandType(CMD_INPUT_FOCUS_LOST);
422 commands.push_back(cmd);
424 if (actevt.state & SDL_APPACTIVE) {
425 Command* cmd =
new Command();
427 cmd->setCommandType(CMD_APP_RESTORED);
429 cmd->setCommandType(CMD_APP_ICONIFIED);
431 commands.push_back(cmd);
434 std::vector<Command*>::iterator it = commands.begin();
435 for (; it != commands.end(); ++it) {
441 void EventManager::processKeyEvent(SDL_Event event) {
443 keyevt.setSource(
this);
444 fillKeyEvent(event, keyevt);
445 m_keystatemap[keyevt.getKey().getValue()] = (keyevt.getType() == KeyEvent::PRESSED);
447 bool dispatchAsSdl = !keyevt.getKey().isFunctionKey();
448 if( dispatchAsSdl && m_keyfilter ) {
449 dispatchAsSdl = !m_keyfilter->
isFiltered(keyevt);
452 if( dispatchAsSdl ) {
453 if( dispatchSdlEvent(event) )
457 dispatchKeyEvent(keyevt);
460 void EventManager::processMouseEvent(SDL_Event event) {
461 if (event.type == SDL_MOUSEMOTION && (!Mathf::Equal(m_mousesensitivity, 0.0) || m_acceleration)) {
462 uint16_t tmp_x =
event.motion.x;
463 uint16_t tmp_y =
event.motion.y;
472 if (m_acceleration) {
473 uint32_t ticks = SDL_GetTicks();
474 float difference =
static_cast<float>((ticks - m_lastticks) + 1);
476 float dx =
static_cast<float>(tmp_x - m_oldx);
477 float dy =
static_cast<float>(tmp_y - m_oldy);
478 float distance = Mathf::Sqrt(dx * dx + dy * dy);
479 float acceleration =
static_cast<float>((distance / difference) / difference);
480 float velocity = (m_oldvelocity + acceleration * difference)/2;
481 if (velocity > m_mousesensitivity+1) {
482 velocity = m_mousesensitivity+1;
484 m_oldvelocity = velocity;
487 modifier = m_mousesensitivity;
490 int16_t tmp_xrel =
static_cast<int16_t
>(tmp_x - m_oldx);
491 int16_t tmp_yrel =
static_cast<int16_t
>(tmp_y - m_oldy);
492 if ((tmp_xrel != 0) || (tmp_yrel != 0)) {
493 Rect screen = RenderBackend::instance()->getArea();
494 int16_t x_fact =
static_cast<int16_t
>(round(static_cast<float>(tmp_xrel * modifier)));
495 int16_t y_fact =
static_cast<int16_t
>(round(static_cast<float>(tmp_yrel * modifier)));
496 if ((tmp_x + x_fact) > screen.w) {
498 }
else if ((tmp_x + x_fact) < screen.x) {
504 if (tmp_y + y_fact > screen.h) {
506 }
else if ((tmp_y + y_fact) < screen.y) {
513 event.motion.x = tmp_x;
514 event.motion.y = tmp_y;
516 SDL_WarpMouse(tmp_x, tmp_y);
521 if (dispatchSdlEvent(event)) {
525 mouseevt.setSource(
this);
526 fillMouseEvent(event, mouseevt);
527 fillModifiers(mouseevt);
528 if (event.type == SDL_MOUSEBUTTONDOWN) {
529 m_mousestate |=
static_cast<int32_t
>(mouseevt.getButton());
530 m_mostrecentbtn = mouseevt.getButton();
531 }
else if (event.type == SDL_MOUSEBUTTONUP) {
532 m_mousestate &= ~static_cast<int32_t>(mouseevt.getButton());
535 if (event.button.button == SDL_BUTTON_WHEELDOWN || event.button.button == SDL_BUTTON_WHEELUP) {
536 if (event.type == SDL_MOUSEBUTTONUP) {
540 dispatchMouseEvent(mouseevt);
544 void EventManager::fillMouseEvent(
const SDL_Event& sdlevt, MouseEvent& mouseevt) {
549 mouseevt.setX(sdlevt.button.x);
550 mouseevt.setY(sdlevt.button.y);
552 mouseevt.setButton(MouseEvent::EMPTY);
553 mouseevt.setType(MouseEvent::MOVED);
554 if ((sdlevt.type == SDL_MOUSEBUTTONUP) || (sdlevt.type == SDL_MOUSEBUTTONDOWN)) {
555 switch (sdlevt.button.button) {
556 case SDL_BUTTON_LEFT:
557 mouseevt.setButton(MouseEvent::LEFT);
559 case SDL_BUTTON_RIGHT:
560 mouseevt.setButton(MouseEvent::RIGHT);
562 case SDL_BUTTON_MIDDLE:
563 mouseevt.setButton(MouseEvent::MIDDLE);
566 mouseevt.setButton(MouseEvent::UNKNOWN_BUTTON);
570 if (sdlevt.type == SDL_MOUSEBUTTONUP ) {
571 mouseevt.setType(MouseEvent::RELEASED);
573 mouseevt.setType(MouseEvent::PRESSED);
576 switch (sdlevt.button.button) {
577 case SDL_BUTTON_WHEELDOWN:
578 mouseevt.setType(MouseEvent::WHEEL_MOVED_DOWN);
580 case SDL_BUTTON_WHEELUP:
581 mouseevt.setType(MouseEvent::WHEEL_MOVED_UP);
587 if ((mouseevt.getType() == MouseEvent::MOVED) && m_mousestate) {
588 mouseevt.setType(MouseEvent::DRAGGED);
589 mouseevt.setButton(m_mostrecentbtn);
593 void EventManager::fillKeyEvent(
const SDL_Event& sdlevt, KeyEvent& keyevt) {
594 if (sdlevt.type == SDL_KEYDOWN) {
595 keyevt.setType(KeyEvent::PRESSED);
596 }
else if (sdlevt.type == SDL_KEYUP) {
597 keyevt.setType(KeyEvent::RELEASED);
599 FL_WARN(_log, LMsg(
"fillKeyEvent()")
600 <<
" Invalid key event type of " << sdlevt.type <<
". Ignoring event.");
603 SDL_keysym keysym = sdlevt.key.keysym;
605 keyevt.setShiftPressed((keysym.mod & KMOD_SHIFT) != 0);
606 keyevt.setControlPressed((keysym.mod & KMOD_CTRL) != 0);
607 keyevt.setAltPressed((keysym.mod & KMOD_ALT) != 0);
608 keyevt.setMetaPressed((keysym.mod & KMOD_META) != 0);
609 keyevt.setNumericPad(keysym.sym >= SDLK_KP0 && keysym.sym <= SDLK_KP_EQUALS);
610 keyevt.setKey(Key(static_cast<Key::KeyType>(keysym.sym), keysym.unicode));
613 void EventManager::fillModifiers(InputEvent& evt) {
614 evt.setAltPressed(m_keystatemap[Key::ALT_GR] |
615 m_keystatemap[Key::LEFT_ALT] |
616 m_keystatemap[Key::RIGHT_ALT]);
617 evt.setControlPressed(m_keystatemap[Key::LEFT_CONTROL] |
618 m_keystatemap[Key::RIGHT_CONTROL]);
619 evt.setMetaPressed(m_keystatemap[Key::LEFT_META] |
620 m_keystatemap[Key::RIGHT_META]);
621 evt.setShiftPressed(m_keystatemap[Key::LEFT_SHIFT] |
622 m_keystatemap[Key::RIGHT_SHIFT]);
629 void EventManager::setKeyFilter(
IKeyFilter* keyFilter) {
630 m_keyfilter = keyFilter;
634 if (sensitivity < -0.99) {
636 }
else if (sensitivity > 10.0) {
639 m_mousesensitivity = sensitivity;
643 return m_mousesensitivity;
647 m_acceleration = acceleration;
651 return m_acceleration;
void removeMouseListener(IMouseListener *listener)
float getMouseSensitivity() const
bool getMouseAcceleration() const
void addKeyListenerFront(IKeyListener *listener)
virtual bool isConsumed() const
virtual void setSource(IEventSource *source)
void addSdlEventListener(ISdlEventListener *listener)
void dispatchCommand(Command &command)
void addCommandListenerFront(ICommandListener *listener)
void removeCommandListener(ICommandListener *listener)
void addCommandListener(ICommandListener *listener)
EventSourceType getEventSourceType()
void removeKeyListener(IKeyListener *listener)
void addMouseListener(IMouseListener *listener)
void setMouseAcceleration(bool acceleration)
void addSdlEventListenerFront(ISdlEventListener *listener)
void setMouseSensitivity(float sensitivity)
void addMouseListenerFront(IMouseListener *listener)
virtual bool isFiltered(const KeyEvent &event)=0
void addKeyListener(IKeyListener *listener)
credit to phoku for his NodeDisplay example which the visitor code is adapted from ( he coded the qua...
void removeSdlEventListener(ISdlEventListener *listener)