mirror of
https://github.com/RGBCube/serenity
synced 2025-05-22 19:35:06 +00:00
Port LibGUI to use CIPCClientSideConnection
As a consequence, move to use an explicit handshake() method rather than calling virtuals from the constructor. This seemed to not bother AClientConnection, but LibGUI crashes (rightfully) because of it.
This commit is contained in:
parent
41bece0682
commit
2177594c96
18 changed files with 195 additions and 280 deletions
|
@ -23,39 +23,8 @@
|
|||
//#define GEVENTLOOP_DEBUG
|
||||
//#define COALESCING_DEBUG
|
||||
|
||||
int GEventLoop::s_windowserver_fd = -1;
|
||||
int GEventLoop::s_my_client_id = -1;
|
||||
pid_t GEventLoop::s_server_pid = -1;
|
||||
|
||||
void GEventLoop::connect_to_server()
|
||||
void GWindowServerConnection::handshake()
|
||||
{
|
||||
ASSERT(s_windowserver_fd == -1);
|
||||
s_windowserver_fd = socket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
if (s_windowserver_fd < 0) {
|
||||
perror("socket");
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
sockaddr_un address;
|
||||
address.sun_family = AF_LOCAL;
|
||||
strcpy(address.sun_path, "/tmp/wsportal");
|
||||
|
||||
int retries = 1000;
|
||||
int rc = 0;
|
||||
while (retries) {
|
||||
rc = connect(s_windowserver_fd, (const sockaddr*)&address, sizeof(address));
|
||||
if (rc == 0)
|
||||
break;
|
||||
#ifdef GEVENTLOOP_DEBUG
|
||||
dbgprintf("connect failed: %d, %s\n", errno, strerror(errno));
|
||||
#endif
|
||||
sleep(1);
|
||||
--retries;
|
||||
}
|
||||
if (rc < 0) {
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::Greeting;
|
||||
request.greeting.client_pid = getpid();
|
||||
|
@ -65,25 +34,17 @@ void GEventLoop::connect_to_server()
|
|||
|
||||
GEventLoop::GEventLoop()
|
||||
{
|
||||
static bool connected = false;
|
||||
if (!connected) {
|
||||
connect_to_server();
|
||||
connected = true;
|
||||
}
|
||||
|
||||
#ifdef GEVENTLOOP_DEBUG
|
||||
dbgprintf("(%u) GEventLoop constructed :)\n", getpid());
|
||||
#endif
|
||||
m_connection.handshake();
|
||||
}
|
||||
|
||||
GEventLoop::~GEventLoop()
|
||||
{
|
||||
}
|
||||
|
||||
void GEventLoop::handle_paint_event(const WSAPI_ServerMessage& event, GWindow& window, const ByteBuffer& extra_data)
|
||||
void GWindowServerConnection::handle_paint_event(const WSAPI_ServerMessage& event, GWindow& window, const ByteBuffer& extra_data)
|
||||
{
|
||||
#ifdef GEVENTLOOP_DEBUG
|
||||
dbgprintf("WID=%x Paint [%d,%d %dx%d]\n", event.window_id, event.paint.rect.location.x, event.paint.rect.location.y, event.paint.rect.size.width, event.paint.rect.size.height);
|
||||
dbgprintf("WID=%x Paint\n", event.window_id);
|
||||
#endif
|
||||
Vector<Rect, 32> rects;
|
||||
for (int i = 0; i < min(WSAPI_ServerMessage::max_inline_rect_count, event.rect_count); ++i)
|
||||
|
@ -93,33 +54,33 @@ void GEventLoop::handle_paint_event(const WSAPI_ServerMessage& event, GWindow& w
|
|||
for (int i = 0; i < event.rect_count - WSAPI_ServerMessage::max_inline_rect_count; ++i)
|
||||
rects.append(extra_rects[i]);
|
||||
}
|
||||
post_event(window, make<GMultiPaintEvent>(rects, event.paint.window_size));
|
||||
CEventLoop::current().post_event(window, make<GMultiPaintEvent>(rects, event.paint.window_size));
|
||||
}
|
||||
|
||||
void GEventLoop::handle_resize_event(const WSAPI_ServerMessage& event, GWindow& window)
|
||||
void GWindowServerConnection::handle_resize_event(const WSAPI_ServerMessage& event, GWindow& window)
|
||||
{
|
||||
post_event(window, make<GResizeEvent>(event.window.old_rect.size, event.window.rect.size));
|
||||
CEventLoop::current().post_event(window, make<GResizeEvent>(event.window.old_rect.size, event.window.rect.size));
|
||||
}
|
||||
|
||||
void GEventLoop::handle_window_activation_event(const WSAPI_ServerMessage& event, GWindow& window)
|
||||
void GWindowServerConnection::handle_window_activation_event(const WSAPI_ServerMessage& event, GWindow& window)
|
||||
{
|
||||
#ifdef GEVENTLOOP_DEBUG
|
||||
dbgprintf("WID=%x WindowActivation\n", event.window_id);
|
||||
#endif
|
||||
post_event(window, make<GEvent>(event.type == WSAPI_ServerMessage::Type::WindowActivated ? GEvent::WindowBecameActive : GEvent::WindowBecameInactive));
|
||||
CEventLoop::current().post_event(window, make<GEvent>(event.type == WSAPI_ServerMessage::Type::WindowActivated ? GEvent::WindowBecameActive : GEvent::WindowBecameInactive));
|
||||
}
|
||||
|
||||
void GEventLoop::handle_window_close_request_event(const WSAPI_ServerMessage&, GWindow& window)
|
||||
void GWindowServerConnection::handle_window_close_request_event(const WSAPI_ServerMessage&, GWindow& window)
|
||||
{
|
||||
post_event(window, make<GEvent>(GEvent::WindowCloseRequest));
|
||||
CEventLoop::current().post_event(window, make<GEvent>(GEvent::WindowCloseRequest));
|
||||
}
|
||||
|
||||
void GEventLoop::handle_window_entered_or_left_event(const WSAPI_ServerMessage& message, GWindow& window)
|
||||
void GWindowServerConnection::handle_window_entered_or_left_event(const WSAPI_ServerMessage& message, GWindow& window)
|
||||
{
|
||||
post_event(window, make<GEvent>(message.type == WSAPI_ServerMessage::Type::WindowEntered ? GEvent::WindowEntered : GEvent::WindowLeft));
|
||||
CEventLoop::current().post_event(window, make<GEvent>(message.type == WSAPI_ServerMessage::Type::WindowEntered ? GEvent::WindowEntered : GEvent::WindowLeft));
|
||||
}
|
||||
|
||||
void GEventLoop::handle_key_event(const WSAPI_ServerMessage& event, GWindow& window)
|
||||
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);
|
||||
|
@ -145,10 +106,10 @@ void GEventLoop::handle_key_event(const WSAPI_ServerMessage& event, GWindow& win
|
|||
}
|
||||
}
|
||||
}
|
||||
post_event(window, move(key_event));
|
||||
CEventLoop::current().post_event(window, move(key_event));
|
||||
}
|
||||
|
||||
void GEventLoop::handle_mouse_event(const WSAPI_ServerMessage& event, GWindow& window)
|
||||
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);
|
||||
|
@ -192,10 +153,10 @@ void GEventLoop::handle_mouse_event(const WSAPI_ServerMessage& event, GWindow& w
|
|||
ASSERT_NOT_REACHED();
|
||||
break;
|
||||
}
|
||||
post_event(window, make<GMouseEvent>(type, event.mouse.position, event.mouse.buttons, button, event.mouse.modifiers, event.mouse.wheel_delta));
|
||||
CEventLoop::current().post_event(window, make<GMouseEvent>(type, event.mouse.position, event.mouse.buttons, button, event.mouse.modifiers, event.mouse.wheel_delta));
|
||||
}
|
||||
|
||||
void GEventLoop::handle_menu_event(const WSAPI_ServerMessage& event)
|
||||
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);
|
||||
|
@ -210,27 +171,28 @@ void GEventLoop::handle_menu_event(const WSAPI_ServerMessage& event)
|
|||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
void GEventLoop::handle_wm_event(const WSAPI_ServerMessage& event, GWindow& window)
|
||||
void GWindowServerConnection::handle_wm_event(const WSAPI_ServerMessage& event, GWindow& window)
|
||||
{
|
||||
#ifdef GEVENTLOOP_DEBUG
|
||||
dbgprintf("GEventLoop: handle_wm_event: %d\n", (int)event.type);
|
||||
#endif
|
||||
if (event.type == WSAPI_ServerMessage::WM_WindowStateChanged)
|
||||
return 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));
|
||||
if (event.type == WSAPI_ServerMessage::WM_WindowRectChanged)
|
||||
return post_event(window, make<GWMWindowRectChangedEvent>(event.wm.client_id, event.wm.window_id, event.wm.rect));
|
||||
if (event.type == WSAPI_ServerMessage::WM_WindowIconChanged)
|
||||
return post_event(window, make<GWMWindowIconChangedEvent>(event.wm.client_id, event.wm.window_id, String(event.text, event.text_length)));
|
||||
if (event.type == WSAPI_ServerMessage::WM_WindowRemoved)
|
||||
return post_event(window, make<GWMWindowRemovedEvent>(event.wm.client_id, event.wm.window_id));
|
||||
ASSERT_NOT_REACHED();
|
||||
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_WindowIconChanged)
|
||||
CEventLoop::current().post_event(window, make<GWMWindowIconChangedEvent>(event.wm.client_id, event.wm.window_id, String(event.text, event.text_length)));
|
||||
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();
|
||||
}
|
||||
|
||||
void GEventLoop::process_unprocessed_bundles()
|
||||
void GWindowServerConnection::postprocess_bundles(Vector<CIPCClientSideConnection::IncomingASMessageBundle>& bundles)
|
||||
{
|
||||
int coalesced_paints = 0;
|
||||
int coalesced_resizes = 0;
|
||||
auto unprocessed_bundles = move(m_unprocessed_bundles);
|
||||
auto unprocessed_bundles = move(bundles);
|
||||
|
||||
HashMap<int, Size> latest_size_for_window_id;
|
||||
for (auto& bundle : unprocessed_bundles) {
|
||||
|
@ -247,7 +209,7 @@ void GEventLoop::process_unprocessed_bundles()
|
|||
if (event.type == WSAPI_ServerMessage::Type::Paint) {
|
||||
++paint_count;
|
||||
#ifdef COALESCING_DEBUG
|
||||
dbgprintf(" %s (window: %s)\n", Rect(event.paint.rect).to_string().characters(), Size(event.paint.window_size).to_string().characters());
|
||||
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);
|
||||
}
|
||||
|
@ -259,7 +221,9 @@ void GEventLoop::process_unprocessed_bundles()
|
|||
for (auto& bundle : unprocessed_bundles) {
|
||||
auto& event = bundle.message;
|
||||
if (event.type == WSAPI_ServerMessage::Type::Greeting) {
|
||||
handle_greeting(event);
|
||||
// Shouldn't get a second greeting
|
||||
dbg() << "Got second Greeting!?";
|
||||
ASSERT_NOT_REACHED();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -271,7 +235,7 @@ void GEventLoop::process_unprocessed_bundles()
|
|||
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());
|
||||
quit(1);
|
||||
CEventLoop::current().quit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -343,105 +307,9 @@ void GEventLoop::process_unprocessed_bundles()
|
|||
#endif
|
||||
}
|
||||
|
||||
bool GEventLoop::drain_messages_from_server()
|
||||
void GWindowServerConnection::handle_greeting(WSAPI_ServerMessage& message)
|
||||
{
|
||||
for (;;) {
|
||||
WSAPI_ServerMessage message;
|
||||
ssize_t nread = recv(s_windowserver_fd, &message, sizeof(WSAPI_ServerMessage), MSG_DONTWAIT);
|
||||
if (nread < 0) {
|
||||
if (errno == EAGAIN) {
|
||||
return true;
|
||||
}
|
||||
perror("read");
|
||||
quit(1);
|
||||
return false;
|
||||
}
|
||||
if (nread == 0) {
|
||||
fprintf(stderr, "EOF on WindowServer fd\n");
|
||||
quit(1);
|
||||
exit(-1);
|
||||
return false;
|
||||
}
|
||||
ASSERT(nread == sizeof(message));
|
||||
ByteBuffer extra_data;
|
||||
if (message.extra_size) {
|
||||
extra_data = ByteBuffer::create_uninitialized(message.extra_size);
|
||||
int extra_nread = read(s_windowserver_fd, extra_data.data(), extra_data.size());
|
||||
if (extra_nread < 0) {
|
||||
perror("read");
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
ASSERT((size_t)extra_nread == message.extra_size);
|
||||
}
|
||||
m_unprocessed_bundles.append({ move(message), move(extra_data) });
|
||||
}
|
||||
}
|
||||
|
||||
bool GEventLoop::post_message_to_server(const WSAPI_ClientMessage& message, const ByteBuffer& extra_data)
|
||||
{
|
||||
if (!extra_data.is_empty())
|
||||
const_cast<WSAPI_ClientMessage&>(message).extra_size = extra_data.size();
|
||||
|
||||
struct iovec iov[2];
|
||||
int iov_count = 1;
|
||||
iov[0].iov_base = const_cast<WSAPI_ClientMessage*>(&message);
|
||||
iov[0].iov_len = sizeof(message);
|
||||
|
||||
if (!extra_data.is_empty()) {
|
||||
iov[1].iov_base = const_cast<u8*>(extra_data.data());
|
||||
iov[1].iov_len = extra_data.size();
|
||||
++iov_count;
|
||||
}
|
||||
|
||||
int nwritten = writev(s_windowserver_fd, iov, iov_count);
|
||||
if (nwritten < 0) {
|
||||
perror("writev");
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
ASSERT((size_t)nwritten == sizeof(message) + extra_data.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GEventLoop::wait_for_specific_event(WSAPI_ServerMessage::Type type, WSAPI_ServerMessage& event)
|
||||
{
|
||||
for (;;) {
|
||||
fd_set rfds;
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(s_windowserver_fd, &rfds);
|
||||
int rc = select(s_windowserver_fd + 1, &rfds, nullptr, nullptr, nullptr);
|
||||
if (rc < 0) {
|
||||
perror("select");
|
||||
}
|
||||
ASSERT(rc > 0);
|
||||
ASSERT(FD_ISSET(s_windowserver_fd, &rfds));
|
||||
bool success = drain_messages_from_server();
|
||||
if (!success)
|
||||
return false;
|
||||
for (ssize_t i = 0; i < m_unprocessed_bundles.size(); ++i) {
|
||||
if (m_unprocessed_bundles[i].message.type == type) {
|
||||
event = move(m_unprocessed_bundles[i].message);
|
||||
m_unprocessed_bundles.remove(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WSAPI_ServerMessage GEventLoop::sync_request(const WSAPI_ClientMessage& request, WSAPI_ServerMessage::Type response_type)
|
||||
{
|
||||
bool success = post_message_to_server(request);
|
||||
ASSERT(success);
|
||||
|
||||
WSAPI_ServerMessage response;
|
||||
success = wait_for_specific_event(response_type, response);
|
||||
ASSERT(success);
|
||||
return response;
|
||||
}
|
||||
|
||||
void GEventLoop::handle_greeting(WSAPI_ServerMessage& message)
|
||||
{
|
||||
s_server_pid = message.greeting.server_pid;
|
||||
s_my_client_id = message.greeting.your_client_id;
|
||||
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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue