1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 11:37:34 +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

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