Start working on a GUI kernel API.

This commit is contained in:
Andreas Kling 2019-01-13 01:59:38 +01:00
parent becc2c7fa5
commit 8f8c8d1ca3
Notes: sideshowbarker 2024-07-19 16:03:20 +09:00
17 changed files with 150 additions and 11 deletions

23
Kernel/GUITypes.h Normal file
View file

@ -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];
};

View file

@ -5,6 +5,7 @@ KERNEL_OBJS = \
StdLib.o \
i386.o \
Process.o \
ProcessGUI.o \
i8253.o \
Keyboard.o \
CMOS.o \

View file

@ -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()

View file

@ -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;

77
Kernel/ProcessGUI.cpp Normal file
View file

@ -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;
}

View file

@ -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;

View file

@ -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 {

View file

@ -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();
}

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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 $<

View file

@ -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; }

View file

@ -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 {

View file

@ -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 };
};

View file

@ -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

View file

@ -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);
}