mirror of
https://github.com/RGBCube/serenity
synced 2025-05-30 22:28:12 +00:00
Start bringing up LibGUI properly (formerly Widgets.)
This commit is contained in:
parent
b91479d9b9
commit
8eae89a405
17 changed files with 258 additions and 33 deletions
|
@ -104,6 +104,7 @@ static void init_stage2()
|
||||||
Process::create_user_process("/bin/Terminal", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, move(environment), tty0);
|
Process::create_user_process("/bin/Terminal", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, move(environment), tty0);
|
||||||
#ifdef SPAWN_GUI_TEST_APP
|
#ifdef SPAWN_GUI_TEST_APP
|
||||||
Process::create_user_process("/bin/guitest", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, move(environment), tty0);
|
Process::create_user_process("/bin/guitest", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, move(environment), tty0);
|
||||||
|
Process::create_user_process("/bin/guitest2", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, move(environment), tty0);
|
||||||
#endif
|
#endif
|
||||||
#ifdef SPAWN_MULTIPLE_SHELLS
|
#ifdef SPAWN_MULTIPLE_SHELLS
|
||||||
Process::create_user_process("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, { }, tty1);
|
Process::create_user_process("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, { }, tty1);
|
||||||
|
|
|
@ -4,6 +4,10 @@ sudo id
|
||||||
|
|
||||||
make -C ../LibC clean && \
|
make -C ../LibC clean && \
|
||||||
make -C ../LibC && \
|
make -C ../LibC && \
|
||||||
|
make -C ../LibGUI clean && \
|
||||||
|
make -C ../LibGUI && \
|
||||||
|
make -C ../Terminal clean && \
|
||||||
|
make -C ../Terminal && \
|
||||||
make -C ../Userland clean && \
|
make -C ../Userland clean && \
|
||||||
make -C ../Userland && \
|
make -C ../Userland && \
|
||||||
sudo ./sync.sh
|
sudo ./sync.sh
|
||||||
|
|
|
@ -43,6 +43,7 @@ cp -v ../Userland/touch mnt/bin/touch
|
||||||
cp -v ../Userland/sync mnt/bin/sync
|
cp -v ../Userland/sync mnt/bin/sync
|
||||||
cp -v ../Userland/more mnt/bin/more
|
cp -v ../Userland/more mnt/bin/more
|
||||||
cp -v ../Userland/guitest mnt/bin/guitest
|
cp -v ../Userland/guitest mnt/bin/guitest
|
||||||
|
cp -v ../Userland/guitest2 mnt/bin/guitest2
|
||||||
cp -v ../Userland/sysctl mnt/bin/sysctl
|
cp -v ../Userland/sysctl mnt/bin/sysctl
|
||||||
cp -v ../Terminal/Terminal mnt/bin/Terminal
|
cp -v ../Terminal/Terminal mnt/bin/Terminal
|
||||||
sh sync-local.sh
|
sh sync-local.sh
|
||||||
|
|
|
@ -134,9 +134,9 @@ private:
|
||||||
|
|
||||||
class GMouseEvent final : public GEvent {
|
class GMouseEvent final : public GEvent {
|
||||||
public:
|
public:
|
||||||
GMouseEvent(Type type, int x, int y, GMouseButton button = GMouseButton::None)
|
GMouseEvent(Type type, const Point& position, GMouseButton button = GMouseButton::None)
|
||||||
: GEvent(type)
|
: GEvent(type)
|
||||||
, m_position(x, y)
|
, m_position(position)
|
||||||
, m_button(button)
|
, m_button(button)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
#include "GEventLoop.h"
|
#include "GEventLoop.h"
|
||||||
#include "GEvent.h"
|
#include "GEvent.h"
|
||||||
#include "GObject.h"
|
#include "GObject.h"
|
||||||
|
#include "GWindow.h"
|
||||||
|
#include <LibC/unistd.h>
|
||||||
|
#include <LibC/stdio.h>
|
||||||
|
#include <LibC/fcntl.h>
|
||||||
|
#include <LibC/string.h>
|
||||||
|
#include <LibC/sys/select.h>
|
||||||
|
#include <LibC/gui.h>
|
||||||
|
|
||||||
static GEventLoop* s_mainGEventLoop;
|
static GEventLoop* s_mainGEventLoop;
|
||||||
|
|
||||||
|
@ -27,13 +34,19 @@ GEventLoop& GEventLoop::main()
|
||||||
|
|
||||||
int GEventLoop::exec()
|
int GEventLoop::exec()
|
||||||
{
|
{
|
||||||
|
m_event_fd = open("/dev/gui_events", O_RDONLY);
|
||||||
|
if (m_event_fd < 0) {
|
||||||
|
perror("GEventLoop::exec(): open");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
m_running = true;
|
m_running = true;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (m_queuedEvents.is_empty())
|
if (m_queued_events.is_empty())
|
||||||
waitForEvent();
|
wait_for_event();
|
||||||
Vector<QueuedEvent> events;
|
Vector<QueuedEvent> events;
|
||||||
{
|
{
|
||||||
events = move(m_queuedEvents);
|
events = move(m_queued_events);
|
||||||
}
|
}
|
||||||
for (auto& queuedEvent : events) {
|
for (auto& queuedEvent : events) {
|
||||||
auto* receiver = queuedEvent.receiver;
|
auto* receiver = queuedEvent.receiver;
|
||||||
|
@ -56,12 +69,81 @@ int GEventLoop::exec()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GEventLoop::postEvent(GObject* receiver, OwnPtr<GEvent>&& event)
|
void GEventLoop::post_event(GObject* receiver, OwnPtr<GEvent>&& event)
|
||||||
{
|
{
|
||||||
//printf("GEventLoop::postGEvent: {%u} << receiver=%p, event=%p\n", m_queuedEvents.size(), receiver, event.ptr());
|
//printf("GEventLoop::postGEvent: {%u} << receiver=%p, event=%p\n", m_queuedEvents.size(), receiver, event.ptr());
|
||||||
m_queuedEvents.append({ receiver, move(event) });
|
m_queued_events.append({ receiver, move(event) });
|
||||||
}
|
}
|
||||||
|
|
||||||
void GEventLoop::waitForEvent()
|
void GEventLoop::handle_paint_event(const GUI_Event& event, GWindow& window)
|
||||||
{
|
{
|
||||||
|
post_event(&window, make<GPaintEvent>(event.paint.rect));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GEventLoop::handle_mouse_event(const GUI_Event& event, GWindow& window)
|
||||||
|
{
|
||||||
|
GMouseEvent::Type type;
|
||||||
|
switch (event.type) {
|
||||||
|
case GUI_Event::Type::MouseMove: type = GEvent::MouseMove; break;
|
||||||
|
case GUI_Event::Type::MouseUp: type = GEvent::MouseUp; break;
|
||||||
|
case GUI_Event::Type::MouseDown: type = GEvent::MouseDown; break;
|
||||||
|
default: ASSERT_NOT_REACHED(); break;
|
||||||
|
}
|
||||||
|
GMouseButton button { GMouseButton::None };
|
||||||
|
switch (event.mouse.button) {
|
||||||
|
case GUI_MouseButton::NoButton: button = GMouseButton::None; break;
|
||||||
|
case GUI_MouseButton::Left: button = GMouseButton::Left; break;
|
||||||
|
case GUI_MouseButton::Right: button = GMouseButton::Right; break;
|
||||||
|
case GUI_MouseButton::Middle: button = GMouseButton::Middle; break;
|
||||||
|
default: ASSERT_NOT_REACHED(); break;
|
||||||
|
}
|
||||||
|
auto mouse_event = make<GMouseEvent>(type, event.mouse.position, button);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GEventLoop::wait_for_event()
|
||||||
|
{
|
||||||
|
fd_set rfds;
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_SET(m_event_fd, &rfds);
|
||||||
|
int rc = select(m_event_fd + 1, &rfds, nullptr, nullptr, nullptr);
|
||||||
|
if (rc < 0) {
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FD_ISSET(m_event_fd, &rfds))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
GUI_Event event;
|
||||||
|
ssize_t nread = read(m_event_fd, &event, sizeof(GUI_Event));
|
||||||
|
if (nread < 0) {
|
||||||
|
perror("read");
|
||||||
|
exit(1); // FIXME: This should cause EventLoop::exec() to return 1.
|
||||||
|
}
|
||||||
|
if (nread == 0)
|
||||||
|
break;
|
||||||
|
assert(nread == sizeof(event));
|
||||||
|
auto* window = GWindow::from_window_id(event.window_id);
|
||||||
|
if (!window) {
|
||||||
|
dbgprintf("GEventLoop received event for invalid window ID %d\n", event.window_id);
|
||||||
|
}
|
||||||
|
switch (event.type) {
|
||||||
|
case GUI_Event::Type::Paint:
|
||||||
|
dbgprintf("WID=%x Paint [%d,%d %dx%d]\n", event.window_id, event.paint.rect.location.x, event.paint.rect.location.y, event.paint.rect.size.width, event.paint.rect.size.height); break;
|
||||||
|
handle_paint_event(event, *window);
|
||||||
|
break;
|
||||||
|
case GUI_Event::Type::MouseDown:
|
||||||
|
case GUI_Event::Type::MouseUp:
|
||||||
|
case GUI_Event::Type::MouseMove:
|
||||||
|
dbgprintf("WID=%x MouseEvent %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y);
|
||||||
|
handle_mouse_event(event, *window);
|
||||||
|
break;
|
||||||
|
case GUI_Event::Type::WindowActivated:
|
||||||
|
dbgprintf("WID=%x WindowActivated\n", event.window_id);
|
||||||
|
break;
|
||||||
|
case GUI_Event::Type::WindowDeactivated:
|
||||||
|
dbgprintf("WID=%x WindowDeactivated\n", event.window_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
|
|
||||||
class GObject;
|
class GObject;
|
||||||
|
class GWindow;
|
||||||
|
struct GUI_Event;
|
||||||
|
|
||||||
class GEventLoop {
|
class GEventLoop {
|
||||||
public:
|
public:
|
||||||
|
@ -13,7 +15,7 @@ public:
|
||||||
|
|
||||||
int exec();
|
int exec();
|
||||||
|
|
||||||
void postEvent(GObject* receiver, OwnPtr<GEvent>&&);
|
void post_event(GObject* receiver, OwnPtr<GEvent>&&);
|
||||||
|
|
||||||
static GEventLoop& main();
|
static GEventLoop& main();
|
||||||
|
|
||||||
|
@ -22,13 +24,16 @@ public:
|
||||||
bool running() const { return m_running; }
|
bool running() const { return m_running; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void waitForEvent();
|
void wait_for_event();
|
||||||
|
void handle_paint_event(const GUI_Event&, GWindow&);
|
||||||
|
void handle_mouse_event(const GUI_Event&, GWindow&);
|
||||||
|
|
||||||
struct QueuedEvent {
|
struct QueuedEvent {
|
||||||
GObject* receiver { nullptr };
|
GObject* receiver { nullptr };
|
||||||
OwnPtr<GEvent> event;
|
OwnPtr<GEvent> event;
|
||||||
};
|
};
|
||||||
Vector<QueuedEvent> m_queuedEvents;
|
Vector<QueuedEvent> m_queued_events;
|
||||||
|
|
||||||
|
int m_event_fd { -1 };
|
||||||
bool m_running { false };
|
bool m_running { false };
|
||||||
};
|
};
|
||||||
|
|
|
@ -71,6 +71,6 @@ void GObject::stopTimer()
|
||||||
|
|
||||||
void GObject::deleteLater()
|
void GObject::deleteLater()
|
||||||
{
|
{
|
||||||
GEventLoop::main().postEvent(this, make<GEvent>(GEvent::DeferredDestroy));
|
GEventLoop::main().post_event(this, make<GEvent>(GEvent::DeferredDestroy));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,6 @@ void GWidget::event(GEvent& event)
|
||||||
case GEvent::Paint:
|
case GEvent::Paint:
|
||||||
m_hasPendingPaintEvent = false;
|
m_hasPendingPaintEvent = false;
|
||||||
if (auto* win = window()) {
|
if (auto* win = window()) {
|
||||||
if (win->is_being_dragged())
|
|
||||||
return;
|
|
||||||
if (!win->is_visible())
|
if (!win->is_visible())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -112,7 +110,7 @@ void GWidget::update()
|
||||||
if (m_hasPendingPaintEvent)
|
if (m_hasPendingPaintEvent)
|
||||||
return;
|
return;
|
||||||
m_hasPendingPaintEvent = true;
|
m_hasPendingPaintEvent = true;
|
||||||
GEventLoop::main().postEvent(w, make<GPaintEvent>(relativeRect()));
|
GEventLoop::main().post_event(w, make<GPaintEvent>(relativeRect()));
|
||||||
}
|
}
|
||||||
|
|
||||||
GWidget::HitTestResult GWidget::hitTest(int x, int y)
|
GWidget::HitTestResult GWidget::hitTest(int x, int y)
|
||||||
|
|
|
@ -2,10 +2,51 @@
|
||||||
#include "GEvent.h"
|
#include "GEvent.h"
|
||||||
#include "GEventLoop.h"
|
#include "GEventLoop.h"
|
||||||
#include <SharedGraphics/GraphicsBitmap.h>
|
#include <SharedGraphics/GraphicsBitmap.h>
|
||||||
|
#include <LibC/gui.h>
|
||||||
|
#include <LibC/stdio.h>
|
||||||
|
#include <LibC/stdlib.h>
|
||||||
|
#include <AK/HashMap.h>
|
||||||
|
|
||||||
GWindow::GWindow(int window_id)
|
static HashMap<int, GWindow*>* s_windows;
|
||||||
: m_window_id(window_id)
|
|
||||||
|
static HashMap<int, GWindow*>& windows()
|
||||||
{
|
{
|
||||||
|
if (!s_windows)
|
||||||
|
s_windows = new HashMap<int, GWindow*>;
|
||||||
|
return *s_windows;
|
||||||
|
}
|
||||||
|
|
||||||
|
GWindow* GWindow::from_window_id(int window_id)
|
||||||
|
{
|
||||||
|
auto it = windows().find(window_id);
|
||||||
|
if (it != windows().end())
|
||||||
|
return (*it).value;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
GWindow::GWindow(GObject* parent)
|
||||||
|
: GObject(parent)
|
||||||
|
{
|
||||||
|
GUI_CreateWindowParameters wparams;
|
||||||
|
wparams.rect = { { 100, 400 }, { 140, 140 } };
|
||||||
|
wparams.background_color = 0xffc0c0;
|
||||||
|
strcpy(wparams.title, "GWindow");
|
||||||
|
m_window_id = gui_create_window(&wparams);
|
||||||
|
if (m_window_id < 0) {
|
||||||
|
perror("gui_create_window");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
GUI_WindowBackingStoreInfo backing;
|
||||||
|
int rc = gui_get_window_backing_store(m_window_id, &backing);
|
||||||
|
if (rc < 0) {
|
||||||
|
perror("gui_get_window_backing_store");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_backing = GraphicsBitmap::create_wrapper(backing.size, backing.pixels);
|
||||||
|
|
||||||
|
windows().set(m_window_id, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
GWindow::~GWindow()
|
GWindow::~GWindow()
|
||||||
|
@ -40,3 +81,19 @@ void GWindow::close()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GWindow::show()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void GWindow::update()
|
||||||
|
{
|
||||||
|
gui_invalidate_window(m_window_id, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GWindow::set_main_widget(GWidget* widget)
|
||||||
|
{
|
||||||
|
if (m_main_widget == widget)
|
||||||
|
return;
|
||||||
|
m_main_widget = widget;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
|
@ -5,11 +5,15 @@
|
||||||
#include <SharedGraphics/GraphicsBitmap.h>
|
#include <SharedGraphics/GraphicsBitmap.h>
|
||||||
#include <AK/AKString.h>
|
#include <AK/AKString.h>
|
||||||
|
|
||||||
|
class GWidget;
|
||||||
|
|
||||||
class GWindow final : public GObject {
|
class GWindow final : public GObject {
|
||||||
public:
|
public:
|
||||||
explicit GWindow(int window_id);
|
GWindow(GObject* parent = nullptr);
|
||||||
virtual ~GWindow() override;
|
virtual ~GWindow() override;
|
||||||
|
|
||||||
|
static GWindow* from_window_id(int);
|
||||||
|
|
||||||
int window_id() const { return m_window_id; }
|
int window_id() const { return m_window_id; }
|
||||||
|
|
||||||
String title() const { return m_title; }
|
String title() const { return m_title; }
|
||||||
|
@ -29,21 +33,24 @@ public:
|
||||||
|
|
||||||
virtual void event(GEvent&) override;
|
virtual void event(GEvent&) override;
|
||||||
|
|
||||||
bool is_being_dragged() const { return m_is_being_dragged; }
|
|
||||||
void set_is_being_dragged(bool b) { m_is_being_dragged = b; }
|
|
||||||
|
|
||||||
bool is_visible() const;
|
bool is_visible() const;
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
|
void set_main_widget(GWidget*);
|
||||||
|
|
||||||
GraphicsBitmap* backing() { return m_backing.ptr(); }
|
GraphicsBitmap* backing() { return m_backing.ptr(); }
|
||||||
|
|
||||||
|
void show();
|
||||||
|
|
||||||
|
void update();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
String m_title;
|
String m_title;
|
||||||
Rect m_rect;
|
Rect m_rect;
|
||||||
bool m_is_being_dragged { false };
|
|
||||||
|
|
||||||
RetainPtr<GraphicsBitmap> m_backing;
|
RetainPtr<GraphicsBitmap> m_backing;
|
||||||
int m_window_id { -1 };
|
int m_window_id { -1 };
|
||||||
|
GWidget* m_main_widget { nullptr };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
1
Userland/.gitignore
vendored
1
Userland/.gitignore
vendored
|
@ -22,4 +22,5 @@ touch
|
||||||
sync
|
sync
|
||||||
more
|
more
|
||||||
guitest
|
guitest
|
||||||
|
guitest2
|
||||||
sysctl
|
sysctl
|
||||||
|
|
|
@ -20,6 +20,7 @@ OBJS = \
|
||||||
touch.o \
|
touch.o \
|
||||||
more.o \
|
more.o \
|
||||||
guitest.o \
|
guitest.o \
|
||||||
|
guitest2.o \
|
||||||
sysctl.o
|
sysctl.o
|
||||||
|
|
||||||
APPS = \
|
APPS = \
|
||||||
|
@ -45,6 +46,7 @@ APPS = \
|
||||||
sync \
|
sync \
|
||||||
more \
|
more \
|
||||||
guitest \
|
guitest \
|
||||||
|
guitest2 \
|
||||||
sysctl
|
sysctl
|
||||||
|
|
||||||
ARCH_FLAGS =
|
ARCH_FLAGS =
|
||||||
|
@ -131,6 +133,9 @@ more: more.o
|
||||||
guitest: guitest.o
|
guitest: guitest.o
|
||||||
$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
|
$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
|
||||||
|
|
||||||
|
guitest2: guitest2.o
|
||||||
|
$(LD) -o $@ $(LDFLAGS) $< ../LibGUI/LibGUI.a ../LibC/LibC.a
|
||||||
|
|
||||||
sysctl: sysctl.o
|
sysctl: sysctl.o
|
||||||
$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
|
$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
|
||||||
|
|
||||||
|
|
54
Userland/guitest2.cpp
Normal file
54
Userland/guitest2.cpp
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <Kernel/Syscall.h>
|
||||||
|
#include <SharedGraphics/GraphicsBitmap.h>
|
||||||
|
#include <SharedGraphics/Painter.h>
|
||||||
|
#include <LibGUI/GWindow.h>
|
||||||
|
#include <LibGUI/GWidget.h>
|
||||||
|
#include <LibGUI/GLabel.h>
|
||||||
|
#include <LibGUI/GEventLoop.h>
|
||||||
|
|
||||||
|
static GWindow* make_font_test_window();
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
auto* window = make_font_test_window();
|
||||||
|
window->show();
|
||||||
|
|
||||||
|
GEventLoop loop;
|
||||||
|
return loop.exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
GWindow* make_font_test_window()
|
||||||
|
{
|
||||||
|
auto* window = new GWindow;
|
||||||
|
window->set_title("Font test");
|
||||||
|
window->set_rect({ 140, 100, 300, 80 });
|
||||||
|
|
||||||
|
auto* widget = new GWidget;
|
||||||
|
window->set_main_widget(widget);
|
||||||
|
widget->setWindowRelativeRect({ 0, 0, 300, 80 });
|
||||||
|
|
||||||
|
auto* l1 = new GLabel(widget);
|
||||||
|
l1->setWindowRelativeRect({ 0, 0, 300, 20 });
|
||||||
|
l1->setText("0123456789");
|
||||||
|
|
||||||
|
auto* l2 = new GLabel(widget);
|
||||||
|
l2->setWindowRelativeRect({ 0, 20, 300, 20 });
|
||||||
|
l2->setText("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||||
|
|
||||||
|
auto* l3 = new GLabel(widget);
|
||||||
|
l3->setWindowRelativeRect({ 0, 40, 300, 20 });
|
||||||
|
l3->setText("abcdefghijklmnopqrstuvwxyz");
|
||||||
|
|
||||||
|
auto* l4 = new GLabel(widget);
|
||||||
|
l4->setWindowRelativeRect({ 0, 60, 300, 20 });
|
||||||
|
l4->setText("!\"#$%&'()*+,-./:;<=>?@[\\]^_{|}~");
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
|
@ -80,9 +80,9 @@ private:
|
||||||
|
|
||||||
enum class MouseButton : byte {
|
enum class MouseButton : byte {
|
||||||
None = 0,
|
None = 0,
|
||||||
Left,
|
Left = 1,
|
||||||
Middle,
|
Right = 2,
|
||||||
Right,
|
Middle = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum KeyboardKey {
|
enum KeyboardKey {
|
||||||
|
@ -121,9 +121,10 @@ private:
|
||||||
|
|
||||||
class MouseEvent final : public WSEvent {
|
class MouseEvent final : public WSEvent {
|
||||||
public:
|
public:
|
||||||
MouseEvent(Type type, int x, int y, MouseButton button = MouseButton::None)
|
MouseEvent(Type type, const Point& position, unsigned buttons, MouseButton button = MouseButton::None)
|
||||||
: WSEvent(type)
|
: WSEvent(type)
|
||||||
, m_position(x, y)
|
, m_position(position)
|
||||||
|
, m_buttons(buttons)
|
||||||
, m_button(button)
|
, m_button(button)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -132,8 +133,10 @@ public:
|
||||||
int x() const { return m_position.x(); }
|
int x() const { return m_position.x(); }
|
||||||
int y() const { return m_position.y(); }
|
int y() const { return m_position.y(); }
|
||||||
MouseButton button() const { return m_button; }
|
MouseButton button() const { return m_button; }
|
||||||
|
unsigned buttons() const { return m_buttons; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Point m_position;
|
Point m_position;
|
||||||
|
unsigned m_buttons { 0 };
|
||||||
MouseButton m_button { MouseButton::None };
|
MouseButton m_button { MouseButton::None };
|
||||||
};
|
};
|
||||||
|
|
|
@ -41,8 +41,13 @@ void WSScreen::on_receive_mouse_data(int dx, int dy, bool left_button, bool righ
|
||||||
m_cursor_location.set_x(width() - 1);
|
m_cursor_location.set_x(width() - 1);
|
||||||
if (m_cursor_location.y() >= height())
|
if (m_cursor_location.y() >= height())
|
||||||
m_cursor_location.set_y(height() - 1);
|
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) {
|
if (m_cursor_location != prev_location) {
|
||||||
auto event = make<MouseEvent>(WSEvent::MouseMove, m_cursor_location.x(), m_cursor_location.y());
|
auto event = make<MouseEvent>(WSEvent::MouseMove, m_cursor_location, buttons);
|
||||||
WSEventLoop::the().post_event(&WSWindowManager::the(), move(event));
|
WSEventLoop::the().post_event(&WSWindowManager::the(), move(event));
|
||||||
}
|
}
|
||||||
bool prev_left_button = m_left_mouse_button_pressed;
|
bool prev_left_button = m_left_mouse_button_pressed;
|
||||||
|
@ -50,11 +55,11 @@ void WSScreen::on_receive_mouse_data(int dx, int dy, bool left_button, bool righ
|
||||||
m_left_mouse_button_pressed = left_button;
|
m_left_mouse_button_pressed = left_button;
|
||||||
m_right_mouse_button_pressed = right_button;
|
m_right_mouse_button_pressed = right_button;
|
||||||
if (prev_left_button != left_button) {
|
if (prev_left_button != left_button) {
|
||||||
auto event = make<MouseEvent>(left_button ? WSEvent::MouseDown : WSEvent::MouseUp, m_cursor_location.x(), m_cursor_location.y(), MouseButton::Left);
|
auto event = make<MouseEvent>(left_button ? WSEvent::MouseDown : WSEvent::MouseUp, m_cursor_location, buttons, MouseButton::Left);
|
||||||
WSEventLoop::the().post_event(&WSWindowManager::the(), move(event));
|
WSEventLoop::the().post_event(&WSWindowManager::the(), move(event));
|
||||||
}
|
}
|
||||||
if (prev_right_button != right_button) {
|
if (prev_right_button != right_button) {
|
||||||
auto event = make<MouseEvent>(right_button ? WSEvent::MouseDown : WSEvent::MouseUp, m_cursor_location.x(), m_cursor_location.y(), MouseButton::Right);
|
auto event = make<MouseEvent>(right_button ? WSEvent::MouseDown : WSEvent::MouseUp, m_cursor_location, buttons, MouseButton::Right);
|
||||||
WSEventLoop::the().post_event(&WSWindowManager::the(), move(event));
|
WSEventLoop::the().post_event(&WSWindowManager::the(), move(event));
|
||||||
}
|
}
|
||||||
if (m_cursor_location != prev_location || prev_left_button != left_button)
|
if (m_cursor_location != prev_location || prev_left_button != left_button)
|
||||||
|
|
|
@ -59,6 +59,7 @@ void WSWindow::event(WSEvent& event)
|
||||||
case WSEvent::MouseMove:
|
case WSEvent::MouseMove:
|
||||||
gui_event.type = GUI_Event::Type::MouseMove;
|
gui_event.type = GUI_Event::Type::MouseMove;
|
||||||
gui_event.mouse.position = static_cast<MouseEvent&>(event).position();
|
gui_event.mouse.position = static_cast<MouseEvent&>(event).position();
|
||||||
|
gui_event.mouse.button = GUI_MouseButton::NoButton;
|
||||||
break;
|
break;
|
||||||
case WSEvent::MouseDown:
|
case WSEvent::MouseDown:
|
||||||
gui_event.type = GUI_Event::Type::MouseDown;
|
gui_event.type = GUI_Event::Type::MouseDown;
|
||||||
|
|
|
@ -285,9 +285,10 @@ void WSWindowManager::process_mouse_event(MouseEvent& event)
|
||||||
move_to_front(*window);
|
move_to_front(*window);
|
||||||
set_active_window(window);
|
set_active_window(window);
|
||||||
}
|
}
|
||||||
// FIXME: Re-use the existing event instead of crafting a new one?
|
// FIXME: Should we just alter the coordinates of the existing MouseEvent and pass it through?
|
||||||
auto localEvent = make<MouseEvent>(event.type(), event.x() - window->rect().x(), event.y() - window->rect().y(), event.button());
|
Point position { event.x() - window->rect().x(), event.y() - window->rect().y() };
|
||||||
window->event(*localEvent);
|
auto local_event = make<MouseEvent>(event.type(), position, event.buttons(), event.button());
|
||||||
|
window->event(*local_event);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue