diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-02-14 01:21:32 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-02-14 01:21:32 +0100 |
commit | f529b845ecd5d2f023ebb56b03afe086df6c21e2 (patch) | |
tree | dfcd320d70c26e879829779b6047789655429cb0 | |
parent | ef4e9860fdb013a5caf76dbd51b071914cb1588a (diff) | |
download | serenity-f529b845ecd5d2f023ebb56b03afe086df6c21e2.zip |
WindowServer: Convert entire API to be message-based.
One big step towards userspace WindowServer. :^)
-rw-r--r-- | Applications/Terminal/main.cpp | 1 | ||||
-rw-r--r-- | Kernel/GUITypes.h | 39 | ||||
-rw-r--r-- | Kernel/Process.cpp | 1 | ||||
-rw-r--r-- | Kernel/Process.h | 18 | ||||
-rw-r--r-- | Kernel/ProcessGUI.cpp | 255 | ||||
-rw-r--r-- | Kernel/Syscall.cpp | 22 | ||||
-rw-r--r-- | Kernel/Syscall.h | 11 | ||||
-rwxr-xr-x | Kernel/sync.sh | 1 | ||||
-rw-r--r-- | LibC/Makefile | 1 | ||||
-rw-r--r-- | LibC/gui.cpp | 70 | ||||
-rw-r--r-- | LibC/gui.h | 21 | ||||
-rw-r--r-- | LibGUI/GEventLoop.cpp | 1 | ||||
-rw-r--r-- | LibGUI/GMenu.cpp | 13 | ||||
-rw-r--r-- | LibGUI/GMenuBar.cpp | 1 | ||||
-rw-r--r-- | LibGUI/GWindow.cpp | 121 | ||||
-rw-r--r-- | SharedGraphics/Painter.cpp | 25 | ||||
-rw-r--r-- | Userland/.gitignore | 1 | ||||
-rw-r--r-- | Userland/Makefile | 5 | ||||
-rw-r--r-- | Userland/guitest.cpp | 94 | ||||
-rw-r--r-- | WindowServer/WSMessage.h | 189 | ||||
-rw-r--r-- | WindowServer/WSMessageLoop.cpp | 58 | ||||
-rw-r--r-- | WindowServer/WSMessageLoop.h | 1 | ||||
-rw-r--r-- | WindowServer/WSWindow.cpp | 16 | ||||
-rw-r--r-- | WindowServer/WSWindowManager.cpp | 146 | ||||
-rw-r--r-- | WindowServer/WSWindowManager.h | 6 |
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; |