1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 15:57:45 +00:00

Hook up the PS2MouseDevice to the AbstractScreen+WindowManager.

Render the mouse cursor by xor'ing the pixels. I don't know anything about
hardware cursors yet and this way we don't need to recompose the window
hierarchy every time you move the mouse. :^)
This commit is contained in:
Andreas Kling 2019-01-11 03:52:09 +01:00
parent 31667b47a5
commit e5e295052f
10 changed files with 117 additions and 5 deletions

View file

@ -1,10 +1,13 @@
#include "PS2MouseDevice.h" #include "PS2MouseDevice.h"
#include "IO.h" #include "IO.h"
static PS2MouseDevice* s_the;
PS2MouseDevice::PS2MouseDevice() PS2MouseDevice::PS2MouseDevice()
: IRQHandler(12) : IRQHandler(12)
, CharacterDevice(10, 1) , CharacterDevice(10, 1)
{ {
s_the = this;
initialize(); initialize();
} }
@ -12,6 +15,11 @@ PS2MouseDevice::~PS2MouseDevice()
{ {
} }
PS2MouseDevice& PS2MouseDevice::the()
{
return *s_the;
}
void PS2MouseDevice::handle_irq() void PS2MouseDevice::handle_irq()
{ {
byte data = IO::in8(0x60); byte data = IO::in8(0x60);
@ -32,6 +40,8 @@ void PS2MouseDevice::handle_irq()
(m_data[0] & 1) ? "Left" : "", (m_data[0] & 1) ? "Left" : "",
(m_data[0] & 2) ? "Right" : "" (m_data[0] & 2) ? "Right" : ""
); );
if (m_client)
m_client->did_receive_mouse_data(m_data[1], -m_data[2], m_data[0] & 1, m_data[0] & 2);
break; break;
} }
} }
@ -120,3 +130,7 @@ ssize_t PS2MouseDevice::write(const byte *buffer, size_t buffer_size)
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
return 0; return 0;
} }
MouseClient::~MouseClient()
{
}

View file

@ -3,11 +3,17 @@
#include <VirtualFileSystem/CharacterDevice.h> #include <VirtualFileSystem/CharacterDevice.h>
#include "IRQHandler.h" #include "IRQHandler.h"
class MouseClient;
class PS2MouseDevice final : public IRQHandler, public CharacterDevice { class PS2MouseDevice final : public IRQHandler, public CharacterDevice {
public: public:
PS2MouseDevice(); PS2MouseDevice();
virtual ~PS2MouseDevice() override; virtual ~PS2MouseDevice() override;
static PS2MouseDevice& the();
void set_client(MouseClient* client) { m_client = client; }
private: private:
virtual bool has_data_available_for_reading() const override; virtual bool has_data_available_for_reading() const override;
virtual ssize_t read(byte* buffer, size_t buffer_size) override; virtual ssize_t read(byte* buffer, size_t buffer_size) override;
@ -23,6 +29,13 @@ private:
void wait_then_write(byte port, byte data); void wait_then_write(byte port, byte data);
byte wait_then_read(byte port); byte wait_then_read(byte port);
MouseClient* m_client { nullptr };
byte m_data_state { 0 }; byte m_data_state { 0 };
signed_byte m_data[3]; signed_byte m_data[3];
}; };
class MouseClient {
public:
virtual ~MouseClient();
virtual void did_receive_mouse_data(int dx, int dy, bool left_button, bool right_button) = 0;
};

View file

@ -2,6 +2,7 @@
#include "EventLoop.h" #include "EventLoop.h"
#include "Event.h" #include "Event.h"
#include "Widget.h" #include "Widget.h"
#include "WindowManager.h"
#include <AK/Assertions.h> #include <AK/Assertions.h>
static AbstractScreen* s_the; static AbstractScreen* s_the;
@ -24,9 +25,40 @@ AbstractScreen::AbstractScreen(unsigned width, unsigned height)
{ {
ASSERT(!s_the); ASSERT(!s_the);
s_the = this; s_the = this;
m_cursor_location = rect().center();
PS2MouseDevice::the().set_client(this);
} }
AbstractScreen::~AbstractScreen() AbstractScreen::~AbstractScreen()
{ {
} }
void AbstractScreen::did_receive_mouse_data(int dx, int dy, bool left_button, bool right_button)
{
auto prev_location = m_cursor_location;
m_cursor_location.moveBy(dx, dy);
if (m_cursor_location.x() >= width())
m_cursor_location.setX(width() - 1);
if (m_cursor_location.y() >= height())
m_cursor_location.setY(height() - 1);
if (m_cursor_location != prev_location) {
auto event = make<MouseEvent>(Event::MouseMove, m_cursor_location.x(), m_cursor_location.y());
EventLoop::main().postEvent(&WindowManager::the(), move(event));
}
bool prev_left_button = m_left_mouse_button_pressed;
bool prev_right_button = m_right_mouse_button_pressed;
m_left_mouse_button_pressed = left_button;
m_right_mouse_button_pressed = right_button;
if (prev_left_button != left_button) {
auto event = make<MouseEvent>(left_button ? Event::MouseDown : Event::MouseUp, m_cursor_location.x(), m_cursor_location.y(), MouseButton::Left);
EventLoop::main().postEvent(&WindowManager::the(), move(event));
}
if (prev_right_button != right_button) {
auto event = make<MouseEvent>(right_button ? Event::MouseDown : Event::MouseUp, m_cursor_location.x(), m_cursor_location.y(), MouseButton::Right);
EventLoop::main().postEvent(&WindowManager::the(), move(event));
}
if (m_cursor_location != prev_location)
WindowManager::the().redraw_cursor();
}

View file

@ -3,8 +3,9 @@
#include "Object.h" #include "Object.h"
#include "Rect.h" #include "Rect.h"
#include "Size.h" #include "Size.h"
#include "PS2MouseDevice.h"
class AbstractScreen : public Object { class AbstractScreen : public Object, public MouseClient {
public: public:
virtual ~AbstractScreen(); virtual ~AbstractScreen();
@ -18,11 +19,22 @@ public:
static void initialize(); static void initialize();
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; }
protected: protected:
AbstractScreen(unsigned width, unsigned height); AbstractScreen(unsigned width, unsigned height);
private: private:
// ^MouseClient
virtual void did_receive_mouse_data(int dx, int dy, bool left_button, bool right_button) final;
int m_width { 0 }; int m_width { 0 };
int m_height { 0 }; int m_height { 0 };
Point m_cursor_location;
bool m_left_mouse_button_pressed { false };
bool m_right_mouse_button_pressed { false };
}; };

View file

@ -53,7 +53,7 @@ int EventLoop::exec()
void EventLoop::postEvent(Object* receiver, OwnPtr<Event>&& event) void EventLoop::postEvent(Object* receiver, OwnPtr<Event>&& event)
{ {
printf("EventLoop::postEvent: {%u} << receiver=%p, event=%p\n", m_queuedEvents.size(), receiver, event.ptr()); //printf("EventLoop::postEvent: {%u} << receiver=%p, event=%p\n", m_queuedEvents.size(), receiver, event.ptr());
m_queuedEvents.append({ receiver, move(event) }); m_queuedEvents.append({ receiver, move(event) });
} }

View file

@ -136,6 +136,14 @@ void Painter::drawPixel(const Point& p, Color color)
m_target->scanline(point.y())[point.x()] = color.value(); m_target->scanline(point.y())[point.x()] = color.value();
} }
void Painter::set_pixel_with_draw_op(dword& pixel, const Color& color)
{
if (m_draw_op == DrawOp::Copy)
pixel = color.value();
else if (m_draw_op == DrawOp::Xor)
pixel ^= color.value();
}
void Painter::drawLine(const Point& p1, const Point& p2, Color color) void Painter::drawLine(const Point& p1, const Point& p2, Color color)
{ {
auto point1 = p1; auto point1 = p1;
@ -152,7 +160,7 @@ void Painter::drawLine(const Point& p1, const Point& p2, Color color)
if (point1.y() > point2.y()) if (point1.y() > point2.y())
swap(point1, point2); swap(point1, point2);
for (int y = max(point1.y(), m_clipRect.top()); y <= min(point2.y(), m_clipRect.bottom()); ++y) for (int y = max(point1.y(), m_clipRect.top()); y <= min(point2.y(), m_clipRect.bottom()); ++y)
m_target->scanline(y)[x] = color.value(); set_pixel_with_draw_op(m_target->scanline(y)[x], color);
return; return;
} }
@ -168,7 +176,7 @@ void Painter::drawLine(const Point& p1, const Point& p2, Color color)
swap(point1, point2); swap(point1, point2);
auto* pixels = m_target->scanline(point1.y()); auto* pixels = m_target->scanline(point1.y());
for (int x = max(point1.x(), m_clipRect.left()); x <= min(point2.x(), m_clipRect.right()); ++x) for (int x = max(point1.x(), m_clipRect.left()); x <= min(point2.x(), m_clipRect.right()); ++x)
pixels[x] = color.value(); set_pixel_with_draw_op(pixels[x], color);
return; return;
} }

View file

@ -30,11 +30,18 @@ public:
const Font& font() const { return *m_font; } const Font& font() const { return *m_font; }
enum class DrawOp { Copy, Xor };
void set_draw_op(DrawOp op) { m_draw_op = op; }
DrawOp draw_op() const { return m_draw_op; }
private: private:
void set_pixel_with_draw_op(dword& pixel, const Color&);
Widget& m_widget; Widget& m_widget;
const Font* m_font; const Font* m_font;
Point m_translation; Point m_translation;
Rect m_clipRect; Rect m_clipRect;
RetainPtr<GraphicsBitmap> m_target; RetainPtr<GraphicsBitmap> m_target;
Window* m_window { nullptr }; Window* m_window { nullptr };
DrawOp m_draw_op { DrawOp::Copy };
}; };

View file

@ -28,6 +28,11 @@ public:
&& m_y == other.m_y; && m_y == other.m_y;
} }
bool operator!=(const Point& other) const
{
return !(*this == other);
}
private: private:
int m_x { 0 }; int m_x { 0 };
int m_y { 0 }; int m_y { 0 };

View file

@ -281,6 +281,24 @@ void WindowManager::recompose()
framebuffer.blit(window->position(), *window->backing()); framebuffer.blit(window->position(), *window->backing());
} }
framebuffer.flush(); framebuffer.flush();
m_last_drawn_cursor_location = { -1, -1 };
redraw_cursor();
}
void WindowManager::redraw_cursor()
{
auto cursor_location = AbstractScreen::the().cursor_location();
Painter painter(*m_rootWidget);
painter.set_draw_op(Painter::DrawOp::Xor);
auto draw_cross = [&painter] (const Point& p) {
painter.drawLine({ p.x() - 10, p.y() }, { p.x() + 10, p.y() }, Color::Red);
painter.drawLine({ p.x(), p.y() - 10 }, { p.x(), p.y() + 10 }, Color::Red);
};
if (cursor_location != m_last_drawn_cursor_location && m_last_drawn_cursor_location.x() != -1)
draw_cross(m_last_drawn_cursor_location);
draw_cross(cursor_location);
m_last_drawn_cursor_location = cursor_location;
FrameBuffer::the().flush();
} }
void WindowManager::event(Event& event) void WindowManager::event(Event& event)
@ -329,4 +347,3 @@ bool WindowManager::isVisible(Window& window) const
{ {
return m_windows.contains(&window); return m_windows.contains(&window);
} }

View file

@ -36,6 +36,8 @@ public:
static void initialize(); static void initialize();
void redraw_cursor();
private: private:
WindowManager(); WindowManager();
~WindowManager(); ~WindowManager();
@ -68,6 +70,8 @@ private:
Rect m_dragStartRect; Rect m_dragStartRect;
Rect m_dragEndRect; Rect m_dragEndRect;
Point m_last_drawn_cursor_location;
unsigned m_recompose_count { 0 }; unsigned m_recompose_count { 0 };
unsigned m_frontmost_only_compose_count { 0 }; unsigned m_frontmost_only_compose_count { 0 };
}; };