WindowServer: Convert entire API to be message-based.

One big step towards userspace WindowServer. :^)
This commit is contained in:
Andreas Kling 2019-02-14 01:21:32 +01:00
parent ef4e9860fd
commit f529b845ec
Notes: sideshowbarker 2024-07-19 15:45:25 +09:00
25 changed files with 508 additions and 625 deletions

View File

@ -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>

View File

@ -76,11 +76,21 @@ 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;
@ -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;
};
};

View File

@ -2133,7 +2133,6 @@ void Process::finalize()
{
ASSERT(current == g_finalizer);
destroy_all_menus();
destroy_all_windows();
m_fds.clear();
m_tty = nullptr;

View File

@ -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 };

View File

@ -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)

View File

@ -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:

View File

@ -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) \

View File

@ -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

View File

@ -41,7 +41,6 @@ LIBC_OBJS = \
ioctl.o \
math.o \
utime.o \
gui.o \
sys/select.o \
poll.o \
locale.o \

View File

@ -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);
}

View File

@ -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

View File

@ -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>

View File

@ -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);
}
}

View File

@ -1,6 +1,5 @@
#include <LibGUI/GMenuBar.h>
#include <LibGUI/GEventLoop.h>
#include <LibC/gui.h>
GMenuBar::GMenuBar()
{

View File

@ -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);
}
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;
}
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);
}

View File

@ -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
}

1
Userland/.gitignore vendored
View File

@ -22,7 +22,6 @@ mkdir
touch
sync
more
guitest
guitest2
sysctl
rm

View File

@ -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

View File

@ -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);
}

View File

@ -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)
, m_rect(rect)
{
}
const Rect& rect() const { return m_rect; }
private:
Rect m_rect;
};
class WSSetWindowTitleMessage final : public WSMessage {
public:
explicit WSSetWindowTitleMessage(String&& title)
: WSMessage(WSMessage::WM_SetWindowTitle)
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 WSSetWindowRectMessage final : public WSMessage {
class WSAPIGetWindowTitleRequest final : public WSAPIClientRequest {
public:
explicit WSSetWindowRectMessage(const Rect& rect)
: WSMessage(WSMessage::WM_SetWindowRect)
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)
{
}
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 WSAPIGetWindowRectRequest final : public WSAPIClientRequest {
public:
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 WSClientWantsToPaintMessage final : public WSMessage {
class WSAPIDestroyWindowRequest : public WSAPIClientRequest {
public:
explicit WSClientWantsToPaintMessage(const Rect& rect = Rect())
: WSMessage(WSMessage::WM_ClientWantsToPaint)
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)
{
}
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;
};
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 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)
{
}
int window_id() const { return m_window_id; }
Rect rect() const { return m_rect; }
private:
int m_window_id { 0 };
Rect m_rect;
};

View File

@ -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;
}

View File

@ -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();

View File

@ -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;

View File

@ -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;
}

View File

@ -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;