diff options
author | Hans de Goede <hdegoede@redhat.com> | 2010-10-06 18:54:31 +0200 |
---|---|---|
committer | Hans de Goede <hdegoede@redhat.com> | 2010-10-06 19:17:08 +0200 |
commit | 9b00e93efb197bb215390d9f96204a9f20ffb262 (patch) | |
tree | b0cea52e215e65ea6c8068e10cf6b9d87cc79508 | |
parent | dddb6ad48ada0ddd5327ee8ab70b87540d5150a5 (diff) | |
download | spice-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.cpp | 33 | ||||
-rw-r--r-- | 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 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); |