1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 10:18:11 +00:00

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
25 changed files with 508 additions and 625 deletions

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