summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Kernel/GUITypes.h23
-rw-r--r--Kernel/Makefile1
-rw-r--r--Kernel/Process.cpp1
-rw-r--r--Kernel/Process.h8
-rw-r--r--Kernel/ProcessGUI.cpp77
-rw-r--r--Kernel/Syscall.cpp4
-rw-r--r--Kernel/Syscall.h2
-rw-r--r--Kernel/WindowComposer.cpp9
-rw-r--r--Kernel/init.cpp4
-rwxr-xr-xKernel/sync.sh1
-rw-r--r--LibC/errno_numbers.h1
-rw-r--r--Userland/Makefile9
-rw-r--r--Widgets/Color.h1
-rw-r--r--Widgets/EventLoop.cpp7
-rw-r--r--Widgets/EventLoop.h7
-rw-r--r--Widgets/GraphicsBitmap.cpp5
-rw-r--r--Widgets/Window.cpp1
17 files changed, 150 insertions, 11 deletions
diff --git a/Kernel/GUITypes.h b/Kernel/GUITypes.h
new file mode 100644
index 0000000000..f5dfc22961
--- /dev/null
+++ b/Kernel/GUITypes.h
@@ -0,0 +1,23 @@
+#pragma once
+
+// GUI system call API types.
+
+struct GUI_Rect {
+ int x;
+ int y;
+ int width;
+ int height;
+};
+
+struct GUI_WindowFlags { enum {
+ Visible = 1 << 0,
+}; };
+
+typedef unsigned GUI_Color;
+
+struct GUI_CreateWindowParameters {
+ GUI_Rect rect;
+ GUI_Color background_color;
+ unsigned flags;
+ char title[128];
+};
diff --git a/Kernel/Makefile b/Kernel/Makefile
index ac6ce72827..469f09fe50 100644
--- a/Kernel/Makefile
+++ b/Kernel/Makefile
@@ -5,6 +5,7 @@ KERNEL_OBJS = \
StdLib.o \
i386.o \
Process.o \
+ ProcessGUI.o \
i8253.o \
Keyboard.o \
CMOS.o \
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp
index 5843bd730b..8a29eb5cfa 100644
--- a/Kernel/Process.cpp
+++ b/Kernel/Process.cpp
@@ -54,6 +54,7 @@ void Process::initialize()
g_processes = new InlineLinkedList<Process>;
s_hostname = new String("courage");
Scheduler::initialize();
+ initialize_gui_statics();
}
Vector<Process*> Process::allProcesses()
diff --git a/Kernel/Process.h b/Kernel/Process.h
index 3dd906dc63..219eed2845 100644
--- a/Kernel/Process.h
+++ b/Kernel/Process.h
@@ -5,6 +5,7 @@
#include "i386.h"
#include "TTY.h"
#include "Syscall.h"
+#include "GUITypes.h"
#include <VirtualFileSystem/VirtualFileSystem.h>
#include <VirtualFileSystem/UnixTypes.h>
#include <AK/InlineLinkedList.h>
@@ -16,6 +17,7 @@ class PageDirectory;
class Region;
class VMObject;
class Zone;
+class Window;
#define COOL_GLOBALS
#ifdef COOL_GLOBALS
@@ -185,9 +187,13 @@ public:
Unix::clock_t sys$times(Unix::tms*);
int sys$utime(const char* pathname, const struct Unix::utimbuf*);
+ int gui$create_window(const GUI_CreateWindowParameters*);
+ int gui$destroy_window(int window_id);
+
DisplayInfo get_display_info();
static void initialize();
+ static void initialize_gui_statics();
void crash() NORETURN;
static int reap(Process&) WARN_UNUSED_RESULT;
@@ -331,6 +337,8 @@ private:
Region* m_signal_stack_kernel_region { nullptr };
RetainPtr<Region> m_display_framebuffer_region;
+
+ Vector<Window*> m_windows;
};
extern Process* current;
diff --git a/Kernel/ProcessGUI.cpp b/Kernel/ProcessGUI.cpp
new file mode 100644
index 0000000000..7b19a550e1
--- /dev/null
+++ b/Kernel/ProcessGUI.cpp
@@ -0,0 +1,77 @@
+#include "Process.h"
+#include "MemoryManager.h"
+#include <LibC/errno_numbers.h>
+#include <Widgets/AbstractScreen.h>
+#include <Widgets/FrameBuffer.h>
+#include <Widgets/EventLoop.h>
+#include <Widgets/Font.h>
+#include <Widgets/Widget.h>
+#include <Widgets/Window.h>
+#include <Widgets/WindowManager.h>
+
+void Process::initialize_gui_statics()
+{
+ Font::initialize();
+ FrameBuffer::initialize();
+ EventLoop::initialize();
+ WindowManager::initialize();
+ AbstractScreen::initialize();
+
+ new EventLoop;
+}
+
+static void wait_for_gui_server()
+{
+ // FIXME: Time out after a while and return an error.
+ while (!EventLoop::main().running())
+ sleep(10);
+}
+
+int Process::gui$create_window(const GUI_CreateWindowParameters* user_params)
+{
+ wait_for_gui_server();
+
+ if (!validate_read_typed(user_params))
+ return -EFAULT;
+
+ GUI_CreateWindowParameters params = *user_params;
+ Rect rect { params.rect.x, params.rect.y, params.rect.width, params.rect.height };
+
+ if (rect.is_empty())
+ return -EINVAL;
+
+ ProcessPagingScope scope(EventLoop::main().server_process());
+
+ auto* window = new Window;
+ if (!window)
+ return -ENOMEM;
+
+ int window_id = m_windows.size();
+ m_windows.append(window);
+
+ window->setTitle(params.title);
+ window->setRect(rect);
+
+ auto* main_widget = new Widget;
+ window->setMainWidget(main_widget);
+ main_widget->setWindowRelativeRect({ 0, 0, rect.width(), 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, rect.x(), rect.y(), rect.width(), rect.height());
+
+ return window_id;
+}
+
+int Process::gui$destroy_window(int window_id)
+{
+ wait_for_gui_server();
+ dbgprintf("%s<%u> gui$destroy_window (window_id=%d)\n", name().characters(), pid(), window_id);
+ if (window_id < 0)
+ return -EINVAL;
+ if (window_id >= static_cast<int>(m_windows.size()))
+ return -EBADWIN;
+ auto* window = m_windows[window_id];
+ m_windows.remove(window_id);
+ window->deleteLater();
+ return 0;
+}
diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp
index a429fe770b..a8b53db20d 100644
--- a/Kernel/Syscall.cpp
+++ b/Kernel/Syscall.cpp
@@ -187,6 +187,10 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2,
return current->sys$utime((const char*)arg1, (const Unix::utimbuf*)arg2);
case Syscall::SC_sync:
return sync();
+ case Syscall::SC_gui_create_window:
+ return current->gui$create_window((const GUI_CreateWindowParameters*)arg1);
+ case Syscall::SC_gui_destroy_window:
+ return current->gui$destroy_window((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 78b2b81a0f..c6eab70007 100644
--- a/Kernel/Syscall.h
+++ b/Kernel/Syscall.h
@@ -66,6 +66,8 @@
__ENUMERATE_SYSCALL(times) \
__ENUMERATE_SYSCALL(utime) \
__ENUMERATE_SYSCALL(sync) \
+ __ENUMERATE_SYSCALL(gui_create_window) \
+ __ENUMERATE_SYSCALL(gui_destroy_window) \
namespace Syscall {
diff --git a/Kernel/WindowComposer.cpp b/Kernel/WindowComposer.cpp
index 683a8418d1..b616d40398 100644
--- a/Kernel/WindowComposer.cpp
+++ b/Kernel/WindowComposer.cpp
@@ -14,18 +14,11 @@
void WindowComposer_main()
{
- Font::initialize();
- FrameBuffer::initialize();
- EventLoop::initialize();
- WindowManager::initialize();
- AbstractScreen::initialize();
-
auto info = current->get_display_info();
dbgprintf("Screen is %ux%ux%ubpp\n", info.width, info.height, info.bpp);
FrameBuffer framebuffer((dword*)info.framebuffer, info.width, info.height);
- EventLoop loop;
MsgBox(nullptr, "Serenity Operating System");
@@ -75,7 +68,7 @@ void WindowComposer_main()
}
dbgprintf("Entering WindowComposer main loop.\n");
- loop.exec();
+ EventLoop::main().exec();
ASSERT_NOT_REACHED();
}
diff --git a/Kernel/init.cpp b/Kernel/init.cpp
index 7b82fadd5a..b16fe7c1cd 100644
--- a/Kernel/init.cpp
+++ b/Kernel/init.cpp
@@ -22,6 +22,7 @@
#include "Scheduler.h"
#include "PS2MouseDevice.h"
+#define SPAWN_GUI_TEST_APP
//#define SPAWN_MULTIPLE_SHELLS
//#define STRESS_TEST_SPAWNING
@@ -94,6 +95,9 @@ static void init_stage2()
int error;
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
#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, { }, { }, tty2);
diff --git a/Kernel/sync.sh b/Kernel/sync.sh
index 674564d91e..4bf0e36419 100755
--- a/Kernel/sync.sh
+++ b/Kernel/sync.sh
@@ -30,6 +30,7 @@ cp -v ../Userland/mkdir mnt/bin/mkdir
cp -v ../Userland/touch mnt/bin/touch
cp -v ../Userland/sync mnt/bin/sync
cp -v ../Userland/more mnt/bin/more
+cp -v ../Userland/guitest mnt/bin/guitest
sh sync-local.sh
cp -v kernel.map mnt/
ln -s dir_a mnt/dir_cur
diff --git a/LibC/errno_numbers.h b/LibC/errno_numbers.h
index fde1369071..728500530d 100644
--- a/LibC/errno_numbers.h
+++ b/LibC/errno_numbers.h
@@ -42,6 +42,7 @@
__ERROR(ENOTIMPL, "Not implemented") \
__ERROR(EAFNOSUPPORT, "Address family not supported") \
__ERROR(EWHYTHO, "Failed without setting an error code (Bug!)") \
+ __ERROR(EBADWIN, "Bad WindowID") \
enum __errno_values {
#undef __ERROR
diff --git a/Userland/Makefile b/Userland/Makefile
index f5018664c0..7dc23d5970 100644
--- a/Userland/Makefile
+++ b/Userland/Makefile
@@ -18,7 +18,8 @@ OBJS = \
tty.o \
mkdir.o \
touch.o \
- more.o
+ more.o \
+ guitest.o
APPS = \
id \
@@ -41,7 +42,8 @@ APPS = \
mkdir \
touch \
sync \
- more
+ more \
+ guitest
ARCH_FLAGS =
STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib -nostdinc
@@ -124,6 +126,9 @@ sync: sync.o
more: more.o
$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
+guitest: guitest.o
+ $(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
+
.cpp.o:
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
diff --git a/Widgets/Color.h b/Widgets/Color.h
index 648c00356a..50abcdc2ea 100644
--- a/Widgets/Color.h
+++ b/Widgets/Color.h
@@ -22,6 +22,7 @@ public:
Color() { }
Color(NamedColor);
Color(byte r, byte g, byte b);
+ Color(RGBA32 rgba) : m_value(rgba) { }
RGBA32 value() const { return m_value; }
diff --git a/Widgets/EventLoop.cpp b/Widgets/EventLoop.cpp
index 22b94cdd03..d4b49661d0 100644
--- a/Widgets/EventLoop.cpp
+++ b/Widgets/EventLoop.cpp
@@ -6,6 +6,7 @@
#ifdef SERENITY
#include "PS2MouseDevice.h"
+#include "Scheduler.h"
#endif
static EventLoop* s_mainEventLoop;
@@ -33,6 +34,10 @@ EventLoop& EventLoop::main()
int EventLoop::exec()
{
+#ifdef SERENITY
+ m_server_process = current;
+#endif
+ m_running = true;
for (;;) {
if (m_queuedEvents.is_empty())
waitForEvent();
@@ -48,9 +53,11 @@ int EventLoop::exec()
if (!receiver) {
switch (event.type()) {
case Event::Quit:
+ ASSERT_NOT_REACHED();
return 0;
default:
printf("event type %u with no receiver :(\n", event.type());
+ ASSERT_NOT_REACHED();
return 1;
}
} else {
diff --git a/Widgets/EventLoop.h b/Widgets/EventLoop.h
index d0982bb751..4576ed7acb 100644
--- a/Widgets/EventLoop.h
+++ b/Widgets/EventLoop.h
@@ -9,6 +9,7 @@
#endif
class Object;
+class Process;
class EventLoop {
public:
@@ -23,6 +24,9 @@ public:
static void initialize();
+ bool running() const { return m_running; }
+ Process& server_process() { return *m_server_process; }
+
private:
void waitForEvent();
@@ -35,4 +39,7 @@ private:
OwnPtr<Event> event;
};
Vector<QueuedEvent> m_queuedEvents;
+
+ Process* m_server_process { nullptr };
+ bool m_running { false };
};
diff --git a/Widgets/GraphicsBitmap.cpp b/Widgets/GraphicsBitmap.cpp
index aeb31ba356..1a0a78feda 100644
--- a/Widgets/GraphicsBitmap.cpp
+++ b/Widgets/GraphicsBitmap.cpp
@@ -1,4 +1,5 @@
#include "GraphicsBitmap.h"
+#include "EventLoop.h"
#include <AK/kmalloc.h>
#ifdef SERENITY
@@ -21,7 +22,9 @@ GraphicsBitmap::GraphicsBitmap(const Size& size)
, m_pitch(size.width() * sizeof(RGBA32))
{
#ifdef SERENITY
- m_region = current->allocate_region(LinearAddress(), size.width() * size.height() * sizeof(RGBA32), "GraphicsBitmap", true, true, true);
+ // FIXME: Oh god this is so horrible.
+ Process* server_process = EventLoop::main().running() ? &EventLoop::main().server_process() : current;
+ m_region = server_process->allocate_region(LinearAddress(), size.width() * size.height() * sizeof(RGBA32), "GraphicsBitmap", true, true, true);
m_data = (RGBA32*)m_region->linearAddress.asPtr();
m_owned = false;
#else
diff --git a/Widgets/Window.cpp b/Widgets/Window.cpp
index 63c0408329..5713d3332b 100644
--- a/Widgets/Window.cpp
+++ b/Widgets/Window.cpp
@@ -43,6 +43,7 @@ void Window::setRect(const Rect& rect)
return;
auto oldRect = m_rect;
m_rect = rect;
+ dbgprintf("Window::setRect %d,%d %dx%d\n", m_rect.x(), m_rect.y(), m_rect.width(), m_rect.height());
m_backing = GraphicsBitmap::create(m_rect.size());
WindowManager::the().notifyRectChanged(*this, oldRect, m_rect);
}