EventLoop.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Debug.h>
  7. #include <Kernel/API/MousePacket.h>
  8. #include <WindowServer/ClientConnection.h>
  9. #include <WindowServer/Cursor.h>
  10. #include <WindowServer/EventLoop.h>
  11. #include <WindowServer/Screen.h>
  12. #include <WindowServer/WMClientConnection.h>
  13. #include <WindowServer/WindowManager.h>
  14. #include <fcntl.h>
  15. #include <stdio.h>
  16. #include <unistd.h>
  17. namespace WindowServer {
  18. EventLoop::EventLoop()
  19. : m_window_server(Core::LocalServer::construct())
  20. , m_wm_server(Core::LocalServer::construct())
  21. {
  22. m_keyboard_fd = open("/dev/keyboard0", O_RDONLY | O_NONBLOCK | O_CLOEXEC);
  23. m_mouse_fd = open("/dev/mouse0", O_RDONLY | O_NONBLOCK | O_CLOEXEC);
  24. bool ok = m_window_server->take_over_from_system_server("/tmp/portal/window");
  25. VERIFY(ok);
  26. ok = m_wm_server->take_over_from_system_server("/tmp/portal/wm");
  27. VERIFY(ok);
  28. m_window_server->on_ready_to_accept = [this] {
  29. auto client_socket = m_window_server->accept();
  30. if (!client_socket) {
  31. dbgln("WindowServer: accept failed.");
  32. return;
  33. }
  34. static int s_next_client_id = 0;
  35. int client_id = ++s_next_client_id;
  36. IPC::new_client_connection<ClientConnection>(client_socket.release_nonnull(), client_id);
  37. };
  38. m_wm_server->on_ready_to_accept = [this] {
  39. auto client_socket = m_wm_server->accept();
  40. if (!client_socket) {
  41. dbgln("WindowServer: WM accept failed.");
  42. return;
  43. }
  44. static int s_next_wm_id = 0;
  45. int wm_id = ++s_next_wm_id;
  46. IPC::new_client_connection<WMClientConnection>(client_socket.release_nonnull(), wm_id);
  47. };
  48. if (m_keyboard_fd >= 0) {
  49. m_keyboard_notifier = Core::Notifier::construct(m_keyboard_fd, Core::Notifier::Read);
  50. m_keyboard_notifier->on_ready_to_read = [this] { drain_keyboard(); };
  51. } else {
  52. dbgln("Couldn't open /dev/keyboard0");
  53. }
  54. if (m_mouse_fd >= 0) {
  55. m_mouse_notifier = Core::Notifier::construct(m_mouse_fd, Core::Notifier::Read);
  56. m_mouse_notifier->on_ready_to_read = [this] { drain_mouse(); };
  57. } else {
  58. dbgln("Couldn't open /dev/mouse0");
  59. }
  60. }
  61. EventLoop::~EventLoop()
  62. {
  63. }
  64. void EventLoop::drain_mouse()
  65. {
  66. auto& screen_input = ScreenInput::the();
  67. MousePacket state;
  68. state.buttons = screen_input.mouse_button_state();
  69. unsigned buttons = state.buttons;
  70. MousePacket packets[32];
  71. ssize_t nread = read(m_mouse_fd, &packets, sizeof(packets));
  72. if (nread < 0) {
  73. perror("EventLoop::drain_mouse read");
  74. return;
  75. }
  76. size_t npackets = nread / sizeof(MousePacket);
  77. if (!npackets)
  78. return;
  79. for (size_t i = 0; i < npackets; ++i) {
  80. auto& packet = packets[i];
  81. dbgln_if(WSMESSAGELOOP_DEBUG, "EventLoop: Mouse X {}, Y {}, Z {}, relative={}", packet.x, packet.y, packet.z, packet.is_relative);
  82. buttons = packet.buttons;
  83. state.is_relative = packet.is_relative;
  84. if (packet.is_relative) {
  85. state.x += packet.x;
  86. state.y -= packet.y;
  87. state.z += packet.z;
  88. } else {
  89. state.x = packet.x;
  90. state.y = packet.y;
  91. state.z += packet.z;
  92. }
  93. if (buttons != state.buttons) {
  94. state.buttons = buttons;
  95. dbgln_if(WSMESSAGELOOP_DEBUG, "EventLoop: Mouse Button Event");
  96. screen_input.on_receive_mouse_data(state);
  97. if (state.is_relative) {
  98. state.x = 0;
  99. state.y = 0;
  100. state.z = 0;
  101. }
  102. }
  103. }
  104. if (state.is_relative && (state.x || state.y || state.z))
  105. screen_input.on_receive_mouse_data(state);
  106. if (!state.is_relative)
  107. screen_input.on_receive_mouse_data(state);
  108. }
  109. void EventLoop::drain_keyboard()
  110. {
  111. auto& screen_input = ScreenInput::the();
  112. for (;;) {
  113. ::KeyEvent event;
  114. ssize_t nread = read(m_keyboard_fd, (u8*)&event, sizeof(::KeyEvent));
  115. if (nread == 0)
  116. break;
  117. VERIFY(nread == sizeof(::KeyEvent));
  118. screen_input.on_receive_keyboard_data(event);
  119. }
  120. }
  121. }