[Spice-devel] [PATCH spice 3/5] spicec: don't send agent messages directly from ClipboardListener callbacks

Hans de Goede hdegoede at redhat.com
Wed Oct 6 11:14:23 PDT 2010


ClipboardListener callbacks can run from another thread then the
main channel loop thread, where agent messages are normally dispatched from.

So they may not send agent messages directly, instead they should post
events to the main channel loop.
---
 client/red_client.cpp |   33 +++++++++++++++++++++++++++------
 client/red_client.h   |   32 ++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+), 6 deletions(-)

diff --git a/client/red_client.cpp b/client/red_client.cpp
index 0650e35..cf2ee35 100644
--- a/client/red_client.cpp
+++ b/client/red_client.cpp
@@ -101,6 +101,21 @@ void ClipboardRequestEvent::response(AbstractProcessLoop& events_loop)
         VD_AGENT_CLIPBOARD_REQUEST, sizeof(request), &request);
 }
 
+void ClipboardNotifyEvent::response(AbstractProcessLoop& events_loop)
+{
+    static_cast<RedClient*>(events_loop.get_owner())->send_agent_clipboard_notify_message(
+        _type, _data, _size);
+}
+
+void ClipboardReleaseEvent::response(AbstractProcessLoop& events_loop)
+{
+    if (Platform::get_clipboard_owner() != Platform::owner_client)
+        return;
+
+    static_cast<RedClient*>(events_loop.get_owner())->send_agent_clipboard_message(
+        VD_AGENT_CLIPBOARD_RELEASE, 0, NULL);
+}
+
 Migrate::Migrate(RedClient& client)
     : _client (client)
     , _running (false)
@@ -861,6 +876,18 @@ void RedClient::on_clipboard_request(uint32_t type)
 
 void RedClient::on_clipboard_notify(uint32_t type, uint8_t* data, int32_t size)
 {
+    AutoRef<ClipboardNotifyEvent> event(new ClipboardNotifyEvent(type, data, size));
+    get_process_loop().push_event(*event);
+}
+
+void RedClient::on_clipboard_release()
+{
+    AutoRef<ClipboardReleaseEvent> event(new ClipboardReleaseEvent());
+    get_process_loop().push_event(*event);
+}
+
+void RedClient::send_agent_clipboard_notify_message(uint32_t type, uint8_t *data, uint32_t size)
+{
     ASSERT(size && data);
     if (!_agent_connected) {
         return;
@@ -892,12 +919,6 @@ void RedClient::on_clipboard_notify(uint32_t type, uint8_t* data, int32_t size)
     }
 }
 
-void RedClient::on_clipboard_release()
-{
-    if (Platform::get_clipboard_owner() == Platform::owner_client)
-        send_agent_clipboard_message(VD_AGENT_CLIPBOARD_RELEASE, 0, NULL);
-}
-
 void RedClient::set_mouse_mode(uint32_t supported_modes, uint32_t current_mode)
 {
     if (current_mode != _mouse_mode) {
diff --git a/client/red_client.h b/client/red_client.h
index 15f0617..dd64682 100644
--- a/client/red_client.h
+++ b/client/red_client.h
@@ -173,6 +173,35 @@ private:
     uint32_t _type;
 };
 
+class ClipboardNotifyEvent : public Event {
+public:
+    ClipboardNotifyEvent(uint32_t type, uint8_t *data, uint32_t size)
+    {
+        _type = type;
+        _data = new uint8_t [size];
+        memcpy(_data, data, size);
+        _size = size;
+    }
+    ~ClipboardNotifyEvent()
+    {
+        delete[] _data;
+    }
+
+    virtual void response(AbstractProcessLoop& events_loop);
+
+private:
+    uint32_t _type;
+    uint8_t *_data;
+    uint32_t _size;
+};
+
+class ClipboardReleaseEvent : public Event {
+public:
+    ClipboardReleaseEvent() {}
+    virtual void response(AbstractProcessLoop& events_loop);
+};
+
+
 class RedClient: public RedChannel,
                  public Platform::ClipboardListener {
 public:
@@ -180,6 +209,8 @@ public:
     friend class Migrate;
     friend class ClipboardGrabEvent;
     friend class ClipboardRequestEvent;
+    friend class ClipboardNotifyEvent;
+    friend class ClipboardReleaseEvent;
 
     RedClient(Application& application);
     ~RedClient();
@@ -265,6 +296,7 @@ private:
                                         uint32_t msg_size);
     void do_send_agent_clipboard();
     void send_agent_clipboard_message(uint32_t message_type, uint32_t size = 0, void* data = NULL);
+    void send_agent_clipboard_notify_message(uint32_t type, uint8_t *data, uint32_t size);
 
     ChannelFactory* find_factory(uint32_t type);
     void create_channel(uint32_t type, uint32_t id);
-- 
1.7.2.2



More information about the Spice-devel mailing list