mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-30 08:41:15 +00:00
Start working on a GUI kernel API.
This commit is contained in:
parent
becc2c7fa5
commit
8f8c8d1ca3
Notes:
sideshowbarker
2024-07-19 16:03:20 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/8f8c8d1ca34
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 \
|
||||
i386.o \
|
||||
Process.o \
|
||||
ProcessGUI.o \
|
||||
i8253.o \
|
||||
Keyboard.o \
|
||||
CMOS.o \
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
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);
|
||||
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;
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 $<
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 };
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue