diff options
author | Hans de Goede <hdegoede@redhat.com> | 2010-10-02 16:29:36 +0200 |
---|---|---|
committer | Hans de Goede <hdegoede@redhat.com> | 2010-10-02 16:29:36 +0200 |
commit | 8a160078d0852ff5a2f8ec438cec1b18858e3c5d (patch) | |
tree | 05b7cdfb2523242e013e561c8a83a630e4762eaf /client/red_client.cpp | |
parent | deb849dfd54deafa894692f4e44208c2de9f33aa (diff) | |
download | spice-8a160078d0852ff5a2f8ec438cec1b18858e3c5d.tar.gz spice-8a160078d0852ff5a2f8ec438cec1b18858e3c5d.tar.xz spice-8a160078d0852ff5a2f8ec438cec1b18858e3c5d.zip |
Keep track of clipboard ownership
Given that all clipboard handling is async, it is possible to for
example receive a request for clipboard data from the agent
while the client no longer owns the clipboard (ie a
VD_AGENT_CLIPBOARD_RELEASE message is in transit to the agent).
Thus it is necessary to keep track of our notion of clipboard ownership
and check received clipboard messages (both from other apps on the client
machine and from the agent) to see if they match our notion and if not
drop, or in case were a counter message is expected nack the clipboard
message.
Diffstat (limited to 'client/red_client.cpp')
-rw-r--r-- | client/red_client.cpp | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/client/red_client.cpp b/client/red_client.cpp index 3f01fb1c..a022499f 100644 --- a/client/red_client.cpp +++ b/client/red_client.cpp @@ -85,10 +85,17 @@ void ClipboardGrabEvent::response(AbstractProcessLoop& events_loop) { static_cast<RedClient*>(events_loop.get_owner())->send_agent_clipboard_message( VD_AGENT_CLIPBOARD_GRAB, _type_count * sizeof(uint32_t), _types); + Platform::set_clipboard_owner(Platform::owner_client); } void ClipboardRequestEvent::response(AbstractProcessLoop& events_loop) { + if (Platform::get_clipboard_owner() != Platform::owner_guest) { + LOG_WARN("received clipboard req from client while clipboard is not owned by guest"); + Platform::on_clipboard_notify(VD_AGENT_CLIPBOARD_NONE, NULL, 0); + return; + } + VDAgentClipboardRequest request = {_type}; static_cast<RedClient*>(events_loop.get_owner())->send_agent_clipboard_message( VD_AGENT_CLIPBOARD_REQUEST, sizeof(request), &request); @@ -865,6 +872,11 @@ void RedClient::on_clipboard_notify(uint32_t type, uint8_t* data, int32_t size) DBG(0, "clipboard change is already pending"); return; } + if (Platform::get_clipboard_owner() != Platform::owner_client) { + LOG_WARN("received clipboard data from client while clipboard is not owned by client"); + type = VD_AGENT_CLIPBOARD_NONE; + size = 0; + } _agent_out_msg_pos = 0; _agent_out_msg_size = sizeof(VDAgentMessage) + sizeof(VDAgentClipboard) + size; _agent_out_msg = (VDAgentMessage*)new uint8_t[_agent_out_msg_size]; @@ -880,6 +892,12 @@ 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) { @@ -1086,6 +1104,12 @@ void RedClient::dispatch_agent_message(VDAgentMessage* msg, void* data) break; } case VD_AGENT_CLIPBOARD: { + if (Platform::get_clipboard_owner() != Platform::owner_guest) { + LOG_WARN("received clipboard data from guest while clipboard is not owned by guest"); + Platform::on_clipboard_notify(VD_AGENT_CLIPBOARD_NONE, NULL, 0); + break; + } + VDAgentClipboard* clipboard = (VDAgentClipboard*)data; Platform::on_clipboard_notify(clipboard->type, clipboard->data, msg->size - sizeof(VDAgentClipboard)); @@ -1094,14 +1118,27 @@ void RedClient::dispatch_agent_message(VDAgentMessage* msg, void* data) case VD_AGENT_CLIPBOARD_GRAB: Platform::on_clipboard_grab((uint32_t *)data, msg->size / sizeof(uint32_t)); + Platform::set_clipboard_owner(Platform::owner_guest); break; case VD_AGENT_CLIPBOARD_REQUEST: + if (Platform::get_clipboard_owner() != Platform::owner_client) { + LOG_WARN("received clipboard req from guest while clipboard is not owned by client"); + on_clipboard_notify(VD_AGENT_CLIPBOARD_NONE, NULL, 0); + break; + } + if (!Platform::on_clipboard_request(((VDAgentClipboardRequest*)data)->type)) { on_clipboard_notify(VD_AGENT_CLIPBOARD_NONE, NULL, 0); } break; case VD_AGENT_CLIPBOARD_RELEASE: + if (Platform::get_clipboard_owner() != Platform::owner_guest) { + LOG_WARN("received clipboard release from guest while clipboard is not owned by guest"); + break; + } + Platform::on_clipboard_release(); + Platform::set_clipboard_owner(Platform::owner_none); break; default: DBG(0, "Unsupported message type %u size %u", msg->type, msg->size); |