WSMessageLoop.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. #include "WSMessageLoop.h"
  2. #include "WSMessage.h"
  3. #include "WSMessageReceiver.h"
  4. #include "WSWindowManager.h"
  5. #include "WSScreen.h"
  6. #include "PS2MouseDevice.h"
  7. #include <Kernel/Keyboard.h>
  8. #include <AK/Bitmap.h>
  9. #include "Process.h"
  10. //#define WSEVENTLOOP_DEBUG
  11. static WSMessageLoop* s_the;
  12. WSMessageLoop::WSMessageLoop()
  13. : m_lock("WSMessageLoop")
  14. {
  15. if (!s_the)
  16. s_the = this;
  17. }
  18. WSMessageLoop::~WSMessageLoop()
  19. {
  20. }
  21. WSMessageLoop& WSMessageLoop::the()
  22. {
  23. ASSERT(s_the);
  24. return *s_the;
  25. }
  26. int WSMessageLoop::exec()
  27. {
  28. ASSERT(m_server_process == current);
  29. m_keyboard_fd = m_server_process->sys$open("/dev/keyboard", O_RDONLY);
  30. m_mouse_fd = m_server_process->sys$open("/dev/psaux", O_RDONLY);
  31. ASSERT(m_keyboard_fd >= 0);
  32. ASSERT(m_mouse_fd >= 0);
  33. m_running = true;
  34. for (;;) {
  35. wait_for_message();
  36. Vector<QueuedMessage> messages;
  37. {
  38. ASSERT_INTERRUPTS_ENABLED();
  39. LOCKER(m_lock);
  40. messages = move(m_queued_messages);
  41. }
  42. for (auto& queued_message : messages) {
  43. auto* receiver = queued_message.receiver;
  44. auto& message = *queued_message.message;
  45. #ifdef WSEVENTLOOP_DEBUG
  46. dbgprintf("WSMessageLoop: receiver{%p} message %u\n", receiver, (unsigned)message.type());
  47. #endif
  48. if (!receiver) {
  49. dbgprintf("WSMessage type %u with no receiver :(\n", message.type());
  50. ASSERT_NOT_REACHED();
  51. return 1;
  52. } else {
  53. receiver->on_message(message);
  54. }
  55. }
  56. }
  57. }
  58. void WSMessageLoop::post_message(WSMessageReceiver* receiver, OwnPtr<WSMessage>&& message)
  59. {
  60. LOCKER(m_lock);
  61. #ifdef WSEVENTLOOP_DEBUG
  62. dbgprintf("WSMessageLoop::post_message: {%u} << receiver=%p, message=%p (type=%u)\n", m_queued_messages.size(), receiver, message.ptr(), message->type());
  63. #endif
  64. if (message->type() == WSMessage::WM_ClientFinishedPaint) {
  65. auto& invalidation_message = static_cast<WSClientFinishedPaintMessage&>(*message);
  66. for (auto& queued_message : m_queued_messages) {
  67. if (receiver == queued_message.receiver && queued_message.message->type() == WSMessage::WM_ClientFinishedPaint) {
  68. auto& queued_invalidation_message = static_cast<WSClientFinishedPaintMessage&>(*queued_message.message);
  69. if (queued_invalidation_message.rect().is_empty() || queued_invalidation_message.rect().contains(invalidation_message.rect())) {
  70. #ifdef WSEVENTLOOP_DEBUG
  71. dbgprintf("Swallow WM_ClientFinishedPaint\n");
  72. #endif
  73. return;
  74. }
  75. }
  76. }
  77. }
  78. if (message->type() == WSMessage::WM_ClientWantsToPaint) {
  79. auto& invalidation_message = static_cast<WSClientWantsToPaintMessage&>(*message);
  80. for (auto& queued_message : m_queued_messages) {
  81. if (receiver == queued_message.receiver && queued_message.message->type() == WSMessage::WM_ClientWantsToPaint) {
  82. auto& queued_invalidation_message = static_cast<WSClientWantsToPaintMessage&>(*queued_message.message);
  83. if (queued_invalidation_message.rect().is_empty() || queued_invalidation_message.rect().contains(invalidation_message.rect())) {
  84. #ifdef WSEVENTLOOP_DEBUG
  85. dbgprintf("Swallow WM_ClientWantsToPaint\n");
  86. #endif
  87. return;
  88. }
  89. }
  90. }
  91. }
  92. m_queued_messages.append({ receiver, move(message) });
  93. if (current != m_server_process)
  94. m_server_process->request_wakeup();
  95. }
  96. void WSMessageLoop::Timer::reload()
  97. {
  98. struct timeval now;
  99. current->sys$gettimeofday(&now);
  100. next_fire_time = {
  101. now.tv_sec + (interval / 1000),
  102. now.tv_usec + (interval % 1000)
  103. };
  104. }
  105. int WSMessageLoop::start_timer(int interval, Function<void()>&& callback)
  106. {
  107. auto timer = make<Timer>();
  108. int timer_id = m_next_timer_id++;
  109. timer->timer_id = timer_id;
  110. timer->callback = move(callback);
  111. timer->interval = interval;
  112. timer->reload();
  113. m_timers.set(timer_id, move(timer));
  114. return timer_id;
  115. }
  116. int WSMessageLoop::stop_timer(int timer_id)
  117. {
  118. auto it = m_timers.find(timer_id);
  119. if (it == m_timers.end())
  120. return -1;
  121. m_timers.remove(it);
  122. return 0;
  123. }
  124. void WSMessageLoop::wait_for_message()
  125. {
  126. fd_set rfds;
  127. memset(&rfds, 0, sizeof(rfds));
  128. auto bitmap = Bitmap::wrap((byte*)&rfds, FD_SETSIZE);
  129. bitmap.set(m_keyboard_fd, true);
  130. bitmap.set(m_mouse_fd, true);
  131. Syscall::SC_select_params params;
  132. params.nfds = max(m_keyboard_fd, m_mouse_fd) + 1;
  133. params.readfds = &rfds;
  134. params.writefds = nullptr;
  135. params.exceptfds = nullptr;
  136. struct timeval timeout = { 0, 0 };
  137. bool had_any_timer = false;
  138. for (auto& it : m_timers) {
  139. auto& timer = *it.value;
  140. if (!had_any_timer) {
  141. timeout = timer.next_fire_time;
  142. had_any_timer = true;
  143. continue;
  144. }
  145. if (timer.next_fire_time.tv_sec > timeout.tv_sec || (timer.next_fire_time.tv_sec == timeout.tv_sec && timer.next_fire_time.tv_usec > timeout.tv_usec))
  146. timeout = timer.next_fire_time;
  147. }
  148. if (m_timers.is_empty() && m_queued_messages.is_empty())
  149. params.timeout = nullptr;
  150. else
  151. params.timeout = &timeout;
  152. int rc = m_server_process->sys$select(&params);
  153. memory_barrier();
  154. if (rc < 0) {
  155. ASSERT_NOT_REACHED();
  156. }
  157. struct timeval now;
  158. current->sys$gettimeofday(&now);
  159. for (auto& it : m_timers) {
  160. auto& timer = *it.value;
  161. if (now.tv_sec > timer.next_fire_time.tv_sec || (now.tv_sec == timer.next_fire_time.tv_sec && now.tv_usec > timer.next_fire_time.tv_usec)) {
  162. timer.callback();
  163. timer.reload();
  164. }
  165. }
  166. if (bitmap.get(m_keyboard_fd))
  167. drain_keyboard();
  168. if (bitmap.get(m_mouse_fd))
  169. drain_mouse();
  170. }
  171. void WSMessageLoop::drain_mouse()
  172. {
  173. auto& screen = WSScreen::the();
  174. auto& mouse = PS2MouseDevice::the();
  175. bool prev_left_button = screen.left_mouse_button_pressed();
  176. bool prev_right_button = screen.right_mouse_button_pressed();
  177. int dx = 0;
  178. int dy = 0;
  179. while (mouse.can_read(*m_server_process)) {
  180. byte data[3];
  181. ssize_t nread = mouse.read(*m_server_process, (byte*)data, sizeof(data));
  182. ASSERT(nread == sizeof(data));
  183. bool left_button = data[0] & 1;
  184. bool right_button = data[0] & 2;
  185. bool x_overflow = data[0] & 0x40;
  186. bool y_overflow = data[0] & 0x80;
  187. bool x_sign = data[0] & 0x10;
  188. bool y_sign = data[0] & 0x20;
  189. if (x_overflow || y_overflow)
  190. continue;
  191. int x = data[1];
  192. int y = data[2];
  193. if (x && x_sign)
  194. x -= 0x100;
  195. if (y && y_sign)
  196. y -= 0x100;
  197. dx += x;
  198. dy += -y;
  199. if (left_button != prev_left_button || right_button != prev_right_button || !mouse.can_read(*m_server_process)) {
  200. prev_left_button = left_button;
  201. prev_right_button = right_button;
  202. screen.on_receive_mouse_data(dx, dy, left_button, right_button);
  203. dx = 0;
  204. dy = 0;
  205. }
  206. }
  207. }
  208. void WSMessageLoop::drain_keyboard()
  209. {
  210. auto& screen = WSScreen::the();
  211. auto& keyboard = Keyboard::the();
  212. while (keyboard.can_read(*m_server_process)) {
  213. Keyboard::Event event;
  214. ssize_t nread = keyboard.read(*m_server_process, (byte*)&event, sizeof(Keyboard::Event));
  215. ASSERT(nread == sizeof(Keyboard::Event));
  216. screen.on_receive_keyboard_data(event);
  217. }
  218. }