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:
parent
31667b47a5
commit
e5e295052f
10 changed files with 117 additions and 5 deletions
|
@ -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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
};
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
@ -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 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 };
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 };
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue