Browse Source

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.
Robin Burchell 6 years ago
parent
commit
2177594c96

+ 1 - 0
Applications/Piano/main.cpp

@@ -11,6 +11,7 @@ int main(int argc, char** argv)
 {
 {
     GApplication app(argc, argv);
     GApplication app(argc, argv);
     AClientConnection audio_connection;
     AClientConnection audio_connection;
+    audio_connection.handshake();
 
 
     auto* window = new GWindow;
     auto* window = new GWindow;
     window->set_title("Piano");
     window->set_title("Piano");

+ 1 - 1
Applications/Taskbar/TaskbarButton.cpp

@@ -20,5 +20,5 @@ void TaskbarButton::context_menu_event(GContextMenuEvent&)
     request.wm.client_id = m_identifier.client_id();
     request.wm.client_id = m_identifier.client_id();
     request.wm.window_id = m_identifier.window_id();
     request.wm.window_id = m_identifier.window_id();
     request.wm.position = screen_relative_rect().location();
     request.wm.position = screen_relative_rect().location();
-    GEventLoop::post_message_to_server(request);
+    GEventLoop::current().connection().post_message_to_server(request);
 }
 }

+ 1 - 1
Applications/Taskbar/WindowList.cpp

@@ -35,7 +35,7 @@ Window& WindowList::ensure_window(const WindowIdentifier& identifier)
         }
         }
         message.wm.client_id = identifier.client_id();
         message.wm.client_id = identifier.client_id();
         message.wm.window_id = identifier.window_id();
         message.wm.window_id = identifier.window_id();
-        bool success = GEventLoop::post_message_to_server(message);
+        bool success = GEventLoop::current().connection().post_message_to_server(message);
         ASSERT(success);
         ASSERT(success);
     };
     };
     auto& window_ref = *window;
     auto& window_ref = *window;

+ 2 - 2
Libraries/LibAudio/AClientConnection.cpp

@@ -3,11 +3,11 @@
 #include "AClientConnection.h"
 #include "AClientConnection.h"
 
 
 AClientConnection::AClientConnection()
 AClientConnection::AClientConnection()
-    : CIPCClientSideConnection()
+    : CIPCClientSideConnection("/tmp/asportal")
 {
 {
 }
 }
 
 
-void AClientConnection::send_greeting()
+void AClientConnection::handshake()
 {
 {
     ASAPI_ClientMessage request;
     ASAPI_ClientMessage request;
     request.type = ASAPI_ClientMessage::Type::Greeting;
     request.type = ASAPI_ClientMessage::Type::Greeting;

+ 1 - 1
Libraries/LibAudio/AClientConnection.h

@@ -11,6 +11,6 @@ class AClientConnection : public CIPCClientSideConnection<ASAPI_ServerMessage, A
 public:
 public:
     AClientConnection();
     AClientConnection();
 
 
-    void send_greeting() override;
+    void handshake() override;
     void play(const ABuffer& buffer);
     void play(const ABuffer& buffer);
 };
 };

+ 76 - 15
Libraries/LibCore/CIPCClientSideConnection.h

@@ -1,6 +1,7 @@
 #pragma once
 #pragma once
 
 
 #include <LibCore/CEventLoop.h>
 #include <LibCore/CEventLoop.h>
+#include <LibCore/CEvent.h>
 #include <LibCore/CLocalSocket.h>
 #include <LibCore/CLocalSocket.h>
 #include <LibCore/CNotifier.h>
 #include <LibCore/CNotifier.h>
 #include <LibAudio/ASAPI.h>
 #include <LibAudio/ASAPI.h>
@@ -12,26 +13,51 @@
 #include <sys/socket.h>
 #include <sys/socket.h>
 #include <sys/uio.h>
 #include <sys/uio.h>
 
 
+//#define CIPC_DEBUG
+
+class CIPCClientEvent : public CEvent {
+public:
+    enum Type {
+        Invalid = 2000,
+        DoPostprocess,
+    };
+    CIPCClientEvent() {}
+    explicit CIPCClientEvent(Type type)
+        : CEvent(type)
+    {
+    }
+};
+
+class CIPCClientPostprocessEvent : public CIPCClientEvent {
+public:
+    explicit CIPCClientPostprocessEvent(int client_id)
+        : CIPCClientEvent(DoPostprocess)
+        , m_client_id(client_id)
+    {
+    }
+
+    int client_id() const { return m_client_id; }
+
+private:
+    int m_client_id { 0 };
+};
+
 template <typename ServerMessage, typename ClientMessage>
 template <typename ServerMessage, typename ClientMessage>
-class CIPCClientSideConnection {
+class CIPCClientSideConnection : public CObject {
 public:
 public:
-    CIPCClientSideConnection()
+    CIPCClientSideConnection(const StringView& address)
         : m_notifier(CNotifier(m_connection.fd(), CNotifier::Read))
         : m_notifier(CNotifier(m_connection.fd(), CNotifier::Read))
     {
     {
         // We want to rate-limit our clients
         // We want to rate-limit our clients
         m_connection.set_blocking(true);
         m_connection.set_blocking(true);
         m_notifier.on_ready_to_read = [this] {
         m_notifier.on_ready_to_read = [this] {
             drain_messages_from_server();
             drain_messages_from_server();
-        };
-        m_connection.on_connected = [this] {
-            dbg() << "IPC: Connected, sending greeting";
-            send_greeting();
-            dbg() << "IPC: Greeting sent!";
+            CEventLoop::current().post_event(*this, make<CIPCClientPostprocessEvent>(m_connection.fd()));
         };
         };
 
 
         int retries = 1000;
         int retries = 1000;
         while (retries) {
         while (retries) {
-            if (m_connection.connect(CSocketAddress::local("/tmp/asportal"))) {
+            if (m_connection.connect(CSocketAddress::local(address))) {
                 break;
                 break;
             }
             }
 
 
@@ -39,18 +65,39 @@ public:
             sleep(1);
             sleep(1);
             --retries;
             --retries;
         }
         }
+        ASSERT(m_connection.is_connected());
+    }
+
+    virtual void handshake() = 0;
+
+
+    virtual void event(CEvent& event) override
+    {
+        if (event.type() == CIPCClientEvent::DoPostprocess) {
+            postprocess_bundles(m_unprocessed_bundles);
+        } else {
+            CObject::event(event);
+        }
     }
     }
 
 
-    virtual void send_greeting() = 0;
     void set_server_pid(pid_t pid) { m_server_pid = pid; }
     void set_server_pid(pid_t pid) { m_server_pid = pid; }
     pid_t server_pid() const { return m_server_pid; }
     pid_t server_pid() const { return m_server_pid; }
     void set_my_client_id(int id) { m_my_client_id = id; }
     void set_my_client_id(int id) { m_my_client_id = id; }
     int my_client_id() const { return m_my_client_id; }
     int my_client_id() const { return m_my_client_id; }
 
 
-protected:
     template <typename MessageType>
     template <typename MessageType>
     bool wait_for_specific_event(MessageType type, ServerMessage& event)
     bool wait_for_specific_event(MessageType type, ServerMessage& event)
     {
     {
+        // Double check we don't already have the event waiting for us.
+        // Otherwise we might end up blocked for a while for no reason.
+        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);
+                CEventLoop::current().post_event(*this, make<CIPCClientPostprocessEvent>(m_connection.fd()));
+                return true;
+            }
+        }
         for (;;) {
         for (;;) {
             fd_set rfds;
             fd_set rfds;
             FD_ZERO(&rfds);
             FD_ZERO(&rfds);
@@ -68,6 +115,7 @@ protected:
                 if (m_unprocessed_bundles[i].message.type == type) {
                 if (m_unprocessed_bundles[i].message.type == type) {
                     event = move(m_unprocessed_bundles[i].message);
                     event = move(m_unprocessed_bundles[i].message);
                     m_unprocessed_bundles.remove(i);
                     m_unprocessed_bundles.remove(i);
+                    CEventLoop::current().post_event(*this, make<CIPCClientPostprocessEvent>(m_connection.fd()));
                     return true;
                     return true;
                 }
                 }
             }
             }
@@ -76,6 +124,9 @@ protected:
 
 
     bool post_message_to_server(const ClientMessage& message, const ByteBuffer&& extra_data = {})
     bool post_message_to_server(const ClientMessage& message, const ByteBuffer&& extra_data = {})
     {
     {
+#if defined(CIPC_DEBUG)
+        dbg() << "C: -> S " << int(message.type) << " extra " << extra_data.size();
+#endif
         if (!extra_data.is_empty())
         if (!extra_data.is_empty())
             const_cast<ClientMessage&>(message).extra_size = extra_data.size();
             const_cast<ClientMessage&>(message).extra_size = extra_data.size();
 
 
@@ -112,6 +163,18 @@ protected:
         return response;
         return response;
     }
     }
 
 
+protected:
+    struct IncomingASMessageBundle {
+        ServerMessage message;
+        ByteBuffer extra_data;
+    };
+
+    virtual void postprocess_bundles(Vector<IncomingASMessageBundle>& new_bundles)
+    {
+        dbg() << "CIPCClientSideConnection " << " warning: discarding " << new_bundles.size() << " unprocessed bundles; this may not be what you want";
+        new_bundles.clear();
+    }
+
 private:
 private:
     bool drain_messages_from_server()
     bool drain_messages_from_server()
     {
     {
@@ -142,17 +205,15 @@ private:
                 }
                 }
                 ASSERT((size_t)extra_nread == message.extra_size);
                 ASSERT((size_t)extra_nread == message.extra_size);
             }
             }
+#if defined(CIPC_DEBUG)
+            dbg() << "C: <- S " << int(message.type) << " extra " << extra_data.size();
+#endif
             m_unprocessed_bundles.append({ move(message), move(extra_data) });
             m_unprocessed_bundles.append({ move(message), move(extra_data) });
         }
         }
     }
     }
 
 
     CLocalSocket m_connection;
     CLocalSocket m_connection;
     CNotifier m_notifier;
     CNotifier m_notifier;
-
-    struct IncomingASMessageBundle {
-        ServerMessage message;
-        ByteBuffer extra_data;
-    };
     Vector<IncomingASMessageBundle> m_unprocessed_bundles;
     Vector<IncomingASMessageBundle> m_unprocessed_bundles;
     int m_server_pid;
     int m_server_pid;
     int m_my_client_id;
     int m_my_client_id;

+ 14 - 2
Libraries/LibCore/CIPCServerSideClient.h

@@ -13,6 +13,8 @@
 #include <sys/socket.h>
 #include <sys/socket.h>
 #include <stdio.h>
 #include <stdio.h>
 
 
+//#define CIPC_DEBUG
+
 class CIPCServerEvent : public CEvent {
 class CIPCServerEvent : public CEvent {
 public:
 public:
     enum Type {
     enum Type {
@@ -58,16 +60,23 @@ public:
         , m_client_id(client_id)
         , m_client_id(client_id)
     {
     {
         m_notifier.on_ready_to_read = [this] { drain_client(); };
         m_notifier.on_ready_to_read = [this] { drain_client(); };
-        dbg() << "********** S: Created new CIPCServerSideClient " << fd << client_id << " and said hello";
+#if defined(CIPC_DEBUG)
+        dbg() << "S: Created new CIPCServerSideClient " << fd << client_id << " and said hello";
+#endif
     }
     }
 
 
     ~CIPCServerSideClient()
     ~CIPCServerSideClient()
     {
     {
-        dbg() << "********** S: Destroyed CIPCServerSideClient " << m_socket.fd() << client_id();
+#if defined(CIPC_DEBUG)
+        dbg() << "S: Destroyed CIPCServerSideClient " << m_socket.fd() << client_id();
+#endif
     }
     }
 
 
     void post_message(const ServerMessage& message, const ByteBuffer& extra_data = {})
     void post_message(const ServerMessage& message, const ByteBuffer& extra_data = {})
     {
     {
+#if defined(CIPC_DEBUG)
+        dbg() << "S: -> C " << int(message.type) << " extra " << extra_data.size();
+#endif
         if (!extra_data.is_empty())
         if (!extra_data.is_empty())
             const_cast<ServerMessage&>(message).extra_size = extra_data.size();
             const_cast<ServerMessage&>(message).extra_size = extra_data.size();
 
 
@@ -139,6 +148,9 @@ public:
                     return did_misbehave();
                     return did_misbehave();
                 }
                 }
             }
             }
+#if defined(CIPC_DEBUG)
+            dbg() << "S: <- C " << int(message.type) << " extra " << extra_data.size();
+#endif
             if (!handle_message(message, move(extra_data)))
             if (!handle_message(message, move(extra_data)))
                 return;
                 return;
             ++messages_received;
             ++messages_received;

+ 3 - 3
Libraries/LibGUI/GClipboard.cpp

@@ -19,7 +19,7 @@ String GClipboard::data() const
 {
 {
     WSAPI_ClientMessage request;
     WSAPI_ClientMessage request;
     request.type = WSAPI_ClientMessage::Type::GetClipboardContents;
     request.type = WSAPI_ClientMessage::Type::GetClipboardContents;
-    auto response = GEventLoop::current().sync_request(request, WSAPI_ServerMessage::Type::DidGetClipboardContents);
+    auto response = GEventLoop::current().connection().sync_request(request, WSAPI_ServerMessage::Type::DidGetClipboardContents);
     if (response.clipboard.shared_buffer_id < 0)
     if (response.clipboard.shared_buffer_id < 0)
         return {};
         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.clipboard.shared_buffer_id);
@@ -38,7 +38,7 @@ void GClipboard::set_data(const StringView& data)
 {
 {
     WSAPI_ClientMessage request;
     WSAPI_ClientMessage request;
     request.type = WSAPI_ClientMessage::Type::SetClipboardContents;
     request.type = WSAPI_ClientMessage::Type::SetClipboardContents;
-    auto shared_buffer = SharedBuffer::create(GEventLoop::current().server_pid(), data.length() + 1);
+    auto shared_buffer = SharedBuffer::create(GEventLoop::current().connection().server_pid(), data.length() + 1);
     if (!shared_buffer) {
     if (!shared_buffer) {
         dbgprintf("GClipboard::set_data() failed to create a shared buffer\n");
         dbgprintf("GClipboard::set_data() failed to create a shared buffer\n");
         return;
         return;
@@ -50,6 +50,6 @@ void GClipboard::set_data(const StringView& data)
     shared_buffer->seal();
     shared_buffer->seal();
     request.clipboard.shared_buffer_id = shared_buffer->shared_buffer_id();
     request.clipboard.shared_buffer_id = shared_buffer->shared_buffer_id();
     request.clipboard.contents_size = data.length();
     request.clipboard.contents_size = data.length();
-    auto response = GEventLoop::current().sync_request(request, WSAPI_ServerMessage::Type::DidSetClipboardContents);
+    auto response = GEventLoop::current().connection().sync_request(request, WSAPI_ServerMessage::Type::DidSetClipboardContents);
     ASSERT(response.clipboard.shared_buffer_id == shared_buffer->shared_buffer_id());
     ASSERT(response.clipboard.shared_buffer_id == shared_buffer->shared_buffer_id());
 }
 }

+ 3 - 3
Libraries/LibGUI/GDesktop.cpp

@@ -15,7 +15,7 @@ GDesktop::GDesktop()
 {
 {
 }
 }
 
 
-void GDesktop::did_receive_screen_rect(Badge<GEventLoop>, const Rect& rect)
+void GDesktop::did_receive_screen_rect(Badge<GWindowServerConnection>, const Rect& rect)
 {
 {
     if (m_rect == rect)
     if (m_rect == rect)
         return;
         return;
@@ -31,7 +31,7 @@ bool GDesktop::set_wallpaper(const StringView& path)
     ASSERT(path.length() < (int)sizeof(message.text));
     ASSERT(path.length() < (int)sizeof(message.text));
     strncpy(message.text, path.characters_without_null_termination(), path.length());
     strncpy(message.text, path.characters_without_null_termination(), path.length());
     message.text_length = path.length();
     message.text_length = path.length();
-    auto response = GEventLoop::current().sync_request(message, WSAPI_ServerMessage::Type::DidSetWallpaper);
+    auto response = GEventLoop::current().connection().sync_request(message, WSAPI_ServerMessage::Type::DidSetWallpaper);
     return response.value;
     return response.value;
 }
 }
 
 
@@ -39,6 +39,6 @@ String GDesktop::wallpaper() const
 {
 {
     WSAPI_ClientMessage message;
     WSAPI_ClientMessage message;
     message.type = WSAPI_ClientMessage::Type::GetWallpaper;
     message.type = WSAPI_ClientMessage::Type::GetWallpaper;
-    auto response = GEventLoop::current().sync_request(message, WSAPI_ServerMessage::Type::DidGetWallpaper);
+    auto response = GEventLoop::current().connection().sync_request(message, WSAPI_ServerMessage::Type::DidGetWallpaper);
     return String(response.text, response.text_length);
     return String(response.text, response.text_length);
 }
 }

+ 2 - 2
Libraries/LibGUI/GDesktop.h

@@ -5,7 +5,7 @@
 #include <AK/Function.h>
 #include <AK/Function.h>
 #include <SharedGraphics/Rect.h>
 #include <SharedGraphics/Rect.h>
 
 
-class GEventLoop;
+class GWindowServerConnection;
 
 
 class GDesktop {
 class GDesktop {
 public:
 public:
@@ -16,7 +16,7 @@ public:
     bool set_wallpaper(const StringView& path);
     bool set_wallpaper(const StringView& path);
 
 
     Rect rect() const { return m_rect; }
     Rect rect() const { return m_rect; }
-    void did_receive_screen_rect(Badge<GEventLoop>, const Rect&);
+    void did_receive_screen_rect(Badge<GWindowServerConnection>, const Rect&);
 
 
     Function<void(const Rect&)> on_rect_change;
     Function<void(const Rect&)> on_rect_change;
 
 

+ 1 - 1
Libraries/LibGUI/GEvent.h

@@ -242,7 +242,7 @@ public:
     String text() const { return m_text; }
     String text() const { return m_text; }
 
 
 private:
 private:
-    friend class GEventLoop;
+    friend class GWindowServerConnection;
     int m_key { 0 };
     int m_key { 0 };
     u8 m_modifiers { 0 };
     u8 m_modifiers { 0 };
     String m_text;
     String m_text;

+ 38 - 170
Libraries/LibGUI/GEventLoop.cpp

@@ -23,39 +23,8 @@
 //#define GEVENTLOOP_DEBUG
 //#define GEVENTLOOP_DEBUG
 //#define COALESCING_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;
     WSAPI_ClientMessage request;
     request.type = WSAPI_ClientMessage::Type::Greeting;
     request.type = WSAPI_ClientMessage::Type::Greeting;
     request.greeting.client_pid = getpid();
     request.greeting.client_pid = getpid();
@@ -65,25 +34,17 @@ void GEventLoop::connect_to_server()
 
 
 GEventLoop::GEventLoop()
 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()
 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
 #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
 #endif
     Vector<Rect, 32> rects;
     Vector<Rect, 32> rects;
     for (int i = 0; i < min(WSAPI_ServerMessage::max_inline_rect_count, event.rect_count); ++i)
     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)
         for (int i = 0; i < event.rect_count - WSAPI_ServerMessage::max_inline_rect_count; ++i)
             rects.append(extra_rects[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
 #ifdef GEVENTLOOP_DEBUG
     dbgprintf("WID=%x WindowActivation\n", event.window_id);
     dbgprintf("WID=%x WindowActivation\n", event.window_id);
 #endif
 #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
 #ifdef GEVENTLOOP_DEBUG
     dbgprintf("WID=%x KeyEvent character=0x%b\n", event.window_id, event.key.character);
     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
 #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);
     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();
         ASSERT_NOT_REACHED();
         break;
         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) {
     if (event.type == WSAPI_ServerMessage::Type::MenuItemActivated) {
         auto* menu = GMenu::from_menu_id(event.menu.menu_id);
         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();
     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
 #ifdef GEVENTLOOP_DEBUG
     dbgprintf("GEventLoop: handle_wm_event: %d\n", (int)event.type);
     dbgprintf("GEventLoop: handle_wm_event: %d\n", (int)event.type);
 #endif
 #endif
     if (event.type == WSAPI_ServerMessage::WM_WindowStateChanged)
     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_paints = 0;
     int coalesced_resizes = 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;
     HashMap<int, Size> latest_size_for_window_id;
     for (auto& bundle : unprocessed_bundles) {
     for (auto& bundle : unprocessed_bundles) {
@@ -247,7 +209,7 @@ void GEventLoop::process_unprocessed_bundles()
         if (event.type == WSAPI_ServerMessage::Type::Paint) {
         if (event.type == WSAPI_ServerMessage::Type::Paint) {
             ++paint_count;
             ++paint_count;
 #ifdef COALESCING_DEBUG
 #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
 #endif
             latest_paint_size_for_window_id.set(event.window_id, event.paint.window_size);
             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) {
     for (auto& bundle : unprocessed_bundles) {
         auto& event = bundle.message;
         auto& event = bundle.message;
         if (event.type == WSAPI_ServerMessage::Type::Greeting) {
         if (event.type == WSAPI_ServerMessage::Type::Greeting) {
-            handle_greeting(event);
+            // Shouldn't get a second greeting
+            dbg() << "Got second Greeting!?";
+            ASSERT_NOT_REACHED();
             continue;
             continue;
         }
         }
 
 
@@ -271,7 +235,7 @@ void GEventLoop::process_unprocessed_bundles()
         if (event.type == WSAPI_ServerMessage::Error) {
         if (event.type == WSAPI_ServerMessage::Error) {
             dbgprintf("GEventLoop got error message from server\n");
             dbgprintf("GEventLoop got error message from server\n");
             dbgprintf("  - error message: %s\n", String(event.text, event.text_length).characters());
             dbgprintf("  - error message: %s\n", String(event.text, event.text_length).characters());
-            quit(1);
+            CEventLoop::current().quit(1);
             return;
             return;
         }
         }
 
 
@@ -343,105 +307,9 @@ void GEventLoop::process_unprocessed_bundles()
 #endif
 #endif
 }
 }
 
 
-bool GEventLoop::drain_messages_from_server()
-{
-    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)
+void GWindowServerConnection::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);
     GDesktop::the().did_receive_screen_rect({}, message.greeting.screen_rect);
 }
 }

+ 19 - 47
Libraries/LibGUI/GEventLoop.h

@@ -1,6 +1,7 @@
 #pragma once
 #pragma once
 
 
 #include <LibCore/CEventLoop.h>
 #include <LibCore/CEventLoop.h>
+#include <LibCore/CIPCClientSideConnection.h>
 #include <LibGUI/GEvent.h>
 #include <LibGUI/GEvent.h>
 #include <WindowServer/WSAPITypes.h>
 #include <WindowServer/WSAPITypes.h>
 
 
@@ -9,48 +10,16 @@ class CObject;
 class CNotifier;
 class CNotifier;
 class GWindow;
 class GWindow;
 
 
-class GEventLoop final : public CEventLoop {
+class GWindowServerConnection : public CIPCClientSideConnection<WSAPI_ServerMessage, WSAPI_ClientMessage> {
 public:
 public:
-    GEventLoop();
-    virtual ~GEventLoop() override;
-
-    static GEventLoop& current() { return static_cast<GEventLoop&>(CEventLoop::current()); }
-
-    static bool post_message_to_server(const WSAPI_ClientMessage&, const ByteBuffer& extra_data = {});
-    bool wait_for_specific_event(WSAPI_ServerMessage::Type, WSAPI_ServerMessage&);
-    WSAPI_ServerMessage sync_request(const WSAPI_ClientMessage& request, WSAPI_ServerMessage::Type response_type);
+    GWindowServerConnection()
+        : CIPCClientSideConnection("/tmp/wsportal")
+    {}
 
 
-    static pid_t server_pid() { return s_server_pid; }
-    static int my_client_id() { return s_my_client_id; }
-
-    virtual void take_pending_events_from(CEventLoop& other) override
-    {
-        CEventLoop::take_pending_events_from(other);
-        m_unprocessed_bundles.append(move(static_cast<GEventLoop&>(other).m_unprocessed_bundles));
-    }
+    void handshake() override;
 
 
 private:
 private:
-    virtual void add_file_descriptors_for_select(fd_set& fds, int& max_fd_added) override
-    {
-        FD_SET(s_windowserver_fd, &fds);
-        max_fd_added = s_windowserver_fd;
-    }
-
-    virtual void process_file_descriptors_after_select(const fd_set& fds) override
-    {
-        if (FD_ISSET(s_windowserver_fd, &fds))
-            drain_messages_from_server();
-    }
-
-    virtual void do_processing() override
-    {
-        while (!m_unprocessed_bundles.is_empty())
-            process_unprocessed_bundles();
-    }
-
-    void wait_for_event();
-    bool drain_messages_from_server();
-    void process_unprocessed_bundles();
+    void postprocess_bundles(Vector<IncomingASMessageBundle>& m_unprocessed_bundles) override;
     void handle_paint_event(const WSAPI_ServerMessage&, GWindow&, const ByteBuffer& extra_data);
     void handle_paint_event(const WSAPI_ServerMessage&, GWindow&, const ByteBuffer& extra_data);
     void handle_resize_event(const WSAPI_ServerMessage&, GWindow&);
     void handle_resize_event(const WSAPI_ServerMessage&, GWindow&);
     void handle_mouse_event(const WSAPI_ServerMessage&, GWindow&);
     void handle_mouse_event(const WSAPI_ServerMessage&, GWindow&);
@@ -61,15 +30,18 @@ private:
     void handle_window_entered_or_left_event(const WSAPI_ServerMessage&, GWindow&);
     void handle_window_entered_or_left_event(const WSAPI_ServerMessage&, GWindow&);
     void handle_wm_event(const WSAPI_ServerMessage&, GWindow&);
     void handle_wm_event(const WSAPI_ServerMessage&, GWindow&);
     void handle_greeting(WSAPI_ServerMessage&);
     void handle_greeting(WSAPI_ServerMessage&);
-    void connect_to_server();
+};
+
+class GEventLoop final : public CEventLoop {
+public:
+    GEventLoop();
+    virtual ~GEventLoop() override;
+
+    static GEventLoop& current() { return static_cast<GEventLoop&>(CEventLoop::current()); }
 
 
-    struct IncomingWSMessageBundle {
-        WSAPI_ServerMessage message;
-        ByteBuffer extra_data;
-    };
+    GWindowServerConnection& connection() { return m_connection; }
 
 
-    Vector<IncomingWSMessageBundle> m_unprocessed_bundles;
-    static pid_t s_server_pid;
-    static int s_my_client_id;
-    static int s_windowserver_fd;
+private:
+    void process_unprocessed_bundles();
+    GWindowServerConnection m_connection;
 };
 };

+ 6 - 6
Libraries/LibGUI/GMenu.cpp

@@ -52,7 +52,7 @@ void GMenu::popup(const Point& screen_position)
     request.type = WSAPI_ClientMessage::Type::PopupMenu;
     request.type = WSAPI_ClientMessage::Type::PopupMenu;
     request.menu.menu_id = m_menu_id;
     request.menu.menu_id = m_menu_id;
     request.menu.position = screen_position;
     request.menu.position = screen_position;
-    GEventLoop::post_message_to_server(request);
+    GEventLoop::current().connection().post_message_to_server(request);
 }
 }
 
 
 void GMenu::dismiss()
 void GMenu::dismiss()
@@ -62,7 +62,7 @@ void GMenu::dismiss()
     WSAPI_ClientMessage request;
     WSAPI_ClientMessage request;
     request.type = WSAPI_ClientMessage::Type::DismissMenu;
     request.type = WSAPI_ClientMessage::Type::DismissMenu;
     request.menu.menu_id = m_menu_id;
     request.menu.menu_id = m_menu_id;
-    GEventLoop::post_message_to_server(request);
+    GEventLoop::current().connection().post_message_to_server(request);
 }
 }
 
 
 int GMenu::realize_menu()
 int GMenu::realize_menu()
@@ -72,7 +72,7 @@ int GMenu::realize_menu()
     ASSERT(m_name.length() < (ssize_t)sizeof(request.text));
     ASSERT(m_name.length() < (ssize_t)sizeof(request.text));
     strcpy(request.text, m_name.characters());
     strcpy(request.text, m_name.characters());
     request.text_length = m_name.length();
     request.text_length = m_name.length();
-    auto response = GEventLoop::current().sync_request(request, WSAPI_ServerMessage::Type::DidCreateMenu);
+    auto response = GEventLoop::current().connection().sync_request(request, WSAPI_ServerMessage::Type::DidCreateMenu);
     m_menu_id = response.menu.menu_id;
     m_menu_id = response.menu.menu_id;
 
 
 #ifdef GMENU_DEBUG
 #ifdef GMENU_DEBUG
@@ -87,7 +87,7 @@ int GMenu::realize_menu()
             WSAPI_ClientMessage request;
             WSAPI_ClientMessage request;
             request.type = WSAPI_ClientMessage::Type::AddMenuSeparator;
             request.type = WSAPI_ClientMessage::Type::AddMenuSeparator;
             request.menu.menu_id = m_menu_id;
             request.menu.menu_id = m_menu_id;
-            GEventLoop::current().sync_request(request, WSAPI_ServerMessage::Type::DidAddMenuSeparator);
+            GEventLoop::current().connection().sync_request(request, WSAPI_ServerMessage::Type::DidAddMenuSeparator);
             continue;
             continue;
         }
         }
         if (item.type() == GMenuItem::Action) {
         if (item.type() == GMenuItem::Action) {
@@ -113,7 +113,7 @@ int GMenu::realize_menu()
                 request.menu.shortcut_text_length = 0;
                 request.menu.shortcut_text_length = 0;
             }
             }
 
 
-            GEventLoop::current().sync_request(request, WSAPI_ServerMessage::Type::DidAddMenuItem);
+            GEventLoop::current().connection().sync_request(request, WSAPI_ServerMessage::Type::DidAddMenuItem);
         }
         }
     }
     }
     all_menus().set(m_menu_id, this);
     all_menus().set(m_menu_id, this);
@@ -128,7 +128,7 @@ void GMenu::unrealize_menu()
     WSAPI_ClientMessage request;
     WSAPI_ClientMessage request;
     request.type = WSAPI_ClientMessage::Type::DestroyMenu;
     request.type = WSAPI_ClientMessage::Type::DestroyMenu;
     request.menu.menu_id = m_menu_id;
     request.menu.menu_id = m_menu_id;
-    GEventLoop::current().sync_request(request, WSAPI_ServerMessage::Type::DidDestroyMenu);
+    GEventLoop::current().connection().sync_request(request, WSAPI_ServerMessage::Type::DidDestroyMenu);
     m_menu_id = 0;
     m_menu_id = 0;
 }
 }
 
 

+ 4 - 4
Libraries/LibGUI/GMenuBar.cpp

@@ -19,7 +19,7 @@ int GMenuBar::realize_menubar()
 {
 {
     WSAPI_ClientMessage request;
     WSAPI_ClientMessage request;
     request.type = WSAPI_ClientMessage::Type::CreateMenubar;
     request.type = WSAPI_ClientMessage::Type::CreateMenubar;
-    WSAPI_ServerMessage response = GEventLoop::current().sync_request(request, WSAPI_ServerMessage::Type::DidCreateMenubar);
+    WSAPI_ServerMessage response = GEventLoop::current().connection().sync_request(request, WSAPI_ServerMessage::Type::DidCreateMenubar);
     return response.menu.menubar_id;
     return response.menu.menubar_id;
 }
 }
 
 
@@ -30,7 +30,7 @@ void GMenuBar::unrealize_menubar()
     WSAPI_ClientMessage request;
     WSAPI_ClientMessage request;
     request.type = WSAPI_ClientMessage::Type::DestroyMenubar;
     request.type = WSAPI_ClientMessage::Type::DestroyMenubar;
     request.menu.menubar_id = m_menubar_id;
     request.menu.menubar_id = m_menubar_id;
-    GEventLoop::current().sync_request(request, WSAPI_ServerMessage::Type::DidDestroyMenubar);
+    GEventLoop::current().connection().sync_request(request, WSAPI_ServerMessage::Type::DidDestroyMenubar);
     m_menubar_id = -1;
     m_menubar_id = -1;
 }
 }
 
 
@@ -47,12 +47,12 @@ void GMenuBar::notify_added_to_application(Badge<GApplication>)
         request.type = WSAPI_ClientMessage::Type::AddMenuToMenubar;
         request.type = WSAPI_ClientMessage::Type::AddMenuToMenubar;
         request.menu.menubar_id = m_menubar_id;
         request.menu.menubar_id = m_menubar_id;
         request.menu.menu_id = menu_id;
         request.menu.menu_id = menu_id;
-        GEventLoop::current().sync_request(request, WSAPI_ServerMessage::Type::DidAddMenuToMenubar);
+        GEventLoop::current().connection().sync_request(request, WSAPI_ServerMessage::Type::DidAddMenuToMenubar);
     }
     }
     WSAPI_ClientMessage request;
     WSAPI_ClientMessage request;
     request.type = WSAPI_ClientMessage::Type::SetApplicationMenubar;
     request.type = WSAPI_ClientMessage::Type::SetApplicationMenubar;
     request.menu.menubar_id = m_menubar_id;
     request.menu.menubar_id = m_menubar_id;
-    GEventLoop::current().sync_request(request, WSAPI_ServerMessage::Type::DidSetApplicationMenubar);
+    GEventLoop::current().connection().sync_request(request, WSAPI_ServerMessage::Type::DidSetApplicationMenubar);
 }
 }
 
 
 void GMenuBar::notify_removed_from_application(Badge<GApplication>)
 void GMenuBar::notify_removed_from_application(Badge<GApplication>)

+ 1 - 1
Libraries/LibGUI/GMenuItem.cpp

@@ -70,5 +70,5 @@ void GMenuItem::update_window_server()
         request.menu.shortcut_text_length = 0;
         request.menu.shortcut_text_length = 0;
     }
     }
 
 
-    GEventLoop::current().sync_request(request, WSAPI_ServerMessage::Type::DidUpdateMenuItem);
+    GEventLoop::current().connection().sync_request(request, WSAPI_ServerMessage::Type::DidUpdateMenuItem);
 }
 }

+ 18 - 18
Libraries/LibGUI/GWindow.cpp

@@ -59,7 +59,7 @@ void GWindow::move_to_front()
     WSAPI_ClientMessage request;
     WSAPI_ClientMessage request;
     request.type = WSAPI_ClientMessage::Type::MoveWindowToFront;
     request.type = WSAPI_ClientMessage::Type::MoveWindowToFront;
     request.window_id = m_window_id;
     request.window_id = m_window_id;
-    GEventLoop::post_message_to_server(request);
+    GEventLoop::current().connection().post_message_to_server(request);
 }
 }
 
 
 void GWindow::show()
 void GWindow::show()
@@ -84,7 +84,7 @@ void GWindow::show()
     ASSERT(m_title_when_windowless.length() < (ssize_t)sizeof(request.text));
     ASSERT(m_title_when_windowless.length() < (ssize_t)sizeof(request.text));
     strcpy(request.text, m_title_when_windowless.characters());
     strcpy(request.text, m_title_when_windowless.characters());
     request.text_length = m_title_when_windowless.length();
     request.text_length = m_title_when_windowless.length();
-    auto response = GEventLoop::current().sync_request(request, WSAPI_ServerMessage::Type::DidCreateWindow);
+    auto response = GEventLoop::current().connection().sync_request(request, WSAPI_ServerMessage::Type::DidCreateWindow);
     m_window_id = response.window_id;
     m_window_id = response.window_id;
 
 
     windows().set(m_window_id, this);
     windows().set(m_window_id, this);
@@ -99,7 +99,7 @@ void GWindow::hide()
     WSAPI_ClientMessage request;
     WSAPI_ClientMessage request;
     request.type = WSAPI_ClientMessage::Type::DestroyWindow;
     request.type = WSAPI_ClientMessage::Type::DestroyWindow;
     request.window_id = m_window_id;
     request.window_id = m_window_id;
-    GEventLoop::current().sync_request(request, WSAPI_ServerMessage::Type::DidDestroyWindow);
+    GEventLoop::current().connection().sync_request(request, WSAPI_ServerMessage::Type::DidDestroyWindow);
     m_window_id = 0;
     m_window_id = 0;
     m_pending_paint_event_rects.clear();
     m_pending_paint_event_rects.clear();
     m_back_bitmap = nullptr;
     m_back_bitmap = nullptr;
@@ -118,7 +118,7 @@ void GWindow::set_title(const StringView& title)
     ASSERT(m_title_when_windowless.length() < (ssize_t)sizeof(request.text));
     ASSERT(m_title_when_windowless.length() < (ssize_t)sizeof(request.text));
     strcpy(request.text, m_title_when_windowless.characters());
     strcpy(request.text, m_title_when_windowless.characters());
     request.text_length = m_title_when_windowless.length();
     request.text_length = m_title_when_windowless.length();
-    GEventLoop::current().post_message_to_server(request);
+    GEventLoop::current().connection().post_message_to_server(request);
 }
 }
 
 
 String GWindow::title() const
 String GWindow::title() const
@@ -129,7 +129,7 @@ String GWindow::title() const
     WSAPI_ClientMessage request;
     WSAPI_ClientMessage request;
     request.type = WSAPI_ClientMessage::Type::GetWindowTitle;
     request.type = WSAPI_ClientMessage::Type::GetWindowTitle;
     request.window_id = m_window_id;
     request.window_id = m_window_id;
-    auto response = GEventLoop::current().sync_request(request, WSAPI_ServerMessage::Type::DidGetWindowTitle);
+    auto response = GEventLoop::current().connection().sync_request(request, WSAPI_ServerMessage::Type::DidGetWindowTitle);
     return String(response.text, response.text_length);
     return String(response.text, response.text_length);
 }
 }
 
 
@@ -141,7 +141,7 @@ Rect GWindow::rect() const
     WSAPI_ClientMessage request;
     WSAPI_ClientMessage request;
     request.type = WSAPI_ClientMessage::Type::GetWindowRect;
     request.type = WSAPI_ClientMessage::Type::GetWindowRect;
     request.window_id = m_window_id;
     request.window_id = m_window_id;
-    auto response = GEventLoop::current().sync_request(request, WSAPI_ServerMessage::Type::DidGetWindowRect);
+    auto response = GEventLoop::current().connection().sync_request(request, WSAPI_ServerMessage::Type::DidGetWindowRect);
     ASSERT(response.window_id == m_window_id);
     ASSERT(response.window_id == m_window_id);
     return response.window.rect;
     return response.window.rect;
 }
 }
@@ -158,7 +158,7 @@ void GWindow::set_rect(const Rect& a_rect)
     request.type = WSAPI_ClientMessage::Type::SetWindowRect;
     request.type = WSAPI_ClientMessage::Type::SetWindowRect;
     request.window_id = m_window_id;
     request.window_id = m_window_id;
     request.window.rect = a_rect;
     request.window.rect = a_rect;
-    GEventLoop::current().post_message_to_server(request);
+    GEventLoop::current().connection().post_message_to_server(request);
     if (m_back_bitmap && m_back_bitmap->size() != a_rect.size())
     if (m_back_bitmap && m_back_bitmap->size() != a_rect.size())
         m_back_bitmap = nullptr;
         m_back_bitmap = nullptr;
     if (m_front_bitmap && m_front_bitmap->size() != a_rect.size())
     if (m_front_bitmap && m_front_bitmap->size() != a_rect.size())
@@ -180,7 +180,7 @@ void GWindow::set_override_cursor(GStandardCursor cursor)
     request.type = WSAPI_ClientMessage::Type::SetWindowOverrideCursor;
     request.type = WSAPI_ClientMessage::Type::SetWindowOverrideCursor;
     request.window_id = m_window_id;
     request.window_id = m_window_id;
     request.cursor.cursor = (WSAPI_StandardCursor)cursor;
     request.cursor.cursor = (WSAPI_StandardCursor)cursor;
-    GEventLoop::current().post_message_to_server(request);
+    GEventLoop::current().connection().post_message_to_server(request);
 }
 }
 
 
 void GWindow::event(CEvent& event)
 void GWindow::event(CEvent& event)
@@ -260,7 +260,7 @@ void GWindow::event(CEvent& event)
             ByteBuffer extra_data;
             ByteBuffer extra_data;
             if (rects.size() > WSAPI_ClientMessage::max_inline_rect_count)
             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));
                 extra_data = ByteBuffer::wrap(&rects[WSAPI_ClientMessage::max_inline_rect_count], (rects.size() - WSAPI_ClientMessage::max_inline_rect_count) * sizeof(WSAPI_Rect));
-            GEventLoop::current().post_message_to_server(message, extra_data);
+            GEventLoop::current().connection().post_message_to_server(message, move(extra_data));
         }
         }
         return;
         return;
     }
     }
@@ -453,7 +453,7 @@ void GWindow::update(const Rect& a_rect)
             if (rects.size() > WSAPI_ClientMessage::max_inline_rect_count)
             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));
                 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();
             request.rect_count = rects.size();
-            GEventLoop::current().post_message_to_server(request, extra_data);
+            GEventLoop::current().connection().post_message_to_server(request, move(extra_data));
         });
         });
     }
     }
     m_pending_paint_event_rects.append(a_rect);
     m_pending_paint_event_rects.append(a_rect);
@@ -524,7 +524,7 @@ void GWindow::set_has_alpha_channel(bool value)
     message.type = WSAPI_ClientMessage::Type::SetWindowHasAlphaChannel;
     message.type = WSAPI_ClientMessage::Type::SetWindowHasAlphaChannel;
     message.window_id = m_window_id;
     message.window_id = m_window_id;
     message.value = value;
     message.value = value;
-    GEventLoop::current().sync_request(message, WSAPI_ServerMessage::DidSetWindowHasAlphaChannel);
+    GEventLoop::current().connection().sync_request(message, WSAPI_ServerMessage::DidSetWindowHasAlphaChannel);
 
 
     update();
     update();
 }
 }
@@ -545,7 +545,7 @@ void GWindow::set_opacity(float opacity)
     request.window_id = m_window_id;
     request.window_id = m_window_id;
     request.window.opacity = opacity;
     request.window.opacity = opacity;
     m_opacity_when_windowless = opacity;
     m_opacity_when_windowless = opacity;
-    GEventLoop::current().post_message_to_server(request);
+    GEventLoop::current().connection().post_message_to_server(request);
 }
 }
 
 
 void GWindow::set_hovered_widget(GWidget* widget)
 void GWindow::set_hovered_widget(GWidget* widget)
@@ -573,7 +573,7 @@ void GWindow::set_current_backing_bitmap(GraphicsBitmap& bitmap, bool flush_imme
     message.backing.has_alpha_channel = bitmap.has_alpha_channel();
     message.backing.has_alpha_channel = bitmap.has_alpha_channel();
     message.backing.size = bitmap.size();
     message.backing.size = bitmap.size();
     message.backing.flush_immediately = flush_immediately;
     message.backing.flush_immediately = flush_immediately;
-    GEventLoop::current().sync_request(message, WSAPI_ServerMessage::Type::DidSetWindowBackingStore);
+    GEventLoop::current().connection().sync_request(message, WSAPI_ServerMessage::Type::DidSetWindowBackingStore);
 }
 }
 
 
 void GWindow::flip(const Vector<Rect, 32>& dirty_rects)
 void GWindow::flip(const Vector<Rect, 32>& dirty_rects)
@@ -596,11 +596,11 @@ void GWindow::flip(const Vector<Rect, 32>& dirty_rects)
 
 
 NonnullRefPtr<GraphicsBitmap> GWindow::create_backing_bitmap(const Size& size)
 NonnullRefPtr<GraphicsBitmap> GWindow::create_backing_bitmap(const Size& size)
 {
 {
-    ASSERT(GEventLoop::server_pid());
+    ASSERT(GEventLoop::current().connection().server_pid());
     ASSERT(!size.is_empty());
     ASSERT(!size.is_empty());
     size_t pitch = round_up_to_power_of_two(size.width() * sizeof(RGBA32), 16);
     size_t pitch = round_up_to_power_of_two(size.width() * sizeof(RGBA32), 16);
     size_t size_in_bytes = size.height() * pitch;
     size_t size_in_bytes = size.height() * pitch;
-    auto shared_buffer = SharedBuffer::create(GEventLoop::server_pid(), size_in_bytes);
+    auto shared_buffer = SharedBuffer::create(GEventLoop::current().connection().server_pid(), size_in_bytes);
     ASSERT(shared_buffer);
     ASSERT(shared_buffer);
     auto format = m_has_alpha_channel ? GraphicsBitmap::Format::RGBA32 : GraphicsBitmap::Format::RGB32;
     auto format = m_has_alpha_channel ? GraphicsBitmap::Format::RGBA32 : GraphicsBitmap::Format::RGB32;
     return GraphicsBitmap::create_with_shared_buffer(format, *shared_buffer, size);
     return GraphicsBitmap::create_with_shared_buffer(format, *shared_buffer, size);
@@ -629,16 +629,16 @@ void GWindow::set_icon_path(const StringView& path)
     ASSERT(path.length() < (int)sizeof(message.text));
     ASSERT(path.length() < (int)sizeof(message.text));
     strcpy(message.text, String(path).characters());
     strcpy(message.text, String(path).characters());
     message.text_length = path.length();
     message.text_length = path.length();
-    GEventLoop::post_message_to_server(message);
+    GEventLoop::current().connection().post_message_to_server(message);
 }
 }
 
 
 void GWindow::start_wm_resize()
 void GWindow::start_wm_resize()
 {
 {
     WSAPI_ClientMessage message;
     WSAPI_ClientMessage message;
     message.type = WSAPI_ClientMessage::Type::WM_StartWindowResize;
     message.type = WSAPI_ClientMessage::Type::WM_StartWindowResize;
-    message.wm.client_id = GEventLoop::my_client_id();
+    message.wm.client_id = GEventLoop::current().connection().my_client_id();
     message.wm.window_id = m_window_id;
     message.wm.window_id = m_window_id;
-    GEventLoop::post_message_to_server(message);
+    GEventLoop::current().connection().post_message_to_server(message);
 }
 }
 
 
 Vector<GWidget*> GWindow::focusable_widgets() const
 Vector<GWidget*> GWindow::focusable_widgets() const

+ 1 - 0
Userland/aplay.cpp

@@ -14,6 +14,7 @@ int main(int argc, char **argv)
 
 
     printf("Establishing connection\n");
     printf("Establishing connection\n");
     AClientConnection a_conn;
     AClientConnection a_conn;
+    a_conn.handshake();
     printf("Established connection\n");
     printf("Established connection\n");
     AWavLoader loader;
     AWavLoader loader;
     const auto& buffer = loader.load_wav(argv[1]);
     const auto& buffer = loader.load_wav(argv[1]);