summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2010-10-06 18:54:31 +0200
committerHans de Goede <hdegoede@redhat.com>2010-10-06 19:17:08 +0200
commit9b00e93efb197bb215390d9f96204a9f20ffb262 (patch)
treeb0cea52e215e65ea6c8068e10cf6b9d87cc79508
parentdddb6ad48ada0ddd5327ee8ab70b87540d5150a5 (diff)
downloadspice-9b00e93efb197bb215390d9f96204a9f20ffb262.tar.gz
spice-9b00e93efb197bb215390d9f96204a9f20ffb262.tar.xz
spice-9b00e93efb197bb215390d9f96204a9f20ffb262.zip
spicec: don't send agent messages directly from ClipboardListener callbacks
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.
-rw-r--r--client/red_client.cpp33
-rw-r--r--client/red_client.h32
2 files changed, 59 insertions, 6 deletions
diff --git a/client/red_client.cpp b/client/red_client.cpp
index 0650e35a..cf2ee354 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 15f06170..dd646820 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);