summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-01-14 14:21:51 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-01-14 14:42:49 +0100
commitb0e3f733759a006622b14f75c5379641ef82776f (patch)
tree010bff69271f7174c1f4728a371785d010a602db
parentb4da4e8fbdccd34792579f82338e09a727177b33 (diff)
downloadserenity-b0e3f733759a006622b14f75c5379641ef82776f.zip
Start refactoring the windowing system to use an event loop.
Userspace programs can now open /dev/gui_events and read a stream of GUI_Event structs one at a time. I was stuck on a stupid problem where we'd reenter Scheduler::yield() due to having one of the has_data_available_for_reading() implementations using locks.
-rw-r--r--Kernel/Console.cpp2
-rw-r--r--Kernel/Console.h2
-rw-r--r--Kernel/GUITypes.h59
-rw-r--r--Kernel/Keyboard.cpp2
-rw-r--r--Kernel/Keyboard.h2
-rw-r--r--Kernel/Makefile3
-rw-r--r--Kernel/PS2MouseDevice.cpp2
-rw-r--r--Kernel/PS2MouseDevice.h2
-rw-r--r--Kernel/Process.cpp3
-rw-r--r--Kernel/Process.h14
-rw-r--r--Kernel/ProcessGUI.cpp92
-rw-r--r--Kernel/Scheduler.cpp12
-rw-r--r--Kernel/Syscall.cpp4
-rw-r--r--Kernel/Syscall.h2
-rw-r--r--Kernel/TTY.cpp2
-rw-r--r--Kernel/TTY.h2
-rw-r--r--Kernel/WindowComposer.cpp53
-rw-r--r--Kernel/i386.cpp6
-rw-r--r--Kernel/init.cpp6
-rwxr-xr-xKernel/sync.sh2
-rw-r--r--LibC/errno_numbers.h1
-rw-r--r--LibC/stdio.cpp17
-rw-r--r--LibC/stdio.h1
-rw-r--r--Userland/guitest.cpp37
-rw-r--r--VirtualFileSystem/CharacterDevice.h2
-rw-r--r--VirtualFileSystem/FileDescriptor.cpp4
-rw-r--r--VirtualFileSystem/FileDescriptor.h3
-rw-r--r--VirtualFileSystem/FullDevice.cpp2
-rw-r--r--VirtualFileSystem/FullDevice.h2
-rw-r--r--VirtualFileSystem/NullDevice.cpp2
-rw-r--r--VirtualFileSystem/NullDevice.h2
-rw-r--r--VirtualFileSystem/RandomDevice.cpp2
-rw-r--r--VirtualFileSystem/RandomDevice.h2
-rw-r--r--VirtualFileSystem/ZeroDevice.cpp2
-rw-r--r--VirtualFileSystem/ZeroDevice.h2
-rw-r--r--Widgets/Event.h2
-rw-r--r--Widgets/EventLoop.cpp4
-rw-r--r--Widgets/GUIEventDevice.cpp38
-rw-r--r--Widgets/GUIEventDevice.h14
-rw-r--r--Widgets/MsgBox.cpp6
-rw-r--r--Widgets/Point.h4
-rw-r--r--Widgets/Rect.h5
-rw-r--r--Widgets/Size.h5
-rw-r--r--Widgets/Widget.cpp11
-rw-r--r--Widgets/Window.cpp114
-rw-r--r--Widgets/Window.h19
46 files changed, 283 insertions, 292 deletions
diff --git a/Kernel/Console.cpp b/Kernel/Console.cpp
index 30fc4cd2fb..fb8734d860 100644
--- a/Kernel/Console.cpp
+++ b/Kernel/Console.cpp
@@ -23,7 +23,7 @@ Console::~Console()
{
}
-bool Console::has_data_available_for_reading() const
+bool Console::has_data_available_for_reading(Process&) const
{
return false;
}
diff --git a/Kernel/Console.h b/Kernel/Console.h
index 74fbaedbec..3568592884 100644
--- a/Kernel/Console.h
+++ b/Kernel/Console.h
@@ -18,7 +18,7 @@ public:
Console();
virtual ~Console() override;
- virtual bool has_data_available_for_reading() const override;
+ virtual bool has_data_available_for_reading(Process&) const override;
virtual ssize_t read(byte* buffer, size_t size) override;
virtual ssize_t write(const byte* data, size_t size) override;
diff --git a/Kernel/GUITypes.h b/Kernel/GUITypes.h
index 38ecb4d566..a5ff63a30f 100644
--- a/Kernel/GUITypes.h
+++ b/Kernel/GUITypes.h
@@ -11,23 +11,60 @@ struct GUI_WindowFlags { enum {
typedef unsigned GUI_Color;
+struct GUI_Point {
+ int x;
+ int y;
+};
+
+struct GUI_Size {
+ int width;
+ int height;
+};
+
+struct GUI_Rect {
+ GUI_Point location;
+ GUI_Size size;
+};
+
struct GUI_CreateWindowParameters {
- Rect rect;
+ GUI_Rect rect;
Color background_color;
unsigned flags { 0 };
char title[128];
};
-enum class GUI_WidgetType : unsigned {
- Label,
- Button,
+enum class GUI_MouseButton : unsigned char {
+ NoButton = 0,
+ Left = 1,
+ Right = 2,
+ Middle = 4,
};
-struct GUI_CreateWidgetParameters {
- GUI_WidgetType type;
- Rect rect;
- Color background_color;
- bool opaque { true };
- unsigned flags { 0 };
- char text[256];
+struct GUI_Event {
+ enum Type : unsigned {
+ Invalid,
+ Paint,
+ MouseMove,
+ MouseDown,
+ MouseUp,
+ };
+ Type type { Invalid };
+ int window_id { -1 };
+
+ union {
+ struct {
+ GUI_Rect rect;
+ } paint;
+ struct {
+ GUI_Point position;
+ GUI_MouseButton button;
+ } mouse;
+ };
};
+
+inline Rect::Rect(const GUI_Rect& r) : Rect(r.location, r.size) { }
+inline Point::Point(const GUI_Point& p) : Point(p.x, p.y) { }
+inline Size::Size(const GUI_Size& s) : Size(s.width, s.height) { }
+inline Rect::operator GUI_Rect() const { return { m_location, m_size }; }
+inline Point::operator GUI_Point() const { return { m_x, m_y }; }
+inline Size::operator GUI_Size() const { return { m_width, m_height }; }
diff --git a/Kernel/Keyboard.cpp b/Kernel/Keyboard.cpp
index 9632d382c7..4ab8447bd7 100644
--- a/Kernel/Keyboard.cpp
+++ b/Kernel/Keyboard.cpp
@@ -114,7 +114,7 @@ Keyboard::~Keyboard()
{
}
-bool Keyboard::has_data_available_for_reading() const
+bool Keyboard::has_data_available_for_reading(Process&) const
{
return !m_queue.is_empty();
}
diff --git a/Kernel/Keyboard.h b/Kernel/Keyboard.h
index 6b207fcc60..9ebb096dbc 100644
--- a/Kernel/Keyboard.h
+++ b/Kernel/Keyboard.h
@@ -39,7 +39,7 @@ private:
// ^CharacterDevice
virtual ssize_t read(byte* buffer, size_t) override;
virtual ssize_t write(const byte* buffer, size_t) override;
- virtual bool has_data_available_for_reading() const override;
+ virtual bool has_data_available_for_reading(Process&) const override;
void emit(byte);
diff --git a/Kernel/Makefile b/Kernel/Makefile
index 469f09fe50..dab935cfe9 100644
--- a/Kernel/Makefile
+++ b/Kernel/Makefile
@@ -62,7 +62,8 @@ WIDGETS_OBJS = \
../Widgets/ListBox.o \
../Widgets/CheckBox.o \
../Widgets/TextBox.o \
- ../Widgets/AbstractScreen.o
+ ../Widgets/AbstractScreen.o \
+ ../Widgets/GUIEventDevice.o \
AK_OBJS = \
../AK/String.o \
diff --git a/Kernel/PS2MouseDevice.cpp b/Kernel/PS2MouseDevice.cpp
index dd9a72c230..9aea27c962 100644
--- a/Kernel/PS2MouseDevice.cpp
+++ b/Kernel/PS2MouseDevice.cpp
@@ -116,7 +116,7 @@ byte PS2MouseDevice::mouse_read()
return IO::in8(0x60);
}
-bool PS2MouseDevice::has_data_available_for_reading() const
+bool PS2MouseDevice::has_data_available_for_reading(Process&) const
{
return !m_buffer.is_empty();
}
diff --git a/Kernel/PS2MouseDevice.h b/Kernel/PS2MouseDevice.h
index 3c8d77f664..89e3ce542a 100644
--- a/Kernel/PS2MouseDevice.h
+++ b/Kernel/PS2MouseDevice.h
@@ -12,7 +12,7 @@ public:
static PS2MouseDevice& the();
// ^CharacterDevice
- virtual bool has_data_available_for_reading() const override;
+ virtual bool has_data_available_for_reading(Process&) const override;
virtual ssize_t read(byte* buffer, size_t) override;
virtual ssize_t write(const byte* buffer, size_t) override;
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp
index 8a29eb5cfa..7e806b3ee5 100644
--- a/Kernel/Process.cpp
+++ b/Kernel/Process.cpp
@@ -18,6 +18,7 @@
#include "Scheduler.h"
#include "FIFO.h"
#include "KSyms.h"
+#include <Widgets/Window.h>
//#define DEBUG_IO
//#define TASK_DEBUG
@@ -1057,7 +1058,7 @@ ssize_t Process::sys$read(int fd, void* outbuf, size_t nread)
if (!descriptor)
return -EBADF;
if (descriptor->is_blocking()) {
- if (!descriptor->has_data_available_for_reading()) {
+ if (!descriptor->has_data_available_for_reading(*this)) {
m_blocked_fd = fd;
block(BlockedRead);
sched_yield();
diff --git a/Kernel/Process.h b/Kernel/Process.h
index faa51bea7c..5739cc0045 100644
--- a/Kernel/Process.h
+++ b/Kernel/Process.h
@@ -12,6 +12,7 @@
#include <AK/AKString.h>
#include <AK/Vector.h>
#include <AK/WeakPtr.h>
+#include <AK/Lock.h>
class FileDescriptor;
class PageDirectory;
@@ -191,13 +192,12 @@ public:
int gui$create_window(const GUI_CreateWindowParameters*);
int gui$destroy_window(int window_id);
- int gui$create_widget(int window_id, const GUI_CreateWidgetParameters*);
- int gui$destroy_widget(int widget_id);
DisplayInfo get_display_info();
static void initialize();
static void initialize_gui_statics();
+ int make_window_id();
void crash() NORETURN;
static int reap(Process&) WARN_UNUSED_RESULT;
@@ -248,6 +248,9 @@ public:
bool is_root() const { return m_euid == 0; }
+ Vector<GUI_Event>& gui_events() { return m_gui_events; }
+ SpinLock& gui_events_lock() { return m_gui_events_lock; }
+
private:
friend class MemoryManager;
friend class Scheduler;
@@ -342,8 +345,11 @@ private:
RetainPtr<Region> m_display_framebuffer_region;
- Vector<WeakPtr<Window>> m_windows;
- Vector<WeakPtr<Widget>> m_widgets;
+ HashMap<int, OwnPtr<Window>> m_windows;
+
+ Vector<GUI_Event> m_gui_events;
+ SpinLock m_gui_events_lock;
+ int m_next_window_id { 1 };
};
extern Process* current;
diff --git a/Kernel/ProcessGUI.cpp b/Kernel/ProcessGUI.cpp
index c4ef73dfc5..c0049488bc 100644
--- a/Kernel/ProcessGUI.cpp
+++ b/Kernel/ProcessGUI.cpp
@@ -22,6 +22,14 @@ void Process::initialize_gui_statics()
new EventLoop;
}
+int Process::make_window_id()
+{
+ int new_id = m_next_window_id++;
+ while (!new_id || m_windows.contains(new_id))
+ new_id = m_next_window_id++;
+ return new_id;
+}
+
static void wait_for_gui_server()
{
// FIXME: Time out after a while and return an error.
@@ -37,28 +45,26 @@ int Process::gui$create_window(const GUI_CreateWindowParameters* user_params)
return -EFAULT;
auto params = *user_params;
+ Rect rect = params.rect;
- if (params.rect.is_empty())
+ if (rect.is_empty())
return -EINVAL;
ProcessPagingScope scope(EventLoop::main().server_process());
- auto* window = new Window;
- if (!window)
+ int window_id = make_window_id();
+ if (!window_id)
return -ENOMEM;
- int window_id = m_windows.size();
- m_windows.append(window->makeWeakPtr());
+ auto window = make<Window>(*this, window_id);
+ if (!window)
+ return -ENOMEM;
window->setTitle(params.title);
- window->setRect(params.rect);
+ window->setRect(rect);
- auto* main_widget = new Widget;
- window->setMainWidget(main_widget);
- main_widget->setWindowRelativeRect({ 0, 0, params.rect.width(), params.rect.height() });
- main_widget->setBackgroundColor(params.background_color);
- main_widget->setFillWithBackgroundColor(true);
- dbgprintf("%s<%u> gui$create_window: %d with rect {%d,%d %dx%d}\n", name().characters(), pid(), window_id, params.rect.x(), params.rect.y(), params.rect.width(), params.rect.height());
+ m_windows.set(window_id, move(window));
+ dbgprintf("%s<%u> gui$create_window: %d with rect {%d,%d %dx%d}\n", name().characters(), pid(), window_id, rect.x(), rect.y(), rect.width(), rect.height());
return window_id;
}
@@ -70,65 +76,9 @@ int Process::gui$destroy_window(int window_id)
return -EINVAL;
if (window_id >= static_cast<int>(m_windows.size()))
return -EBADWINDOW;
- auto* window = m_windows[window_id].ptr();
- if (!window)
- return -EBADWINDOW;
- window->deleteLater();
- return 0;
-}
-
-int Process::gui$create_widget(int window_id, const GUI_CreateWidgetParameters* user_params)
-{
- if (!validate_read_typed(user_params))
- return -EFAULT;
-
- if (window_id < 0)
- return -EINVAL;
- if (window_id >= static_cast<int>(m_windows.size()))
- return -EINVAL;
- if (!m_windows[window_id])
- return -EINVAL;
- auto& window = *m_windows[window_id];
-
- auto params = *user_params;
-
- if (params.rect.is_empty())
- return -EINVAL;
-
- Widget* widget = nullptr;
- switch (params.type) {
- case GUI_WidgetType::Label:
- widget = new Label(window.mainWidget());
- static_cast<Label*>(widget)->setText(params.text);
- widget->setFillWithBackgroundColor(params.opaque);
- break;
- case GUI_WidgetType::Button:
- widget = new Button(window.mainWidget());
- static_cast<Button*>(widget)->setCaption(params.text);
- break;
- }
-
- int widget_id = m_widgets.size();
- m_widgets.append(widget->makeWeakPtr());
-
- widget->setWindowRelativeRect(params.rect);
- widget->setBackgroundColor(params.background_color);
- dbgprintf("%s<%u> gui$create_widget: %d with rect {%d,%d %dx%d}\n", name().characters(), pid(), widget_id, params.rect.x(), params.rect.y(), params.rect.width(), params.rect.height());
-
- return window_id;
-}
-
-int Process::gui$destroy_widget(int widget_id)
-{
- dbgprintf("%s<%u> gui$destroy_widget (widget_id=%d)\n", name().characters(), pid(), widget_id);
- if (widget_id < 0)
- return -EINVAL;
- if (widget_id >= static_cast<int>(m_widgets.size()))
+ auto it = m_windows.find(window_id);
+ if (it == m_windows.end())
return -EBADWINDOW;
- auto* widget = m_widgets[widget_id].ptr();
- if (!widget)
- return -EBADWIDGET;
- widget->deleteLater();
+ m_windows.remove(window_id);
return 0;
}
-
diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp
index a730b85432..cd797cb722 100644
--- a/Kernel/Scheduler.cpp
+++ b/Kernel/Scheduler.cpp
@@ -9,6 +9,7 @@ static const dword time_slice = 5; // *10 = 50ms
Process* current;
static Process* s_colonel_process;
+static bool s_in_yield;
struct TaskRedirectionData {
word selector;
@@ -51,7 +52,7 @@ bool Scheduler::pick_next()
if (process.state() == Process::BlockedRead) {
ASSERT(process.m_blocked_fd != -1);
// FIXME: Block until the amount of data wanted is available.
- if (process.m_fds[process.m_blocked_fd].descriptor->has_data_available_for_reading())
+ if (process.m_fds[process.m_blocked_fd].descriptor->has_data_available_for_reading(process))
process.unblock();
return true;
}
@@ -142,6 +143,9 @@ bool Scheduler::pick_next()
bool Scheduler::yield()
{
+ ASSERT(!s_in_yield);
+ s_in_yield = true;
+
if (!current) {
kprintf("PANIC: sched_yield() with !current");
HANG;
@@ -150,9 +154,12 @@ bool Scheduler::yield()
//dbgprintf("%s<%u> yield()\n", current->name().characters(), current->pid());
InterruptDisabler disabler;
- if (!pick_next())
+ if (!pick_next()) {
+ s_in_yield = false;
return 1;
+ }
+ s_in_yield = false;
//dbgprintf("yield() jumping to new process: %x (%s)\n", current->farPtr().selector, current->name().characters());
switch_now();
return 0;
@@ -271,6 +278,7 @@ void Scheduler::initialize()
initialize_redirection();
s_colonel_process = Process::create_kernel_process("colonel", nullptr);
current = nullptr;
+ s_in_yield = false;
load_task_register(s_redirection.selector);
}
diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp
index 467eb551fe..a8b53db20d 100644
--- a/Kernel/Syscall.cpp
+++ b/Kernel/Syscall.cpp
@@ -191,10 +191,6 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2,
return current->gui$create_window((const GUI_CreateWindowParameters*)arg1);
case Syscall::SC_gui_destroy_window:
return current->gui$destroy_window((int)arg1);
- case Syscall::SC_gui_create_widget:
- return current->gui$create_widget((int)arg1, (const GUI_CreateWidgetParameters*)arg2);
- case Syscall::SC_gui_destroy_widget:
- return current->gui$destroy_widget((int)arg1);
default:
kprintf("<%u> int0x80: Unknown function %u requested {%x, %x, %x}\n", current->pid(), function, arg1, arg2, arg3);
break;
diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h
index 66a6369d1f..c6eab70007 100644
--- a/Kernel/Syscall.h
+++ b/Kernel/Syscall.h
@@ -68,8 +68,6 @@
__ENUMERATE_SYSCALL(sync) \
__ENUMERATE_SYSCALL(gui_create_window) \
__ENUMERATE_SYSCALL(gui_destroy_window) \
- __ENUMERATE_SYSCALL(gui_create_widget) \
- __ENUMERATE_SYSCALL(gui_destroy_widget) \
namespace Syscall {
diff --git a/Kernel/TTY.cpp b/Kernel/TTY.cpp
index c2a64f9a9e..5261e251e1 100644
--- a/Kernel/TTY.cpp
+++ b/Kernel/TTY.cpp
@@ -42,7 +42,7 @@ ssize_t TTY::write(const byte* buffer, size_t size)
return size;
}
-bool TTY::has_data_available_for_reading() const
+bool TTY::has_data_available_for_reading(Process&) const
{
return !m_buffer.is_empty();
}
diff --git a/Kernel/TTY.h b/Kernel/TTY.h
index 699dc1ea6d..8d92f89391 100644
--- a/Kernel/TTY.h
+++ b/Kernel/TTY.h
@@ -12,7 +12,7 @@ public:
virtual ssize_t read(byte*, size_t) override;
virtual ssize_t write(const byte*, size_t) override;
- virtual bool has_data_available_for_reading() const override;
+ virtual bool has_data_available_for_reading(Process&) const override;
virtual int ioctl(Process&, unsigned request, unsigned arg) override final;
virtual String tty_name() const = 0;
diff --git a/Kernel/WindowComposer.cpp b/Kernel/WindowComposer.cpp
index b616d40398..b5fa1ff7d6 100644
--- a/Kernel/WindowComposer.cpp
+++ b/Kernel/WindowComposer.cpp
@@ -4,12 +4,6 @@
#include <Widgets/FrameBuffer.h>
#include <Widgets/WindowManager.h>
#include <Widgets/EventLoop.h>
-#include <Widgets/MsgBox.h>
-#include <Widgets/TextBox.h>
-#include <Widgets/Label.h>
-#include <Widgets/ListBox.h>
-#include <Widgets/Button.h>
-#include <Widgets/CheckBox.h>
#include <Widgets/Window.h>
void WindowComposer_main()
@@ -20,52 +14,7 @@ void WindowComposer_main()
FrameBuffer framebuffer((dword*)info.framebuffer, info.width, info.height);
- MsgBox(nullptr, "Serenity Operating System");
-
- {
- auto* widgetTestWindow = new Window;
- widgetTestWindow->setTitle("Widget test");
- widgetTestWindow->setRect({ 20, 40, 100, 180 });
-
- auto* widgetTestWindowWidget = new Widget;
- widgetTestWindowWidget->setWindowRelativeRect({ 0, 0, 100, 100 });
- widgetTestWindow->setMainWidget(widgetTestWindowWidget);
-
- auto* l = new Label(widgetTestWindowWidget);
- l->setWindowRelativeRect({ 0, 0, 100, 20 });
- l->setText("Label");
-
- auto* b = new Button(widgetTestWindowWidget);
- b->setWindowRelativeRect({ 0, 20, 100, 20 });
- b->setCaption("Button");
-
- b->onClick = [] (Button& button) {
- printf("Button %p clicked!\n", &button);
- };
-
- auto* c = new CheckBox(widgetTestWindowWidget);
- c->setWindowRelativeRect({ 0, 40, 100, 20 });
- c->setCaption("CheckBox");
-
- auto *lb = new ListBox(widgetTestWindowWidget);
- lb->setWindowRelativeRect({ 0, 60, 100, 100 });
- lb->addItem("This");
- lb->addItem("is");
- lb->addItem("a");
- lb->addItem("ListBox");
-
- auto *tb = new TextBox(widgetTestWindowWidget);
- tb->setWindowRelativeRect({ 0, 160, 100, 20 });
- tb->setText("Hello!");
- tb->setFocus(true);
-
- tb->onReturnPressed = [] (TextBox& textBox) {
- printf("TextBox %p return pressed: '%s'\n", &textBox, textBox.text().characters());
- MsgBox(nullptr, textBox.text());
- };
-
- WindowManager::the().setActiveWindow(widgetTestWindow);
- }
+ WindowManager::the();
dbgprintf("Entering WindowComposer main loop.\n");
EventLoop::main().exec();
diff --git a/Kernel/i386.cpp b/Kernel/i386.cpp
index 40bc91d707..d24dac9c1c 100644
--- a/Kernel/i386.cpp
+++ b/Kernel/i386.cpp
@@ -7,7 +7,7 @@
#include "IRQHandler.h"
#include "PIC.h"
-//#define PAGE_FAULT_DEBUG
+#define PAGE_FAULT_DEBUG
struct DescriptorTablePointer {
word size;
@@ -34,7 +34,7 @@ word gdt_alloc_entry()
void gdt_free_entry(word entry)
{
- s_gdt_freelist->unchecked_append(entry);
+ s_gdt_freelist->append(entry);
}
extern "C" void handle_irq();
@@ -325,7 +325,7 @@ void gdt_init()
s_gdt_freelist = new Vector<word, KmallocEternalAllocator>();
s_gdt_freelist->ensureCapacity(256);
for (size_t i = s_gdtLength; i < 256; ++i)
- s_gdt_freelist->unchecked_append(i * 8);
+ s_gdt_freelist->append(i * 8);
s_gdtLength = 256;
s_gdtr.address = s_gdt;
diff --git a/Kernel/init.cpp b/Kernel/init.cpp
index b16fe7c1cd..50763fd5a7 100644
--- a/Kernel/init.cpp
+++ b/Kernel/init.cpp
@@ -15,6 +15,7 @@
#include <VirtualFileSystem/RandomDevice.h>
#include <VirtualFileSystem/Ext2FileSystem.h>
#include <VirtualFileSystem/VirtualFileSystem.h>
+#include <Widgets/GUIEventDevice.h>
#include "MemoryManager.h"
#include "ProcFileSystem.h"
#include "RTC.h"
@@ -34,6 +35,7 @@ VirtualConsole* tty2;
VirtualConsole* tty3;
Keyboard* keyboard;
PS2MouseDevice* ps2mouse;
+GUIEventDevice* gui_event_device;
#ifdef STRESS_TEST_SPAWNING
static void spawn_stress() NORETURN;
@@ -75,6 +77,7 @@ static void init_stage2()
vfs->register_character_device(*keyboard);
vfs->register_character_device(*ps2mouse);
+ vfs->register_character_device(*gui_event_device);
vfs->register_character_device(*tty0);
vfs->register_character_device(*tty1);
vfs->register_character_device(*tty2);
@@ -94,7 +97,7 @@ static void init_stage2()
environment.append("TERM=ansi");
int error;
- Process::create_user_process("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, move(environment), tty0);
+ //Process::create_user_process("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, move(environment), tty0);
#ifdef SPAWN_GUI_TEST_APP
Process::create_user_process("/bin/guitest", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, move(environment), tty0);
#endif
@@ -132,6 +135,7 @@ void init()
keyboard = new Keyboard;
ps2mouse = new PS2MouseDevice;
+ gui_event_device = new GUIEventDevice;
VirtualConsole::initialize();
tty0 = new VirtualConsole(0, VirtualConsole::AdoptCurrentVGABuffer);
diff --git a/Kernel/sync.sh b/Kernel/sync.sh
index 4bf0e36419..5051382e05 100755
--- a/Kernel/sync.sh
+++ b/Kernel/sync.sh
@@ -8,6 +8,8 @@ mknod mnt/dev/tty0 c 4 0
mknod mnt/dev/tty1 c 4 1
mknod mnt/dev/tty2 c 4 2
mknod mnt/dev/tty3 c 4 3
+mknod mnt/dev/psaux c 10 1
+mknod mnt/dev/gui_events c 66 1
cp -R ../Base/* mnt/
cp -v ../Userland/sh mnt/bin/sh
cp -v ../Userland/id mnt/bin/id
diff --git a/LibC/errno_numbers.h b/LibC/errno_numbers.h
index 6d2aae4b90..62fd2c09e2 100644
--- a/LibC/errno_numbers.h
+++ b/LibC/errno_numbers.h
@@ -43,7 +43,6 @@
__ERROR(EAFNOSUPPORT, "Address family not supported") \
__ERROR(EWHYTHO, "Failed without setting an error code (Bug!)") \
__ERROR(EBADWINDOW, "Bad Window ID") \
- __ERROR(EBADWIDGET, "Bad Widget ID") \
enum __errno_values {
#undef __ERROR
diff --git a/LibC/stdio.cpp b/LibC/stdio.cpp
index 23223ca035..5665d20324 100644
--- a/LibC/stdio.cpp
+++ b/LibC/stdio.cpp
@@ -9,6 +9,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <AK/printf.cpp>
+#include <Kernel/Syscall.h>
extern "C" {
@@ -226,6 +227,20 @@ void rewind(FILE* stream)
static void sys_putch(char*&, char ch)
{
+ syscall(SC_putch, ch);
+}
+
+int sys_printf(const char* fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ int ret = printfInternal(sys_putch, nullptr, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
+static void stdout_putch(char*&, char ch)
+{
putchar(ch);
}
@@ -254,7 +269,7 @@ int printf(const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
- int ret = printfInternal(sys_putch, nullptr, fmt, ap);
+ int ret = printfInternal(stdout_putch, nullptr, fmt, ap);
va_end(ap);
return ret;
}
diff --git a/LibC/stdio.h b/LibC/stdio.h
index 664c8d79e5..e65ffabd13 100644
--- a/LibC/stdio.h
+++ b/LibC/stdio.h
@@ -54,6 +54,7 @@ int vfprintf(FILE*, const char* fmt, va_list);
int vsprintf(char* buffer, const char* fmt, va_list);
int fprintf(FILE*, const char* fmt, ...);
int printf(const char* fmt, ...);
+int sys_printf(const char* fmt, ...);
int sprintf(char* buffer, const char* fmt, ...);
int putchar(int ch);
int putc(int ch, FILE*);
diff --git a/Userland/guitest.cpp b/Userland/guitest.cpp
index 597458c635..48af3a9d24 100644
--- a/Userland/guitest.cpp
+++ b/Userland/guitest.cpp
@@ -11,7 +11,7 @@
int main(int argc, char** argv)
{
GUI_CreateWindowParameters wparams;
- wparams.rect = { 200, 200, 300, 200 };
+ wparams.rect = { { 200, 200 }, { 300, 200 } };
wparams.background_color = 0xffc0c0;
strcpy(wparams.title, "GUI test app");
int window_id = syscall(SC_gui_create_window, &wparams);
@@ -20,28 +20,27 @@ int main(int argc, char** argv)
return 1;
}
- GUI_CreateWidgetParameters label_params;
- label_params.type = GUI_WidgetType::Label;
- label_params.rect = { 20, 20, 260, 20 };
- label_params.opaque = false;
- strcpy(label_params.text, "Hello World!");
- int label_id = syscall(SC_gui_create_widget, window_id, &label_params);
- if (label_id < 0) {
- perror("gui_create_widget");
- return 1;
- }
-
- GUI_CreateWidgetParameters button_params;
- button_params.type = GUI_WidgetType::Button;
- button_params.rect = { 60, 60, 120, 20 };
- strcpy(button_params.text, "I'm a button!");
- int button_id = syscall(SC_gui_create_widget, window_id, &button_params);
- if (button_id < 0) {
- perror("gui_create_widget");
+ int fd = open("/dev/gui_events", O_RDONLY);
+ if (fd < 0) {
+ perror("open");
return 1;
}
for (;;) {
+ GUI_Event event;
+ ssize_t nread = read(fd, &event, sizeof(event));
+ if (nread < 0) {
+ perror("read");
+ return 1;
+ }
+ assert(nread == sizeof(event));
+ switch (event.type) {
+ case GUI_Event::Type::Paint: sys_printf("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;
+ case GUI_Event::Type::MouseDown: sys_printf("WID=%x MouseDown %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
+ case GUI_Event::Type::MouseUp: sys_printf("WID=%x MouseUp %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
+ case GUI_Event::Type::MouseMove: sys_printf("WID=%x MouseMove %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
+ }
+
}
return 0;
}
diff --git a/VirtualFileSystem/CharacterDevice.h b/VirtualFileSystem/CharacterDevice.h
index 78cb46486a..2028ee0f5d 100644
--- a/VirtualFileSystem/CharacterDevice.h
+++ b/VirtualFileSystem/CharacterDevice.h
@@ -12,7 +12,7 @@ public:
RetainPtr<FileDescriptor> open(int options);
- virtual bool has_data_available_for_reading() const = 0;
+ virtual bool has_data_available_for_reading(Process&) const = 0;
virtual ssize_t read(byte* buffer, size_t bufferSize) = 0;
virtual ssize_t write(const byte* buffer, size_t bufferSize) = 0;
diff --git a/VirtualFileSystem/FileDescriptor.cpp b/VirtualFileSystem/FileDescriptor.cpp
index 7cc7cdb961..7fb9700907 100644
--- a/VirtualFileSystem/FileDescriptor.cpp
+++ b/VirtualFileSystem/FileDescriptor.cpp
@@ -173,14 +173,14 @@ bool FileDescriptor::can_write()
return true;
}
-bool FileDescriptor::has_data_available_for_reading()
+bool FileDescriptor::has_data_available_for_reading(Process& process)
{
if (is_fifo()) {
ASSERT(fifo_direction() == FIFO::Reader);
return m_fifo->can_read();
}
if (m_vnode->isCharacterDevice())
- return m_vnode->characterDevice()->has_data_available_for_reading();
+ return m_vnode->characterDevice()->has_data_available_for_reading(process);
return true;
}
diff --git a/VirtualFileSystem/FileDescriptor.h b/VirtualFileSystem/FileDescriptor.h
index 2fc5c41e07..675f1aeb2b 100644
--- a/VirtualFileSystem/FileDescriptor.h
+++ b/VirtualFileSystem/FileDescriptor.h
@@ -9,6 +9,7 @@
#ifdef SERENITY
class TTY;
+class Process;
#endif
class FileDescriptor : public Retainable<FileDescriptor> {
@@ -27,7 +28,7 @@ public:
ssize_t write(const byte* data, size_t);
int stat(Unix::stat*);
- bool has_data_available_for_reading();
+ bool has_data_available_for_reading(Process&);
bool can_write();
ssize_t get_dir_entries(byte* buffer, size_t);
diff --git a/VirtualFileSystem/FullDevice.cpp b/VirtualFileSystem/FullDevice.cpp
index 58f014895f..32f5b0bf10 100644
--- a/VirtualFileSystem/FullDevice.cpp
+++ b/VirtualFileSystem/FullDevice.cpp
@@ -13,7 +13,7 @@ FullDevice::~FullDevice()
{
}
-bool FullDevice::has_data_available_for_reading() const
+bool FullDevice::has_data_available_for_reading(Process&) const
{
return true;
}
diff --git a/VirtualFileSystem/FullDevice.h b/VirtualFileSystem/FullDevice.h
index da2d6d5b19..f75c5a6edf 100644
--- a/VirtualFileSystem/FullDevice.h
+++ b/VirtualFileSystem/FullDevice.h
@@ -10,6 +10,6 @@ public:
virtual ssize_t read(byte* buffer, size_t bufferSize) override;
virtual ssize_t write(const byte* buffer, size_t bufferSize) override;
- virtual bool has_data_available_for_reading() const override;
+ virtual bool has_data_available_for_reading(Process&) const override;
};
diff --git a/VirtualFileSystem/NullDevice.cpp b/VirtualFileSystem/NullDevice.cpp
index 1ad8c5f784..2fb2e527e1 100644
--- a/VirtualFileSystem/NullDevice.cpp
+++ b/VirtualFileSystem/NullDevice.cpp
@@ -12,7 +12,7 @@ NullDevice::~NullDevice()
{
}
-bool NullDevice::has_data_available_for_reading() const
+bool NullDevice::has_data_available_for_reading(Process&) const
{
return true;
}
diff --git a/VirtualFileSystem/NullDevice.h b/VirtualFileSystem/NullDevice.h
index 8cfe658bb7..c73f35a9bb 100644
--- a/VirtualFileSystem/NullDevice.h
+++ b/VirtualFileSystem/NullDevice.h
@@ -10,6 +10,6 @@ public:
virtual ssize_t read(byte* buffer, size_t bufferSize) override;
virtual ssize_t write(const byte* buffer, size_t bufferSize) override;
- virtual bool has_data_available_for_reading() const override;
+ virtual bool has_data_available_for_reading(Process&) const override;
};
diff --git a/VirtualFileSystem/RandomDevice.cpp b/VirtualFileSystem/RandomDevice.cpp
index 0bd2559085..26d85a8692 100644
--- a/VirtualFileSystem/RandomDevice.cpp
+++ b/VirtualFileSystem/RandomDevice.cpp
@@ -29,7 +29,7 @@ static void mysrand(unsigned seed)
}
#endif
-bool RandomDevice::has_data_available_for_reading() const
+bool RandomDevice::has_data_available_for_reading(Process&) const
{
return true;
}
diff --git a/VirtualFileSystem/RandomDevice.h b/VirtualFileSystem/RandomDevice.h
index 4b5fa98c72..4d7436dacb 100644
--- a/VirtualFileSystem/RandomDevice.h
+++ b/VirtualFileSystem/RandomDevice.h
@@ -10,6 +10,6 @@ public:
virtual ssize_t read(byte* buffer, size_t bufferSize) override;
virtual ssize_t write(const byte* buffer, size_t bufferSize) override;
- virtual bool has_data_available_for_reading() const override;
+ virtual bool has_data_available_for_reading(Process&) const override;
};
diff --git a/VirtualFileSystem/ZeroDevice.cpp b/VirtualFileSystem/ZeroDevice.cpp
index 529f87550b..661b776968 100644
--- a/VirtualFileSystem/ZeroDevice.cpp
+++ b/VirtualFileSystem/ZeroDevice.cpp
@@ -12,7 +12,7 @@ ZeroDevice::~ZeroDevice()
{
}
-bool ZeroDevice::has_data_available_for_reading() const
+bool ZeroDevice::has_data_available_for_reading(Process&) const
{
return true;
}
diff --git a/VirtualFileSystem/ZeroDevice.h b/VirtualFileSystem/ZeroDevice.h
index 702857baca..9bc64b6908 100644
--- a/VirtualFileSystem/ZeroDevice.h
+++ b/VirtualFileSystem/ZeroDevice.h
@@ -10,6 +10,6 @@ public:
virtual ssize_t read(byte* buffer, size_t bufferSize) override;
virtual ssize_t write(const byte* buffer, size_t bufferSize) override;
- virtual bool has_data_available_for_reading() const override;
+ virtual bool has_data_available_for_reading(Process&) const override;
};
diff --git a/Widgets/Event.h b/Widgets/Event.h
index afc3f2e5ae..1314a4dd61 100644
--- a/Widgets/Event.h
+++ b/Widgets/Event.h
@@ -37,8 +37,6 @@ public:
DeferredDestroy,
WindowBecameInactive,
WindowBecameActive,
- FocusIn,
- FocusOut,
WM_Compose,
};
diff --git a/Widgets/EventLoop.cpp b/Widgets/EventLoop.cpp
index d4b49661d0..57a8118ee5 100644
--- a/Widgets/EventLoop.cpp
+++ b/Widgets/EventLoop.cpp
@@ -82,7 +82,7 @@ void EventLoop::waitForEvent()
bool prev_right_button = screen.right_mouse_button_pressed();
int dx = 0;
int dy = 0;
- while (mouse.has_data_available_for_reading()) {
+ while (mouse.has_data_available_for_reading(*m_server_process)) {
signed_byte data[3];
ssize_t nread = mouse.read((byte*)data, 3);
ASSERT(nread == 3);
@@ -90,7 +90,7 @@ void EventLoop::waitForEvent()
bool right_button = data[0] & 2;
dx += data[1];
dy += -data[2];
- if (left_button != prev_left_button || right_button != prev_right_button || !mouse.has_data_available_for_reading()) {
+ if (left_button != prev_left_button || right_button != prev_right_button || !mouse.has_data_available_for_reading(*m_server_process)) {
prev_left_button = left_button;
prev_right_button = right_button;
screen.on_receive_mouse_data(dx, dy, left_button, right_button);
diff --git a/Widgets/GUIEventDevice.cpp b/Widgets/GUIEventDevice.cpp
new file mode 100644
index 0000000000..f9bd86f623
--- /dev/null
+++ b/Widgets/GUIEventDevice.cpp
@@ -0,0 +1,38 @@
+#include "GUIEventDevice.h"
+#include <Kernel/Process.h>
+#include <AK/Lock.h>
+#include <LibC/errno_numbers.h>
+
+//#define GUIEVENTDEVICE_DEBUG
+
+GUIEventDevice::GUIEventDevice()
+ : CharacterDevice(66, 1)
+{
+}
+
+GUIEventDevice::~GUIEventDevice()
+{
+}
+
+bool GUIEventDevice::has_data_available_for_reading(Process& process) const
+{
+ return !process.gui_events().is_empty();
+}
+
+ssize_t GUIEventDevice::read(byte* buffer, size_t size)
+{
+#ifdef GUIEVENTDEVICE_DEBUG
+ dbgprintf("GUIEventDevice::read(): %s<%u>, size=%u, sizeof(GUI_Event)=%u\n", current->name().characters(), current->pid(), size, sizeof(GUI_Event));
+#endif
+ if (current->gui_events().is_empty())
+ return 0;
+ LOCKER(current->gui_events_lock());
+ ASSERT(size == sizeof(GUI_Event));
+ *reinterpret_cast<GUI_Event*>(buffer) = current->gui_events().take_first();
+ return size;
+}
+
+ssize_t GUIEventDevice::write(const byte*, size_t)
+{
+ return -EINVAL;
+}
diff --git a/Widgets/GUIEventDevice.h b/Widgets/GUIEventDevice.h
new file mode 100644
index 0000000000..061fc96e71
--- /dev/null
+++ b/Widgets/GUIEventDevice.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <VirtualFileSystem/CharacterDevice.h>
+
+class GUIEventDevice final : public CharacterDevice {
+public:
+ GUIEventDevice();
+ virtual ~GUIEventDevice() override;
+
+private:
+ virtual bool has_data_available_for_reading(Process&) const override;
+ virtual ssize_t read(byte* buffer, size_t bufferSize) override;
+ virtual ssize_t write(const byte* buffer, size_t bufferSize) override;
+};
diff --git a/Widgets/MsgBox.cpp b/Widgets/MsgBox.cpp
index 06bfbf0643..c6c8ce0c84 100644
--- a/Widgets/MsgBox.cpp
+++ b/Widgets/MsgBox.cpp
@@ -4,7 +4,9 @@
#include "Window.h"
#include "Label.h"
#include "Button.h"
+#include "Process.h"
+#if 0
void MsgBox(Window* owner, String&& text)
{
Font& font = Font::defaultFont();
@@ -33,7 +35,7 @@ void MsgBox(Window* owner, String&& text)
buttonHeight
);
- auto* window = new Window;
+ auto* window = new Window(*current, current->make_window_id());
window->setTitle("MsgBox");
window->setRect(windowRect);
auto* widget = new Widget;
@@ -56,4 +58,4 @@ void MsgBox(Window* owner, String&& text)
button.window()->close();
};
}
-
+#endif
diff --git a/Widgets/Point.h b/Widgets/Point.h
index 99fd6db1bd..895bfa4441 100644
--- a/Widgets/Point.h
+++ b/Widgets/Point.h
@@ -1,11 +1,13 @@
#pragma once
class Rect;
+struct GUI_Point;
class Point {
public:
Point() { }
Point(int x, int y) : m_x(x) , m_y(y) { }
+ Point(const GUI_Point&);
int x() const { return m_x; }
int y() const { return m_y; }
@@ -37,6 +39,8 @@ public:
return !(*this == other);
}
+ operator GUI_Point() const;
+
private:
int m_x { 0 };
int m_y { 0 };
diff --git a/Widgets/Rect.h b/Widgets/Rect.h
index 95f98dd1c7..4131cbba85 100644
--- a/Widgets/Rect.h
+++ b/Widgets/Rect.h
@@ -3,6 +3,8 @@
#include "Point.h"
#include "Size.h"
+struct GUI_Rect;
+
class Rect {
public:
Rect() { }
@@ -16,6 +18,7 @@ public:
, m_size(size)
{
}
+ Rect(const GUI_Rect&);
bool is_empty() const
{
@@ -117,6 +120,8 @@ public:
Point location() const { return m_location; }
Size size() const { return m_size; }
+ operator GUI_Rect() const;
+
bool operator==(const Rect& other) const
{
return m_location == other.m_location
diff --git a/Widgets/Size.h b/Widgets/Size.h
index 6fd8a21f6f..197a848d34 100644
--- a/Widgets/Size.h
+++ b/Widgets/Size.h
@@ -1,9 +1,12 @@
#pragma once
+struct GUI_Size;
+
class Size {
public:
Size() { }
Size(int w, int h) : m_width(w), m_height(h) { }
+ Size(const GUI_Size&);
bool is_empty() const { return !m_width || !m_height; }
@@ -19,6 +22,8 @@ public:
m_height == other.m_height;
}
+ operator GUI_Size() const;
+
private:
int m_width { 0 };
int m_height { 0 };
diff --git a/Widgets/Widget.cpp b/Widgets/Widget.cpp
index e26a3c3e7e..d83877e3ff 100644
--- a/Widgets/Widget.cpp
+++ b/Widgets/Widget.cpp
@@ -56,10 +56,7 @@ void Widget::event(Event& event)
case Event::MouseMove:
return mouseMoveEvent(static_cast<MouseEvent&>(event));
case Event::MouseDown:
- if (auto* win = window()) {
- // FIXME: if (acceptsFocus())
- win->setFocusedWidget(this);
- }
+ // FIXME: Focus self if needed.
return mouseDownEvent(static_cast<MouseEvent&>(event));
case Event::MouseUp:
return mouseUpEvent(static_cast<MouseEvent&>(event));
@@ -141,8 +138,7 @@ void Widget::setWindow(Window* window)
bool Widget::isFocused() const
{
- if (auto* win = window())
- return win->isActive() && win->focusedWidget() == this;
+ // FIXME: Implement.
return false;
}
@@ -150,8 +146,7 @@ void Widget::setFocus(bool focus)
{
if (focus == isFocused())
return;
- if (auto* win = window())
- win->setFocusedWidget(this);
+ // FIXME: Implement.
}
void Widget::setFont(RetainPtr<Font>&& font)
diff --git a/Widgets/Window.cpp b/Widgets/Window.cpp
index 5713d3332b..bc46a61958 100644
--- a/Widgets/Window.cpp
+++ b/Widgets/Window.cpp
@@ -3,31 +3,20 @@
#include "Event.h"
#include "EventLoop.h"
#include "Widget.h"
+#include "Process.h"
-Window::Window(Object* parent)
- : Object(parent)
+Window::Window(Process& process, int window_id)
+ : m_process(process)
+ , m_window_id(window_id)
{
WindowManager::the().addWindow(*this);
}
Window::~Window()
{
- delete m_mainWidget;
- m_mainWidget = nullptr;
- if (parent())
- parent()->removeChild(*this);
WindowManager::the().removeWindow(*this);
}
-void Window::setMainWidget(Widget* widget)
-{
- if (m_mainWidget == widget)
- return;
-
- m_mainWidget = widget;
- widget->setWindow(this);
-}
-
void Window::setTitle(String&& title)
{
if (m_title == title)
@@ -58,51 +47,50 @@ void Window::update(const Rect& rect)
EventLoop::main().postEvent(this, make<PaintEvent>(rect));
}
-void Window::event(Event& event)
+// FIXME: Just use the same types.
+static GUI_MouseButton to_api(MouseButton button)
{
- if (event.isMouseEvent()) {
- auto& me = static_cast<MouseEvent&>(event);
- //printf("Window{%p}: %s %d,%d\n", this, me.name(), me.x(), me.y());
- if (m_mainWidget) {
- auto result = m_mainWidget->hitTest(me.x(), me.y());
- //printf("hit test for %d,%d found: %s{%p} %d,%d\n", me.x(), me.y(), result.widget->class_name(), result.widget, result.localX, result.localY);
- // FIXME: Re-use the existing event instead of crafting a new one?
- auto localEvent = make<MouseEvent>(event.type(), result.localX, result.localY, me.button());
- return result.widget->event(*localEvent);
- }
- return Object::event(event);
+ switch (button) {
+ case MouseButton::None: return GUI_MouseButton::NoButton;
+ case MouseButton::Left: return GUI_MouseButton::Left;
+ case MouseButton::Right: return GUI_MouseButton::Right;
+ case MouseButton::Middle: return GUI_MouseButton::Middle;
}
+}
- if (event.isPaintEvent()) {
- auto& pe = static_cast<PaintEvent&>(event);
- printf("Window[\"%s\"]: paintEvent %d,%d %dx%d\n", title().characters(),
- pe.rect().x(),
- pe.rect().y(),
- pe.rect().width(),
- pe.rect().height());
-
- if (isBeingDragged()) {
- // Ignore paint events during window drag.
- return;
- }
- if (m_mainWidget) {
- if (pe.rect().is_empty())
- m_mainWidget->event(*make<PaintEvent>(m_mainWidget->rect()));
- else
- m_mainWidget->event(event);
- WindowManager::the().did_paint(*this);
- return;
- }
- return Object::event(event);
+void Window::event(Event& event)
+{
+ GUI_Event gui_event;
+ gui_event.window_id = window_id();
+
+ switch (event.type()) {
+ case Event::Paint:
+ gui_event.type = GUI_Event::Type::Paint;
+ gui_event.paint.rect = static_cast<PaintEvent&>(event).rect();
+ break;
+ case Event::MouseMove:
+ gui_event.type = GUI_Event::Type::MouseMove;
+ gui_event.mouse.position = static_cast<MouseEvent&>(event).position();
+ break;
+ case Event::MouseDown:
+ gui_event.type = GUI_Event::Type::MouseDown;
+ gui_event.mouse.position = static_cast<MouseEvent&>(event).position();
+ gui_event.mouse.button = to_api(static_cast<MouseEvent&>(event).button());
+ break;
+ case Event::MouseUp:
+ gui_event.type = GUI_Event::Type::MouseUp;
+ gui_event.mouse.position = static_cast<MouseEvent&>(event).position();
+ gui_event.mouse.button = to_api(static_cast<MouseEvent&>(event).button());
+ break;
}
- if (event.isKeyEvent()) {
- if (m_focusedWidget)
- return m_focusedWidget->event(event);
- return Object::event(event);
- }
+ if (gui_event.type == GUI_Event::Type::Invalid)
+ return;
- return Object::event(event);
+ {
+ LOCKER(m_process.gui_events_lock());
+ m_process.gui_events().append(move(gui_event));
+ }
}
void Window::did_paint()
@@ -120,24 +108,6 @@ bool Window::isVisible() const
return WindowManager::the().isVisible(const_cast<Window&>(*this));
}
-void Window::setFocusedWidget(Widget* widget)
-{
- if (m_focusedWidget.ptr() == widget)
- return;
- auto* previously_focused_widget = m_focusedWidget.ptr();
- if (!widget)
- m_focusedWidget = nullptr;
- else {
- m_focusedWidget = widget->makeWeakPtr();
- m_focusedWidget->update();
- EventLoop::main().postEvent(m_focusedWidget.ptr(), make<Event>(Event::FocusIn));
- }
- if (previously_focused_widget) {
- previously_focused_widget->update();
- EventLoop::main().postEvent(previously_focused_widget, make<Event>(Event::FocusOut));
- }
-}
-
void Window::close()
{
WindowManager::the().removeWindow(*this);
diff --git a/Widgets/Window.h b/Widgets/Window.h
index be53f0fccc..2d311c82c7 100644
--- a/Widgets/Window.h
+++ b/Widgets/Window.h
@@ -7,13 +7,16 @@
#include <AK/InlineLinkedList.h>
#include <AK/WeakPtr.h>
+class Process;
class Widget;
class Window final : public Object, public InlineLinkedListNode<Window> {
public:
- explicit Window(Object* parent = nullptr);
+ Window(Process&, int window_id);
virtual ~Window() override;
+ int window_id() const { return m_window_id; }
+
String title() const { return m_title; }
void setTitle(String&&);
@@ -30,11 +33,6 @@ public:
void setPosition(const Point& position) { setRect({ position.x(), position.y(), width(), height() }); }
void setPositionWithoutRepaint(const Point& position) { setRectWithoutRepaint({ position.x(), position.y(), width(), height() }); }
- Widget* mainWidget() { return m_mainWidget; }
- const Widget* mainWidget() const { return m_mainWidget; }
-
- void setMainWidget(Widget*);
-
virtual void event(Event&) override;
bool isBeingDragged() const { return m_isBeingDragged; }
@@ -45,10 +43,6 @@ public:
bool isActive() const;
- Widget* focusedWidget() { return m_focusedWidget.ptr(); }
- const Widget* focusedWidget() const { return m_focusedWidget.ptr(); }
- void setFocusedWidget(Widget*);
-
bool isVisible() const;
void close();
@@ -65,11 +59,10 @@ public:
private:
String m_title;
Rect m_rect;
- Widget* m_mainWidget { nullptr };
bool m_isBeingDragged { false };
- WeakPtr<Widget> m_focusedWidget;
-
RetainPtr<GraphicsBitmap> m_backing;
+ Process& m_process;
+ int m_window_id { -1 };
};