[Spice-devel] [PATCH vdagent-win 2/3] vdagent: release clipboard ownership on agent stop & desktop switch rhbz#731628
Arnon Gilboa
agilboa at redhat.com
Wed Nov 16 02:16:36 PST 2011
-use event queue for agent stop & desktop switch
-exit gracefully on session end
---
vdagent/vdagent.cpp | 86 ++++++++++++++++++++++++++++++++++++++------------
1 files changed, 65 insertions(+), 21 deletions(-)
diff --git a/vdagent/vdagent.cpp b/vdagent/vdagent.cpp
index 646afed..f0f5243 100644
--- a/vdagent/vdagent.cpp
+++ b/vdagent/vdagent.cpp
@@ -20,6 +20,7 @@
#include "display_setting.h"
#include "ximage.h"
#include <lmcons.h>
+#include <queue>
#include <set>
#define VD_AGENT_LOG_PATH TEXT("%svdagent.log")
@@ -88,6 +89,9 @@ private:
DWORD get_cximage_format(uint32_t type);
enum { owner_none, owner_guest, owner_client };
void set_clipboard_owner(int new_owner);
+ enum { CONTROL_STOP, CONTROL_DESKTOP_SWITCH };
+ void set_control_event(int control_command);
+ void handle_control_event();
uint8_t* write_lock(DWORD bytes = 0);
void write_unlock(DWORD bytes = 0);
bool write_message(uint32_t type, uint32_t size, void* data);
@@ -109,7 +113,7 @@ private:
LONG _mouse_y;
INPUT _input;
DWORD _input_time;
- HANDLE _desktop_switch_event;
+ HANDLE _control_event;
HANDLE _clipboard_event;
VDAgentMessage* _in_msg;
uint32_t _in_msg_pos;
@@ -119,10 +123,13 @@ private:
bool _pending_input;
bool _pending_write;
bool _running;
+ bool _desktop_switch;
DesktopLayout* _desktop_layout;
DisplaySetting _display_setting;
VDPipeState _pipe_state;
mutex_t _write_mutex;
+ mutex_t _control_mutex;
+ std::queue<int> _control_queue;
bool _logon_desktop;
bool _display_setting_initialized;
@@ -154,7 +161,7 @@ VDAgent::VDAgent()
, _mouse_x (0)
, _mouse_y (0)
, _input_time (0)
- , _desktop_switch_event (NULL)
+ , _control_event (NULL)
, _clipboard_event (NULL)
, _in_msg (NULL)
, _in_msg_pos (0)
@@ -164,6 +171,7 @@ VDAgent::VDAgent()
, _pending_input (false)
, _pending_write (false)
, _running (false)
+ , _desktop_switch (false)
, _desktop_layout (NULL)
, _display_setting (VD_AGENT_REGISTRY_KEY)
, _logon_desktop (false)
@@ -182,6 +190,7 @@ VDAgent::VDAgent()
ZeroMemory(&_input, sizeof(INPUT));
ZeroMemory(&_pipe_state, sizeof(VDPipeState));
MUTEX_INIT(_write_mutex);
+ MUTEX_INIT(_control_mutex);
_singleton = this;
}
@@ -203,7 +212,7 @@ DWORD WINAPI VDAgent::event_thread_proc(LPVOID param)
DWORD wait_ret = WaitForSingleObject(desktop_event, INFINITE);
switch (wait_ret) {
case WAIT_OBJECT_0:
- SetEvent((HANDLE)param);
+ _singleton->set_control_event(CONTROL_DESKTOP_SWITCH);
break;
case WAIT_TIMEOUT:
default:
@@ -233,9 +242,9 @@ bool VDAgent::run()
if (!SetProcessShutdownParameters(0x100, 0)) {
vd_printf("SetProcessShutdownParameters failed %u", GetLastError());
}
- _desktop_switch_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+ _control_event = CreateEvent(NULL, FALSE, FALSE, NULL);
_clipboard_event = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (!_desktop_switch_event || !_clipboard_event) {
+ if (!_control_event || !_clipboard_event) {
vd_printf("CreateEvent() failed: %d", GetLastError());
cleanup();
return false;
@@ -257,8 +266,7 @@ bool VDAgent::run()
return false;
}
_running = true;
- event_thread = CreateThread(NULL, 0, event_thread_proc, _desktop_switch_event, 0,
- &event_thread_id);
+ event_thread = CreateThread(NULL, 0, event_thread_proc, NULL, 0, &event_thread_id);
if (!event_thread) {
vd_printf("CreateThread() failed: %d", GetLastError());
cleanup();
@@ -268,6 +276,9 @@ bool VDAgent::run()
read_completion(0, 0, &_pipe_state.read.overlap);
while (_running) {
input_desktop_message_loop();
+ if (_clipboard_owner == owner_guest) {
+ set_clipboard_owner(owner_none);
+ }
}
vd_printf("Agent stopped");
CloseHandle(event_thread);
@@ -277,15 +288,45 @@ bool VDAgent::run()
void VDAgent::cleanup()
{
- CloseHandle(_desktop_switch_event);
+ CloseHandle(_control_event);
CloseHandle(_clipboard_event);
CloseHandle(_pipe_state.pipe);
delete _desktop_layout;
}
+void VDAgent::set_control_event(int control_command)
+{
+ MUTEX_LOCK(_control_mutex);
+ _control_queue.push(control_command);
+ if (_control_event && !SetEvent(_control_event)) {
+ vd_printf("SetEvent() failed: %u", GetLastError());
+ }
+ MUTEX_UNLOCK(_control_mutex);
+}
+
+void VDAgent::handle_control_event()
+{
+ MUTEX_LOCK(_control_mutex);
+ while (_control_queue.size()) {
+ int control_command = _control_queue.front();
+ _control_queue.pop();
+ vd_printf("Control command %d", control_command);
+ switch (control_command) {
+ case CONTROL_STOP:
+ _running = false;
+ break;
+ case CONTROL_DESKTOP_SWITCH:
+ _desktop_switch = true;
+ break;
+ default:
+ vd_printf("Unsupported control command %u", control_command);
+ }
+ }
+ MUTEX_UNLOCK(_control_mutex);
+}
+
void VDAgent::input_desktop_message_loop()
{
- bool desktop_switch = false;
TCHAR desktop_name[MAX_PATH];
DWORD wait_ret;
HDESK hdesk;
@@ -333,13 +374,12 @@ void VDAgent::input_desktop_message_loop()
return;
}
_hwnd_next_viewer = SetClipboardViewer(_hwnd);
- while (_running && !desktop_switch) {
- wait_ret = MsgWaitForMultipleObjectsEx(1, &_desktop_switch_event, INFINITE, QS_ALLINPUT,
+ while (_running && !_desktop_switch) {
+ wait_ret = MsgWaitForMultipleObjectsEx(1, &_control_event, INFINITE, QS_ALLINPUT,
MWMO_ALERTABLE);
switch (wait_ret) {
case WAIT_OBJECT_0:
- vd_printf("WinSta0_DesktopSwitch");
- desktop_switch = true;
+ handle_control_event();
break;
case WAIT_OBJECT_0 + 1:
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
@@ -354,6 +394,7 @@ void VDAgent::input_desktop_message_loop()
vd_printf("MsgWaitForMultipleObjectsEx(): %u", wait_ret);
}
}
+ _desktop_switch = false;
if (_pending_input) {
KillTimer(_hwnd, VD_TIMER_ID);
_pending_input = false;
@@ -901,7 +942,7 @@ bool VDAgent::handle_clipboard_grab(VDAgentClipboardGrab* clipboard_grab, uint32
_grab_types.clear();
for (uint32_t i = 0; i < size / sizeof(clipboard_grab->types[0]); i++) {
- vd_printf("grab %u", clipboard_grab->types[i]);
+ vd_printf("grab type %u", clipboard_grab->types[i]);
uint32_t format = get_clipboard_format(clipboard_grab->types[i]);
//On first supported type, open and empty the clipboard
if (format && grab_formats.empty()) {
@@ -1154,7 +1195,7 @@ VOID CALLBACK VDAgent::read_completion(DWORD err, DWORD bytes, LPOVERLAPPED over
return;
}
if (err) {
- vd_printf("error %u", err);
+ vd_printf("vdservice disconnected (%u)", err);
a->_running = false;
return;
}
@@ -1225,7 +1266,7 @@ VOID CALLBACK VDAgent::write_completion(DWORD err, DWORD bytes, LPOVERLAPPED ove
return;
}
if (err) {
- vd_printf("error %u", err);
+ vd_printf("vdservice disconnected (%u)", err);
a->_running = false;
return;
}
@@ -1297,11 +1338,14 @@ LRESULT CALLBACK VDAgent::wnd_proc(HWND hwnd, UINT message, WPARAM wparam, LPARA
case WM_RENDERFORMAT:
a->on_clipboard_request((UINT)wparam);
break;
- case WM_RENDERALLFORMATS:
- vd_printf("WM_RENDERALLFORMATS");
- break;
- case WM_DESTROYCLIPBOARD:
- vd_printf("WM_DESTROYCLIPBOARD");
+ case WM_ENDSESSION:
+ if (wparam) {
+ vd_printf("Session ended");
+ if (a->_clipboard_owner == owner_guest) {
+ a->set_clipboard_owner(owner_none);
+ }
+ a->set_control_event(CONTROL_STOP);
+ }
break;
default:
return DefWindowProc(hwnd, message, wparam, lparam);
--
1.7.4.1
More information about the Spice-devel
mailing list