1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 12:17:35 +00:00

Kernel+WindowServer: Move mouse input signal parsing to kernel driver.

It was silly for the WindowServer to have to know anything about the
format of PS/2 mouse packets.

This patch also enables use of the middle mouse button.
This commit is contained in:
Andreas Kling 2019-03-05 13:59:44 +01:00
parent 1cc32ebc7e
commit 26a9d662f4
6 changed files with 74 additions and 42 deletions

View file

@ -6,6 +6,7 @@
#include <WindowServer/WSClientConnection.h>
#include <WindowServer/WSAPITypes.h>
#include <Kernel/KeyCode.h>
#include <Kernel/MousePacket.h>
#include <LibC/sys/socket.h>
#include <LibC/sys/select.h>
#include <LibC/unistd.h>
@ -200,45 +201,35 @@ void WSMessageLoop::drain_mouse()
auto& screen = WSScreen::the();
bool prev_left_button = screen.left_mouse_button_pressed();
bool prev_right_button = screen.right_mouse_button_pressed();
bool prev_middle_button = screen.middle_mouse_button_pressed();
int dx = 0;
int dy = 0;
bool left_button = prev_left_button;
bool right_button = prev_right_button;
bool middle_button = prev_middle_button;
for (;;) {
byte data[3];
ssize_t nread = read(m_mouse_fd, data, sizeof(data));
MousePacket packet;
ssize_t nread = read(m_mouse_fd, &packet, sizeof(MousePacket));
if (nread == 0)
break;
ASSERT(nread == sizeof(data));
bool left_button = data[0] & 1;
bool right_button = data[0] & 2;
bool x_overflow = data[0] & 0x40;
bool y_overflow = data[0] & 0x80;
bool x_sign = data[0] & 0x10;
bool y_sign = data[0] & 0x20;
ASSERT(nread == sizeof(packet));
left_button = packet.buttons & 1;
right_button = packet.buttons & 2;
middle_button = packet.buttons & 4;
if (x_overflow || y_overflow)
continue;
int x = data[1];
int y = data[2];
if (x && x_sign)
x -= 0x100;
if (y && y_sign)
y -= 0x100;
dx += x;
dy += -y;
if (left_button != prev_left_button || right_button != prev_right_button) {
dx += packet.dx;
dy += -packet.dy;
if (left_button != prev_left_button || right_button != prev_right_button || middle_button != prev_middle_button) {
prev_left_button = left_button;
prev_right_button = right_button;
screen.on_receive_mouse_data(dx, dy, left_button, right_button);
prev_middle_button = middle_button;
screen.on_receive_mouse_data(dx, dy, left_button, right_button, middle_button);
dx = 0;
dy = 0;
}
}
if (dx || dy) {
screen.on_receive_mouse_data(dx, dy, left_button, right_button);
screen.on_receive_mouse_data(dx, dy, left_button, right_button, middle_button);
}
}

View file

@ -58,28 +58,24 @@ void WSScreen::set_resolution(int width, int height)
m_cursor_location.constrain(rect());
}
void WSScreen::on_receive_mouse_data(int dx, int dy, bool left_button, bool right_button)
void WSScreen::on_receive_mouse_data(int dx, int dy, bool left_button, bool right_button, bool middle_button)
{
auto prev_location = m_cursor_location;
m_cursor_location.move_by(dx, dy);
m_cursor_location.constrain(rect());
if (m_cursor_location.x() >= width())
m_cursor_location.set_x(width() - 1);
if (m_cursor_location.y() >= height())
m_cursor_location.set_y(height() - 1);
unsigned buttons = 0;
if (left_button)
buttons |= (unsigned)MouseButton::Left;
if (right_button)
buttons |= (unsigned)MouseButton::Right;
if (m_cursor_location != prev_location) {
auto message = make<WSMouseEvent>(WSMessage::MouseMove, m_cursor_location, buttons);
WSMessageLoop::the().post_message(WSWindowManager::the(), move(message));
}
if (middle_button)
buttons |= (unsigned)MouseButton::Middle;
bool prev_left_button = m_left_mouse_button_pressed;
bool prev_right_button = m_right_mouse_button_pressed;
bool prev_middle_button = m_middle_mouse_button_pressed;
m_left_mouse_button_pressed = left_button;
m_right_mouse_button_pressed = right_button;
m_middle_mouse_button_pressed = middle_button;
if (prev_left_button != left_button) {
auto message = make<WSMouseEvent>(left_button ? WSMessage::MouseDown : WSMessage::MouseUp, m_cursor_location, buttons, MouseButton::Left);
WSMessageLoop::the().post_message(WSWindowManager::the(), move(message));
@ -88,6 +84,15 @@ void WSScreen::on_receive_mouse_data(int dx, int dy, bool left_button, bool righ
auto message = make<WSMouseEvent>(right_button ? WSMessage::MouseDown : WSMessage::MouseUp, m_cursor_location, buttons, MouseButton::Right);
WSMessageLoop::the().post_message(WSWindowManager::the(), move(message));
}
if (prev_middle_button != middle_button) {
auto message = make<WSMouseEvent>(middle_button ? WSMessage::MouseDown : WSMessage::MouseUp, m_cursor_location, buttons, MouseButton::Middle);
WSMessageLoop::the().post_message(WSWindowManager::the(), move(message));
}
if (m_cursor_location != prev_location) {
auto message = make<WSMouseEvent>(WSMessage::MouseMove, m_cursor_location, buttons);
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 || prev_left_button != left_button)
WSWindowManager::the().invalidate_cursor();
}

View file

@ -26,8 +26,9 @@ public:
Point cursor_location() const { return m_cursor_location; }
bool left_mouse_button_pressed() const { return m_left_mouse_button_pressed; }
bool right_mouse_button_pressed() const { return m_right_mouse_button_pressed; }
bool middle_mouse_button_pressed() const { return m_middle_mouse_button_pressed; }
void on_receive_mouse_data(int dx, int dy, bool left_button, bool right_button);
void on_receive_mouse_data(int dx, int dy, bool left_button, bool right_button, bool middle_button);
void on_receive_keyboard_data(KeyEvent);
private:
@ -40,6 +41,7 @@ private:
Point m_cursor_location;
bool m_left_mouse_button_pressed { false };
bool m_right_mouse_button_pressed { false };
bool m_middle_mouse_button_pressed { false };
};
inline RGBA32* WSScreen::scanline(int y)