EventLoop.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #include "EventLoop.h"
  2. #include "Event.h"
  3. #include "Object.h"
  4. #include "WindowManager.h"
  5. static EventLoop* s_mainEventLoop;
  6. void EventLoop::initialize()
  7. {
  8. s_mainEventLoop = nullptr;
  9. }
  10. EventLoop::EventLoop()
  11. {
  12. if (!s_mainEventLoop)
  13. s_mainEventLoop = this;
  14. }
  15. EventLoop::~EventLoop()
  16. {
  17. }
  18. EventLoop& EventLoop::main()
  19. {
  20. ASSERT(s_mainEventLoop);
  21. return *s_mainEventLoop;
  22. }
  23. int EventLoop::exec()
  24. {
  25. for (;;) {
  26. if (m_queuedEvents.is_empty())
  27. waitForEvent();
  28. auto events = move(m_queuedEvents);
  29. for (auto& queuedEvent : events) {
  30. auto* receiver = queuedEvent.receiver;
  31. auto& event = *queuedEvent.event;
  32. //printf("EventLoop: Object{%p} event %u (%s)\n", receiver, (unsigned)event.type(), event.name());
  33. if (!receiver) {
  34. switch (event.type()) {
  35. case Event::Quit:
  36. return 0;
  37. default:
  38. printf("event type %u with no receiver :(\n", event.type());
  39. return 1;
  40. }
  41. } else {
  42. receiver->event(event);
  43. }
  44. }
  45. }
  46. }
  47. void EventLoop::postEvent(Object* receiver, OwnPtr<Event>&& event)
  48. {
  49. printf("EventLoop::postEvent: {%u} << receiver=%p, event=%p\n", m_queuedEvents.size(), receiver, event.ptr());
  50. m_queuedEvents.append({ receiver, move(event) });
  51. }
  52. #ifdef SERENITY
  53. void EventLoop::waitForEvent()
  54. {
  55. }
  56. #endif
  57. #ifdef USE_SDL
  58. static inline MouseButton toMouseButton(byte sdlButton)
  59. {
  60. if (sdlButton == 1)
  61. return MouseButton::Left;
  62. if (sdlButton == 2)
  63. return MouseButton::Middle;
  64. if (sdlButton == 3)
  65. return MouseButton::Right;
  66. ASSERT_NOT_REACHED();
  67. return MouseButton::None;
  68. }
  69. void EventLoop::handleKeyEvent(Event::Type type, const SDL_KeyboardEvent& sdlKey)
  70. {
  71. auto keyEvent = make<KeyEvent>(type, 0);
  72. int key = 0;
  73. switch (sdlKey.keysym.sym) {
  74. case SDLK_LEFT: key = KeyboardKey::LeftArrow; break;
  75. case SDLK_RIGHT: key = KeyboardKey::RightArrow; break;
  76. case SDLK_UP: key = KeyboardKey::UpArrow; break;
  77. case SDLK_DOWN: key = KeyboardKey::DownArrow; break;
  78. case SDLK_BACKSPACE: key = KeyboardKey::Backspace; break;
  79. case SDLK_RETURN: key = KeyboardKey::Return; break;
  80. }
  81. keyEvent->m_key = key;
  82. if (sdlKey.keysym.sym > SDLK_UNKNOWN && sdlKey.keysym.sym <= 'z') {
  83. char buf[] = { 0, 0 };
  84. char& ch = buf[0];
  85. ch = (char)sdlKey.keysym.sym;
  86. if (sdlKey.keysym.mod & KMOD_SHIFT) {
  87. if (ch >= 'a' && ch <= 'z') {
  88. ch &= ~0x20;
  89. } else {
  90. switch (ch) {
  91. case '1': ch = '!'; break;
  92. case '2': ch = '@'; break;
  93. case '3': ch = '#'; break;
  94. case '4': ch = '$'; break;
  95. case '5': ch = '%'; break;
  96. case '6': ch = '^'; break;
  97. case '7': ch = '&'; break;
  98. case '8': ch = '*'; break;
  99. case '9': ch = '('; break;
  100. case '0': ch = ')'; break;
  101. case '-': ch = '_'; break;
  102. case '=': ch = '+'; break;
  103. case '`': ch = '~'; break;
  104. case ',': ch = '<'; break;
  105. case '.': ch = '>'; break;
  106. case '/': ch = '?'; break;
  107. case '[': ch = '{'; break;
  108. case ']': ch = '}'; break;
  109. case '\\': ch = '|'; break;
  110. case '\'': ch = '"'; break;
  111. case ';': ch = ':'; break;
  112. }
  113. }
  114. }
  115. keyEvent->m_text = buf;
  116. }
  117. keyEvent->m_shift = sdlKey.keysym.mod & KMOD_SHIFT;
  118. keyEvent->m_ctrl = sdlKey.keysym.mod & KMOD_CTRL;
  119. keyEvent->m_alt = sdlKey.keysym.mod & KMOD_ALT;
  120. postEvent(&WindowManager::the(), move(keyEvent));
  121. }
  122. void EventLoop::waitForEvent()
  123. {
  124. SDL_Event sdlEvent;
  125. while (SDL_PollEvent(&sdlEvent) != 0) {
  126. switch (sdlEvent.type) {
  127. case SDL_QUIT:
  128. postEvent(nullptr, make<QuitEvent>());
  129. return;
  130. case SDL_WINDOWEVENT:
  131. if (sdlEvent.window.event == SDL_WINDOWEVENT_EXPOSED) {
  132. // Spam paint events whenever we get exposed.
  133. // This is obviously not ideal, but the SDL backend here is just a prototype anyway.
  134. postEvent(&WindowManager::the(), make<PaintEvent>());
  135. }
  136. return;
  137. case SDL_MOUSEMOTION:
  138. postEvent(&WindowManager::the(), make<MouseEvent>(Event::MouseMove, sdlEvent.motion.x, sdlEvent.motion.y));
  139. return;
  140. case SDL_MOUSEBUTTONDOWN:
  141. postEvent(&WindowManager::the(), make<MouseEvent>(Event::MouseDown, sdlEvent.button.x, sdlEvent.button.y, toMouseButton(sdlEvent.button.button)));
  142. return;
  143. case SDL_MOUSEBUTTONUP:
  144. postEvent(&WindowManager::the(), make<MouseEvent>(Event::MouseUp, sdlEvent.button.x, sdlEvent.button.y, toMouseButton(sdlEvent.button.button)));
  145. return;
  146. case SDL_KEYDOWN:
  147. handleKeyEvent(Event::KeyDown, sdlEvent.key);
  148. return;
  149. case SDL_KEYUP:
  150. handleKeyEvent(Event::KeyUp, sdlEvent.key);
  151. return;
  152. }
  153. }
  154. }
  155. #endif