summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-02-14 01:21:32 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-02-14 01:21:32 +0100
commitf529b845ecd5d2f023ebb56b03afe086df6c21e2 (patch)
treedfcd320d70c26e879829779b6047789655429cb0
parentef4e9860fdb013a5caf76dbd51b071914cb1588a (diff)
downloadserenity-f529b845ecd5d2f023ebb56b03afe086df6c21e2.zip
WindowServer: Convert entire API to be message-based.
One big step towards userspace WindowServer. :^)
-rw-r--r--Applications/Terminal/main.cpp1
-rw-r--r--Kernel/GUITypes.h39
-rw-r--r--Kernel/Process.cpp1
-rw-r--r--Kernel/Process.h18
-rw-r--r--Kernel/ProcessGUI.cpp255
-rw-r--r--Kernel/Syscall.cpp22
-rw-r--r--Kernel/Syscall.h11
-rwxr-xr-xKernel/sync.sh1
-rw-r--r--LibC/Makefile1
-rw-r--r--LibC/gui.cpp70
-rw-r--r--LibC/gui.h21
-rw-r--r--LibGUI/GEventLoop.cpp1
-rw-r--r--LibGUI/GMenu.cpp13
-rw-r--r--LibGUI/GMenuBar.cpp1
-rw-r--r--LibGUI/GWindow.cpp121
-rw-r--r--SharedGraphics/Painter.cpp25
-rw-r--r--Userland/.gitignore1
-rw-r--r--Userland/Makefile5
-rw-r--r--Userland/guitest.cpp94
-rw-r--r--WindowServer/WSMessage.h189
-rw-r--r--WindowServer/WSMessageLoop.cpp58
-rw-r--r--WindowServer/WSMessageLoop.h1
-rw-r--r--WindowServer/WSWindow.cpp16
-rw-r--r--WindowServer/WSWindowManager.cpp146
-rw-r--r--WindowServer/WSWindowManager.h6
25 files changed, 500 insertions, 617 deletions
diff --git a/Applications/Terminal/main.cpp b/Applications/Terminal/main.cpp
index 58563dfab2..780c1b32fa 100644
--- a/Applications/Terminal/main.cpp
+++ b/Applications/Terminal/main.cpp
@@ -7,7 +7,6 @@
#include <assert.h>
#include <sys/ioctl.h>
#include <sys/select.h>
-#include <LibC/gui.h>
#include "Terminal.h"
#include <Kernel/KeyCode.h>
#include <LibGUI/GApplication.h>
diff --git a/Kernel/GUITypes.h b/Kernel/GUITypes.h
index 89bc85cfe6..ac62cb7954 100644
--- a/Kernel/GUITypes.h
+++ b/Kernel/GUITypes.h
@@ -76,13 +76,23 @@ struct GUI_ServerMessage {
DidSetApplicationMenubar,
DidAddMenuItem,
DidAddMenuSeparator,
+ DidCreateWindow,
+ DidDestroyWindow,
+ DidGetWindowTitle,
+ DidGetWindowRect,
+ DidGetWindowBackingStore,
};
Type type { Invalid };
int window_id { -1 };
+ size_t text_length;
+ char text[256];
union {
struct {
GUI_Rect rect;
+ } window;
+ struct {
+ GUI_Rect rect;
} paint;
struct {
GUI_Point position;
@@ -102,6 +112,13 @@ struct GUI_ServerMessage {
int menu_id;
unsigned identifier;
} menu;
+ struct {
+ void* backing_store_id;
+ GUI_Size size;
+ size_t bpp;
+ size_t pitch;
+ RGBA32* pixels;
+ } backing;
};
};
@@ -116,18 +133,36 @@ struct GUI_ClientMessage {
SetApplicationMenubar,
AddMenuItem,
AddMenuSeparator,
+ CreateWindow,
+ DestroyWindow,
+ SetWindowTitle,
+ GetWindowTitle,
+ SetWindowRect,
+ GetWindowRect,
+ InvalidateRect,
+ DidFinishPainting,
+ GetWindowBackingStore,
+ ReleaseWindowBackingStore,
+ SetGlobalCursorTracking,
};
Type type { Invalid };
int window_id { -1 };
+ size_t text_length;
+ char text[256];
+ int value { 0 };
union {
struct {
int menubar_id;
int menu_id;
unsigned identifier;
- unsigned text_length;
- char text[256];
} menu;
+ struct {
+ GUI_Rect rect;
+ } window;
+ struct {
+ void* backing_store_id;
+ } backing;
};
};
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp
index 07fd8e69ea..d1958ecafd 100644
--- a/Kernel/Process.cpp
+++ b/Kernel/Process.cpp
@@ -2133,7 +2133,6 @@ void Process::finalize()
{
ASSERT(current == g_finalizer);
- destroy_all_menus();
destroy_all_windows();
m_fds.clear();
m_tty = nullptr;
diff --git a/Kernel/Process.h b/Kernel/Process.h
index 6fcf190ce0..2e60a708d3 100644
--- a/Kernel/Process.h
+++ b/Kernel/Process.h
@@ -219,24 +219,10 @@ public:
int sys$read_tsc(dword* lsw, dword* msw);
int sys$chmod(const char* pathname, mode_t);
- int gui$create_window(const GUI_WindowParameters*);
- int gui$destroy_window(int window_id);
- int gui$get_window_backing_store(int window_id, GUI_WindowBackingStoreInfo*);
- int gui$release_window_backing_store(void* backing_store_id);
- int gui$invalidate_window(int window_id, const GUI_Rect*);
- int gui$notify_paint_finished(int window_id, const GUI_Rect*);
- int gui$get_window_title(int window_id, char* buffer, size_t size);
- int gui$set_window_title(int window_id, const char* title, size_t size);
- int gui$get_window_rect(int window_id, GUI_Rect*);
- int gui$set_window_rect(int window_id, const GUI_Rect*);
- int gui$set_global_cursor_tracking_enabled(int window_id, bool enabled);
-
DisplayInfo set_video_resolution(int width, int height);
static void initialize();
static void initialize_gui_statics();
- int make_window_id();
- void destroy_all_menus();
void destroy_all_windows();
void crash() NORETURN;
@@ -408,12 +394,8 @@ private:
RetainPtr<Region> m_display_framebuffer_region;
- HashMap<int, OwnPtr<WSWindow>> m_windows;
- Vector<RetainPtr<GraphicsBitmap>> m_retained_backing_stores;
-
Vector<GUI_ServerMessage> m_gui_events;
Lock m_gui_events_lock;
- int m_next_window_id { 1 };
dword m_wakeup_requested { false };
bool m_has_used_fpu { false };
diff --git a/Kernel/ProcessGUI.cpp b/Kernel/ProcessGUI.cpp
index 6e9310261e..cfdfff3269 100644
--- a/Kernel/ProcessGUI.cpp
+++ b/Kernel/ProcessGUI.cpp
@@ -16,262 +16,11 @@ void Process::initialize_gui_statics()
new WSMessageLoop;
}
-int Process::make_window_id()
-{
- int new_id = m_next_window_id++;
- while (!new_id || m_windows.contains(new_id)) {
- new_id = m_next_window_id++;
- if (new_id < 0)
- new_id = 1;
- }
- return new_id;
-}
-
-static void wait_for_gui_server()
-{
- // FIXME: Time out after a while and return an error.
- while (!WSMessageLoop::the().running())
- sleep(10);
-}
-
-int Process::gui$create_window(const GUI_WindowParameters* user_params)
-{
- wait_for_gui_server();
-
- if (!validate_read_typed(user_params))
- return -EFAULT;
-
- auto params = *user_params;
- Rect rect = params.rect;
-
- if (rect.is_empty())
- return -EINVAL;
-
- ProcessPagingScope scope(WSMessageLoop::the().server_process());
-
- int window_id = make_window_id();
- if (!window_id)
- return -ENOMEM;
-
- auto window = make<WSWindow>(*this, window_id);
- if (!window)
- return -ENOMEM;
-
- window->set_title(params.title);
- window->set_rect(rect);
-
- m_windows.set(window_id, move(window));
-#ifdef LOG_GUI_SYSCALLS
- 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());
-#endif
- return window_id;
-}
-
-int Process::gui$destroy_window(int window_id)
-{
-#ifdef LOG_GUI_SYSCALLS
- dbgprintf("%s<%u> gui$destroy_window (window_id=%d)\n", name().characters(), pid(), window_id);
-#endif
- if (window_id < 0)
- return -EINVAL;
- auto it = m_windows.find(window_id);
- if (it == m_windows.end())
- return -EBADWINDOW;
- auto message = make<WSMessage>(WSMessage::WM_DestroyWindow);
- WSMessageLoop::the().post_message((*it).value.leak_ptr(), move(message));
- m_windows.remove(window_id);
- return 0;
-}
-
-int Process::gui$get_window_backing_store(int window_id, GUI_WindowBackingStoreInfo* info)
-{
-#ifdef LOG_GUI_SYSCALLS
- dbgprintf("%s<%u> gui$get_window_backing_store (window_id=%d, info=%p)\n", name().characters(), pid(), window_id, info);
-#endif
- if (!validate_write_typed(info))
- return -EFAULT;
- if (window_id < 0)
- return -EINVAL;
- auto it = m_windows.find(window_id);
- if (it == m_windows.end())
- return -EBADWINDOW;
- auto& window = *(*it).value;
- WSWindowLocker locker(window);
- auto* backing_store = window.backing();
-#ifdef BACKING_STORE_DEBUG
- dbgprintf("%s<%u> +++ %p[%d] (%dx%d)\n", name().characters(), pid(), backing_store, backing_store->width(), backing_store->height());
-#endif
- m_retained_backing_stores.append(backing_store);
- info->backing_store_id = backing_store;
- info->bpp = sizeof(RGBA32);
- info->pitch = backing_store->pitch();
- info->size = backing_store->size();
- info->pixels = reinterpret_cast<RGBA32*>(backing_store->client_region()->laddr().as_ptr());
- return 0;
-}
-
-int Process::gui$release_window_backing_store(void* backing_store_id)
-{
- for (size_t i = 0; i < m_retained_backing_stores.size(); ++i) {
- if (m_retained_backing_stores[i].ptr() == backing_store_id) {
-#ifdef BACKING_STORE_DEBUG
- auto* backing_store = m_retained_backing_stores[i].ptr();
- dbgprintf("%s<%u> --- %p (%dx%d)\n", name().characters(), pid(), backing_store, backing_store->width(), backing_store->height());
-#endif
- m_retained_backing_stores.remove(i);
- return 0;
- }
- }
- return -EBADBACKING;
-}
-
-int Process::gui$invalidate_window(int window_id, const GUI_Rect* a_rect)
-{
- if (window_id < 0)
- return -EINVAL;
- if (a_rect && !validate_read_typed(a_rect))
- return -EFAULT;
- auto it = m_windows.find(window_id);
- if (it == m_windows.end())
- return -EBADWINDOW;
-#ifdef LOG_GUI_SYSCALLS
- if (!a_rect)
- dbgprintf("%s<%u> gui$invalidate_window (window_id=%d, rect=(entire))\n", name().characters(), pid(), window_id);
- else
- dbgprintf("%s<%u> gui$invalidate_window (window_id=%d, rect={%d,%d %dx%d})\n", name().characters(), pid(), window_id, a_rect->location.x, a_rect->location.y, a_rect->size.width, a_rect->size.height);
-#endif
- auto& window = *(*it).value;
- Rect rect;
- if (a_rect)
- rect = *a_rect;
- WSMessageLoop::the().post_message(&window, make<WSClientWantsToPaintMessage>(rect));
- WSMessageLoop::the().server_process().request_wakeup();
- return 0;
-}
-
-int Process::gui$notify_paint_finished(int window_id, const GUI_Rect* a_rect)
-{
- if (window_id < 0)
- return -EINVAL;
- if (a_rect && !validate_read_typed(a_rect))
- return -EFAULT;
- auto it = m_windows.find(window_id);
- if (it == m_windows.end())
- return -EBADWINDOW;
-#ifdef LOG_GUI_SYSCALLS
- if (!a_rect)
- dbgprintf("%s<%u> gui$notify_paint_finished (window_id=%d, rect=(entire))\n", name().characters(), pid(), window_id);
- else
- dbgprintf("%s<%u> gui$notify_paint_finished (window_id=%d, rect={%d,%d %dx%d})\n", name().characters(), pid(), window_id, a_rect->location.x, a_rect->location.y, a_rect->size.width, a_rect->size.height);
-#endif
- auto& window = *(*it).value;
- Rect rect;
- if (a_rect)
- rect = *a_rect;
- WSMessageLoop::the().post_message(&window, make<WSClientFinishedPaintMessage>(rect));
- WSMessageLoop::the().server_process().request_wakeup();
- return 0;
-}
-
-int Process::gui$get_window_title(int window_id, char* buffer, size_t size)
-{
- if (window_id < 0)
- return -EINVAL;
- if (!validate_write(buffer, size))
- return -EFAULT;
- auto it = m_windows.find(window_id);
- if (it == m_windows.end())
- return -EBADWINDOW;
- auto& window = *(*it).value;
- String title;
- {
- WSWindowLocker locker(window);
- title = window.title();
- }
- if (title.length() > size)
- return -ERANGE;
- memcpy(buffer, title.characters(), title.length());
- return title.length();
-
-}
-
-int Process::gui$set_window_title(int window_id, const char* title, size_t size)
-{
- if (window_id < 0)
- return -EINVAL;
- if (!validate_read(title, size))
- return -EFAULT;
- auto it = m_windows.find(window_id);
- if (it == m_windows.end())
- return -EBADWINDOW;
- auto& window = *(*it).value;
- String new_title(title, size);
- WSMessageLoop::the().post_message(&window, make<WSSetWindowTitleMessage>(move(new_title)));
- WSMessageLoop::the().server_process().request_wakeup();
- return 0;
-}
-
-int Process::gui$get_window_rect(int window_id, GUI_Rect* rect)
-{
- if (window_id < 0)
- return -EINVAL;
- if (!validate_write_typed(rect))
- return -EFAULT;
- auto it = m_windows.find(window_id);
- if (it == m_windows.end())
- return -EBADWINDOW;
- auto& window = *(*it).value;
- {
- WSWindowLocker locker(window);
- *rect = window.rect();
- }
- return 0;
-}
-
-int Process::gui$set_window_rect(int window_id, const GUI_Rect* rect)
-{
- if (window_id < 0)
- return -EINVAL;
- if (!validate_read_typed(rect))
- return -EFAULT;
- auto it = m_windows.find(window_id);
- if (it == m_windows.end())
- return -EBADWINDOW;
- auto& window = *(*it).value;
- Rect new_rect = *rect;
- WSMessageLoop::the().post_message(&window, make<WSSetWindowRectMessage>(new_rect));
- WSMessageLoop::the().server_process().request_wakeup();
- return 0;
-}
-
-int Process::gui$set_global_cursor_tracking_enabled(int window_id, bool enabled)
-{
- if (window_id < 0)
- return -EINVAL;
- auto it = m_windows.find(window_id);
- if (it == m_windows.end())
- return -EBADWINDOW;
- auto& window = *(*it).value;
- WSWindowLocker locker(window);
- window.set_global_cursor_tracking_enabled(enabled);
- return 0;
-}
-
-void Process::destroy_all_menus()
+void Process::destroy_all_windows()
{
if (!WSMessageLoop::the().running())
return;
- WSWindowManager::the().destroy_all_menus(*this);
-}
-
-void Process::destroy_all_windows()
-{
- for (auto& it : m_windows) {
- auto message = make<WSMessage>(WSMessage::WM_DestroyWindow);
- it.value->notify_process_died(Badge<Process>());
- WSMessageLoop::the().post_message(it.value.leak_ptr(), move(message));
- }
- m_windows.clear();
+ WSMessageLoop::the().notify_client_died(gui_client_id());
}
DisplayInfo Process::set_video_resolution(int width, int height)
diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp
index a96a9de536..4aebf73bf3 100644
--- a/Kernel/Syscall.cpp
+++ b/Kernel/Syscall.cpp
@@ -195,30 +195,8 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2,
return sync();
case Syscall::SC_unlink:
return current->sys$unlink((const char*)arg1);
- case Syscall::SC_gui_create_window:
- return current->gui$create_window((const GUI_WindowParameters*)arg1);
- case Syscall::SC_gui_destroy_window:
- return current->gui$destroy_window((int)arg1);
- case Syscall::SC_gui_get_window_backing_store:
- return current->gui$get_window_backing_store((int)arg1, (GUI_WindowBackingStoreInfo*)arg2);
- case Syscall::SC_gui_release_window_backing_store:
- return current->gui$release_window_backing_store((void*)arg1);
- case Syscall::SC_gui_invalidate_window:
- return current->gui$invalidate_window((int)arg1, (const GUI_Rect*)arg2);
- case Syscall::SC_gui_set_window_title:
- return current->gui$set_window_title((int)arg1, (const char*)arg2, (size_t)arg3);
- case Syscall::SC_gui_get_window_title:
- return current->gui$get_window_title((int)arg1, (char*)arg2, (size_t)arg3);
- case Syscall::SC_gui_set_window_rect:
- return current->gui$set_window_rect((int)arg1, (const GUI_Rect*)arg2);
- case Syscall::SC_gui_get_window_rect:
- return current->gui$get_window_rect((int)arg1, (GUI_Rect*)arg2);
case Syscall::SC_read_tsc:
return current->sys$read_tsc((dword*)arg1, (dword*)arg2);
- case Syscall::SC_gui_notify_paint_finished:
- return current->gui$notify_paint_finished((int)arg1, (const GUI_Rect*)arg2);
- case Syscall::SC_gui_set_global_cursor_tracking_enabled:
- return current->gui$set_global_cursor_tracking_enabled((int)arg1, (bool)arg2);
case Syscall::SC_rmdir:
return current->sys$rmdir((const char*)arg1);
case Syscall::SC_chmod:
diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h
index 964426454d..806a7472d0 100644
--- a/Kernel/Syscall.h
+++ b/Kernel/Syscall.h
@@ -71,17 +71,6 @@
__ENUMERATE_SYSCALL(unlink) \
__ENUMERATE_SYSCALL(poll) \
__ENUMERATE_SYSCALL(read_tsc) \
- __ENUMERATE_SYSCALL(gui_create_window) \
- __ENUMERATE_SYSCALL(gui_destroy_window) \
- __ENUMERATE_SYSCALL(gui_get_window_backing_store) \
- __ENUMERATE_SYSCALL(gui_release_window_backing_store) \
- __ENUMERATE_SYSCALL(gui_invalidate_window) \
- __ENUMERATE_SYSCALL(gui_get_window_title) \
- __ENUMERATE_SYSCALL(gui_set_window_title) \
- __ENUMERATE_SYSCALL(gui_get_window_rect) \
- __ENUMERATE_SYSCALL(gui_set_window_rect) \
- __ENUMERATE_SYSCALL(gui_notify_paint_finished) \
- __ENUMERATE_SYSCALL(gui_set_global_cursor_tracking_enabled) \
__ENUMERATE_SYSCALL(rmdir) \
__ENUMERATE_SYSCALL(chmod) \
__ENUMERATE_SYSCALL(usleep) \
diff --git a/Kernel/sync.sh b/Kernel/sync.sh
index c4b8fef6c1..087f096c0a 100755
--- a/Kernel/sync.sh
+++ b/Kernel/sync.sh
@@ -57,7 +57,6 @@ cp -v ../Userland/more mnt/bin/more
cp -v ../Userland/rm mnt/bin/rm
cp -v ../Userland/rmdir mnt/bin/rmdir
cp -v ../Userland/cp mnt/bin/cp
-cp -v ../Userland/guitest mnt/bin/guitest
cp -v ../Userland/guitest2 mnt/bin/guitest2
cp -v ../Userland/sysctl mnt/bin/sysctl
cp -v ../Userland/pape mnt/bin/pape
diff --git a/LibC/Makefile b/LibC/Makefile
index e7758391b4..067ecbedc6 100644
--- a/LibC/Makefile
+++ b/LibC/Makefile
@@ -41,7 +41,6 @@ LIBC_OBJS = \
ioctl.o \
math.o \
utime.o \
- gui.o \
sys/select.o \
poll.o \
locale.o \
diff --git a/LibC/gui.cpp b/LibC/gui.cpp
deleted file mode 100644
index da1fecef05..0000000000
--- a/LibC/gui.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-#include "gui.h"
-#include <Kernel/GUITypes.h>
-#include <Kernel/Syscall.h>
-#include <errno.h>
-
-int gui_create_window(const GUI_WindowParameters* params)
-{
- int rc = syscall(SC_gui_create_window, params);
- __RETURN_WITH_ERRNO(rc, rc, -1);
-}
-
-int gui_destroy_window(int window_id)
-{
- int rc = syscall(SC_gui_destroy_window, window_id);
- __RETURN_WITH_ERRNO(rc, rc, -1);
-}
-
-int gui_invalidate_window(int window_id, const GUI_Rect* rect)
-{
- int rc = syscall(SC_gui_invalidate_window, window_id, rect);
- __RETURN_WITH_ERRNO(rc, rc, -1);
-}
-
-int gui_get_window_backing_store(int window_id, GUI_WindowBackingStoreInfo* info)
-{
- int rc = syscall(SC_gui_get_window_backing_store, window_id, info);
- __RETURN_WITH_ERRNO(rc, rc, -1);
-}
-
-int gui_release_window_backing_store(void* backing_store_id)
-{
- int rc = syscall(SC_gui_release_window_backing_store, backing_store_id);
- __RETURN_WITH_ERRNO(rc, rc, -1);
-}
-
-int gui_get_window_title(int window_id, char* buffer, size_t size)
-{
- int rc = syscall(SC_gui_get_window_title, window_id, buffer, size);
- __RETURN_WITH_ERRNO(rc, rc, -1);
-}
-
-int gui_set_window_title(int window_id, const char* title, size_t length)
-{
- int rc = syscall(SC_gui_set_window_title, window_id, title, length);
- __RETURN_WITH_ERRNO(rc, rc, -1);
-}
-
-int gui_get_window_rect(int window_id, GUI_Rect* rect)
-{
- int rc = syscall(SC_gui_get_window_rect, window_id, rect);
- __RETURN_WITH_ERRNO(rc, rc, -1);
-}
-
-int gui_set_window_rect(int window_id, const GUI_Rect* rect)
-{
- int rc = syscall(SC_gui_set_window_rect, window_id, rect);
- __RETURN_WITH_ERRNO(rc, rc, -1);
-}
-
-int gui_notify_paint_finished(int window_id, const GUI_Rect* rect)
-{
- int rc = syscall(SC_gui_notify_paint_finished, window_id, rect);
- __RETURN_WITH_ERRNO(rc, rc, -1);
-}
-
-int gui_set_global_cursor_tracking_enabled(int window_id, bool enabled)
-{
- int rc = syscall(SC_gui_set_global_cursor_tracking_enabled, window_id, enabled);
- __RETURN_WITH_ERRNO(rc, rc, -1);
-}
diff --git a/LibC/gui.h b/LibC/gui.h
deleted file mode 100644
index 4b7abbb88d..0000000000
--- a/LibC/gui.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#pragma once
-
-#include <sys/cdefs.h>
-#include <Kernel/GUITypes.h>
-
-__BEGIN_DECLS
-
-int gui_create_window(const GUI_WindowParameters*);
-int gui_destroy_window(int window_id);
-int gui_invalidate_window(int window_id, const GUI_Rect*);
-int gui_notify_paint_finished(int window_id, const GUI_Rect*);
-int gui_get_window_backing_store(int window_id, GUI_WindowBackingStoreInfo*);
-int gui_release_window_backing_store(void* backing_store_id);
-int gui_get_window_title(int window_id, char*, size_t);
-int gui_set_window_title(int window_id, const char*, size_t);
-int gui_get_window_rect(int window_id, GUI_Rect*);
-int gui_set_window_rect(int window_id, const GUI_Rect*);
-int gui_set_global_cursor_tracking_enabled(int window_id, bool);
-
-__END_DECLS
-
diff --git a/LibGUI/GEventLoop.cpp b/LibGUI/GEventLoop.cpp
index 553cc602c1..a9e9fa2c5c 100644
--- a/LibGUI/GEventLoop.cpp
+++ b/LibGUI/GEventLoop.cpp
@@ -11,7 +11,6 @@
#include <LibC/string.h>
#include <LibC/time.h>
#include <LibC/sys/select.h>
-#include <LibC/gui.h>
#include <errno.h>
#include <string.h>
diff --git a/LibGUI/GMenu.cpp b/LibGUI/GMenu.cpp
index a7857d5788..2852e4090f 100644
--- a/LibGUI/GMenu.cpp
+++ b/LibGUI/GMenu.cpp
@@ -1,7 +1,6 @@
#include <LibGUI/GAction.h>
#include <LibGUI/GMenu.h>
#include <LibGUI/GEventLoop.h>
-#include <LibC/gui.h>
#include <AK/HashMap.h>
static HashMap<int, GMenu*>& all_menus()
@@ -44,9 +43,9 @@ int GMenu::realize_menu()
{
GUI_ClientMessage request;
request.type = GUI_ClientMessage::Type::CreateMenu;
- ASSERT(m_name.length() < sizeof(request.menu.text));
- strcpy(request.menu.text, m_name.characters());
- request.menu.text_length = m_name.length();
+ ASSERT(m_name.length() < sizeof(request.text));
+ strcpy(request.text, m_name.characters());
+ request.text_length = m_name.length();
auto response = GEventLoop::main().sync_request(request, GUI_ServerMessage::Type::DidCreateMenu);
m_menu_id = response.menu.menu_id;
@@ -66,9 +65,9 @@ int GMenu::realize_menu()
request.type = GUI_ClientMessage::Type::AddMenuItem;
request.menu.menu_id = m_menu_id;
request.menu.identifier = i;
- ASSERT(action.text().length() < sizeof(request.menu.text));
- strcpy(request.menu.text, action.text().characters());
- request.menu.text_length = action.text().length();
+ ASSERT(action.text().length() < sizeof(request.text));
+ strcpy(request.text, action.text().characters());
+ request.text_length = action.text().length();
GEventLoop::main().sync_request(request, GUI_ServerMessage::Type::DidAddMenuItem);
}
}
diff --git a/LibGUI/GMenuBar.cpp b/LibGUI/GMenuBar.cpp
index b44bd5f256..574ab8b3cb 100644
--- a/LibGUI/GMenuBar.cpp
+++ b/LibGUI/GMenuBar.cpp
@@ -1,6 +1,5 @@
#include <LibGUI/GMenuBar.h>
#include <LibGUI/GEventLoop.h>
-#include <LibC/gui.h>
GMenuBar::GMenuBar()
{
diff --git a/LibGUI/GWindow.cpp b/LibGUI/GWindow.cpp
index cd7cc84062..a50f7804fc 100644
--- a/LibGUI/GWindow.cpp
+++ b/LibGUI/GWindow.cpp
@@ -3,7 +3,6 @@
#include "GEventLoop.h"
#include "GWidget.h"
#include <SharedGraphics/GraphicsBitmap.h>
-#include <LibC/gui.h>
#include <LibC/stdio.h>
#include <LibC/stdlib.h>
#include <LibC/unistd.h>
@@ -56,15 +55,15 @@ void GWindow::show()
if (m_window_id)
return;
- GUI_WindowParameters wparams;
- wparams.rect = m_rect_when_windowless;
- wparams.background_color = 0xffc0c0;
- strcpy(wparams.title, m_title_when_windowless.characters());
- m_window_id = gui_create_window(&wparams);
- if (m_window_id < 0) {
- perror("gui_create_window");
- exit(1);
- }
+ GUI_ClientMessage request;
+ request.type = GUI_ClientMessage::Type::CreateWindow;
+ request.window_id = m_window_id;
+ request.window.rect = m_rect_when_windowless;
+ ASSERT(m_title_when_windowless.length() < sizeof(request.text));
+ strcpy(request.text, m_title_when_windowless.characters());
+ request.text_length = m_title_when_windowless.length();
+ auto response = GEventLoop::main().sync_request(request, GUI_ServerMessage::Type::DidCreateWindow);
+ m_window_id = response.window_id;
windows().set(m_window_id, this);
update();
@@ -75,55 +74,68 @@ void GWindow::hide()
if (!m_window_id)
return;
windows().remove(m_window_id);
- int rc = gui_destroy_window(m_window_id);
- if (rc < 0) {
- perror("gui_destroy_window");
- exit(1);
- }
+ GUI_ClientMessage request;
+ request.type = GUI_ClientMessage::Type::DestroyWindow;
+ request.window_id = m_window_id;
+ ASSERT(m_title_when_windowless.length() < sizeof(request.text));
+ strcpy(request.text, m_title_when_windowless.characters());
+ request.text_length = m_title_when_windowless.length();
+ GEventLoop::main().post_message_to_server(request);
}
void GWindow::set_title(String&& title)
{
- m_title_when_windowless = title;
- if (m_window_id) {
- int rc = gui_set_window_title(m_window_id, title.characters(), title.length());
- if (rc < 0) {
- perror("gui_set_window_title");
- exit(1);
- }
- }
+ m_title_when_windowless = move(title);
+ if (!m_window_id)
+ return;
+
+ GUI_ClientMessage request;
+ request.type = GUI_ClientMessage::Type::SetWindowTitle;
+ request.window_id = m_window_id;
+ ASSERT(m_title_when_windowless.length() < sizeof(request.text));
+ strcpy(request.text, m_title_when_windowless.characters());
+ request.text_length = m_title_when_windowless.length();
+ GEventLoop::main().post_message_to_server(request);
}
String GWindow::title() const
{
- if (m_window_id) {
- char buffer[256];
- int rc = gui_get_window_title(m_window_id, buffer, sizeof(buffer));
- ASSERT(rc >= 0);
- return String(buffer, rc);
- }
- return m_title_when_windowless;
+ if (!m_window_id)
+ return m_title_when_windowless;
+
+ GUI_ClientMessage request;
+ request.type = GUI_ClientMessage::Type::GetWindowTitle;
+ request.window_id = m_window_id;
+ ASSERT(m_title_when_windowless.length() < sizeof(request.text));
+ strcpy(request.text, m_title_when_windowless.characters());
+ request.text_length = m_title_when_windowless.length();
+ auto response = GEventLoop::main().sync_request(request, GUI_ServerMessage::Type::DidGetWindowTitle);
+ return String(response.text, response.text_length);
}
Rect GWindow::rect() const
{
- if (m_window_id) {
- GUI_Rect buffer;
- int rc = gui_get_window_rect(m_window_id, &buffer);
- ASSERT(rc >= 0);
- return buffer;
- }
- return m_rect_when_windowless;
+ if (!m_window_id)
+ return m_rect_when_windowless;
+
+ GUI_ClientMessage request;
+ request.type = GUI_ClientMessage::Type::GetWindowRect;
+ request.window_id = m_window_id;
+ auto response = GEventLoop::main().sync_request(request, GUI_ServerMessage::Type::DidGetWindowRect);
+ ASSERT(response.window_id == m_window_id);
+ return response.window.rect;
}
void GWindow::set_rect(const Rect& a_rect)
{
m_rect_when_windowless = a_rect;
- if (m_window_id) {
- GUI_Rect rect = a_rect;
- int rc = gui_set_window_rect(m_window_id, &rect);
- ASSERT(rc == 0);
- }
+ if (!m_window_id)
+ return;
+ GUI_ClientMessage request;
+ request.type = GUI_ClientMessage::Type::SetWindowRect;
+ request.window_id = m_window_id;
+ request.window.rect = a_rect;
+ GEventLoop::main().post_message_to_server(request);
}
void GWindow::event(GEvent& event)
@@ -158,9 +170,11 @@ void GWindow::event(GEvent& event)
rect = m_main_widget->rect();
m_main_widget->event(*make<GPaintEvent>(rect));
if (m_window_id) {
- GUI_Rect gui_rect = rect;
- int rc = gui_notify_paint_finished(m_window_id, &gui_rect);
- ASSERT(rc == 0);
+ GUI_ClientMessage message;
+ message.type = GUI_ClientMessage::Type::DidFinishPainting;
+ message.window_id = m_window_id;
+ message.window.rect = rect;
+ GEventLoop::main().post_message_to_server(message);
}
return;
}
@@ -209,9 +223,11 @@ void GWindow::update(const Rect& a_rect)
}
m_pending_paint_event_rects.append(a_rect);
- GUI_Rect rect = a_rect;
- int rc = gui_invalidate_window(m_window_id, a_rect.is_null() ? nullptr : &rect);
- ASSERT(rc == 0);
+ GUI_ClientMessage request;
+ request.type = GUI_ClientMessage::Type::InvalidateRect;
+ request.window_id = m_window_id;
+ request.window.rect = a_rect;
+ GEventLoop::main().post_message_to_server(request);
}
void GWindow::set_main_widget(GWidget* widget)
@@ -255,5 +271,12 @@ void GWindow::set_global_cursor_tracking_widget(GWidget* widget)
if (widget == m_global_cursor_tracking_widget.ptr())
return;
m_global_cursor_tracking_widget = widget ? widget->make_weak_ptr() : nullptr;
- gui_set_global_cursor_tracking_enabled(m_window_id, widget != nullptr);
+
+ GUI_ClientMessage request;
+ request.type = GUI_ClientMessage::Type::SetGlobalCursorTracking;
+ request.window_id = m_window_id;
+ request.value = widget != nullptr;
+ // FIXME: What if the cursor moves out of our interest range before the server can handle this?
+ // Maybe there could be a response that includes the current cursor location as of enabling.
+ GEventLoop::main().post_message_to_server(request);
}
diff --git a/SharedGraphics/Painter.cpp b/SharedGraphics/Painter.cpp
index e70348f5ea..acc51b7a95 100644
--- a/SharedGraphics/Painter.cpp
+++ b/SharedGraphics/Painter.cpp
@@ -7,7 +7,7 @@
#ifdef USERLAND
#include <LibGUI/GWidget.h>
#include <LibGUI/GWindow.h>
-#include <LibC/gui.h>
+#include <LibGUI/GEventLoop.h>
#include <LibC/stdio.h>
#include <LibC/errno.h>
#include <LibC/string.h>
@@ -26,15 +26,13 @@ Painter::Painter(GraphicsBitmap& bitmap)
Painter::Painter(GWidget& widget)
: m_font(&widget.font())
{
- GUI_WindowBackingStoreInfo backing;
- int rc = gui_get_window_backing_store(widget.window()->window_id(), &backing);
- if (rc < 0) {
- perror("gui_get_window_backing_store");
- ASSERT_NOT_REACHED();
- }
- m_backing_store_id = backing.backing_store_id;
+ GUI_ClientMessage request;
+ request.type = GUI_ClientMessage::Type::GetWindowBackingStore;
+ request.window_id = widget.window()->window_id();
+ auto response = GEventLoop::main().sync_request(request, GUI_ServerMessage::DidGetWindowBackingStore);
+ m_backing_store_id = response.backing.backing_store_id;
- m_target = GraphicsBitmap::create_wrapper(backing.size, backing.pixels);
+ m_target = GraphicsBitmap::create_wrapper(response.backing.size, response.backing.pixels);
ASSERT(m_target);
m_window = widget.window();
m_translation.move_by(widget.window_relative_rect().location());
@@ -55,11 +53,10 @@ Painter::~Painter()
#ifdef USERLAND
m_target = nullptr;
if (m_backing_store_id) {
- int rc = gui_release_window_backing_store(m_backing_store_id);
- if (rc < 0) {
- perror("gui_release_window_backing_store");
- ASSERT_NOT_REACHED();
- }
+ GUI_ClientMessage request;
+ request.type = GUI_ClientMessage::Type::ReleaseWindowBackingStore;
+ request.backing.backing_store_id = m_backing_store_id;
+ GEventLoop::main().post_message_to_server(request);
}
#endif
}
diff --git a/Userland/.gitignore b/Userland/.gitignore
index e557abe617..a3644d8cdc 100644
--- a/Userland/.gitignore
+++ b/Userland/.gitignore
@@ -22,7 +22,6 @@ mkdir
touch
sync
more
-guitest
guitest2
sysctl
rm
diff --git a/Userland/Makefile b/Userland/Makefile
index 04ea1dbe98..6f64eeeeab 100644
--- a/Userland/Makefile
+++ b/Userland/Makefile
@@ -19,7 +19,6 @@ OBJS = \
mkdir.o \
touch.o \
more.o \
- guitest.o \
guitest2.o \
sysctl.o \
pape.o \
@@ -52,7 +51,6 @@ APPS = \
touch \
sync \
more \
- guitest \
guitest2 \
sysctl \
pape \
@@ -147,9 +145,6 @@ sync: sync.o
more: more.o
$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
-guitest: guitest.o
- $(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
-
guitest2: guitest2.o
$(LD) -o $@ $(LDFLAGS) $< ../LibGUI/LibGUI.a ../LibC/LibC.a
diff --git a/Userland/guitest.cpp b/Userland/guitest.cpp
deleted file mode 100644
index 9541289ddd..0000000000
--- a/Userland/guitest.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <Kernel/Syscall.h>
-#include <SharedGraphics/GraphicsBitmap.h>
-#include <SharedGraphics/Painter.h>
-#include <LibC/gui.h>
-
-static void paint(GraphicsBitmap& bitmap, int width, int height);
-
-int main(int argc, char** argv)
-{
- GUI_WindowParameters wparams;
- wparams.rect = { { 100, 100 }, { 120, 120 } };
- wparams.background_color = 0xffc0c0;
- strcpy(wparams.title, "GUI test app");
- int window_id = gui_create_window(&wparams);
- if (window_id < 0) {
- perror("gui_create_window");
- return 1;
- }
-
- int fd = open("/dev/gui_events", O_RDONLY);
- if (fd < 0) {
- perror("open");
- return 1;
- }
-
- // NOTE: We never release the backing store. This is just a simple app. :^)
- GUI_WindowBackingStoreInfo backing;
- int rc = gui_get_window_backing_store(window_id, &backing);
- if (rc < 0) {
- perror("gui_get_window_backing_store");
- return 1;
- }
-
- auto bitmap = GraphicsBitmap::create_wrapper(backing.size, backing.pixels);
-
- dbgprintf("(Client) window backing %ux%u @ %p\n", backing.size.width, backing.size.height, backing.pixels);
-
- paint(*bitmap, backing.size.width, backing.size.height);
-
- rc = gui_invalidate_window(window_id, nullptr);
- if (rc < 0) {
- perror("gui_invalidate_window");
- return 1;
- }
-
- for (;;) {
- GUI_ServerMessage message;
- ssize_t nread = read(fd, &message, sizeof(message));
- if (nread < 0) {
- perror("read");
- return 1;
- }
- dbgprintf("(%d) ", getpid());
- assert(nread == sizeof(message));
- switch (message.type) {
- case GUI_ServerMessage::Type::Paint: dbgprintf("WID=%x Paint [%d,%d %dx%d]\n", message.window_id, message.paint.rect.location.x, message.paint.rect.location.y, message.paint.rect.size.width, message.paint.rect.size.height); break;
- case GUI_ServerMessage::Type::MouseDown: dbgprintf("WID=%x MouseDown %d,%d\n", message.window_id, message.mouse.position.x, message.mouse.position.y); break;
- case GUI_ServerMessage::Type::MouseUp: dbgprintf("WID=%x MouseUp %d,%d\n", message.window_id, message.mouse.position.x, message.mouse.position.y); break;
- case GUI_ServerMessage::Type::MouseMove: dbgprintf("WID=%x MouseMove %d,%d\n", message.window_id, message.mouse.position.x, message.mouse.position.y); break;
- case GUI_ServerMessage::Type::WindowActivated: dbgprintf("WID=%x WindowActivated\n", message.window_id); break;
- case GUI_ServerMessage::Type::WindowDeactivated: dbgprintf("WID=%x WindowDeactivated\n", message.window_id); break;
- case GUI_ServerMessage::Type::WindowCloseRequest: return 0;
- }
-
- if (message.type == GUI_ServerMessage::Type::Paint) {
- paint(*bitmap, backing.size.width, backing.size.height);
- gui_notify_paint_finished(window_id, nullptr);
- }
-
- if (message.type == GUI_ServerMessage::Type::MouseDown) {
- gui_invalidate_window(window_id, nullptr);
- }
-
- }
- return 0;
-}
-
-void paint(GraphicsBitmap& bitmap, int width, int height)
-{
- byte r = rand() % 255;
- byte g = rand() % 255;
- byte b = rand() % 255;
- Color color(r, g, b);
- Painter painter(bitmap);
- painter.fill_rect({0, 0, width, height}, color);
- painter.draw_text({0, 0, width, height}, "Hello World!", TextAlignment::Center, Color::Black);
-}
diff --git a/WindowServer/WSMessage.h b/WindowServer/WSMessage.h
index 210858ae95..9c1e6ad912 100644
--- a/WindowServer/WSMessage.h
+++ b/WindowServer/WSMessage.h
@@ -9,12 +9,8 @@ class WSMessage {
public:
enum Type {
Invalid = 0,
- WM_ClientWantsToPaint,
- WM_ClientFinishedPaint,
- WM_SetWindowTitle,
- WM_SetWindowRect,
WM_DeferredCompose,
- WM_DestroyWindow,
+ WM_ClientDisconnected,
MouseMove,
MouseDown,
MouseUp,
@@ -33,6 +29,17 @@ public:
APIDestroyMenuRequest,
APIAddMenuItemRequest,
APIAddMenuSeparatorRequest,
+ APICreateWindowRequest,
+ APIDestroyWindowRequest,
+ APISetWindowTitleRequest,
+ APIGetWindowTitleRequest,
+ APISetWindowRectRequest,
+ APIGetWindowRectRequest,
+ APIInvalidateRectRequest,
+ APIDidFinishPaintingNotification,
+ APIGetWindowBackingStoreRequest,
+ APIReleaseWindowBackingStoreRequest,
+ APISetGlobalCursorTrackingRequest,
__End_API_Client_Requests,
};
@@ -50,6 +57,20 @@ private:
Type m_type { Invalid };
};
+class WSClientDisconnectedNotification : public WSMessage {
+public:
+ explicit WSClientDisconnectedNotification(int client_id)
+ : WSMessage(WM_ClientDisconnected)
+ , m_client_id(client_id)
+ {
+ }
+
+ int client_id() const { return m_client_id; }
+
+private:
+ int m_client_id { 0 };
+};
+
class WSAPIClientRequest : public WSMessage {
public:
WSAPIClientRequest(Type type, int client_id)
@@ -64,6 +85,20 @@ private:
int m_client_id { 0 };
};
+class WSAPISetGlobalCursorTrackingRequest : public WSAPIClientRequest {
+public:
+ WSAPISetGlobalCursorTrackingRequest(int client_id, bool value)
+ : WSAPIClientRequest(WSMessage::APISetGlobalCursorTrackingRequest, client_id)
+ , m_value(value)
+ {
+ }
+
+ bool value() const { return m_value; }
+
+private:
+ bool m_value { false };
+};
+
class WSAPICreateMenubarRequest : public WSAPIClientRequest {
public:
WSAPICreateMenubarRequest(int client_id)
@@ -179,58 +214,170 @@ private:
int m_menu_id { 0 };
};
-class WSClientFinishedPaintMessage final : public WSMessage {
+class WSAPISetWindowTitleRequest final : public WSAPIClientRequest {
public:
- explicit WSClientFinishedPaintMessage(const Rect& rect = Rect())
- : WSMessage(WSMessage::WM_ClientFinishedPaint)
+ explicit WSAPISetWindowTitleRequest(int client_id, int window_id, String&& title)
+ : WSAPIClientRequest(WSMessage::APISetWindowTitleRequest, client_id)
+ , m_client_id(client_id)
+ , m_window_id(window_id)
+ , m_title(move(title))
+ {
+ }
+
+ int client_id() const { return m_client_id; }
+ int window_id() const { return m_window_id; }
+ String title() const { return m_title; }
+
+private:
+ int m_client_id { 0 };
+ int m_window_id { 0 };
+ String m_title;
+};
+
+class WSAPIGetWindowTitleRequest final : public WSAPIClientRequest {
+public:
+ explicit WSAPIGetWindowTitleRequest(int client_id, int window_id)
+ : WSAPIClientRequest(WSMessage::APIGetWindowTitleRequest, client_id)
+ , m_client_id(client_id)
+ , m_window_id(window_id)
+ {
+ }
+
+ int client_id() const { return m_client_id; }
+ int window_id() const { return m_window_id; }
+
+private:
+ int m_client_id { 0 };
+ int m_window_id { 0 };
+};
+
+class WSAPISetWindowRectRequest final : public WSAPIClientRequest {
+public:
+ explicit WSAPISetWindowRectRequest(int client_id, int window_id, const Rect& rect)
+ : WSAPIClientRequest(WSMessage::APISetWindowRectRequest, client_id)
+ , m_client_id(client_id)
+ , m_window_id(window_id)
, m_rect(rect)
{
}
- const Rect& rect() const { return m_rect; }
+ int client_id() const { return m_client_id; }
+ int window_id() const { return m_window_id; }
+ Rect rect() const { return m_rect; }
+
private:
+ int m_client_id { 0 };
+ int m_window_id { 0 };
Rect m_rect;
};
-class WSSetWindowTitleMessage final : public WSMessage {
+class WSAPIGetWindowRectRequest final : public WSAPIClientRequest {
public:
- explicit WSSetWindowTitleMessage(String&& title)
- : WSMessage(WSMessage::WM_SetWindowTitle)
- , m_title(move(title))
+ explicit WSAPIGetWindowRectRequest(int client_id, int window_id)
+ : WSAPIClientRequest(WSMessage::APIGetWindowRectRequest, client_id)
+ , m_client_id(client_id)
+ , m_window_id(window_id)
{
}
+ int client_id() const { return m_client_id; }
+ int window_id() const { return m_window_id; }
+
+private:
+ int m_client_id { 0 };
+ int m_window_id { 0 };
+};
+
+class WSAPICreateWindowRequest : public WSAPIClientRequest {
+public:
+ WSAPICreateWindowRequest(int client_id, const Rect& rect, const String& title)
+ : WSAPIClientRequest(WSMessage::APICreateWindowRequest, client_id)
+ , m_rect(rect)
+ , m_title(title)
+ {
+ }
+
+ Rect rect() const { return m_rect; }
String title() const { return m_title; }
private:
+ Rect m_rect;
String m_title;
};
-class WSSetWindowRectMessage final : public WSMessage {
+class WSAPIDestroyWindowRequest : public WSAPIClientRequest {
public:
- explicit WSSetWindowRectMessage(const Rect& rect)
- : WSMessage(WSMessage::WM_SetWindowRect)
+ WSAPIDestroyWindowRequest(int client_id, int window_id)
+ : WSAPIClientRequest(WSMessage::APIDestroyWindowRequest, client_id)
+ , m_window_id(window_id)
+ {
+ }
+
+ int window_id() const { return m_window_id; }
+
+private:
+ int m_window_id { 0 };
+};
+
+class WSAPIInvalidateRectRequest final : public WSAPIClientRequest {
+public:
+ explicit WSAPIInvalidateRectRequest(int client_id, int window_id, const Rect& rect)
+ : WSAPIClientRequest(WSMessage::APIInvalidateRectRequest, client_id)
+ , m_window_id(window_id)
, m_rect(rect)
{
}
+ int window_id() const { return m_window_id; }
Rect rect() const { return m_rect; }
private:
+ int m_window_id { 0 };
Rect m_rect;
};
-class WSClientWantsToPaintMessage final : public WSMessage {
+class WSAPIGetWindowBackingStoreRequest final : public WSAPIClientRequest {
+public:
+ explicit WSAPIGetWindowBackingStoreRequest(int client_id, int window_id)
+ : WSAPIClientRequest(WSMessage::APIGetWindowBackingStoreRequest, client_id)
+ , m_window_id(window_id)
+ {
+ }
+
+ int window_id() const { return m_window_id; }
+
+private:
+ int m_window_id { 0 };
+};
+
+class WSAPIReleaseWindowBackingStoreRequest final : public WSAPIClientRequest {
public:
- explicit WSClientWantsToPaintMessage(const Rect& rect = Rect())
- : WSMessage(WSMessage::WM_ClientWantsToPaint)
+ explicit WSAPIReleaseWindowBackingStoreRequest(int client_id, int backing_store_id)
+ : WSAPIClientRequest(WSMessage::APIReleaseWindowBackingStoreRequest, client_id)
+ , m_backing_store_id(backing_store_id)
+ {
+ }
+
+ int backing_store_id() const { return m_backing_store_id; }
+
+private:
+ int m_backing_store_id { 0 };
+};
+
+class WSAPIDidFinishPaintingNotification final : public WSAPIClientRequest {
+public:
+ explicit WSAPIDidFinishPaintingNotification(int client_id, int window_id, const Rect& rect)
+ : WSAPIClientRequest(WSMessage::APIDidFinishPaintingNotification, client_id)
+ , m_window_id(window_id)
, m_rect(rect)
{
}
- const Rect& rect() const { return m_rect; }
+ int window_id() const { return m_window_id; }
+ Rect rect() const { return m_rect; }
+
private:
- friend class WSWindowManager;
+ int m_window_id { 0 };
Rect m_rect;
};
diff --git a/WindowServer/WSMessageLoop.cpp b/WindowServer/WSMessageLoop.cpp
index ffdb039621..4493e8e382 100644
--- a/WindowServer/WSMessageLoop.cpp
+++ b/WindowServer/WSMessageLoop.cpp
@@ -89,6 +89,7 @@ void WSMessageLoop::post_message(WSMessageReceiver* receiver, OwnPtr<WSMessage>&
dbgprintf("WSMessageLoop::post_message: {%u} << receiver=%p, message=%p (type=%u)\n", m_queued_messages.size(), receiver, message.ptr(), message->type());
#endif
+#if 0
if (message->type() == WSMessage::WM_ClientFinishedPaint) {
auto& invalidation_message = static_cast<WSClientFinishedPaintMessage&>(*message);
for (auto& queued_message : m_queued_messages) {
@@ -118,6 +119,7 @@ void WSMessageLoop::post_message(WSMessageReceiver* receiver, OwnPtr<WSMessage>&
}
}
}
+#endif
m_queued_messages.append({ receiver, move(message) });
@@ -262,8 +264,18 @@ void WSMessageLoop::drain_keyboard()
}
}
+void WSMessageLoop::notify_client_died(int client_id)
+{
+ LOCKER(m_lock);
+ post_message(&WSWindowManager::the(), make<WSClientDisconnectedNotification>(client_id));
+}
+
ssize_t WSMessageLoop::on_receive_from_client(int client_id, const byte* data, size_t size)
{
+ // FIXME: This should not be necessary.. why is this necessary?
+ while (!running())
+ Scheduler::yield();
+
LOCKER(m_lock);
ASSERT(size == sizeof(GUI_ClientMessage));
auto& message = *reinterpret_cast<const GUI_ClientMessage*>(data);
@@ -281,15 +293,53 @@ ssize_t WSMessageLoop::on_receive_from_client(int client_id, const byte* data, s
post_message(&WSWindowManager::the(), make<WSAPIAddMenuToMenubarRequest>(client_id, message.menu.menubar_id, message.menu.menu_id));
break;
case GUI_ClientMessage::Type::CreateMenu:
- ASSERT(message.menu.text_length < sizeof(message.menu.text));
- post_message(&WSWindowManager::the(), make<WSAPICreateMenuRequest>(client_id, String(message.menu.text, message.menu.text_length)));
+ ASSERT(message.text_length < sizeof(message.text));
+ post_message(&WSWindowManager::the(), make<WSAPICreateMenuRequest>(client_id, String(message.text, message.text_length)));
break;
case GUI_ClientMessage::Type::DestroyMenu:
post_message(&WSWindowManager::the(), make<WSAPIDestroyMenuRequest>(client_id, message.menu.menu_id));
break;
case GUI_ClientMessage::Type::AddMenuItem:
- ASSERT(message.menu.text_length < sizeof(message.menu.text));
- post_message(&WSWindowManager::the(), make<WSAPIAddMenuItemRequest>(client_id, message.menu.menu_id, message.menu.identifier, String(message.menu.text, message.menu.text_length)));
+ ASSERT(message.text_length < sizeof(message.text));
+ post_message(&WSWindowManager::the(), make<WSAPIAddMenuItemRequest>(client_id, message.menu.menu_id, message.menu.identifier, String(message.text, message.text_length)));
+ break;
+ case GUI_ClientMessage::Type::CreateWindow:
+ ASSERT(message.text_length < sizeof(message.text));
+ post_message(&WSWindowManager::the(), make<WSAPICreateWindowRequest>(client_id, message.window.rect, String(message.text, message.text_length)));
+ break;
+ case GUI_ClientMessage::Type::DestroyWindow:
+ post_message(&WSWindowManager::the(), make<WSAPIDestroyWindowRequest>(client_id, message.window_id));
+ break;
+ case GUI_ClientMessage::Type::SetWindowTitle:
+ ASSERT(message.text_length < sizeof(message.text));
+ post_message(&WSWindowManager::the(), make<WSAPISetWindowTitleRequest>(client_id, message.window_id, String(message.text, message.text_length)));
+ break;
+ case GUI_ClientMessage::Type::GetWindowTitle:
+ ASSERT(message.text_length < sizeof(message.text));
+ post_message(&WSWindowManager::the(), make<WSAPIGetWindowTitleRequest>(client_id, message.window_id));
+ break;
+ case GUI_ClientMessage::Type::SetWindowRect:
+ post_message(&WSWindowManager::the(), make<WSAPISetWindowRectRequest>(client_id, message.window_id, message.window.rect));
+ break;
+ case GUI_ClientMessage::Type::GetWindowRect:
+ post_message(&WSWindowManager::the(), make<WSAPIGetWindowRectRequest>(client_id, message.window_id));
+ break;
+ case GUI_ClientMessage::Type::InvalidateRect:
+ post_message(&WSWindowManager::the(), make<WSAPIInvalidateRectRequest>(client_id, message.window_id, message.window.rect));
+ break;
+ case GUI_ClientMessage::Type::DidFinishPainting:
+ post_message(&WSWindowManager::the(), make<WSAPIDidFinishPaintingNotification>(client_id, message.window_id, message.window.rect));
+ break;
+ case GUI_ClientMessage::Type::GetWindowBackingStore:
+ post_message(&WSWindowManager::the(), make<WSAPIGetWindowBackingStoreRequest>(client_id, message.window_id));
+ break;
+ case GUI_ClientMessage::Type::ReleaseWindowBackingStore:
+ post_message(&WSWindowManager::the(), make<WSAPIReleaseWindowBackingStoreRequest>(client_id, (int)message.backing.backing_store_id));
+ break;
+ case GUI_ClientMessage::Type::SetGlobalCursorTracking:
+ post_message(&WSWindowManager::the(), make<WSAPISetGlobalCursorTrackingRequest>(client_id, message.value));
+ break;
}
+ server_process().request_wakeup();
return size;
}
diff --git a/WindowServer/WSMessageLoop.h b/WindowServer/WSMessageLoop.h
index 98b7b34838..b79cf853bf 100644
--- a/WindowServer/WSMessageLoop.h
+++ b/WindowServer/WSMessageLoop.h
@@ -34,6 +34,7 @@ public:
ssize_t on_receive_from_client(int client_id, const byte*, size_t);
static Process* process_from_client_id(int client_id);
+ void notify_client_died(int client_id);
private:
void wait_for_message();
diff --git a/WindowServer/WSWindow.cpp b/WindowServer/WSWindow.cpp
index 50714afe1d..07c933c522 100644
--- a/WindowServer/WSWindow.cpp
+++ b/WindowServer/WSWindow.cpp
@@ -83,10 +83,6 @@ void WSWindow::on_message(WSMessage& message)
gui_event.window_id = window_id();
switch (message.type()) {
- case WSMessage::WM_ClientWantsToPaint:
- gui_event.type = GUI_ServerMessage::Type::Paint;
- gui_event.paint.rect = static_cast<WSClientWantsToPaintMessage&>(message).rect();
- break;
case WSMessage::MouseMove:
gui_event.type = GUI_ServerMessage::Type::MouseMove;
gui_event.mouse.position = static_cast<WSMouseEvent&>(message).position();
@@ -121,18 +117,6 @@ void WSWindow::on_message(WSMessage& message)
gui_event.key.ctrl = static_cast<WSKeyEvent&>(message).ctrl();
gui_event.key.shift = static_cast<WSKeyEvent&>(message).shift();
break;
- case WSMessage::WM_ClientFinishedPaint:
- WSWindowManager::the().invalidate(*this, static_cast<WSClientFinishedPaintMessage&>(message).rect());
- return;
- case WSMessage::WM_SetWindowRect:
- set_rect(static_cast<WSSetWindowRectMessage&>(message).rect());
- return;
- case WSMessage::WM_SetWindowTitle:
- set_title(static_cast<WSSetWindowTitleMessage&>(message).title());
- return;
- case WSMessage::WM_DestroyWindow:
- delete this;
- return;
case WSMessage::WindowActivated:
gui_event.type = GUI_ServerMessage::Type::WindowActivated;
break;
diff --git a/WindowServer/WSWindowManager.cpp b/WindowServer/WSWindowManager.cpp
index cb8744ac39..eb2196f7f9 100644
--- a/WindowServer/WSWindowManager.cpp
+++ b/WindowServer/WSWindowManager.cpp
@@ -734,8 +734,26 @@ void WSWindowManager::on_message(WSMessage& message)
return;
}
- if (message.is_client_request())
+ if (message.is_client_request()) {
handle_client_request(static_cast<WSAPIClientRequest&>(message));
+ return;
+ }
+
+ if (message.type() == WSMessage::WM_ClientDisconnected) {
+ int client_id = static_cast<WSClientDisconnectedNotification&>(message).client_id();
+ dbgprintf("[WM] Client disconnected: %d\n", client_id);
+
+ destroy_all_menus(*WSMessageLoop::process_from_client_id(client_id));
+ Vector<int> windows_belonging_to_client;
+ for (auto& it : m_windows_by_id) {
+ if (it.value->process()->gui_client_id() == client_id)
+ windows_belonging_to_client.append(it.value->window_id());
+ }
+ for (int window_id : windows_belonging_to_client) {
+ m_windows_by_id.remove(window_id);
+ }
+ return;
+ }
}
void WSWindowManager::handle_client_request(WSAPIClientRequest& request)
@@ -864,6 +882,132 @@ void WSWindowManager::handle_client_request(WSAPIClientRequest& request)
WSMessageLoop::the().post_message_to_client(request.client_id(), response);
break;
}
+ case WSMessage::APISetWindowTitleRequest: {
+ int window_id = static_cast<WSAPISetWindowTitleRequest&>(request).window_id();
+ auto it = m_windows_by_id.find(window_id);
+ if (it == m_windows_by_id.end()) {
+ ASSERT_NOT_REACHED();
+ }
+ auto& window = *(*it).value;
+ window.set_title(static_cast<WSAPISetWindowTitleRequest&>(request).title());
+ break;
+ }
+ case WSMessage::APIGetWindowTitleRequest: {
+ int window_id = static_cast<WSAPIGetWindowTitleRequest&>(request).window_id();
+ auto it = m_windows_by_id.find(window_id);
+ if (it == m_windows_by_id.end()) {
+ ASSERT_NOT_REACHED();
+ }
+ auto& window = *(*it).value;
+ GUI_ServerMessage response;
+ response.type = GUI_ServerMessage::Type::DidGetWindowTitle;
+ response.window_id = window.window_id();
+ ASSERT(window.title().length() < sizeof(response.text));
+ strcpy(response.text, window.title().characters());
+ response.text_length = window.title().length();
+ WSMessageLoop::the().post_message_to_client(request.client_id(), response);
+ break;
+ }
+ case WSMessage::APISetWindowRectRequest: {
+ int window_id = static_cast<WSAPISetWindowRectRequest&>(request).window_id();
+ auto it = m_windows_by_id.find(window_id);
+ if (it == m_windows_by_id.end()) {
+ ASSERT_NOT_REACHED();
+ }
+ auto& window = *(*it).value;
+ window.set_rect(static_cast<WSAPISetWindowRectRequest&>(request).rect());
+ break;
+ }
+ case WSMessage::APIGetWindowRectRequest: {
+ int window_id = static_cast<WSAPIGetWindowRectRequest&>(request).window_id();
+ auto it = m_windows_by_id.find(window_id);
+ if (it == m_windows_by_id.end()) {
+ ASSERT_NOT_REACHED();
+ }
+ auto& window = *(*it).value;
+ GUI_ServerMessage response;
+ response.type = GUI_ServerMessage::Type::DidGetWindowRect;
+ response.window_id = window.window_id();
+ response.window.rect = window.rect();
+ WSMessageLoop::the().post_message_to_client(request.client_id(), response);
+ break;
+ }
+ case WSMessage::APICreateWindowRequest: {
+ int window_id = m_next_window_id++;
+ auto window = make<WSWindow>(*WSMessageLoop::process_from_client_id(request.client_id()), window_id);
+ window->set_title(static_cast<WSAPICreateWindowRequest&>(request).title());
+ window->set_rect(static_cast<WSAPICreateWindowRequest&>(request).rect());
+ m_windows_by_id.set(window_id, move(window));
+ GUI_ServerMessage response;
+ response.type = GUI_ServerMessage::Type::DidCreateWindow;
+ response.window_id = window_id;
+ WSMessageLoop::the().post_message_to_client(request.client_id(), response);
+ break;
+ }
+ case WSMessage::APIDestroyWindowRequest: {
+ int window_id = static_cast<WSAPIGetWindowRectRequest&>(request).window_id();
+ auto it = m_windows_by_id.find(window_id);
+ if (it == m_windows_by_id.end()) {
+ ASSERT_NOT_REACHED();
+ }
+ auto& window = *(*it).value;
+ invalidate(window);
+ m_windows_by_id.remove(it);
+ break;
+ }
+ case WSMessage::APIInvalidateRectRequest: {
+ int window_id = static_cast<WSAPIInvalidateRectRequest&>(request).window_id();
+ auto it = m_windows_by_id.find(window_id);
+ if (it == m_windows_by_id.end()) {
+ ASSERT_NOT_REACHED();
+ }
+ GUI_ServerMessage response;
+ response.type = GUI_ServerMessage::Type::Paint;
+ response.window_id = window_id;
+ response.paint.rect = static_cast<WSAPIInvalidateRectRequest&>(request).rect();
+ WSMessageLoop::the().post_message_to_client(request.client_id(), response);
+ break;
+ }
+ case WSMessage::APIDidFinishPaintingNotification: {
+ int window_id = static_cast<WSAPIDidFinishPaintingNotification&>(request).window_id();
+ auto it = m_windows_by_id.find(window_id);
+ if (it == m_windows_by_id.end()) {
+ ASSERT_NOT_REACHED();
+ }
+ auto& window = *(*it).value;
+ invalidate(window, static_cast<WSAPIDidFinishPaintingNotification&>(request).rect());
+ break;
+ }
+ case WSMessage::APIGetWindowBackingStoreRequest: {
+ int window_id = static_cast<WSAPIGetWindowBackingStoreRequest&>(request).window_id();
+ auto it = m_windows_by_id.find(window_id);
+ if (it == m_windows_by_id.end()) {
+ ASSERT_NOT_REACHED();
+ }
+ auto& window = *(*it).value;
+ auto* backing_store = window.backing();
+
+ // FIXME: It shouldn't work this way!
+ backing_store->retain();
+
+ GUI_ServerMessage response;
+ response.type = GUI_ServerMessage::Type::DidGetWindowBackingStore;
+ response.window_id = window_id;
+ response.backing.backing_store_id = backing_store;
+ response.backing.bpp = sizeof(RGBA32);
+ response.backing.pitch = backing_store->pitch();
+ response.backing.size = backing_store->size();
+ response.backing.pixels = reinterpret_cast<RGBA32*>(backing_store->client_region()->laddr().as_ptr());
+ WSMessageLoop::the().post_message_to_client(request.client_id(), response);
+ break;
+ }
+ case WSMessage::APIReleaseWindowBackingStoreRequest: {
+ int backing_store_id = static_cast<WSAPIReleaseWindowBackingStoreRequest&>(request).backing_store_id();
+ // FIXME: It shouldn't work this way!
+ auto* backing_store = (GraphicsBitmap*)backing_store_id;
+ backing_store->release();
+ break;
+ }
default:
break;
}
diff --git a/WindowServer/WSWindowManager.h b/WindowServer/WSWindowManager.h
index 9c15055265..707f82dc85 100644
--- a/WindowServer/WSWindowManager.h
+++ b/WindowServer/WSWindowManager.h
@@ -103,6 +103,7 @@ private:
Color m_dragging_window_border_color2;
Color m_dragging_window_title_color;
+ HashMap<int, OwnPtr<WSWindow>> m_windows_by_id;
HashTable<WSWindow*> m_windows;
InlineLinkedList<WSWindow> m_windows_in_order;
@@ -144,8 +145,9 @@ private:
Lockable<bool> m_flash_flush;
bool m_buffers_are_flipped { false };
- int m_next_menubar_id = 100;
- int m_next_menu_id = 900;
+ int m_next_menubar_id { 100 };
+ int m_next_menu_id { 100 };
+ int m_next_window_id { 1982 };
OwnPtr<WSMenu> m_system_menu;
Color m_menu_selection_color;