mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 05:27:43 +00:00
WindowServer: Port to the new IPC system
This patch introduces code generation for the WindowServer IPC with its clients. The client/server endpoints are defined by the two .ipc files in Servers/WindowServer/: WindowServer.ipc and WindowClient.ipc It now becomes significantly easier to add features and capabilities to WindowServer since you don't have to know nearly as much about all the intricate paths that IPC messages take between LibGUI and WSWindow. The new system also uses significantly less IPC bandwidth since we're now doing packed serialization instead of passing fixed-sized structs of ~600 bytes for each message. Some repaint coalescing optimizations are lost in this conversion and we'll need to look at how to implement those in the new world. The old CoreIPC::Client::Connection and CoreIPC::Server::Connection classes are removed by this patch and replaced by use of ConnectionNG, which will be renamed eventually. Goodbye, old WindowServer IPC. You served us well :^)
This commit is contained in:
parent
30db7813de
commit
272d65e3e2
42 changed files with 843 additions and 2853 deletions
|
@ -5,7 +5,6 @@
|
|||
#include <LibGUI/GPainter.h>
|
||||
#include <LibGUI/GWindow.h>
|
||||
#include <LibGUI/GWindowServerConnection.h>
|
||||
#include <WindowServer/WSAPITypes.h>
|
||||
|
||||
static GApplication* s_the;
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include <LibC/SharedBuffer.h>
|
||||
#include <LibGUI/GClipboard.h>
|
||||
#include <LibGUI/GWindowServerConnection.h>
|
||||
#include <WindowServer/WSAPITypes.h>
|
||||
|
||||
GClipboard& GClipboard::the()
|
||||
{
|
||||
|
@ -17,29 +16,25 @@ GClipboard::GClipboard()
|
|||
|
||||
GClipboard::DataAndType GClipboard::data_and_type() const
|
||||
{
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::GetClipboardContents;
|
||||
auto response = GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidGetClipboardContents);
|
||||
if (response.clipboard.shared_buffer_id < 0)
|
||||
auto response = GWindowServerConnection::the().send_sync<WindowServer::GetClipboardContents>();
|
||||
if (response->shared_buffer_id() < 0)
|
||||
return {};
|
||||
auto shared_buffer = SharedBuffer::create_from_shared_buffer_id(response.clipboard.shared_buffer_id);
|
||||
auto shared_buffer = SharedBuffer::create_from_shared_buffer_id(response->shared_buffer_id());
|
||||
if (!shared_buffer) {
|
||||
dbgprintf("GClipboard::data() failed to attach to the shared buffer\n");
|
||||
return {};
|
||||
}
|
||||
if (response.clipboard.contents_size > shared_buffer->size()) {
|
||||
if (response->content_size() > shared_buffer->size()) {
|
||||
dbgprintf("GClipboard::data() clipping contents size is greater than shared buffer size\n");
|
||||
return {};
|
||||
}
|
||||
auto data = String((const char*)shared_buffer->data(), response.clipboard.contents_size);
|
||||
auto type = String(response.text, response.text_length);
|
||||
auto data = String((const char*)shared_buffer->data(), response->content_size());
|
||||
auto type = response->content_type();
|
||||
return { data, type };
|
||||
}
|
||||
|
||||
void GClipboard::set_data(const StringView& data, const String& type)
|
||||
{
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::SetClipboardContents;
|
||||
auto shared_buffer = SharedBuffer::create_with_size(data.length() + 1);
|
||||
if (!shared_buffer) {
|
||||
dbgprintf("GClipboard::set_data() failed to create a shared buffer\n");
|
||||
|
@ -51,16 +46,8 @@ void GClipboard::set_data(const StringView& data, const String& type)
|
|||
((u8*)shared_buffer->data())[0] = '\0';
|
||||
shared_buffer->seal();
|
||||
shared_buffer->share_with(GWindowServerConnection::the().server_pid());
|
||||
request.clipboard.shared_buffer_id = shared_buffer->shared_buffer_id();
|
||||
request.clipboard.contents_size = data.length();
|
||||
|
||||
ASSERT(type.length() < (ssize_t)sizeof(request.text));
|
||||
if (!type.is_null())
|
||||
strcpy(request.text, type.characters());
|
||||
request.text_length = type.length();
|
||||
|
||||
auto response = GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidSetClipboardContents);
|
||||
ASSERT(response.clipboard.shared_buffer_id == shared_buffer->shared_buffer_id());
|
||||
GWindowServerConnection::the().send_sync<WindowServer::SetClipboardContents>(shared_buffer->shared_buffer_id(), data.length(), type);
|
||||
}
|
||||
|
||||
void GClipboard::did_receive_clipboard_contents_changed(Badge<GWindowServerConnection>, const String& data_type)
|
||||
|
|
|
@ -26,19 +26,11 @@ void GDesktop::did_receive_screen_rect(Badge<GWindowServerConnection>, const Rec
|
|||
|
||||
bool GDesktop::set_wallpaper(const StringView& path)
|
||||
{
|
||||
WSAPI_ClientMessage message;
|
||||
message.type = WSAPI_ClientMessage::Type::SetWallpaper;
|
||||
ASSERT(path.length() < (int)sizeof(message.text));
|
||||
strncpy(message.text, path.characters_without_null_termination(), path.length());
|
||||
message.text_length = path.length();
|
||||
auto response = GWindowServerConnection::the().sync_request(message, WSAPI_ServerMessage::Type::DidSetWallpaper);
|
||||
return response.value;
|
||||
GWindowServerConnection::the().post_message(WindowServer::AsyncSetWallpaper(path));
|
||||
return GWindowServerConnection::the().wait_for_specific_message<WindowClient::AsyncSetWallpaperFinished>()->success();
|
||||
}
|
||||
|
||||
String GDesktop::wallpaper() const
|
||||
{
|
||||
WSAPI_ClientMessage message;
|
||||
message.type = WSAPI_ClientMessage::Type::GetWallpaper;
|
||||
auto response = GWindowServerConnection::the().sync_request(message, WSAPI_ServerMessage::Type::DidGetWallpaper);
|
||||
return String(response.text, response.text_length);
|
||||
return GWindowServerConnection::the().send_sync<WindowServer::GetWallpaper>()->path();
|
||||
}
|
||||
|
|
|
@ -58,32 +58,19 @@ void GMenu::realize_if_needed()
|
|||
void GMenu::popup(const Point& screen_position)
|
||||
{
|
||||
realize_if_needed();
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::PopupMenu;
|
||||
request.menu.menu_id = m_menu_id;
|
||||
request.menu.position = screen_position;
|
||||
GWindowServerConnection::the().post_message_to_server(request);
|
||||
GWindowServerConnection::the().post_message(WindowServer::PopupMenu(m_menu_id, screen_position));
|
||||
}
|
||||
|
||||
void GMenu::dismiss()
|
||||
{
|
||||
if (m_menu_id == -1)
|
||||
return;
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::DismissMenu;
|
||||
request.menu.menu_id = m_menu_id;
|
||||
GWindowServerConnection::the().post_message_to_server(request);
|
||||
GWindowServerConnection::the().post_message(WindowServer::DismissMenu(m_menu_id));
|
||||
}
|
||||
|
||||
int GMenu::realize_menu()
|
||||
{
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::CreateMenu;
|
||||
ASSERT(m_name.length() < (ssize_t)sizeof(request.text));
|
||||
strcpy(request.text, m_name.characters());
|
||||
request.text_length = m_name.length();
|
||||
auto response = GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidCreateMenu);
|
||||
m_menu_id = response.menu.menu_id;
|
||||
m_menu_id = GWindowServerConnection::the().send_sync<WindowServer::CreateMenu>(m_name)->menu_id();
|
||||
|
||||
#ifdef GMENU_DEBUG
|
||||
dbgprintf("GMenu::realize_menu(): New menu ID: %d\n", m_menu_id);
|
||||
|
@ -94,45 +81,18 @@ int GMenu::realize_menu()
|
|||
item.set_menu_id({}, m_menu_id);
|
||||
item.set_identifier({}, i);
|
||||
if (item.type() == GMenuItem::Separator) {
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::AddMenuSeparator;
|
||||
request.menu.menu_id = m_menu_id;
|
||||
request.menu.submenu_id = -1;
|
||||
GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidAddMenuSeparator);
|
||||
GWindowServerConnection::the().send_sync<WindowServer::AddMenuSeparator>(m_menu_id);
|
||||
continue;
|
||||
}
|
||||
if (item.type() == GMenuItem::Submenu) {
|
||||
auto& submenu = *item.submenu();
|
||||
submenu.realize_if_needed();
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::AddMenuItem;
|
||||
request.menu.menu_id = m_menu_id;
|
||||
request.menu.submenu_id = submenu.menu_id();
|
||||
request.menu.identifier = i;
|
||||
// FIXME: It should be possible to disable a submenu.
|
||||
request.menu.enabled = true;
|
||||
request.menu.checkable = false;
|
||||
request.menu.checked = false;
|
||||
|
||||
// no shortcut on submenu, make sure this is cleared out
|
||||
request.menu.shortcut_text_length = 0;
|
||||
strcpy(request.menu.shortcut_text, "\0");
|
||||
|
||||
ASSERT(submenu.name().length() < (ssize_t)sizeof(request.text));
|
||||
strcpy(request.text, submenu.name().characters());
|
||||
request.text_length = submenu.name().length();
|
||||
GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidAddMenuItem);
|
||||
GWindowServerConnection::the().send_sync<WindowServer::AddMenuItem>(m_menu_id, i, submenu.menu_id(), submenu.name(), true, false, false, "", -1);
|
||||
continue;
|
||||
}
|
||||
if (item.type() == GMenuItem::Action) {
|
||||
auto& action = *item.action();
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::AddMenuItem;
|
||||
request.menu.menu_id = m_menu_id;
|
||||
request.menu.submenu_id = -1;
|
||||
request.menu.identifier = i;
|
||||
request.menu.enabled = action.is_enabled();
|
||||
request.menu.checkable = action.is_checkable();
|
||||
int icon_buffer_id = -1;
|
||||
if (action.icon()) {
|
||||
ASSERT(action.icon()->format() == GraphicsBitmap::Format::RGBA32);
|
||||
ASSERT(action.icon()->size() == Size(16, 16));
|
||||
|
@ -145,26 +105,9 @@ int GMenu::realize_menu()
|
|||
shared_buffer->share_with(GWindowServerConnection::the().server_pid());
|
||||
action.set_icon(shared_icon);
|
||||
}
|
||||
request.menu.icon_buffer_id = action.icon()->shared_buffer_id();
|
||||
} else {
|
||||
request.menu.icon_buffer_id = -1;
|
||||
icon_buffer_id = action.icon()->shared_buffer_id();
|
||||
}
|
||||
if (action.is_checkable())
|
||||
request.menu.checked = action.is_checked();
|
||||
ASSERT(action.text().length() < (ssize_t)sizeof(request.text));
|
||||
strcpy(request.text, action.text().characters());
|
||||
request.text_length = action.text().length();
|
||||
|
||||
if (action.shortcut().is_valid()) {
|
||||
auto shortcut_text = action.shortcut().to_string();
|
||||
ASSERT(shortcut_text.length() < (ssize_t)sizeof(request.menu.shortcut_text));
|
||||
strcpy(request.menu.shortcut_text, shortcut_text.characters());
|
||||
request.menu.shortcut_text_length = shortcut_text.length();
|
||||
} else {
|
||||
request.menu.shortcut_text_length = 0;
|
||||
}
|
||||
|
||||
GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidAddMenuItem);
|
||||
GWindowServerConnection::the().send_sync<WindowServer::AddMenuItem>(m_menu_id, i, -1, action.text(), action.is_enabled(), action.is_checkable(), action.is_checkable() ? action.is_checked() : false, action.shortcut().to_string(), icon_buffer_id);
|
||||
}
|
||||
}
|
||||
all_menus().set(m_menu_id, this);
|
||||
|
@ -176,10 +119,7 @@ void GMenu::unrealize_menu()
|
|||
if (m_menu_id == -1)
|
||||
return;
|
||||
all_menus().remove(m_menu_id);
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::DestroyMenu;
|
||||
request.menu.menu_id = m_menu_id;
|
||||
GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidDestroyMenu);
|
||||
GWindowServerConnection::the().send_sync<WindowServer::DestroyMenu>(m_menu_id);
|
||||
m_menu_id = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,20 +17,14 @@ void GMenuBar::add_menu(NonnullOwnPtr<GMenu>&& menu)
|
|||
|
||||
int GMenuBar::realize_menubar()
|
||||
{
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::CreateMenubar;
|
||||
WSAPI_ServerMessage response = GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidCreateMenubar);
|
||||
return response.menu.menubar_id;
|
||||
return GWindowServerConnection::the().send_sync<WindowServer::CreateMenubar>()->menubar_id();
|
||||
}
|
||||
|
||||
void GMenuBar::unrealize_menubar()
|
||||
{
|
||||
if (m_menubar_id == -1)
|
||||
return;
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::DestroyMenubar;
|
||||
request.menu.menubar_id = m_menubar_id;
|
||||
GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidDestroyMenubar);
|
||||
GWindowServerConnection::the().send_sync<WindowServer::DestroyMenubar>(m_menubar_id);
|
||||
m_menubar_id = -1;
|
||||
}
|
||||
|
||||
|
@ -42,16 +36,9 @@ void GMenuBar::notify_added_to_application(Badge<GApplication>)
|
|||
for (auto& menu : m_menus) {
|
||||
int menu_id = menu.realize_menu();
|
||||
ASSERT(menu_id != -1);
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::AddMenuToMenubar;
|
||||
request.menu.menubar_id = m_menubar_id;
|
||||
request.menu.menu_id = menu_id;
|
||||
GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidAddMenuToMenubar);
|
||||
GWindowServerConnection::the().send_sync<WindowServer::AddMenuToMenubar>(m_menubar_id, menu_id);
|
||||
}
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::SetApplicationMenubar;
|
||||
request.menu.menubar_id = m_menubar_id;
|
||||
GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidSetApplicationMenubar);
|
||||
GWindowServerConnection::the().send_sync<WindowServer::SetApplicationMenubar>(m_menubar_id);
|
||||
}
|
||||
|
||||
void GMenuBar::notify_removed_from_application(Badge<GApplication>)
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#include <LibGUI/GMenu.h>
|
||||
#include <LibGUI/GMenuItem.h>
|
||||
#include <LibGUI/GWindowServerConnection.h>
|
||||
#include <WindowServer/WSAPITypes.h>
|
||||
|
||||
GMenuItem::GMenuItem(unsigned menu_id, Type type)
|
||||
: m_type(type)
|
||||
|
@ -57,26 +56,5 @@ void GMenuItem::update_window_server()
|
|||
if (m_menu_id < 0)
|
||||
return;
|
||||
auto& action = *m_action;
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::UpdateMenuItem;
|
||||
request.menu.menu_id = m_menu_id;
|
||||
request.menu.identifier = m_identifier;
|
||||
request.menu.enabled = action.is_enabled();
|
||||
request.menu.checkable = action.is_checkable();
|
||||
if (action.is_checkable())
|
||||
request.menu.checked = action.is_checked();
|
||||
ASSERT(action.text().length() < (ssize_t)sizeof(request.text));
|
||||
strcpy(request.text, action.text().characters());
|
||||
request.text_length = action.text().length();
|
||||
|
||||
if (action.shortcut().is_valid()) {
|
||||
auto shortcut_text = action.shortcut().to_string();
|
||||
ASSERT(shortcut_text.length() < (ssize_t)sizeof(request.menu.shortcut_text));
|
||||
strcpy(request.menu.shortcut_text, shortcut_text.characters());
|
||||
request.menu.shortcut_text_length = shortcut_text.length();
|
||||
} else {
|
||||
request.menu.shortcut_text_length = 0;
|
||||
}
|
||||
|
||||
GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidUpdateMenuItem);
|
||||
GWindowServerConnection::the().send_sync<WindowServer::UpdateMenuItem>(m_menu_id, m_identifier, -1, action.text(), action.is_enabled(), action.is_checkable(), action.is_checkable() ? action.is_checked() : false, action.shortcut().to_string());
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#include <LibGUI/GResizeCorner.h>
|
||||
#include <LibGUI/GWindow.h>
|
||||
#include <LibDraw/GraphicsBitmap.h>
|
||||
#include <WindowServer/WSAPITypes.h>
|
||||
|
||||
GResizeCorner::GResizeCorner(GWidget* parent)
|
||||
: GWidget(parent)
|
||||
|
|
|
@ -50,36 +50,27 @@ void GWindow::move_to_front()
|
|||
if (!m_window_id)
|
||||
return;
|
||||
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::MoveWindowToFront;
|
||||
request.window_id = m_window_id;
|
||||
GWindowServerConnection::the().post_message_to_server(request);
|
||||
GWindowServerConnection::the().send_sync<WindowServer::MoveWindowToFront>(m_window_id);
|
||||
}
|
||||
|
||||
void GWindow::show()
|
||||
{
|
||||
if (m_window_id)
|
||||
return;
|
||||
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::CreateWindow;
|
||||
request.window_id = m_window_id;
|
||||
request.window.rect = m_rect_when_windowless;
|
||||
request.window.has_alpha_channel = m_has_alpha_channel;
|
||||
request.window.modal = m_modal;
|
||||
request.window.resizable = m_resizable;
|
||||
request.window.fullscreen = m_fullscreen;
|
||||
request.window.show_titlebar = m_show_titlebar;
|
||||
request.window.opacity = m_opacity_when_windowless;
|
||||
request.window.background_color = m_background_color.value();
|
||||
request.window.size_increment = m_size_increment;
|
||||
request.window.base_size = m_base_size;
|
||||
request.window.type = (WSAPI_WindowType)m_window_type;
|
||||
ASSERT(m_title_when_windowless.length() < (ssize_t)sizeof(request.text));
|
||||
strcpy(request.text, m_title_when_windowless.characters());
|
||||
request.text_length = m_title_when_windowless.length();
|
||||
auto response = GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidCreateWindow);
|
||||
m_window_id = response.window_id;
|
||||
auto response = GWindowServerConnection::the().send_sync<WindowServer::CreateWindow>(
|
||||
m_rect_when_windowless,
|
||||
m_has_alpha_channel,
|
||||
m_modal,
|
||||
m_resizable,
|
||||
m_fullscreen,
|
||||
m_show_titlebar,
|
||||
m_opacity_when_windowless,
|
||||
m_background_color,
|
||||
m_base_size,
|
||||
m_size_increment,
|
||||
(i32)m_window_type,
|
||||
m_title_when_windowless);
|
||||
m_window_id = response->window_id();
|
||||
|
||||
apply_icon();
|
||||
|
||||
|
@ -93,10 +84,7 @@ void GWindow::hide()
|
|||
if (!m_window_id)
|
||||
return;
|
||||
reified_windows.remove(m_window_id);
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::DestroyWindow;
|
||||
request.window_id = m_window_id;
|
||||
GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidDestroyWindow);
|
||||
GWindowServerConnection::the().send_sync<WindowServer::DestroyWindow>(m_window_id);
|
||||
m_window_id = 0;
|
||||
m_pending_paint_event_rects.clear();
|
||||
m_back_bitmap = nullptr;
|
||||
|
@ -118,39 +106,21 @@ void GWindow::set_title(const StringView& title)
|
|||
m_title_when_windowless = title;
|
||||
if (!m_window_id)
|
||||
return;
|
||||
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::SetWindowTitle;
|
||||
request.window_id = m_window_id;
|
||||
ASSERT(m_title_when_windowless.length() < (ssize_t)sizeof(request.text));
|
||||
strcpy(request.text, m_title_when_windowless.characters());
|
||||
request.text_length = m_title_when_windowless.length();
|
||||
GWindowServerConnection::the().post_message_to_server(request);
|
||||
GWindowServerConnection::the().send_sync<WindowServer::SetWindowTitle>(m_window_id, title);
|
||||
}
|
||||
|
||||
String GWindow::title() const
|
||||
{
|
||||
if (!m_window_id)
|
||||
return m_title_when_windowless;
|
||||
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::GetWindowTitle;
|
||||
request.window_id = m_window_id;
|
||||
auto response = GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidGetWindowTitle);
|
||||
return String(response.text, response.text_length);
|
||||
return GWindowServerConnection::the().send_sync<WindowServer::GetWindowTitle>(m_window_id)->title();
|
||||
}
|
||||
|
||||
Rect GWindow::rect() const
|
||||
{
|
||||
if (!m_window_id)
|
||||
return m_rect_when_windowless;
|
||||
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::GetWindowRect;
|
||||
request.window_id = m_window_id;
|
||||
auto response = GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidGetWindowRect);
|
||||
ASSERT(response.window_id == m_window_id);
|
||||
return response.window.rect;
|
||||
return GWindowServerConnection::the().send_sync<WindowServer::GetWindowRect>(m_window_id)->rect();
|
||||
}
|
||||
|
||||
void GWindow::set_rect(const Rect& a_rect)
|
||||
|
@ -161,11 +131,7 @@ void GWindow::set_rect(const Rect& a_rect)
|
|||
m_main_widget->resize(m_rect_when_windowless.size());
|
||||
return;
|
||||
}
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::SetWindowRect;
|
||||
request.window_id = m_window_id;
|
||||
request.window.rect = a_rect;
|
||||
GWindowServerConnection::the().post_message_to_server(request);
|
||||
GWindowServerConnection::the().send_sync<WindowServer::SetWindowRect>(m_window_id, a_rect);
|
||||
if (m_back_bitmap && m_back_bitmap->size() != a_rect.size())
|
||||
m_back_bitmap = nullptr;
|
||||
if (m_front_bitmap && m_front_bitmap->size() != a_rect.size())
|
||||
|
@ -183,11 +149,7 @@ void GWindow::set_override_cursor(GStandardCursor cursor)
|
|||
{
|
||||
if (!m_window_id)
|
||||
return;
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::SetWindowOverrideCursor;
|
||||
request.window_id = m_window_id;
|
||||
request.cursor.cursor = (WSAPI_StandardCursor)cursor;
|
||||
GWindowServerConnection::the().post_message_to_server(request);
|
||||
GWindowServerConnection::the().send_sync<WindowServer::SetWindowOverrideCursor>(m_window_id, (u32)cursor);
|
||||
}
|
||||
|
||||
void GWindow::event(CEvent& event)
|
||||
|
@ -258,16 +220,10 @@ void GWindow::event(CEvent& event)
|
|||
set_current_backing_bitmap(*m_back_bitmap, true);
|
||||
|
||||
if (m_window_id) {
|
||||
WSAPI_ClientMessage message;
|
||||
message.type = WSAPI_ClientMessage::Type::DidFinishPainting;
|
||||
message.window_id = m_window_id;
|
||||
message.rect_count = rects.size();
|
||||
for (int i = 0; i < min(WSAPI_ClientMessage::max_inline_rect_count, rects.size()); ++i)
|
||||
message.rects[i] = rects[i];
|
||||
ByteBuffer extra_data;
|
||||
if (rects.size() > WSAPI_ClientMessage::max_inline_rect_count)
|
||||
extra_data = ByteBuffer::wrap(&rects[WSAPI_ClientMessage::max_inline_rect_count], (rects.size() - WSAPI_ClientMessage::max_inline_rect_count) * sizeof(WSAPI_Rect));
|
||||
GWindowServerConnection::the().post_message_to_server(message, move(extra_data));
|
||||
Vector<Rect> rects_to_send;
|
||||
for (auto& r : rects)
|
||||
rects_to_send.append(r);
|
||||
GWindowServerConnection::the().post_message(WindowServer::DidFinishPainting(m_window_id, rects_to_send));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -455,16 +411,10 @@ void GWindow::update(const Rect& a_rect)
|
|||
auto rects = move(m_pending_paint_event_rects);
|
||||
if (rects.is_empty())
|
||||
return;
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::InvalidateRect;
|
||||
request.window_id = m_window_id;
|
||||
for (int i = 0; i < min(WSAPI_ClientMessage::max_inline_rect_count, rects.size()); ++i)
|
||||
request.rects[i] = rects[i];
|
||||
ByteBuffer extra_data;
|
||||
if (rects.size() > WSAPI_ClientMessage::max_inline_rect_count)
|
||||
extra_data = ByteBuffer::wrap(&rects[WSAPI_ClientMessage::max_inline_rect_count], (rects.size() - WSAPI_ClientMessage::max_inline_rect_count) * sizeof(WSAPI_Rect));
|
||||
request.rect_count = rects.size();
|
||||
GWindowServerConnection::the().post_message_to_server(request, move(extra_data));
|
||||
Vector<Rect> rects_to_send;
|
||||
for (auto& r : rects)
|
||||
rects_to_send.append(r);
|
||||
GWindowServerConnection::the().post_message(WindowServer::InvalidateRect(m_window_id, rects_to_send));
|
||||
});
|
||||
}
|
||||
m_pending_paint_event_rects.append(a_rect);
|
||||
|
@ -534,12 +484,7 @@ void GWindow::set_has_alpha_channel(bool value)
|
|||
m_back_bitmap = nullptr;
|
||||
m_front_bitmap = nullptr;
|
||||
|
||||
WSAPI_ClientMessage message;
|
||||
message.type = WSAPI_ClientMessage::Type::SetWindowHasAlphaChannel;
|
||||
message.window_id = m_window_id;
|
||||
message.value = value;
|
||||
GWindowServerConnection::the().sync_request(message, WSAPI_ServerMessage::DidSetWindowHasAlphaChannel);
|
||||
|
||||
GWindowServerConnection::the().send_sync<WindowServer::SetWindowHasAlphaChannel>(m_window_id, value);
|
||||
update();
|
||||
}
|
||||
|
||||
|
@ -554,12 +499,7 @@ void GWindow::set_opacity(float opacity)
|
|||
m_opacity_when_windowless = opacity;
|
||||
if (!m_window_id)
|
||||
return;
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::SetWindowOpacity;
|
||||
request.window_id = m_window_id;
|
||||
request.window.opacity = opacity;
|
||||
m_opacity_when_windowless = opacity;
|
||||
GWindowServerConnection::the().post_message_to_server(request);
|
||||
GWindowServerConnection::the().send_sync<WindowServer::SetWindowOpacity>(m_window_id, opacity);
|
||||
}
|
||||
|
||||
void GWindow::set_hovered_widget(GWidget* widget)
|
||||
|
@ -578,16 +518,7 @@ void GWindow::set_hovered_widget(GWidget* widget)
|
|||
|
||||
void GWindow::set_current_backing_bitmap(GraphicsBitmap& bitmap, bool flush_immediately)
|
||||
{
|
||||
WSAPI_ClientMessage message;
|
||||
message.type = WSAPI_ClientMessage::Type::SetWindowBackingStore;
|
||||
message.window_id = m_window_id;
|
||||
message.backing.bpp = 32;
|
||||
message.backing.pitch = bitmap.pitch();
|
||||
message.backing.shared_buffer_id = bitmap.shared_buffer_id();
|
||||
message.backing.has_alpha_channel = bitmap.has_alpha_channel();
|
||||
message.backing.size = bitmap.size();
|
||||
message.backing.flush_immediately = flush_immediately;
|
||||
GWindowServerConnection::the().sync_request(message, WSAPI_ServerMessage::Type::DidSetWindowBackingStore);
|
||||
GWindowServerConnection::the().send_sync<WindowServer::SetWindowBackingStore>(m_window_id, 32, bitmap.pitch(), bitmap.shared_buffer_id(), bitmap.has_alpha_channel(), bitmap.size(), flush_immediately);
|
||||
}
|
||||
|
||||
void GWindow::flip(const Vector<Rect, 32>& dirty_rects)
|
||||
|
@ -668,21 +599,12 @@ void GWindow::apply_icon()
|
|||
if (!has_set_process_icon)
|
||||
set_process_icon(m_icon->shared_buffer_id());
|
||||
|
||||
WSAPI_ClientMessage message;
|
||||
message.type = WSAPI_ClientMessage::Type::SetWindowIconBitmap;
|
||||
message.window_id = m_window_id;
|
||||
message.window.icon_buffer_id = m_icon->shared_buffer_id();
|
||||
message.window.icon_size = m_icon->size();
|
||||
GWindowServerConnection::the().post_message_to_server(message);
|
||||
GWindowServerConnection::the().send_sync<WindowServer::SetWindowIconBitmap>(m_window_id, m_icon->shared_buffer_id(), m_icon->size());
|
||||
}
|
||||
|
||||
void GWindow::start_wm_resize()
|
||||
{
|
||||
WSAPI_ClientMessage message;
|
||||
message.type = WSAPI_ClientMessage::Type::WM_StartWindowResize;
|
||||
message.wm.client_id = GWindowServerConnection::the().my_client_id();
|
||||
message.wm.window_id = m_window_id;
|
||||
GWindowServerConnection::the().post_message_to_server(message);
|
||||
GWindowServerConnection::the().post_message(WindowServer::WM_StartWindowResize(GWindowServerConnection::the().my_client_id(), m_window_id));
|
||||
}
|
||||
|
||||
Vector<GWidget*> GWindow::focusable_widgets() const
|
||||
|
@ -729,12 +651,7 @@ void GWindow::set_fullscreen(bool fullscreen)
|
|||
m_fullscreen = fullscreen;
|
||||
if (!m_window_id)
|
||||
return;
|
||||
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::SetFullscreen;
|
||||
request.window_id = m_window_id;
|
||||
request.value = fullscreen;
|
||||
GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidSetFullscreen);
|
||||
GWindowServerConnection::the().send_sync<WindowServer::SetFullscreen>(m_window_id, fullscreen);
|
||||
}
|
||||
|
||||
void GWindow::schedule_relayout()
|
||||
|
|
|
@ -1,15 +1,3 @@
|
|||
#include <LibC/errno.h>
|
||||
#include <LibC/fcntl.h>
|
||||
#include <LibC/stdio.h>
|
||||
#include <LibC/stdlib.h>
|
||||
#include <LibC/string.h>
|
||||
#include <LibC/sys/select.h>
|
||||
#include <LibC/sys/socket.h>
|
||||
#include <LibC/sys/time.h>
|
||||
#include <LibC/time.h>
|
||||
#include <LibC/unistd.h>
|
||||
#include <LibCore/CNotifier.h>
|
||||
#include <LibCore/CObject.h>
|
||||
#include <LibGUI/GAction.h>
|
||||
#include <LibGUI/GApplication.h>
|
||||
#include <LibGUI/GClipboard.h>
|
||||
|
@ -19,301 +7,258 @@
|
|||
#include <LibGUI/GWidget.h>
|
||||
#include <LibGUI/GWindow.h>
|
||||
#include <LibGUI/GWindowServerConnection.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
//#define GEVENTLOOP_DEBUG
|
||||
//#define COALESCING_DEBUG
|
||||
|
||||
GWindowServerConnection& GWindowServerConnection::the()
|
||||
{
|
||||
static GWindowServerConnection* s_connection = nullptr;
|
||||
if (!s_connection) {
|
||||
s_connection = new GWindowServerConnection();
|
||||
s_connection->handshake();
|
||||
}
|
||||
if (!s_connection)
|
||||
s_connection = new GWindowServerConnection;
|
||||
return *s_connection;
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handshake()
|
||||
{
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::Greeting;
|
||||
request.greeting.client_pid = getpid();
|
||||
auto response = sync_request(request, WSAPI_ServerMessage::Type::Greeting);
|
||||
handle_greeting(response);
|
||||
auto response = send_sync<WindowServer::Greet>(getpid());
|
||||
set_server_pid(response->server_pid());
|
||||
set_my_client_id(response->client_id());
|
||||
GDesktop::the().did_receive_screen_rect({}, response->screen_rect());
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle_paint_event(const WSAPI_ServerMessage& event, GWindow& window, const ByteBuffer& extra_data)
|
||||
void GWindowServerConnection::handle(const WindowClient::Paint& message)
|
||||
{
|
||||
#ifdef GEVENTLOOP_DEBUG
|
||||
dbgprintf("WID=%x Paint\n", event.window_id);
|
||||
dbgprintf("WID=%d Paint\n", message.window_id());
|
||||
#endif
|
||||
Vector<Rect, 32> rects;
|
||||
for (int i = 0; i < min(WSAPI_ServerMessage::max_inline_rect_count, event.rect_count); ++i)
|
||||
rects.append(event.rects[i]);
|
||||
if (event.extra_size) {
|
||||
auto* extra_rects = reinterpret_cast<const WSAPI_Rect*>(extra_data.data());
|
||||
for (int i = 0; i < event.rect_count - WSAPI_ServerMessage::max_inline_rect_count; ++i)
|
||||
rects.append(extra_rects[i]);
|
||||
}
|
||||
CEventLoop::current().post_event(window, make<GMultiPaintEvent>(rects, event.paint.window_size));
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle_resize_event(const WSAPI_ServerMessage& event, GWindow& window)
|
||||
{
|
||||
CEventLoop::current().post_event(window, make<GResizeEvent>(event.window.old_rect.size, event.window.rect.size));
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle_window_activation_event(const WSAPI_ServerMessage& event, GWindow& window)
|
||||
{
|
||||
#ifdef GEVENTLOOP_DEBUG
|
||||
dbgprintf("WID=%x WindowActivation\n", event.window_id);
|
||||
#endif
|
||||
CEventLoop::current().post_event(window, make<GEvent>(event.type == WSAPI_ServerMessage::Type::WindowActivated ? GEvent::WindowBecameActive : GEvent::WindowBecameInactive));
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle_window_close_request_event(const WSAPI_ServerMessage&, GWindow& window)
|
||||
{
|
||||
CEventLoop::current().post_event(window, make<GEvent>(GEvent::WindowCloseRequest));
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle_window_entered_or_left_event(const WSAPI_ServerMessage& message, GWindow& window)
|
||||
{
|
||||
CEventLoop::current().post_event(window, make<GEvent>(message.type == WSAPI_ServerMessage::Type::WindowEntered ? GEvent::WindowEntered : GEvent::WindowLeft));
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle_key_event(const WSAPI_ServerMessage& event, GWindow& window)
|
||||
{
|
||||
#ifdef GEVENTLOOP_DEBUG
|
||||
dbgprintf("WID=%x KeyEvent character=0x%b\n", event.window_id, event.key.character);
|
||||
#endif
|
||||
auto key_event = make<GKeyEvent>(event.type == WSAPI_ServerMessage::Type::KeyDown ? GEvent::KeyDown : GEvent::KeyUp, event.key.key, event.key.modifiers);
|
||||
if (event.key.character != '\0')
|
||||
key_event->m_text = String(&event.key.character, 1);
|
||||
|
||||
if (event.type == WSAPI_ServerMessage::Type::KeyDown) {
|
||||
if (auto* focused_widget = window.focused_widget()) {
|
||||
if (auto* action = focused_widget->action_for_key_event(*key_event)) {
|
||||
if (action->is_enabled()) {
|
||||
action->activate();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (auto* window = GWindow::from_window_id(message.window_id())) {
|
||||
Vector<Rect, 32> rects;
|
||||
for (auto& r : message.rects()) {
|
||||
rects.append(r);
|
||||
}
|
||||
CEventLoop::current().post_event(*window, make<GMultiPaintEvent>(rects, message.window_size()));
|
||||
}
|
||||
}
|
||||
|
||||
if (auto* action = GApplication::the().action_for_key_event(*key_event)) {
|
||||
void GWindowServerConnection::handle(const WindowClient::WindowResized& message)
|
||||
{
|
||||
if (auto* window = GWindow::from_window_id(message.window_id())) {
|
||||
CEventLoop::current().post_event(*window, make<GResizeEvent>(message.old_rect().size(), message.new_rect().size()));
|
||||
}
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle(const WindowClient::WindowActivated& message)
|
||||
{
|
||||
#ifdef GEVENTLOOP_DEBUG
|
||||
dbgprintf("(%d) WID=%d WindowActivated\n", getpid(), message.window_id());
|
||||
#endif
|
||||
if (auto* window = GWindow::from_window_id(message.window_id()))
|
||||
CEventLoop::current().post_event(*window, make<GEvent>(GEvent::WindowBecameActive));
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle(const WindowClient::WindowDeactivated& message)
|
||||
{
|
||||
#ifdef GEVENTLOOP_DEBUG
|
||||
dbgprintf("(%d) WID=%d WindowDeactivated\n", getpid(), message.window_id());
|
||||
#endif
|
||||
if (auto* window = GWindow::from_window_id(message.window_id()))
|
||||
CEventLoop::current().post_event(*window, make<GEvent>(GEvent::WindowBecameInactive));
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle(const WindowClient::WindowCloseRequest& message)
|
||||
{
|
||||
if (auto* window = GWindow::from_window_id(message.window_id()))
|
||||
CEventLoop::current().post_event(*window, make<GEvent>(GEvent::WindowCloseRequest));
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle(const WindowClient::WindowEntered& message)
|
||||
{
|
||||
if (auto* window = GWindow::from_window_id(message.window_id()))
|
||||
CEventLoop::current().post_event(*window, make<GEvent>(GEvent::WindowEntered));
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle(const WindowClient::WindowLeft& message)
|
||||
{
|
||||
if (auto* window = GWindow::from_window_id(message.window_id()))
|
||||
CEventLoop::current().post_event(*window, make<GEvent>(GEvent::WindowLeft));
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle(const WindowClient::KeyDown& message)
|
||||
{
|
||||
#ifdef GEVENTLOOP_DEBUG
|
||||
dbgprintf("WID=%d KeyDown character=0x%02x\n", message.window_id(), message.character());
|
||||
#endif
|
||||
auto* window = GWindow::from_window_id(message.window_id());
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
auto key_event = make<GKeyEvent>(GEvent::KeyDown, message.key(), message.modifiers());
|
||||
if (message.character() != '\0') {
|
||||
char ch = message.character();
|
||||
key_event->m_text = String(&ch, 1);
|
||||
}
|
||||
|
||||
if (auto* focused_widget = window->focused_widget()) {
|
||||
if (auto* action = focused_widget->action_for_key_event(*key_event)) {
|
||||
if (action->is_enabled()) {
|
||||
action->activate();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
CEventLoop::current().post_event(window, move(key_event));
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle_mouse_event(const WSAPI_ServerMessage& event, GWindow& window)
|
||||
{
|
||||
#ifdef GEVENTLOOP_DEBUG
|
||||
dbgprintf("WID=%x MouseEvent %d,%d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y, event.mouse.wheel_delta);
|
||||
#endif
|
||||
GMouseEvent::Type type;
|
||||
switch (event.type) {
|
||||
case WSAPI_ServerMessage::Type::MouseMove:
|
||||
type = GEvent::MouseMove;
|
||||
break;
|
||||
case WSAPI_ServerMessage::Type::MouseUp:
|
||||
type = GEvent::MouseUp;
|
||||
break;
|
||||
case WSAPI_ServerMessage::Type::MouseDown:
|
||||
type = GEvent::MouseDown;
|
||||
break;
|
||||
case WSAPI_ServerMessage::Type::MouseDoubleClick:
|
||||
type = GEvent::MouseDoubleClick;
|
||||
break;
|
||||
case WSAPI_ServerMessage::Type::MouseWheel:
|
||||
type = GEvent::MouseWheel;
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
break;
|
||||
}
|
||||
GMouseButton button { GMouseButton::None };
|
||||
switch (event.mouse.button) {
|
||||
case WSAPI_MouseButton::NoButton:
|
||||
button = GMouseButton::None;
|
||||
break;
|
||||
case WSAPI_MouseButton::Left:
|
||||
button = GMouseButton::Left;
|
||||
break;
|
||||
case WSAPI_MouseButton::Right:
|
||||
button = GMouseButton::Right;
|
||||
break;
|
||||
case WSAPI_MouseButton::Middle:
|
||||
button = GMouseButton::Middle;
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
break;
|
||||
}
|
||||
CEventLoop::current().post_event(window, make<GMouseEvent>(type, event.mouse.position, event.mouse.buttons, button, event.mouse.modifiers, event.mouse.wheel_delta));
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle_menu_event(const WSAPI_ServerMessage& event)
|
||||
{
|
||||
if (event.type == WSAPI_ServerMessage::Type::MenuItemActivated) {
|
||||
auto* menu = GMenu::from_menu_id(event.menu.menu_id);
|
||||
if (!menu) {
|
||||
dbgprintf("GEventLoop received event for invalid window ID %d\n", event.window_id);
|
||||
if (auto* action = GApplication::the().action_for_key_event(*key_event)) {
|
||||
if (action->is_enabled()) {
|
||||
action->activate();
|
||||
return;
|
||||
}
|
||||
if (auto* action = menu->action_at(event.menu.identifier))
|
||||
action->activate();
|
||||
return;
|
||||
}
|
||||
ASSERT_NOT_REACHED();
|
||||
CEventLoop::current().post_event(*window, move(key_event));
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle_wm_event(const WSAPI_ServerMessage& event, GWindow& window)
|
||||
void GWindowServerConnection::handle(const WindowClient::KeyUp& message)
|
||||
{
|
||||
#ifdef GEVENTLOOP_DEBUG
|
||||
dbgprintf("WID=%d KeyUp character=0x%02x\n", message.window_id(), message.character());
|
||||
#endif
|
||||
auto* window = GWindow::from_window_id(message.window_id());
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
auto key_event = make<GKeyEvent>(GEvent::KeyUp, message.key(), message.modifiers());
|
||||
if (message.character() != '\0') {
|
||||
char ch = message.character();
|
||||
key_event->m_text = String(&ch, 1);
|
||||
}
|
||||
|
||||
CEventLoop::current().post_event(*window, move(key_event));
|
||||
}
|
||||
|
||||
GMouseButton to_gmousebutton(u32 button)
|
||||
{
|
||||
switch (button) {
|
||||
case 0:
|
||||
return GMouseButton::None;
|
||||
case 1:
|
||||
return GMouseButton::Left;
|
||||
case 2:
|
||||
return GMouseButton::Right;
|
||||
case 4:
|
||||
return GMouseButton::Middle;
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle(const WindowClient::MouseDown& message)
|
||||
{
|
||||
#ifdef GEVENTLOOP_DEBUG
|
||||
dbgprintf("WID=%d MouseDown %d,%d,%d\n", message.window_id(), message.mouse_position().x(), message.mouse_position().y(), message.wheel_delta();
|
||||
#endif
|
||||
|
||||
if (auto* window = GWindow::from_window_id(message.window_id()))
|
||||
CEventLoop::current().post_event(*window, make<GMouseEvent>(GEvent::MouseDown, message.mouse_position(), message.buttons(), to_gmousebutton(message.button()), message.modifiers(), message.wheel_delta()));
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle(const WindowClient::MouseUp& message)
|
||||
{
|
||||
#ifdef GEVENTLOOP_DEBUG
|
||||
dbgprintf("WID=%d MouseUp %d,%d,%d\n", message.window_id(), message.mouse_position().x(), message.mouse_position().y(), message.wheel_delta();
|
||||
#endif
|
||||
|
||||
if (auto* window = GWindow::from_window_id(message.window_id()))
|
||||
CEventLoop::current().post_event(*window, make<GMouseEvent>(GEvent::MouseUp, message.mouse_position(), message.buttons(), to_gmousebutton(message.button()), message.modifiers(), message.wheel_delta()));
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle(const WindowClient::MouseMove& message)
|
||||
{
|
||||
#ifdef GEVENTLOOP_DEBUG
|
||||
dbgprintf("WID=%d MouseMove %d,%d,%d\n", message.window_id(), message.mouse_position().x(), message.mouse_position().y(), message.wheel_delta();
|
||||
#endif
|
||||
|
||||
if (auto* window = GWindow::from_window_id(message.window_id()))
|
||||
CEventLoop::current().post_event(*window, make<GMouseEvent>(GEvent::MouseMove, message.mouse_position(), message.buttons(), to_gmousebutton(message.button()), message.modifiers(), message.wheel_delta()));
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle(const WindowClient::MouseDoubleClick& message)
|
||||
{
|
||||
#ifdef GEVENTLOOP_DEBUG
|
||||
dbgprintf("WID=%d MouseDoubleClick %d,%d,%d\n", message.window_id(), message.mouse_position().x(), message.mouse_position().y(), message.wheel_delta();
|
||||
#endif
|
||||
|
||||
if (auto* window = GWindow::from_window_id(message.window_id()))
|
||||
CEventLoop::current().post_event(*window, make<GMouseEvent>(GEvent::MouseDoubleClick, message.mouse_position(), message.buttons(), to_gmousebutton(message.button()), message.modifiers(), message.wheel_delta()));
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle(const WindowClient::MouseWheel& message)
|
||||
{
|
||||
#ifdef GEVENTLOOP_DEBUG
|
||||
dbgprintf("WID=%d MouseWheel %d,%d,%d\n", message.window_id(), message.mouse_position().x(), message.mouse_position().y(), message.wheel_delta();
|
||||
#endif
|
||||
|
||||
if (auto* window = GWindow::from_window_id(message.window_id()))
|
||||
CEventLoop::current().post_event(*window, make<GMouseEvent>(GEvent::MouseWheel, message.mouse_position(), message.buttons(), to_gmousebutton(message.button()), message.modifiers(), message.wheel_delta()));
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle(const WindowClient::MenuItemActivated& message)
|
||||
{
|
||||
auto* menu = GMenu::from_menu_id(message.menu_id());
|
||||
if (!menu) {
|
||||
dbgprintf("GEventLoop received event for invalid menu ID %d\n", message.menu_id());
|
||||
return;
|
||||
}
|
||||
if (auto* action = menu->action_at(message.identifier()))
|
||||
action->activate();
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle(const WindowClient::WM_WindowStateChanged& message)
|
||||
{
|
||||
#ifdef GEVENTLOOP_DEBUG
|
||||
dbgprintf("GEventLoop: handle_wm_event: %d\n", (int)event.type);
|
||||
#endif
|
||||
if (event.type == WSAPI_ServerMessage::WM_WindowStateChanged)
|
||||
CEventLoop::current().post_event(window, make<GWMWindowStateChangedEvent>(event.wm.client_id, event.wm.window_id, String(event.text, event.text_length), event.wm.rect, event.wm.is_active, (GWindowType)event.wm.window_type, event.wm.is_minimized));
|
||||
else if (event.type == WSAPI_ServerMessage::WM_WindowRectChanged)
|
||||
CEventLoop::current().post_event(window, make<GWMWindowRectChangedEvent>(event.wm.client_id, event.wm.window_id, event.wm.rect));
|
||||
else if (event.type == WSAPI_ServerMessage::WM_WindowIconBitmapChanged)
|
||||
CEventLoop::current().post_event(window, make<GWMWindowIconBitmapChangedEvent>(event.wm.client_id, event.wm.window_id, event.wm.icon_buffer_id, event.wm.icon_size));
|
||||
else if (event.type == WSAPI_ServerMessage::WM_WindowRemoved)
|
||||
CEventLoop::current().post_event(window, make<GWMWindowRemovedEvent>(event.wm.client_id, event.wm.window_id));
|
||||
else
|
||||
ASSERT_NOT_REACHED();
|
||||
if (auto* window = GWindow::from_window_id(message.window_id()))
|
||||
CEventLoop::current().post_event(*window, make<GWMWindowStateChangedEvent>(message.client_id(), message.window_id(), message.title(), message.rect(), message.is_active(), (GWindowType)message.window_type(), message.is_minimized()));
|
||||
}
|
||||
|
||||
void GWindowServerConnection::postprocess_bundles(Vector<IncomingMessageBundle>& bundles)
|
||||
void GWindowServerConnection::handle(const WindowClient::WM_WindowRectChanged& message)
|
||||
{
|
||||
int coalesced_paints = 0;
|
||||
int coalesced_resizes = 0;
|
||||
auto unprocessed_bundles = move(bundles);
|
||||
|
||||
HashMap<int, Size> latest_size_for_window_id;
|
||||
for (auto& bundle : unprocessed_bundles) {
|
||||
auto& event = bundle.message;
|
||||
if (event.type == WSAPI_ServerMessage::Type::WindowResized) {
|
||||
latest_size_for_window_id.set(event.window_id, event.window.rect.size);
|
||||
}
|
||||
}
|
||||
|
||||
int paint_count = 0;
|
||||
HashMap<int, Size> latest_paint_size_for_window_id;
|
||||
for (auto& bundle : unprocessed_bundles) {
|
||||
auto& event = bundle.message;
|
||||
if (event.type == WSAPI_ServerMessage::Type::Paint) {
|
||||
++paint_count;
|
||||
#ifdef COALESCING_DEBUG
|
||||
dbgprintf(" (window: %s)\n", Size(event.paint.window_size).to_string().characters());
|
||||
#endif
|
||||
latest_paint_size_for_window_id.set(event.window_id, event.paint.window_size);
|
||||
}
|
||||
}
|
||||
#ifdef COALESCING_DEBUG
|
||||
dbgprintf("paint_count: %d\n", paint_count);
|
||||
#endif
|
||||
|
||||
for (auto& bundle : unprocessed_bundles) {
|
||||
auto& event = bundle.message;
|
||||
if (event.type == WSAPI_ServerMessage::Type::Greeting) {
|
||||
// Shouldn't get a second greeting
|
||||
dbg() << "Got second Greeting!?";
|
||||
ASSERT_NOT_REACHED();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (event.type == WSAPI_ServerMessage::Type::ScreenRectChanged) {
|
||||
GDesktop::the().did_receive_screen_rect({}, event.screen.rect);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (event.type == WSAPI_ServerMessage::Type::ClipboardContentsChanged) {
|
||||
GClipboard::the().did_receive_clipboard_contents_changed({}, String(event.text, event.text_length));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (event.type == WSAPI_ServerMessage::Error) {
|
||||
dbgprintf("GEventLoop got error message from server\n");
|
||||
dbgprintf(" - error message: %s\n", String(event.text, event.text_length).characters());
|
||||
CEventLoop::current().quit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.type) {
|
||||
case WSAPI_ServerMessage::MenuItemActivated:
|
||||
handle_menu_event(event);
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
auto* window = GWindow::from_window_id(event.window_id);
|
||||
if (!window) {
|
||||
dbgprintf("GEventLoop received event for invalid window ID %d\n", event.window_id);
|
||||
continue;
|
||||
}
|
||||
switch (event.type) {
|
||||
case WSAPI_ServerMessage::Type::Paint:
|
||||
if (Size(event.paint.window_size) != latest_paint_size_for_window_id.get(event.window_id).value_or({})) {
|
||||
++coalesced_paints;
|
||||
break;
|
||||
}
|
||||
handle_paint_event(event, *window, bundle.extra_data);
|
||||
break;
|
||||
case WSAPI_ServerMessage::Type::MouseDown:
|
||||
case WSAPI_ServerMessage::Type::MouseDoubleClick:
|
||||
case WSAPI_ServerMessage::Type::MouseUp:
|
||||
case WSAPI_ServerMessage::Type::MouseMove:
|
||||
case WSAPI_ServerMessage::Type::MouseWheel:
|
||||
handle_mouse_event(event, *window);
|
||||
break;
|
||||
case WSAPI_ServerMessage::Type::WindowActivated:
|
||||
case WSAPI_ServerMessage::Type::WindowDeactivated:
|
||||
handle_window_activation_event(event, *window);
|
||||
break;
|
||||
case WSAPI_ServerMessage::Type::WindowCloseRequest:
|
||||
handle_window_close_request_event(event, *window);
|
||||
break;
|
||||
case WSAPI_ServerMessage::Type::KeyDown:
|
||||
case WSAPI_ServerMessage::Type::KeyUp:
|
||||
handle_key_event(event, *window);
|
||||
break;
|
||||
case WSAPI_ServerMessage::Type::WindowEntered:
|
||||
case WSAPI_ServerMessage::Type::WindowLeft:
|
||||
handle_window_entered_or_left_event(event, *window);
|
||||
break;
|
||||
case WSAPI_ServerMessage::Type::WindowResized:
|
||||
if (Size(event.window.rect.size) != latest_size_for_window_id.get(event.window_id).value_or({})) {
|
||||
++coalesced_resizes;
|
||||
break;
|
||||
}
|
||||
handle_resize_event(event, *window);
|
||||
break;
|
||||
default:
|
||||
if (event.type > WSAPI_ServerMessage::__Begin_WM_Events__ && event.type < WSAPI_ServerMessage::Type::__End_WM_Events__)
|
||||
handle_wm_event(event, *window);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef COALESCING_DEBUG
|
||||
if (coalesced_paints)
|
||||
dbgprintf("Coalesced %d paints\n", coalesced_paints);
|
||||
if (coalesced_resizes)
|
||||
dbgprintf("Coalesced %d resizes\n", coalesced_resizes);
|
||||
#ifdef GEVENTLOOP_DEBUG
|
||||
dbgprintf("GEventLoop: handle_wm_event: %d\n", (int)event.type);
|
||||
#endif
|
||||
if (auto* window = GWindow::from_window_id(message.window_id()))
|
||||
CEventLoop::current().post_event(*window, make<GWMWindowRectChangedEvent>(message.client_id(), message.window_id(), message.rect()));
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle_greeting(WSAPI_ServerMessage& message)
|
||||
void GWindowServerConnection::handle(const WindowClient::WM_WindowIconBitmapChanged& message)
|
||||
{
|
||||
set_server_pid(message.greeting.server_pid);
|
||||
set_my_client_id(message.greeting.your_client_id);
|
||||
GDesktop::the().did_receive_screen_rect({}, message.greeting.screen_rect);
|
||||
#ifdef GEVENTLOOP_DEBUG
|
||||
dbgprintf("GEventLoop: handle_wm_event: %d\n", (int)event.type);
|
||||
#endif
|
||||
if (auto* window = GWindow::from_window_id(message.window_id()))
|
||||
CEventLoop::current().post_event(*window, make<GWMWindowIconBitmapChangedEvent>(message.client_id(), message.window_id(), message.icon_buffer_id(), message.icon_size()));
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle(const WindowClient::WM_WindowRemoved& message)
|
||||
{
|
||||
#ifdef GEVENTLOOP_DEBUG
|
||||
dbgprintf("GEventLoop: handle_wm_event: %d\n", (int)event.type);
|
||||
#endif
|
||||
if (auto* window = GWindow::from_window_id(message.window_id()))
|
||||
CEventLoop::current().post_event(*window, make<GWMWindowRemovedEvent>(message.client_id(), message.window_id()));
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle(const WindowClient::ScreenRectChanged& message)
|
||||
{
|
||||
GDesktop::the().did_receive_screen_rect({}, message.rect());
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle(const WindowClient::ClipboardContentsChanged& message)
|
||||
{
|
||||
GClipboard::the().did_receive_clipboard_contents_changed({}, message.content_type());
|
||||
}
|
||||
|
||||
void GWindowServerConnection::handle(const WindowClient::AsyncSetWallpaperFinished&)
|
||||
{
|
||||
// This is handled manually by GDesktop::set_wallpaper().
|
||||
}
|
||||
|
|
|
@ -1,35 +1,44 @@
|
|||
#pragma once
|
||||
|
||||
#include <LibCore/CEventLoop.h>
|
||||
#include <LibCore/CoreIPCClient.h>
|
||||
#include <LibGUI/GEvent.h>
|
||||
#include <WindowServer/WSAPITypes.h>
|
||||
#include <WindowServer/WindowClientEndpoint.h>
|
||||
#include <WindowServer/WindowServerEndpoint.h>
|
||||
|
||||
class GAction;
|
||||
class CObject;
|
||||
class CNotifier;
|
||||
class GWindow;
|
||||
|
||||
class GWindowServerConnection : public IPC::Client::Connection<WSAPI_ServerMessage, WSAPI_ClientMessage> {
|
||||
class GWindowServerConnection
|
||||
: public IPC::Client::ConnectionNG<WindowClientEndpoint, WindowServerEndpoint>
|
||||
, public WindowClientEndpoint {
|
||||
C_OBJECT(GWindowServerConnection)
|
||||
public:
|
||||
GWindowServerConnection()
|
||||
: Connection("/tmp/portal/window")
|
||||
{}
|
||||
: ConnectionNG(*this, "/tmp/portal/window")
|
||||
{
|
||||
handshake();
|
||||
}
|
||||
|
||||
void handshake() override;
|
||||
virtual void handshake() override;
|
||||
static GWindowServerConnection& the();
|
||||
|
||||
private:
|
||||
void postprocess_bundles(Vector<IncomingMessageBundle>& m_unprocessed_bundles) override;
|
||||
void handle_paint_event(const WSAPI_ServerMessage&, GWindow&, const ByteBuffer& extra_data);
|
||||
void handle_resize_event(const WSAPI_ServerMessage&, GWindow&);
|
||||
void handle_mouse_event(const WSAPI_ServerMessage&, GWindow&);
|
||||
void handle_key_event(const WSAPI_ServerMessage&, GWindow&);
|
||||
void handle_window_activation_event(const WSAPI_ServerMessage&, GWindow&);
|
||||
void handle_window_close_request_event(const WSAPI_ServerMessage&, GWindow&);
|
||||
void handle_menu_event(const WSAPI_ServerMessage&);
|
||||
void handle_window_entered_or_left_event(const WSAPI_ServerMessage&, GWindow&);
|
||||
void handle_wm_event(const WSAPI_ServerMessage&, GWindow&);
|
||||
void handle_greeting(WSAPI_ServerMessage&);
|
||||
virtual void handle(const WindowClient::Paint&) override;
|
||||
virtual void handle(const WindowClient::MouseMove&) override;
|
||||
virtual void handle(const WindowClient::MouseDown&) override;
|
||||
virtual void handle(const WindowClient::MouseDoubleClick&) override;
|
||||
virtual void handle(const WindowClient::MouseUp&) override;
|
||||
virtual void handle(const WindowClient::MouseWheel&) override;
|
||||
virtual void handle(const WindowClient::WindowEntered&) override;
|
||||
virtual void handle(const WindowClient::WindowLeft&) override;
|
||||
virtual void handle(const WindowClient::KeyDown&) override;
|
||||
virtual void handle(const WindowClient::KeyUp&) override;
|
||||
virtual void handle(const WindowClient::WindowActivated&) override;
|
||||
virtual void handle(const WindowClient::WindowDeactivated&) override;
|
||||
virtual void handle(const WindowClient::WindowCloseRequest&) override;
|
||||
virtual void handle(const WindowClient::WindowResized&) override;
|
||||
virtual void handle(const WindowClient::MenuItemActivated&) override;
|
||||
virtual void handle(const WindowClient::ScreenRectChanged&) override;
|
||||
virtual void handle(const WindowClient::ClipboardContentsChanged&) override;
|
||||
virtual void handle(const WindowClient::WM_WindowRemoved&) override;
|
||||
virtual void handle(const WindowClient::WM_WindowStateChanged&) override;
|
||||
virtual void handle(const WindowClient::WM_WindowIconBitmapChanged&) override;
|
||||
virtual void handle(const WindowClient::WM_WindowRectChanged&) override;
|
||||
virtual void handle(const WindowClient::AsyncSetWallpaperFinished&) override;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue