diff options
-rw-r--r-- | Kernel/GUITypes.h | 23 | ||||
-rw-r--r-- | Kernel/Makefile | 1 | ||||
-rw-r--r-- | Kernel/Process.cpp | 1 | ||||
-rw-r--r-- | Kernel/Process.h | 8 | ||||
-rw-r--r-- | Kernel/ProcessGUI.cpp | 77 | ||||
-rw-r--r-- | Kernel/Syscall.cpp | 4 | ||||
-rw-r--r-- | Kernel/Syscall.h | 2 | ||||
-rw-r--r-- | Kernel/WindowComposer.cpp | 9 | ||||
-rw-r--r-- | Kernel/init.cpp | 4 | ||||
-rwxr-xr-x | Kernel/sync.sh | 1 | ||||
-rw-r--r-- | LibC/errno_numbers.h | 1 | ||||
-rw-r--r-- | Userland/Makefile | 9 | ||||
-rw-r--r-- | Widgets/Color.h | 1 | ||||
-rw-r--r-- | Widgets/EventLoop.cpp | 7 | ||||
-rw-r--r-- | Widgets/EventLoop.h | 7 | ||||
-rw-r--r-- | Widgets/GraphicsBitmap.cpp | 5 | ||||
-rw-r--r-- | Widgets/Window.cpp | 1 |
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); } |