diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-03-20 04:34:14 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-03-20 04:34:14 +0100 |
commit | d17a91f1851e8f0b3a3353d677ad8d1f51e921b7 (patch) | |
tree | 30316253f23ab99c106832deeb6c7d36adab27fc /Servers/WindowServer/WSScreen.cpp | |
parent | 9120b05a4044b346be397b0ae5b9b7e9a8cbd0b1 (diff) | |
download | serenity-d17a91f1851e8f0b3a3353d677ad8d1f51e921b7.zip |
Move WindowServer into Servers.
Diffstat (limited to 'Servers/WindowServer/WSScreen.cpp')
-rw-r--r-- | Servers/WindowServer/WSScreen.cpp | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/Servers/WindowServer/WSScreen.cpp b/Servers/WindowServer/WSScreen.cpp new file mode 100644 index 0000000000..f491b014c6 --- /dev/null +++ b/Servers/WindowServer/WSScreen.cpp @@ -0,0 +1,98 @@ +#include "WSScreen.h" +#include "WSMessageLoop.h" +#include "WSMessage.h" +#include "WSWindowManager.h" +#include <unistd.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/mman.h> + +static WSScreen* s_the; + +WSScreen& WSScreen::the() +{ + ASSERT(s_the); + return *s_the; +} + +WSScreen::WSScreen(unsigned width, unsigned height) + : m_width(width) + , m_height(height) +{ + ASSERT(!s_the); + s_the = this; + m_cursor_location = rect().center(); + m_framebuffer_fd = open("/dev/bxvga", O_RDWR); + ASSERT(m_framebuffer_fd >= 0); + + set_resolution(width, height); +} + +WSScreen::~WSScreen() +{ +} + +void WSScreen::set_resolution(int width, int height) +{ + struct BXVGAResolution { + int width; + int height; + }; + BXVGAResolution resolution { (int)width, (int)height}; + int rc = ioctl(m_framebuffer_fd, 1985, (int)&resolution); + ASSERT(rc == 0); + + if (m_framebuffer) { + size_t previous_size_in_bytes = m_width * m_height * sizeof(RGBA32) * 2; + int rc = munmap(m_framebuffer, previous_size_in_bytes); + ASSERT(rc == 0); + } + + size_t framebuffer_size_in_bytes = width * height * sizeof(RGBA32) * 2; + m_framebuffer = (RGBA32*)mmap(nullptr, framebuffer_size_in_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, m_framebuffer_fd, 0); + ASSERT(m_framebuffer && m_framebuffer != (void*)-1); + + m_width = width; + m_height = height; + + m_cursor_location.constrain(rect()); +} + +void WSScreen::on_receive_mouse_data(int dx, int dy, unsigned buttons) +{ + auto prev_location = m_cursor_location; + m_cursor_location.move_by(dx, dy); + m_cursor_location.constrain(rect()); + unsigned prev_buttons = m_mouse_button_state; + m_mouse_button_state = buttons; + unsigned changed_buttons = prev_buttons ^ buttons; + auto post_mousedown_or_mouseup_if_needed = [&] (MouseButton button) { + if (!(changed_buttons & (unsigned)button)) + return; + auto message = make<WSMouseEvent>(buttons & (unsigned)button ? WSMessage::MouseDown : WSMessage::MouseUp, m_cursor_location, buttons, button, m_modifiers); + WSMessageLoop::the().post_message(WSWindowManager::the(), move(message)); + }; + post_mousedown_or_mouseup_if_needed(MouseButton::Left); + post_mousedown_or_mouseup_if_needed(MouseButton::Right); + post_mousedown_or_mouseup_if_needed(MouseButton::Middle); + if (m_cursor_location != prev_location) { + auto message = make<WSMouseEvent>(WSMessage::MouseMove, m_cursor_location, buttons, MouseButton::None, m_modifiers); + WSMessageLoop::the().post_message(WSWindowManager::the(), move(message)); + } + // NOTE: Invalidate the cursor if it moved, or if the left button changed state (for the cursor color inversion.) + if (m_cursor_location != prev_location || changed_buttons & (unsigned)MouseButton::Left) + WSWindowManager::the().invalidate_cursor(); +} + +void WSScreen::on_receive_keyboard_data(KeyEvent kernel_event) +{ + m_modifiers = kernel_event.modifiers(); + auto message = make<WSKeyEvent>(kernel_event.is_press() ? WSMessage::KeyDown : WSMessage::KeyUp, kernel_event.key, kernel_event.character, kernel_event.modifiers()); + WSMessageLoop::the().post_message(WSWindowManager::the(), move(message)); +} + +void WSScreen::set_y_offset(int offset) +{ + int rc = ioctl(m_framebuffer_fd, 1982, offset); + ASSERT(rc == 0); +} |