Fix bug #4735 - don't leave() until fillClipboard()s all complete

This commit is contained in:
Nye Liu 2015-09-01 17:39:25 -07:00 committed by Xinyu Hou
parent 7a207b4a54
commit 6c11de6a22
2 changed files with 55 additions and 20 deletions

View File

@ -21,7 +21,6 @@
#include "../plugin/ns/SecureSocket.h" #include "../plugin/ns/SecureSocket.h"
#include "client/ServerProxy.h" #include "client/ServerProxy.h"
#include "synergy/Screen.h" #include "synergy/Screen.h"
#include "synergy/Clipboard.h"
#include "synergy/FileChunk.h" #include "synergy/FileChunk.h"
#include "synergy/DropHelper.h" #include "synergy/DropHelper.h"
#include "synergy/PacketStreamFilter.h" #include "synergy/PacketStreamFilter.h"
@ -75,7 +74,10 @@ Client::Client(
m_socket(NULL), m_socket(NULL),
m_useSecureNetwork(false), m_useSecureNetwork(false),
m_args(args), m_args(args),
m_sendClipboardThread(NULL) m_sendClipboardThread(NULL),
m_mutex(NULL),
m_condData(false),
m_condVar(NULL)
{ {
assert(m_socketFactory != NULL); assert(m_socketFactory != NULL);
assert(m_screen != NULL); assert(m_screen != NULL);
@ -107,6 +109,8 @@ Client::Client(
LOG((CLOG_NOTE "crypto disabled because of ns plugin not available")); LOG((CLOG_NOTE "crypto disabled because of ns plugin not available"));
} }
} }
m_mutex = new Mutex();
m_condVar = new CondVar<bool>(m_mutex, m_condData);
} }
Client::~Client() Client::~Client()
@ -125,6 +129,8 @@ Client::~Client()
cleanupConnecting(); cleanupConnecting();
cleanupConnection(); cleanupConnection();
delete m_socketFactory; delete m_socketFactory;
delete m_condVar;
delete m_mutex;
} }
void void
@ -262,8 +268,6 @@ Client::enter(SInt32 xAbs, SInt32 yAbs, UInt32, KeyModifierMask mask, bool)
bool bool
Client::leave() Client::leave()
{ {
m_screen->leave();
m_active = false; m_active = false;
if (m_sendClipboardThread != NULL) { if (m_sendClipboardThread != NULL) {
@ -272,11 +276,17 @@ Client::leave()
m_sendClipboardThread = NULL; m_sendClipboardThread = NULL;
} }
m_condData = false;
m_sendClipboardThread = new Thread( m_sendClipboardThread = new Thread(
new TMethodJob<Client>( new TMethodJob<Client>(
this, this,
&Client::sendClipboardThread, &Client::sendClipboardThread,
NULL)); NULL));
// Bug #4735 - we can't leave() until fillClipboard()s all finish
while (!m_condData)
m_condVar->wait();
m_screen->leave();
if (!m_receivedFileData.empty()) { if (!m_receivedFileData.empty()) {
m_receivedFileData.clear(); m_receivedFileData.clear();
@ -382,9 +392,20 @@ Client::getName() const
} }
void void
Client::sendClipboard(ClipboardID id) Client::fillClipboard(ClipboardID id, Clipboard *clipboard)
{
assert(m_screen != NULL);
assert(m_server != NULL);
if (clipboard->open(m_timeClipboard[id])) {
clipboard->close();
}
m_screen->getClipboard(id, clipboard);
}
void
Client::sendClipboard(ClipboardID id, Clipboard *clipboard)
{ {
// note -- m_mutex must be locked on entry
assert(m_screen != NULL); assert(m_screen != NULL);
assert(m_server != NULL); assert(m_server != NULL);
@ -392,26 +413,21 @@ Client::sendClipboard(ClipboardID id)
// clipboard time before getting the data from the screen // clipboard time before getting the data from the screen
// as the screen may detect an unchanged clipboard and // as the screen may detect an unchanged clipboard and
// avoid copying the data. // avoid copying the data.
Clipboard clipboard;
if (clipboard.open(m_timeClipboard[id])) {
clipboard.close();
}
m_screen->getClipboard(id, &clipboard);
// check time // check time
if (m_timeClipboard[id] == 0 || if (m_timeClipboard[id] == 0 ||
clipboard.getTime() != m_timeClipboard[id]) { clipboard->getTime() != m_timeClipboard[id]) {
// save new time // save new time
m_timeClipboard[id] = clipboard.getTime(); m_timeClipboard[id] = clipboard->getTime();
// marshall the data // marshall the data
String data = clipboard.marshall(); String data = clipboard->marshall();
// save and send data if different or not yet sent // save and send data if different or not yet sent
if (!m_sentClipboard[id] || data != m_dataClipboard[id]) { if (!m_sentClipboard[id] || data != m_dataClipboard[id]) {
m_sentClipboard[id] = true; m_sentClipboard[id] = true;
m_dataClipboard[id] = data; m_dataClipboard[id] = data;
m_server->onClipboardChanged(id, &clipboard); m_server->onClipboardChanged(id, clipboard);
} }
} }
} }
@ -673,8 +689,10 @@ Client::handleClipboardGrabbed(const Event& event, void*)
// if we're not the active screen then send the clipboard now, // if we're not the active screen then send the clipboard now,
// otherwise we'll wait until we leave. // otherwise we'll wait until we leave.
Clipboard clipboard;
if (!m_active) { if (!m_active) {
sendClipboard(info->m_id); fillClipboard(info->m_id, &clipboard);
sendClipboard(info->m_id, &clipboard);
} }
} }
@ -762,12 +780,24 @@ Client::onFileRecieveCompleted()
} }
void void
Client::sendClipboardThread(void*) Client::sendClipboardThread(void * data)
{ {
Clipboard clipboard[kClipboardEnd];
// fill clipboards that we own and that have changed
for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
if (m_ownClipboard[id]) {
fillClipboard(id, &clipboard[id]);
}
}
// signal that fill is done
m_condData = true;
m_condVar->signal();
// send clipboards that we own and that have changed // send clipboards that we own and that have changed
for (ClipboardID id = 0; id < kClipboardEnd; ++id) { for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
if (m_ownClipboard[id]) { if (m_ownClipboard[id]) {
sendClipboard(id); sendClipboard(id, &clipboard[id]);
} }
} }

View File

@ -20,12 +20,13 @@
#include "synergy/IClient.h" #include "synergy/IClient.h"
#include "synergy/IClipboard.h" #include "synergy/Clipboard.h"
#include "synergy/DragInformation.h" #include "synergy/DragInformation.h"
#include "synergy/INode.h" #include "synergy/INode.h"
#include "synergy/ClientArgs.h" #include "synergy/ClientArgs.h"
#include "net/NetworkAddress.h" #include "net/NetworkAddress.h"
#include "base/EventTypes.h" #include "base/EventTypes.h"
#include "mt/CondVar.h"
class EventQueueTimer; class EventQueueTimer;
namespace synergy { class Screen; } namespace synergy { class Screen; }
@ -162,7 +163,8 @@ public:
virtual String getName() const; virtual String getName() const;
private: private:
void sendClipboard(ClipboardID); void fillClipboard(ClipboardID, Clipboard*);
void sendClipboard(ClipboardID, Clipboard*);
void sendEvent(Event::Type, void*); void sendEvent(Event::Type, void*);
void sendConnectionFailedEvent(const char* msg); void sendConnectionFailedEvent(const char* msg);
void sendFileChunk(const void* data); void sendFileChunk(const void* data);
@ -223,4 +225,7 @@ private:
bool m_useSecureNetwork; bool m_useSecureNetwork;
ClientArgs& m_args; ClientArgs& m_args;
Thread* m_sendClipboardThread; Thread* m_sendClipboardThread;
Mutex* m_mutex;
bool m_condData;
CondVar<bool>* m_condVar;
}; };