mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 21:07:35 +00:00
Start working on a GUI kernel API.
This commit is contained in:
parent
becc2c7fa5
commit
8f8c8d1ca3
17 changed files with 150 additions and 11 deletions
23
Kernel/GUITypes.h
Normal file
23
Kernel/GUITypes.h
Normal 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];
|
||||||
|
};
|
|
@ -5,6 +5,7 @@ KERNEL_OBJS = \
|
||||||
StdLib.o \
|
StdLib.o \
|
||||||
i386.o \
|
i386.o \
|
||||||
Process.o \
|
Process.o \
|
||||||
|
ProcessGUI.o \
|
||||||
i8253.o \
|
i8253.o \
|
||||||
Keyboard.o \
|
Keyboard.o \
|
||||||
CMOS.o \
|
CMOS.o \
|
||||||
|
|
|
@ -54,6 +54,7 @@ void Process::initialize()
|
||||||
g_processes = new InlineLinkedList<Process>;
|
g_processes = new InlineLinkedList<Process>;
|
||||||
s_hostname = new String("courage");
|
s_hostname = new String("courage");
|
||||||
Scheduler::initialize();
|
Scheduler::initialize();
|
||||||
|
initialize_gui_statics();
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<Process*> Process::allProcesses()
|
Vector<Process*> Process::allProcesses()
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "i386.h"
|
#include "i386.h"
|
||||||
#include "TTY.h"
|
#include "TTY.h"
|
||||||
#include "Syscall.h"
|
#include "Syscall.h"
|
||||||
|
#include "GUITypes.h"
|
||||||
#include <VirtualFileSystem/VirtualFileSystem.h>
|
#include <VirtualFileSystem/VirtualFileSystem.h>
|
||||||
#include <VirtualFileSystem/UnixTypes.h>
|
#include <VirtualFileSystem/UnixTypes.h>
|
||||||
#include <AK/InlineLinkedList.h>
|
#include <AK/InlineLinkedList.h>
|
||||||
|
@ -16,6 +17,7 @@ class PageDirectory;
|
||||||
class Region;
|
class Region;
|
||||||
class VMObject;
|
class VMObject;
|
||||||
class Zone;
|
class Zone;
|
||||||
|
class Window;
|
||||||
|
|
||||||
#define COOL_GLOBALS
|
#define COOL_GLOBALS
|
||||||
#ifdef COOL_GLOBALS
|
#ifdef COOL_GLOBALS
|
||||||
|
@ -185,9 +187,13 @@ public:
|
||||||
Unix::clock_t sys$times(Unix::tms*);
|
Unix::clock_t sys$times(Unix::tms*);
|
||||||
int sys$utime(const char* pathname, const struct Unix::utimbuf*);
|
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();
|
DisplayInfo get_display_info();
|
||||||
|
|
||||||
static void initialize();
|
static void initialize();
|
||||||
|
static void initialize_gui_statics();
|
||||||
|
|
||||||
void crash() NORETURN;
|
void crash() NORETURN;
|
||||||
static int reap(Process&) WARN_UNUSED_RESULT;
|
static int reap(Process&) WARN_UNUSED_RESULT;
|
||||||
|
@ -331,6 +337,8 @@ private:
|
||||||
Region* m_signal_stack_kernel_region { nullptr };
|
Region* m_signal_stack_kernel_region { nullptr };
|
||||||
|
|
||||||
RetainPtr<Region> m_display_framebuffer_region;
|
RetainPtr<Region> m_display_framebuffer_region;
|
||||||
|
|
||||||
|
Vector<Window*> m_windows;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Process* current;
|
extern Process* current;
|
||||||
|
|
77
Kernel/ProcessGUI.cpp
Normal file
77
Kernel/ProcessGUI.cpp
Normal 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;
|
||||||
|
}
|
|
@ -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);
|
return current->sys$utime((const char*)arg1, (const Unix::utimbuf*)arg2);
|
||||||
case Syscall::SC_sync:
|
case Syscall::SC_sync:
|
||||||
return 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:
|
default:
|
||||||
kprintf("<%u> int0x80: Unknown function %u requested {%x, %x, %x}\n", current->pid(), function, arg1, arg2, arg3);
|
kprintf("<%u> int0x80: Unknown function %u requested {%x, %x, %x}\n", current->pid(), function, arg1, arg2, arg3);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -66,6 +66,8 @@
|
||||||
__ENUMERATE_SYSCALL(times) \
|
__ENUMERATE_SYSCALL(times) \
|
||||||
__ENUMERATE_SYSCALL(utime) \
|
__ENUMERATE_SYSCALL(utime) \
|
||||||
__ENUMERATE_SYSCALL(sync) \
|
__ENUMERATE_SYSCALL(sync) \
|
||||||
|
__ENUMERATE_SYSCALL(gui_create_window) \
|
||||||
|
__ENUMERATE_SYSCALL(gui_destroy_window) \
|
||||||
|
|
||||||
namespace Syscall {
|
namespace Syscall {
|
||||||
|
|
||||||
|
|
|
@ -14,18 +14,11 @@
|
||||||
|
|
||||||
void WindowComposer_main()
|
void WindowComposer_main()
|
||||||
{
|
{
|
||||||
Font::initialize();
|
|
||||||
FrameBuffer::initialize();
|
|
||||||
EventLoop::initialize();
|
|
||||||
WindowManager::initialize();
|
|
||||||
AbstractScreen::initialize();
|
|
||||||
|
|
||||||
auto info = current->get_display_info();
|
auto info = current->get_display_info();
|
||||||
|
|
||||||
dbgprintf("Screen is %ux%ux%ubpp\n", info.width, info.height, info.bpp);
|
dbgprintf("Screen is %ux%ux%ubpp\n", info.width, info.height, info.bpp);
|
||||||
|
|
||||||
FrameBuffer framebuffer((dword*)info.framebuffer, info.width, info.height);
|
FrameBuffer framebuffer((dword*)info.framebuffer, info.width, info.height);
|
||||||
EventLoop loop;
|
|
||||||
|
|
||||||
MsgBox(nullptr, "Serenity Operating System");
|
MsgBox(nullptr, "Serenity Operating System");
|
||||||
|
|
||||||
|
@ -75,7 +68,7 @@ void WindowComposer_main()
|
||||||
}
|
}
|
||||||
|
|
||||||
dbgprintf("Entering WindowComposer main loop.\n");
|
dbgprintf("Entering WindowComposer main loop.\n");
|
||||||
loop.exec();
|
EventLoop::main().exec();
|
||||||
|
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "Scheduler.h"
|
#include "Scheduler.h"
|
||||||
#include "PS2MouseDevice.h"
|
#include "PS2MouseDevice.h"
|
||||||
|
|
||||||
|
#define SPAWN_GUI_TEST_APP
|
||||||
//#define SPAWN_MULTIPLE_SHELLS
|
//#define SPAWN_MULTIPLE_SHELLS
|
||||||
//#define STRESS_TEST_SPAWNING
|
//#define STRESS_TEST_SPAWNING
|
||||||
|
|
||||||
|
@ -94,6 +95,9 @@ static void init_stage2()
|
||||||
|
|
||||||
int error;
|
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
|
||||||
#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);
|
||||||
Process::create_user_process("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, { }, tty2);
|
Process::create_user_process("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, { }, tty2);
|
||||||
|
|
|
@ -30,6 +30,7 @@ cp -v ../Userland/mkdir mnt/bin/mkdir
|
||||||
cp -v ../Userland/touch mnt/bin/touch
|
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
|
||||||
sh sync-local.sh
|
sh sync-local.sh
|
||||||
cp -v kernel.map mnt/
|
cp -v kernel.map mnt/
|
||||||
ln -s dir_a mnt/dir_cur
|
ln -s dir_a mnt/dir_cur
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
__ERROR(ENOTIMPL, "Not implemented") \
|
__ERROR(ENOTIMPL, "Not implemented") \
|
||||||
__ERROR(EAFNOSUPPORT, "Address family not supported") \
|
__ERROR(EAFNOSUPPORT, "Address family not supported") \
|
||||||
__ERROR(EWHYTHO, "Failed without setting an error code (Bug!)") \
|
__ERROR(EWHYTHO, "Failed without setting an error code (Bug!)") \
|
||||||
|
__ERROR(EBADWIN, "Bad WindowID") \
|
||||||
|
|
||||||
enum __errno_values {
|
enum __errno_values {
|
||||||
#undef __ERROR
|
#undef __ERROR
|
||||||
|
|
|
@ -18,7 +18,8 @@ OBJS = \
|
||||||
tty.o \
|
tty.o \
|
||||||
mkdir.o \
|
mkdir.o \
|
||||||
touch.o \
|
touch.o \
|
||||||
more.o
|
more.o \
|
||||||
|
guitest.o
|
||||||
|
|
||||||
APPS = \
|
APPS = \
|
||||||
id \
|
id \
|
||||||
|
@ -41,7 +42,8 @@ APPS = \
|
||||||
mkdir \
|
mkdir \
|
||||||
touch \
|
touch \
|
||||||
sync \
|
sync \
|
||||||
more
|
more \
|
||||||
|
guitest
|
||||||
|
|
||||||
ARCH_FLAGS =
|
ARCH_FLAGS =
|
||||||
STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib -nostdinc
|
STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib -nostdinc
|
||||||
|
@ -124,6 +126,9 @@ sync: sync.o
|
||||||
more: more.o
|
more: more.o
|
||||||
$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
|
$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
|
||||||
|
|
||||||
|
guitest: guitest.o
|
||||||
|
$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
|
||||||
|
|
||||||
.cpp.o:
|
.cpp.o:
|
||||||
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
|
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ public:
|
||||||
Color() { }
|
Color() { }
|
||||||
Color(NamedColor);
|
Color(NamedColor);
|
||||||
Color(byte r, byte g, byte b);
|
Color(byte r, byte g, byte b);
|
||||||
|
Color(RGBA32 rgba) : m_value(rgba) { }
|
||||||
|
|
||||||
RGBA32 value() const { return m_value; }
|
RGBA32 value() const { return m_value; }
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#ifdef SERENITY
|
#ifdef SERENITY
|
||||||
#include "PS2MouseDevice.h"
|
#include "PS2MouseDevice.h"
|
||||||
|
#include "Scheduler.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static EventLoop* s_mainEventLoop;
|
static EventLoop* s_mainEventLoop;
|
||||||
|
@ -33,6 +34,10 @@ EventLoop& EventLoop::main()
|
||||||
|
|
||||||
int EventLoop::exec()
|
int EventLoop::exec()
|
||||||
{
|
{
|
||||||
|
#ifdef SERENITY
|
||||||
|
m_server_process = current;
|
||||||
|
#endif
|
||||||
|
m_running = true;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (m_queuedEvents.is_empty())
|
if (m_queuedEvents.is_empty())
|
||||||
waitForEvent();
|
waitForEvent();
|
||||||
|
@ -48,9 +53,11 @@ int EventLoop::exec()
|
||||||
if (!receiver) {
|
if (!receiver) {
|
||||||
switch (event.type()) {
|
switch (event.type()) {
|
||||||
case Event::Quit:
|
case Event::Quit:
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
printf("event type %u with no receiver :(\n", event.type());
|
printf("event type %u with no receiver :(\n", event.type());
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class Object;
|
class Object;
|
||||||
|
class Process;
|
||||||
|
|
||||||
class EventLoop {
|
class EventLoop {
|
||||||
public:
|
public:
|
||||||
|
@ -23,6 +24,9 @@ public:
|
||||||
|
|
||||||
static void initialize();
|
static void initialize();
|
||||||
|
|
||||||
|
bool running() const { return m_running; }
|
||||||
|
Process& server_process() { return *m_server_process; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void waitForEvent();
|
void waitForEvent();
|
||||||
|
|
||||||
|
@ -35,4 +39,7 @@ private:
|
||||||
OwnPtr<Event> event;
|
OwnPtr<Event> event;
|
||||||
};
|
};
|
||||||
Vector<QueuedEvent> m_queuedEvents;
|
Vector<QueuedEvent> m_queuedEvents;
|
||||||
|
|
||||||
|
Process* m_server_process { nullptr };
|
||||||
|
bool m_running { false };
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "GraphicsBitmap.h"
|
#include "GraphicsBitmap.h"
|
||||||
|
#include "EventLoop.h"
|
||||||
#include <AK/kmalloc.h>
|
#include <AK/kmalloc.h>
|
||||||
|
|
||||||
#ifdef SERENITY
|
#ifdef SERENITY
|
||||||
|
@ -21,7 +22,9 @@ GraphicsBitmap::GraphicsBitmap(const Size& size)
|
||||||
, m_pitch(size.width() * sizeof(RGBA32))
|
, m_pitch(size.width() * sizeof(RGBA32))
|
||||||
{
|
{
|
||||||
#ifdef SERENITY
|
#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_data = (RGBA32*)m_region->linearAddress.asPtr();
|
||||||
m_owned = false;
|
m_owned = false;
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -43,6 +43,7 @@ void Window::setRect(const Rect& rect)
|
||||||
return;
|
return;
|
||||||
auto oldRect = m_rect;
|
auto oldRect = m_rect;
|
||||||
m_rect = 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());
|
m_backing = GraphicsBitmap::create(m_rect.size());
|
||||||
WindowManager::the().notifyRectChanged(*this, oldRect, m_rect);
|
WindowManager::the().notifyRectChanged(*this, oldRect, m_rect);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue