EventLoop.cpp 6.4 KB

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