diff --git a/src/lib/client/CClient.cpp b/src/lib/client/CClient.cpp index 4aa16e3e..0932358c 100644 --- a/src/lib/client/CClient.cpp +++ b/src/lib/client/CClient.cpp @@ -67,7 +67,8 @@ CClient::CClient(IEventQueue* events, m_connectOnResume(false), m_events(events), m_cryptoStream(NULL), - m_crypto(crypto) + m_crypto(crypto), + m_sendFileThread(NULL) { assert(m_socketFactory != NULL); assert(m_screen != NULL); @@ -108,6 +109,7 @@ CClient::~CClient() cleanupConnection(); delete m_socketFactory; delete m_streamFilterFactory; + delete m_sendFileThread; } void @@ -790,7 +792,7 @@ CClient::isReceivedFileSizeValid() void CClient::sendFileToServer(const char* filename) { - CThread* thread = new CThread( + m_sendFileThread = new CThread( new TMethodJob( this, &CClient::sendFileThread, reinterpret_cast(const_cast(filename)))); @@ -806,4 +808,13 @@ CClient::sendFileThread(void* filename) catch (std::runtime_error error) { LOG((CLOG_ERR "failed sending file chunks: %s", error.what())); } + + delete m_sendFileThread; + m_sendFileThread = NULL; +} + +void +CClient::draggingInfoSending(UInt32 fileCount, CString& fileList, size_t size) +{ + m_server->draggingInfoSending(fileCount, fileList, size); } diff --git a/src/lib/client/CClient.h b/src/lib/client/CClient.h index 989e7e22..970bf784 100644 --- a/src/lib/client/CClient.h +++ b/src/lib/client/CClient.h @@ -36,6 +36,7 @@ namespace synergy { class IStream; } class IStreamFilterFactory; class IEventQueue; class CCryptoStream; +class CThread; //! Synergy client /*! @@ -110,7 +111,10 @@ public: //! Set file transder destination void setFileTransferDes(CString& des) { m_fileTransferDes = des; } - + + //! Send dragging file information back to server + void draggingInfoSending(UInt32 fileCount, CString& fileList, size_t size); + //@} //! @name accessors //@{ @@ -229,6 +233,7 @@ private: CString m_fileTransferDes; CDragFileList m_dragFileList; CString m_dragFileExt; + CThread* m_sendFileThread; }; #endif diff --git a/src/lib/client/CServerProxy.cpp b/src/lib/client/CServerProxy.cpp index 41ebb86a..2572fa95 100644 --- a/src/lib/client/CServerProxy.cpp +++ b/src/lib/client/CServerProxy.cpp @@ -28,7 +28,6 @@ #include "TMethodEventJob.h" #include "XBase.h" #include -#include #include "CCryptoStream.h" // @@ -946,3 +945,9 @@ CServerProxy::fileChunkSending(UInt8 mark, char* data, size_t dataSize) CProtocolUtil::writef(m_stream, kMsgDFileTransfer, mark, &chunk); } + +void +CServerProxy::draggingInfoSending(UInt32 fileCount, CString fileList, size_t size) +{ + CProtocolUtil::writef(m_stream, kMsgDDragInfo, fileCount, &fileList); +} diff --git a/src/lib/client/CServerProxy.h b/src/lib/client/CServerProxy.h index 962c0005..0accf6d5 100644 --- a/src/lib/client/CServerProxy.h +++ b/src/lib/client/CServerProxy.h @@ -23,6 +23,7 @@ #include "KeyTypes.h" #include "CEvent.h" #include "CStopwatch.h" +#include "CString.h" class CClient; class CClientInfo; @@ -54,9 +55,12 @@ public: //@} - //! sending file chunk to server + // sending file chunk to server void fileChunkSending(UInt8 mark, char* data, size_t dataSize); + // sending dragging information to server + void draggingInfoSending(UInt32 fileCount, CString fileList, size_t size); + #ifdef TEST_ENV void handleDataForTest() { handleData(CEvent(), NULL); } #endif diff --git a/src/lib/platform/CMSWindowsScreen.cpp b/src/lib/platform/CMSWindowsScreen.cpp index d55a79cf..03b0f9d5 100644 --- a/src/lib/platform/CMSWindowsScreen.cpp +++ b/src/lib/platform/CMSWindowsScreen.cpp @@ -1835,3 +1835,9 @@ CMSWindowsScreen::CHotKeyItem::operator<(const CHotKeyItem& x) const return (m_keycode < x.m_keycode || (m_keycode == x.m_keycode && m_mask < x.m_mask)); } + +void +CMSWindowsScreen::fakeDraggingFiles(CString str) +{ + +} diff --git a/src/lib/platform/CMSWindowsScreen.h b/src/lib/platform/CMSWindowsScreen.h index 00e4f985..80f3fcdc 100644 --- a/src/lib/platform/CMSWindowsScreen.h +++ b/src/lib/platform/CMSWindowsScreen.h @@ -115,6 +115,7 @@ public: virtual void setOptions(const COptionsList& options); virtual void setSequenceNumber(UInt32); virtual bool isPrimary() const; + virtual void fakeDraggingFiles(CString str); protected: // IPlatformScreen overrides diff --git a/src/lib/platform/CMakeLists.txt b/src/lib/platform/CMakeLists.txt index fef544e1..bf7e860c 100644 --- a/src/lib/platform/CMakeLists.txt +++ b/src/lib/platform/CMakeLists.txt @@ -103,6 +103,8 @@ set(inc ../ipc ../net ../io + ../server + ../client ../synwinhk ../synwinxt ) @@ -123,7 +125,7 @@ include_directories(${inc}) add_library(platform STATIC ${src}) if (UNIX) - target_link_libraries(platform io net ipc synergy ${libs}) + target_link_libraries(platform io net ipc synergy server client ${libs}) endif() if (APPLE) diff --git a/src/lib/platform/COSXPasteboardPeeker.m b/src/lib/platform/COSXPasteboardPeeker.m index 0ddd6466..90cd4190 100644 --- a/src/lib/platform/COSXPasteboardPeeker.m +++ b/src/lib/platform/COSXPasteboardPeeker.m @@ -29,6 +29,7 @@ getDraggedFileURL() NSArray* files = [pboard propertyListForType:NSFilenamesPboardType]; for (id file in files) { [string appendString: (NSString*)file]; + [string appendString: @"\0"]; } return (CFStringRef)string; diff --git a/src/lib/platform/COSXScreen.cpp b/src/lib/platform/COSXScreen.cpp index c90a077f..ecbe22bd 100644 --- a/src/lib/platform/COSXScreen.cpp +++ b/src/lib/platform/COSXScreen.cpp @@ -34,6 +34,9 @@ #include "XArch.h" #include "COSXDragSimulator.h" #include "COSXPasteboardPeeker.h" +#include "CClientApp.h" +#include "CServerApp.h" +#include "CClient.h" #include @@ -98,6 +101,7 @@ COSXScreen::COSXScreen(IEventQueue* events, bool isPrimary, bool autoShowHideCur m_eventTapRLSR(nullptr), m_eventTapPort(nullptr), m_pmRootPort(0), + m_draggingStarted(false), m_fakeDraggingStarted(false), m_getDropTargetThread(NULL) { @@ -593,6 +597,7 @@ COSXScreen::fakeMouseButton(ButtonID id, bool press) } m_fakeDraggingStarted = false; + m_draggingStarted = false; } } @@ -638,6 +643,11 @@ COSXScreen::fakeMouseMove(SInt32 x, SInt32 y) fakeKeyDown(kKeyControl_L, 8194, 29); } + // index 0 means left mouse button + if (m_buttonState.test(0)) { + m_draggingStarted = true; + } + // synthesize event CGPoint pos; pos.x = x; @@ -890,6 +900,24 @@ COSXScreen::leave() { hideCursor(); + if (m_draggingStarted) { + if (!m_isPrimary) { + CFStringRef dragInfo = getDraggedFileURL(); + char* dragInfoCStr = CFStringRefToUTF8String(dragInfo); + LOG((CLOG_DEBUG "drag info: %s", dragInfoCStr)); + CFRelease(dragInfo); + CString fileList(dragInfoCStr); + size_t size = fileList.size(); + CClientApp& app = CClientApp::instance(); + CClient* client = app.getClientPtr(); + UInt32 fileCount = 1; + client->draggingInfoSending(fileCount, fileList, size); + LOG((CLOG_DEBUG "send dragging file to server")); + client->sendFileToServer(dragInfoCStr); + m_draggingStarted = false; + } + } + if (m_isPrimary) { // warp to center //warpCursor(m_xCenter, m_yCenter); diff --git a/src/lib/platform/COSXScreen.h b/src/lib/platform/COSXScreen.h index 5c1438ee..e1fc08c7 100644 --- a/src/lib/platform/COSXScreen.h +++ b/src/lib/platform/COSXScreen.h @@ -97,7 +97,6 @@ public: virtual void setOptions(const COptionsList& options); virtual void setSequenceNumber(UInt32); virtual bool isPrimary() const; - virtual void fakeDraggingFiles(CString str); const CString& getDropTarget() const { return m_dropTarget; } @@ -345,6 +344,7 @@ private: IEventQueue* m_events; + bool m_draggingStarted; bool m_fakeDraggingStarted; CThread* m_getDropTargetThread; CString m_dropTarget; diff --git a/src/lib/server/CClientProxy1_5.cpp b/src/lib/server/CClientProxy1_5.cpp index f9394810..274f5a1c 100644 --- a/src/lib/server/CClientProxy1_5.cpp +++ b/src/lib/server/CClientProxy1_5.cpp @@ -76,6 +76,9 @@ CClientProxy1_5::parseMessage(const UInt8* code) if (memcmp(code, kMsgDFileTransfer, 4) == 0) { fileChunkReceived(); } + else if (memcmp(code, kMsgDDragInfo, 4) == 0) { + dragInfoReceived(); + } else { return CClientProxy1_4::parseMessage(code); } @@ -133,3 +136,14 @@ CClientProxy1_5::fileChunkReceived() break; } } + +void +CClientProxy1_5::dragInfoReceived() +{ + // parse + UInt32 fileNum = 0; + CString content; + CProtocolUtil::readf(getStream(), kMsgDDragInfo + 4, &fileNum, &content); + + m_server->dragInfoReceived(fileNum, content); +} diff --git a/src/lib/server/CClientProxy1_5.h b/src/lib/server/CClientProxy1_5.h index 35d0c909..efb33c20 100644 --- a/src/lib/server/CClientProxy1_5.h +++ b/src/lib/server/CClientProxy1_5.h @@ -33,6 +33,7 @@ public: virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize); virtual bool parseMessage(const UInt8* code); void fileChunkReceived(); + void dragInfoReceived(); private: IEventQueue* m_events; diff --git a/src/lib/server/CServer.cpp b/src/lib/server/CServer.cpp index 61bdcff5..605b6540 100644 --- a/src/lib/server/CServer.cpp +++ b/src/lib/server/CServer.cpp @@ -37,7 +37,6 @@ #include "CThread.h" #include "TMethodJob.h" #include "CFileChunker.h" -#include "CDragInformation.h" #include #include #include @@ -75,7 +74,8 @@ CServer::CServer(CConfig& config, CPrimaryClient* primaryClient, CScreen* screen m_relativeMoves(false), m_keyboardBroadcasting(false), m_lockedToScreen(false), - m_screen(screen) + m_screen(screen), + m_sendFileThread(NULL) { // must have a primary client and it must have a canonical name assert(m_primaryClient != NULL); @@ -243,6 +243,8 @@ CServer::~CServer() // disable and disconnect primary client m_primaryClient->disable(); removeClient(m_primaryClient); + + delete m_sendFileThread; } bool @@ -1950,9 +1952,11 @@ void CServer::onFileRecieveCompleted() { if (isReceivedFileSizeValid()) { - if (!m_fileTransferDes.empty()) { + if (!m_fileTransferDes.empty() && m_dragFileList.size() > 0) { std::fstream file; - file.open(m_fileTransferDes.c_str(), std::ios::out | std::ios::binary); + CString dropTarget = m_fileTransferDes; + dropTarget.append("/").append(m_dragFileList.at(0)); + file.open(dropTarget.c_str(), std::ios::out | std::ios::binary); if (!file.is_open()) { // TODO: file open failed } @@ -1960,6 +1964,9 @@ CServer::onFileRecieveCompleted() file.write(m_receivedFileData.c_str(), m_receivedFileData.size()); file.close(); } + else { + LOG((CLOG_ERR "drop file failed: drop target is empty")); + } } } @@ -2262,7 +2269,7 @@ CServer::isReceivedFileSizeValid() void CServer::sendFileToClient(const char* filename) { - CThread* thread = new CThread( + m_sendFileThread = new CThread( new TMethodJob( this, &CServer::sendFileThread, reinterpret_cast(const_cast(filename)))); @@ -2279,4 +2286,23 @@ CServer::sendFileThread(void* filename) catch (std::runtime_error error) { LOG((CLOG_ERR "failed sending file chunks: %s", error.what())); } + + delete m_sendFileThread; + m_sendFileThread = NULL; +} + +void +CServer::dragInfoReceived(UInt32 fileNum, CString content) +{ + CDragInformation::parseDragInfo(m_dragFileList, fileNum, content); + LOG((CLOG_INFO "drag information received")); + LOG((CLOG_INFO "total drag file number: %i", m_dragFileList.size())); + + for(int i = 0; i < m_dragFileList.size(); ++i) { + LOG((CLOG_INFO "dragging file %i name: %s", i + 1, m_dragFileList.at(i).c_str())); + } + + if (m_dragFileList.size() != 0) { + //TODO: fake a dragging operation + } } diff --git a/src/lib/server/CServer.h b/src/lib/server/CServer.h index 04d93867..7fb87542 100644 --- a/src/lib/server/CServer.h +++ b/src/lib/server/CServer.h @@ -31,6 +31,7 @@ #include "stdvector.h" #include "INode.h" #include "CEventTypes.h" +#include "CDragInformation.h" class CBaseClientProxy; class CEventQueueTimer; @@ -38,6 +39,7 @@ class CPrimaryClient; class CInputFilter; class CScreen; class IEventQueue; +class CThread; //! Synergy server /*! @@ -153,6 +155,9 @@ public: //! Create a new thread and use it to send file to client void sendFileToClient(const char* filename); + //! Received dragging information from client + void dragInfoReceived(UInt32 fileNum, CString content); + //@} //! @name accessors //@{ @@ -456,6 +461,8 @@ private: CString m_receivedFileData; CString m_fileTransferSrc; CString m_fileTransferDes; + CDragFileList m_dragFileList; + CThread* m_sendFileThread; }; #endif diff --git a/src/lib/synergy/CClientApp.h b/src/lib/synergy/CClientApp.h index 39f839ec..a19c81fd 100644 --- a/src/lib/synergy/CClientApp.h +++ b/src/lib/synergy/CClientApp.h @@ -83,6 +83,8 @@ public: static CClientApp& instance() { return (CClientApp&)CApp::instance(); } + CClient* getClientPtr() { return s_client; } + private: virtual bool parseArg(const int& argc, const char* const* argv, int& i); void runEventsLoop(void*); diff --git a/src/lib/synergy/CDragInformation.cpp b/src/lib/synergy/CDragInformation.cpp index 7807c77d..69bc648f 100644 --- a/src/lib/synergy/CDragInformation.cpp +++ b/src/lib/synergy/CDragInformation.cpp @@ -27,9 +27,14 @@ CDragInformation::parseDragInfo(CDragFileList& dragFileList, UInt32 fileNum, CSt size_t findResult1 = 0; size_t findResult2 = 0; dragFileList.clear(); + CString slash("\\"); + if (data.find("/", startPos != -1)) { + slash = "/"; + } + while (fileNum) { findResult1 = data.find('\0', startPos); - findResult2 = data.find_last_of("\\", findResult1); + findResult2 = data.find_last_of(slash, findResult1); if (findResult1 == startPos) { //TODO: file number does not match, something goes wrong diff --git a/src/lib/synergy/CServerApp.cpp b/src/lib/synergy/CServerApp.cpp index b3fbe55f..d886fb4a 100644 --- a/src/lib/synergy/CServerApp.cpp +++ b/src/lib/synergy/CServerApp.cpp @@ -47,6 +47,10 @@ #include "COSXScreen.h" #endif +#if defined(__APPLE__) +#include "COSXDragSimulator.h" +#endif + #include #include #include @@ -782,7 +786,17 @@ CServerApp::mainLoop() // later. the timer installed by startServer() will take care of // that. DAEMON_RUNNING(true); + +#if defined(__APPLE__) + CThread thread( + new TMethodJob( + this, &CServerApp::runEventsLoop, + NULL)); + runCocoaApp(); +#else m_events->loop(); +#endif + DAEMON_RUNNING(false); // close down @@ -901,3 +915,10 @@ CServerApp::startNode() m_bye(kExitFailed); } } + +void +CServerApp::runEventsLoop(void*) +{ + m_events->cacheCurrentEventQueueRef(); + m_events->loop(); +} diff --git a/src/lib/synergy/CServerApp.h b/src/lib/synergy/CServerApp.h index 8c3acf51..8bc86e19 100644 --- a/src/lib/synergy/CServerApp.h +++ b/src/lib/synergy/CServerApp.h @@ -111,6 +111,8 @@ public: static CServerApp& instance() { return (CServerApp&)CApp::instance(); } + CServer* getServerPtr() { return s_server; } + // TODO: change s_ to m_ CServer* s_server; EServerState s_serverState; @@ -124,6 +126,7 @@ public: private: virtual bool parseArg(const int& argc, const char* const* argv, int& i); void handleScreenSwitched(const CEvent&, void* data); + void runEventsLoop(void*); }; // configuration file name