WSScreen.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #include "WSScreen.h"
  2. #include "WSMessageLoop.h"
  3. #include "WSMessage.h"
  4. #include "WSWindowManager.h"
  5. #include <unistd.h>
  6. #include <fcntl.h>
  7. #include <sys/ioctl.h>
  8. #include <sys/mman.h>
  9. static WSScreen* s_the;
  10. WSScreen& WSScreen::the()
  11. {
  12. ASSERT(s_the);
  13. return *s_the;
  14. }
  15. WSScreen::WSScreen(unsigned width, unsigned height)
  16. : m_width(width)
  17. , m_height(height)
  18. {
  19. ASSERT(!s_the);
  20. s_the = this;
  21. m_cursor_location = rect().center();
  22. m_framebuffer_fd = open("/dev/bxvga", O_RDWR);
  23. ASSERT(m_framebuffer_fd >= 0);
  24. set_resolution(width, height);
  25. }
  26. WSScreen::~WSScreen()
  27. {
  28. }
  29. void WSScreen::set_resolution(int width, int height)
  30. {
  31. struct BXVGAResolution {
  32. int width;
  33. int height;
  34. };
  35. BXVGAResolution resolution { (int)width, (int)height};
  36. int rc = ioctl(m_framebuffer_fd, 1985, (int)&resolution);
  37. ASSERT(rc == 0);
  38. if (m_framebuffer) {
  39. size_t previous_size_in_bytes = m_width * m_height * sizeof(RGBA32) * 2;
  40. int rc = munmap(m_framebuffer, previous_size_in_bytes);
  41. ASSERT(rc == 0);
  42. }
  43. size_t framebuffer_size_in_bytes = width * height * sizeof(RGBA32) * 2;
  44. m_framebuffer = (RGBA32*)mmap(nullptr, framebuffer_size_in_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, m_framebuffer_fd, 0);
  45. ASSERT(m_framebuffer && m_framebuffer != (void*)-1);
  46. m_width = width;
  47. m_height = height;
  48. m_cursor_location.constrain(rect());
  49. }
  50. void WSScreen::on_receive_mouse_data(int dx, int dy, bool left_button, bool right_button)
  51. {
  52. auto prev_location = m_cursor_location;
  53. m_cursor_location.move_by(dx, dy);
  54. m_cursor_location.constrain(rect());
  55. if (m_cursor_location.x() >= width())
  56. m_cursor_location.set_x(width() - 1);
  57. if (m_cursor_location.y() >= height())
  58. m_cursor_location.set_y(height() - 1);
  59. unsigned buttons = 0;
  60. if (left_button)
  61. buttons |= (unsigned)MouseButton::Left;
  62. if (right_button)
  63. buttons |= (unsigned)MouseButton::Right;
  64. if (m_cursor_location != prev_location) {
  65. auto message = make<WSMouseEvent>(WSMessage::MouseMove, m_cursor_location, buttons);
  66. WSMessageLoop::the().post_message(WSWindowManager::the(), move(message));
  67. }
  68. bool prev_left_button = m_left_mouse_button_pressed;
  69. bool prev_right_button = m_right_mouse_button_pressed;
  70. m_left_mouse_button_pressed = left_button;
  71. m_right_mouse_button_pressed = right_button;
  72. if (prev_left_button != left_button) {
  73. auto message = make<WSMouseEvent>(left_button ? WSMessage::MouseDown : WSMessage::MouseUp, m_cursor_location, buttons, MouseButton::Left);
  74. WSMessageLoop::the().post_message(WSWindowManager::the(), move(message));
  75. }
  76. if (prev_right_button != right_button) {
  77. auto message = make<WSMouseEvent>(right_button ? WSMessage::MouseDown : WSMessage::MouseUp, m_cursor_location, buttons, MouseButton::Right);
  78. WSMessageLoop::the().post_message(WSWindowManager::the(), move(message));
  79. }
  80. if (m_cursor_location != prev_location || prev_left_button != left_button)
  81. WSWindowManager::the().invalidate_cursor();
  82. }
  83. void WSScreen::on_receive_keyboard_data(KeyEvent kernel_event)
  84. {
  85. auto message = make<WSKeyEvent>(kernel_event.is_press() ? WSMessage::KeyDown : WSMessage::KeyUp, kernel_event.key, kernel_event.character, kernel_event.modifiers());
  86. WSMessageLoop::the().post_message(WSWindowManager::the(), move(message));
  87. }
  88. void WSScreen::set_y_offset(int offset)
  89. {
  90. int rc = ioctl(m_framebuffer_fd, 1982, offset);
  91. ASSERT(rc == 0);
  92. }