Feature to drag a file from Windows to Mac:
- On Mac client main thread is used for cocoa application in order to simulate drag. - Send dragging file dir from Windows server to Mac client while dragging after switching screen. - Dragging information sending is immature now (need to support multi files dragging in the future). - Used Cocoa function to monitor dragg pasteboard. - Changed Mac client to use another thread for event queue instead of the main thread. - Change fileRecieveComplete to fileRecieveCompleted.
This commit is contained in:
parent
031a84ca84
commit
ce1b62db14
|
@ -594,3 +594,9 @@ CEventQueue::CTimer::operator<(const CTimer& t) const
|
||||||
{
|
{
|
||||||
return m_time < t.m_time;
|
return m_time < t.m_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CEventQueue::cacheCurrentEventQueueRef()
|
||||||
|
{
|
||||||
|
m_buffer->cacheCurrentEventQueueRef();
|
||||||
|
}
|
||||||
|
|
|
@ -61,6 +61,8 @@ public:
|
||||||
getRegisteredType(const CString& name) const;
|
getRegisteredType(const CString& name) const;
|
||||||
void* getSystemTarget();
|
void* getSystemTarget();
|
||||||
|
|
||||||
|
void cacheCurrentEventQueueRef();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UInt32 saveEvent(const CEvent& event);
|
UInt32 saveEvent(const CEvent& event);
|
||||||
CEvent removeEvent(UInt32 eventID);
|
CEvent removeEvent(UInt32 eventID);
|
||||||
|
|
|
@ -177,7 +177,7 @@ REGISTER_EVENT(IScreen, clipboardGrabbed)
|
||||||
REGISTER_EVENT(IScreen, suspend)
|
REGISTER_EVENT(IScreen, suspend)
|
||||||
REGISTER_EVENT(IScreen, resume)
|
REGISTER_EVENT(IScreen, resume)
|
||||||
REGISTER_EVENT(IScreen, fileChunkSending)
|
REGISTER_EVENT(IScreen, fileChunkSending)
|
||||||
REGISTER_EVENT(IScreen, fileRecieveComplete)
|
REGISTER_EVENT(IScreen, fileRecieveCompleted)
|
||||||
|
|
||||||
//
|
//
|
||||||
// CIpcServer
|
// CIpcServer
|
||||||
|
|
|
@ -629,7 +629,7 @@ public:
|
||||||
m_suspend(CEvent::kUnknown),
|
m_suspend(CEvent::kUnknown),
|
||||||
m_resume(CEvent::kUnknown),
|
m_resume(CEvent::kUnknown),
|
||||||
m_fileChunkSending(CEvent::kUnknown),
|
m_fileChunkSending(CEvent::kUnknown),
|
||||||
m_fileRecieveComplete(CEvent::kUnknown) { }
|
m_fileRecieveCompleted(CEvent::kUnknown) { }
|
||||||
|
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
//@{
|
//@{
|
||||||
|
@ -674,7 +674,7 @@ public:
|
||||||
CEvent::Type fileChunkSending();
|
CEvent::Type fileChunkSending();
|
||||||
|
|
||||||
//! Completed receiving a file
|
//! Completed receiving a file
|
||||||
CEvent::Type fileRecieveComplete();
|
CEvent::Type fileRecieveCompleted();
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
@ -685,5 +685,5 @@ private:
|
||||||
CEvent::Type m_suspend;
|
CEvent::Type m_suspend;
|
||||||
CEvent::Type m_resume;
|
CEvent::Type m_resume;
|
||||||
CEvent::Type m_fileChunkSending;
|
CEvent::Type m_fileChunkSending;
|
||||||
CEvent::Type m_fileRecieveComplete;
|
CEvent::Type m_fileRecieveCompleted;
|
||||||
};
|
};
|
||||||
|
|
|
@ -40,6 +40,7 @@ public:
|
||||||
virtual CEventQueueTimer*
|
virtual CEventQueueTimer*
|
||||||
newTimer(double duration, bool oneShot) const;
|
newTimer(double duration, bool oneShot) const;
|
||||||
virtual void deleteTimer(CEventQueueTimer*) const;
|
virtual void deleteTimer(CEventQueueTimer*) const;
|
||||||
|
void cacheCurrentEventQueueRef() { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::deque<UInt32> CEventDeque;
|
typedef std::deque<UInt32> CEventDeque;
|
||||||
|
|
|
@ -177,6 +177,8 @@ public:
|
||||||
registerTypeOnce(CEvent::Type& type,
|
registerTypeOnce(CEvent::Type& type,
|
||||||
const char* name) = 0;
|
const char* name) = 0;
|
||||||
|
|
||||||
|
virtual void cacheCurrentEventQueueRef() = 0;
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
//@{
|
//@{
|
||||||
|
|
|
@ -67,6 +67,8 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual bool addEvent(UInt32 dataID) = 0;
|
virtual bool addEvent(UInt32 dataID) = 0;
|
||||||
|
|
||||||
|
virtual void cacheCurrentEventQueueRef() = 0;
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
//@{
|
//@{
|
||||||
|
|
|
@ -85,10 +85,10 @@ CClient::CClient(IEventQueue* events,
|
||||||
this,
|
this,
|
||||||
new TMethodEventJob<CClient>(this,
|
new TMethodEventJob<CClient>(this,
|
||||||
&CClient::handleFileChunkSending));
|
&CClient::handleFileChunkSending));
|
||||||
m_events->adoptHandler(m_events->forIScreen().fileRecieveComplete(),
|
m_events->adoptHandler(m_events->forIScreen().fileRecieveCompleted(),
|
||||||
this,
|
this,
|
||||||
new TMethodEventJob<CClient>(this,
|
new TMethodEventJob<CClient>(this,
|
||||||
&CClient::handleFileRecieveComplete));
|
&CClient::handleFileRecieveCompleted));
|
||||||
}
|
}
|
||||||
|
|
||||||
CClient::~CClient()
|
CClient::~CClient()
|
||||||
|
@ -711,17 +711,19 @@ CClient::handleFileChunkSending(const CEvent& event, void*)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CClient::handleFileRecieveComplete(const CEvent& event, void*)
|
CClient::handleFileRecieveCompleted(const CEvent& event, void*)
|
||||||
{
|
{
|
||||||
onFileRecieveComplete();
|
onFileRecieveCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CClient::onFileRecieveComplete()
|
CClient::onFileRecieveCompleted()
|
||||||
{
|
{
|
||||||
if (isReceivedFileSizeValid()) {
|
if (isReceivedFileSizeValid()) {
|
||||||
|
m_fileTransferDes = m_screen->getDropTarget();
|
||||||
if (!m_fileTransferDes.empty()) {
|
if (!m_fileTransferDes.empty()) {
|
||||||
std::fstream file;
|
std::fstream file;
|
||||||
|
m_fileTransferDes.append("/").append(m_dragFileList.at(0));
|
||||||
file.open(m_fileTransferDes.c_str(), std::ios::out | std::ios::binary);
|
file.open(m_fileTransferDes.c_str(), std::ios::out | std::ios::binary);
|
||||||
if (!file.is_open()) {
|
if (!file.is_open()) {
|
||||||
// TODO: file open failed
|
// TODO: file open failed
|
||||||
|
@ -730,6 +732,9 @@ CClient::onFileRecieveComplete()
|
||||||
file.write(m_receivedFileData.c_str(), m_receivedFileData.size());
|
file.write(m_receivedFileData.c_str(), m_receivedFileData.size());
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
LOG((CLOG_ERR "drop file failed: drop target is empty"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,6 +757,30 @@ CClient::fileChunkReceived(CString data)
|
||||||
m_receivedFileData += data;
|
m_receivedFileData += data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CClient::dragInfoReceived(UInt32 fileNum, CString data)
|
||||||
|
{
|
||||||
|
CDragInformation::parseDragInfo(m_dragFileList, fileNum, data);
|
||||||
|
LOG((CLOG_DEBUG "drag information received"));
|
||||||
|
LOG((CLOG_DEBUG "total drag file number: %i", m_dragFileList.size()));
|
||||||
|
|
||||||
|
for(int i = 0; i < m_dragFileList.size(); ++i) {
|
||||||
|
LOG((CLOG_DEBUG2 "dragging file %i name: %s", i + 1, m_dragFileList.at(i).c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_dragFileList.size() == 1) {
|
||||||
|
m_dragFileExt = CDragInformation::getDragFileExtension(m_dragFileList.at(0));
|
||||||
|
}
|
||||||
|
else if (m_dragFileList.size() > 1) {
|
||||||
|
m_dragFileExt.clear();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_screen->startDraggingFiles(m_dragFileExt);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CClient::isReceivedFileSizeValid()
|
CClient::isReceivedFileSizeValid()
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "INode.h"
|
#include "INode.h"
|
||||||
#include "CCryptoOptions.h"
|
#include "CCryptoOptions.h"
|
||||||
#include "CEventTypes.h"
|
#include "CEventTypes.h"
|
||||||
|
#include "CDragInformation.h"
|
||||||
|
|
||||||
class CEventQueueTimer;
|
class CEventQueueTimer;
|
||||||
class CScreen;
|
class CScreen;
|
||||||
|
@ -101,6 +102,9 @@ public:
|
||||||
//! Received a chunk of file data
|
//! Received a chunk of file data
|
||||||
void fileChunkReceived(CString data);
|
void fileChunkReceived(CString data);
|
||||||
|
|
||||||
|
//! Received drag information
|
||||||
|
void dragInfoReceived(UInt32 fileNum, CString data);
|
||||||
|
|
||||||
//! Create a new thread and use it to send file to Server
|
//! Create a new thread and use it to send file to Server
|
||||||
void sendFileToServer(const char* filename);
|
void sendFileToServer(const char* filename);
|
||||||
|
|
||||||
|
@ -193,8 +197,8 @@ private:
|
||||||
void handleSuspend(const CEvent& event, void*);
|
void handleSuspend(const CEvent& event, void*);
|
||||||
void handleResume(const CEvent& event, void*);
|
void handleResume(const CEvent& event, void*);
|
||||||
void handleFileChunkSending(const CEvent&, void*);
|
void handleFileChunkSending(const CEvent&, void*);
|
||||||
void handleFileRecieveComplete(const CEvent&, void*);
|
void handleFileRecieveCompleted(const CEvent&, void*);
|
||||||
void onFileRecieveComplete();
|
void onFileRecieveCompleted();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool m_mock;
|
bool m_mock;
|
||||||
|
@ -223,6 +227,8 @@ private:
|
||||||
CString m_receivedFileData;
|
CString m_receivedFileData;
|
||||||
CString m_fileTransferSrc;
|
CString m_fileTransferSrc;
|
||||||
CString m_fileTransferDes;
|
CString m_fileTransferDes;
|
||||||
|
CDragFileList m_dragFileList;
|
||||||
|
CString m_dragFileExt;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -301,6 +301,9 @@ CServerProxy::parseMessage(const UInt8* code)
|
||||||
else if (memcmp(code, kMsgDFileTransfer, 4) == 0) {
|
else if (memcmp(code, kMsgDFileTransfer, 4) == 0) {
|
||||||
fileChunkReceived();
|
fileChunkReceived();
|
||||||
}
|
}
|
||||||
|
else if (memcmp(code, kMsgDDragInfo, 4) == 0) {
|
||||||
|
dragInfoReceived();
|
||||||
|
}
|
||||||
|
|
||||||
else if (memcmp(code, kMsgCClose, 4) == 0) {
|
else if (memcmp(code, kMsgCClose, 4) == 0) {
|
||||||
// server wants us to hangup
|
// server wants us to hangup
|
||||||
|
@ -865,7 +868,7 @@ void
|
||||||
CServerProxy::fileChunkReceived()
|
CServerProxy::fileChunkReceived()
|
||||||
{
|
{
|
||||||
// parse
|
// parse
|
||||||
UInt8 mark;
|
UInt8 mark = 0;
|
||||||
CString content;
|
CString content;
|
||||||
CProtocolUtil::readf(m_stream, kMsgDFileTransfer + 4, &mark, &content);
|
CProtocolUtil::readf(m_stream, kMsgDFileTransfer + 4, &mark, &content);
|
||||||
|
|
||||||
|
@ -898,7 +901,7 @@ CServerProxy::fileChunkReceived()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kFileEnd:
|
case kFileEnd:
|
||||||
m_events->addEvent(CEvent(m_events->forIScreen().fileRecieveComplete(), m_client));
|
m_events->addEvent(CEvent(m_events->forIScreen().fileRecieveCompleted(), m_client));
|
||||||
if (CLOG->getFilter() >= kDEBUG2) {
|
if (CLOG->getFilter() >= kDEBUG2) {
|
||||||
LOG((CLOG_DEBUG2 "file data transfer finished"));
|
LOG((CLOG_DEBUG2 "file data transfer finished"));
|
||||||
m_elapsedTime += m_stopwatch.getTime();
|
m_elapsedTime += m_stopwatch.getTime();
|
||||||
|
@ -911,6 +914,17 @@ CServerProxy::fileChunkReceived()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CServerProxy::dragInfoReceived()
|
||||||
|
{
|
||||||
|
// parse
|
||||||
|
UInt32 fileNum = 0;
|
||||||
|
CString content;
|
||||||
|
CProtocolUtil::readf(m_stream, kMsgDDragInfo + 4, &fileNum, &content);
|
||||||
|
|
||||||
|
m_client->dragInfoReceived(fileNum, content);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CServerProxy::fileChunkSending(UInt8 mark, char* data, size_t dataSize)
|
CServerProxy::fileChunkSending(UInt8 mark, char* data, size_t dataSize)
|
||||||
{
|
{
|
||||||
|
|
|
@ -103,6 +103,7 @@ private:
|
||||||
void queryInfo();
|
void queryInfo();
|
||||||
void infoAcknowledgment();
|
void infoAcknowledgment();
|
||||||
void fileChunkReceived();
|
void fileChunkReceived();
|
||||||
|
void dragInfoReceived();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef EResult (CServerProxy::*MessageParser)(const UInt8*);
|
typedef EResult (CServerProxy::*MessageParser)(const UInt8*);
|
||||||
|
|
|
@ -40,6 +40,8 @@ public:
|
||||||
newTimer(double duration, bool oneShot) const;
|
newTimer(double duration, bool oneShot) const;
|
||||||
virtual void deleteTimer(CEventQueueTimer*) const;
|
virtual void deleteTimer(CEventQueueTimer*) const;
|
||||||
|
|
||||||
|
virtual void cacheCurrentEventQueueRef() {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DWORD m_thread;
|
DWORD m_thread;
|
||||||
UINT m_userEvent;
|
UINT m_userEvent;
|
||||||
|
|
|
@ -699,7 +699,7 @@ CMSWindowsScreen::fakeMouseButton(ButtonID id, bool press)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CMSWindowsScreen::fakeMouseMove(SInt32 x, SInt32 y) const
|
CMSWindowsScreen::fakeMouseMove(SInt32 x, SInt32 y)
|
||||||
{
|
{
|
||||||
m_desks->fakeMouseMove(x, y);
|
m_desks->fakeMouseMove(x, y);
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ public:
|
||||||
|
|
||||||
// ISecondaryScreen overrides
|
// ISecondaryScreen overrides
|
||||||
virtual void fakeMouseButton(ButtonID id, bool press);
|
virtual void fakeMouseButton(ButtonID id, bool press);
|
||||||
virtual void fakeMouseMove(SInt32 x, SInt32 y) const;
|
virtual void fakeMouseMove(SInt32 x, SInt32 y);
|
||||||
virtual void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const;
|
virtual void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const;
|
||||||
virtual void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const;
|
virtual void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const;
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,9 @@ elseif (APPLE)
|
||||||
COSXScreen.cpp
|
COSXScreen.cpp
|
||||||
COSXScreenSaver.cpp
|
COSXScreenSaver.cpp
|
||||||
COSXScreenSaverUtil.m
|
COSXScreenSaverUtil.m
|
||||||
|
COSXPasteboardPeeker.m
|
||||||
|
COSXDragSimulator.m
|
||||||
|
COSXDragView.m
|
||||||
)
|
)
|
||||||
|
|
||||||
elseif (UNIX)
|
elseif (UNIX)
|
||||||
|
@ -110,9 +113,20 @@ if (UNIX)
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (APPLE)
|
||||||
|
list(APPEND inc
|
||||||
|
/System/Library/Frameworks
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
include_directories(${inc})
|
include_directories(${inc})
|
||||||
add_library(platform STATIC ${src})
|
add_library(platform STATIC ${src})
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
target_link_libraries(platform io net ipc synergy ${libs})
|
target_link_libraries(platform io net ipc synergy ${libs})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (APPLE)
|
||||||
|
FIND_LIBRARY(COCOA_LIBRARY Cocoa)
|
||||||
|
target_link_libraries(platform ${COCOA_LIBRARY})
|
||||||
|
endif()
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2013 Bolton Software Ltd.
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file COPYING that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#import <CoreFoundation/CoreFoundation.h>
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
void runCocoaApp();
|
||||||
|
void fakeDragging(const char* str, int length, int cursorX, int cursorY);
|
||||||
|
CFStringRef getCocoaDropTarget();
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2013 Bolton Software Ltd.
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file COPYING that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "COSXDragSimulator.h"
|
||||||
|
#import "COSXDragView.h"
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <CoreData/CoreData.h>
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
NSWindow* g_dragWindow = NULL;
|
||||||
|
COSXDragView* g_dragView = NULL;
|
||||||
|
|
||||||
|
void
|
||||||
|
runCocoaApp()
|
||||||
|
{
|
||||||
|
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
|
||||||
|
NSApplication* app = [[NSApplication alloc] init];
|
||||||
|
NSWindow* window = [[NSWindow alloc]
|
||||||
|
initWithContentRect: NSMakeRect(-100, -100, 100, 100)
|
||||||
|
styleMask: NSTitledWindowMask | NSMiniaturizableWindowMask
|
||||||
|
backing: NSBackingStoreBuffered
|
||||||
|
defer: NO];
|
||||||
|
[window setTitle: @""];
|
||||||
|
[window makeKeyAndOrderFront:nil];
|
||||||
|
|
||||||
|
COSXDragView* dragView = [[COSXDragView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
|
||||||
|
g_dragWindow = window;
|
||||||
|
g_dragView = dragView;
|
||||||
|
[window setContentView: dragView];
|
||||||
|
|
||||||
|
[app run];
|
||||||
|
|
||||||
|
[pool release];
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fakeDragging(const char* str, int length, int cursorX, int cursorY)
|
||||||
|
{
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
NSRect screen = [[NSScreen mainScreen] frame];
|
||||||
|
NSLog ( @"mouseLocation: %d %d", cursorX, cursorY);
|
||||||
|
NSRect rect = NSMakeRect(cursorX - 50, screen.size.height - cursorY - 50, 100, 100);
|
||||||
|
[g_dragWindow setFrame:rect display:YES];
|
||||||
|
[g_dragWindow makeKeyWindow];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
CFStringRef
|
||||||
|
getCocoaDropTarget()
|
||||||
|
{
|
||||||
|
return [g_dragView getDropTarget];
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2013 Bolton Software Ltd.
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file COPYING that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
@interface COSXDragView : NSView<NSDraggingSource,NSDraggingInfo>
|
||||||
|
{
|
||||||
|
NSMutableString* m_dropTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(CFStringRef)getDropTarget;
|
||||||
|
-(void)clearDropTarget;
|
||||||
|
|
||||||
|
@end
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2013 Bolton Software Ltd.
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file COPYING that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "COSXDragView.h"
|
||||||
|
|
||||||
|
@implementation COSXDragView
|
||||||
|
|
||||||
|
- (id)
|
||||||
|
initWithFrame:(NSRect)frame
|
||||||
|
{
|
||||||
|
self = [super initWithFrame:frame];
|
||||||
|
m_dropTarget = [[NSMutableString alloc] initWithCapacity:0];
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)
|
||||||
|
drawRect:(NSRect)dirtyRect
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)
|
||||||
|
acceptsFirstMouse:(NSEvent *)theEvent
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)
|
||||||
|
mouseDown:(NSEvent *)theEvent
|
||||||
|
{
|
||||||
|
NSPoint dragPosition;
|
||||||
|
NSRect imageLocation;
|
||||||
|
dragPosition = [self convertPoint:[theEvent locationInWindow]
|
||||||
|
fromView:nil];
|
||||||
|
|
||||||
|
dragPosition.x -= 16;
|
||||||
|
dragPosition.y -= 16;
|
||||||
|
imageLocation.origin = dragPosition;
|
||||||
|
imageLocation.size = NSMakeSize(32,32);
|
||||||
|
[self dragPromisedFilesOfTypes:[NSArray arrayWithObject:@"zip"]
|
||||||
|
fromRect:imageLocation
|
||||||
|
source:self
|
||||||
|
slideBack:NO
|
||||||
|
event:theEvent];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray*)
|
||||||
|
namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination
|
||||||
|
{
|
||||||
|
[m_dropTarget setString:@""];
|
||||||
|
[m_dropTarget appendString:dropDestination.path];
|
||||||
|
NSLog ( @"cocoa drop target: %@", m_dropTarget);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(NSDragOperation)
|
||||||
|
draggingSourceOperationMaskForLocal:(BOOL)flag
|
||||||
|
{
|
||||||
|
return NSDragOperationCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(CFStringRef)
|
||||||
|
getDropTarget
|
||||||
|
{
|
||||||
|
NSMutableString* string;
|
||||||
|
string = [[NSMutableString alloc] initWithCapacity:0];
|
||||||
|
[string appendString:m_dropTarget];
|
||||||
|
return (CFStringRef)string;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void)
|
||||||
|
clearDropTarget
|
||||||
|
{
|
||||||
|
[m_dropTarget setString:@""];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -99,7 +99,7 @@ COSXEventQueueBuffer::addEvent(UInt32 dataID)
|
||||||
&event);
|
&event);
|
||||||
|
|
||||||
if (error == noErr) {
|
if (error == noErr) {
|
||||||
error = PostEventToQueue(GetMainEventQueue(), event,
|
error = PostEventToQueue(m_threadEventQueueRef, event,
|
||||||
kEventPriorityStandard);
|
kEventPriorityStandard);
|
||||||
ReleaseEvent(event);
|
ReleaseEvent(event);
|
||||||
}
|
}
|
||||||
|
@ -126,3 +126,9 @@ COSXEventQueueBuffer::deleteTimer(CEventQueueTimer* timer) const
|
||||||
{
|
{
|
||||||
delete timer;
|
delete timer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
COSXEventQueueBuffer::cacheCurrentEventQueueRef()
|
||||||
|
{
|
||||||
|
m_threadEventQueueRef = GetCurrentEventQueue();
|
||||||
|
}
|
||||||
|
|
|
@ -38,10 +38,12 @@ public:
|
||||||
virtual CEventQueueTimer*
|
virtual CEventQueueTimer*
|
||||||
newTimer(double duration, bool oneShot) const;
|
newTimer(double duration, bool oneShot) const;
|
||||||
virtual void deleteTimer(CEventQueueTimer*) const;
|
virtual void deleteTimer(CEventQueueTimer*) const;
|
||||||
|
virtual void cacheCurrentEventQueueRef();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EventRef m_event;
|
EventRef m_event;
|
||||||
IEventQueue* m_eventQueue;
|
IEventQueue* m_eventQueue;
|
||||||
|
EventQueueRef m_threadEventQueueRef;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2013 Bolton Software Ltd.
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file COPYING that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#import <CoreFoundation/CoreFoundation.h>
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CFStringRef getDraggedFileURL();
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2013 Bolton Software Ltd.
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file COPYING that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "COSXPasteboardPeeker.h"
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <CoreData/CoreData.h>
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
CFStringRef
|
||||||
|
getDraggedFileURL()
|
||||||
|
{
|
||||||
|
NSString* pbName = NSDragPboard;
|
||||||
|
NSPasteboard* pboard = [NSPasteboard pasteboardWithName:pbName];
|
||||||
|
|
||||||
|
NSMutableString* string;
|
||||||
|
string = [[NSMutableString alloc] initWithCapacity:0];
|
||||||
|
|
||||||
|
NSArray* files = [pboard propertyListForType:NSFilenamesPboardType];
|
||||||
|
for (id file in files) {
|
||||||
|
[string appendString: (NSString*)file];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (CFStringRef)string;
|
||||||
|
}
|
|
@ -32,6 +32,8 @@
|
||||||
#include "TMethodEventJob.h"
|
#include "TMethodEventJob.h"
|
||||||
#include "TMethodJob.h"
|
#include "TMethodJob.h"
|
||||||
#include "XArch.h"
|
#include "XArch.h"
|
||||||
|
#include "COSXDragSimulator.h"
|
||||||
|
#include "COSXPasteboardPeeker.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
@ -95,7 +97,9 @@ COSXScreen::COSXScreen(IEventQueue* events, bool isPrimary, bool autoShowHideCur
|
||||||
m_autoShowHideCursor(autoShowHideCursor),
|
m_autoShowHideCursor(autoShowHideCursor),
|
||||||
m_eventTapRLSR(nullptr),
|
m_eventTapRLSR(nullptr),
|
||||||
m_eventTapPort(nullptr),
|
m_eventTapPort(nullptr),
|
||||||
m_pmRootPort(0)
|
m_pmRootPort(0),
|
||||||
|
m_fakeDraggingStarted(false),
|
||||||
|
m_getDropTargetThread(NULL)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
m_displayID = CGMainDisplayID();
|
m_displayID = CGMainDisplayID();
|
||||||
|
@ -564,7 +568,7 @@ COSXScreen::fakeMouseButton(ButtonID id, bool press)
|
||||||
|
|
||||||
MouseButtonState state = press ? kMouseButtonDown : kMouseButtonUp;
|
MouseButtonState state = press ? kMouseButtonDown : kMouseButtonUp;
|
||||||
|
|
||||||
LOG((CLOG_DEBUG1 "faking mouse button %s", press ? "press" : "release"));
|
LOG((CLOG_DEBUG1 "faking mouse button id: %d press: %s", id, press ? "pressed" : "released"));
|
||||||
|
|
||||||
MouseButtonEventMapType thisButtonMap = MouseButtonEventMap[index];
|
MouseButtonEventMapType thisButtonMap = MouseButtonEventMap[index];
|
||||||
CGEventType type = thisButtonMap[state];
|
CGEventType type = thisButtonMap[state];
|
||||||
|
@ -580,11 +584,60 @@ COSXScreen::fakeMouseButton(ButtonID id, bool press)
|
||||||
m_lastSingleClickXCursor = m_xCursor;
|
m_lastSingleClickXCursor = m_xCursor;
|
||||||
m_lastSingleClickYCursor = m_yCursor;
|
m_lastSingleClickYCursor = m_yCursor;
|
||||||
}
|
}
|
||||||
|
if (!press && (id == kButtonLeft)) {
|
||||||
|
fakeKeyUp(29);
|
||||||
|
|
||||||
|
if (m_fakeDraggingStarted) {
|
||||||
|
m_getDropTargetThread = new CThread(new TMethodJob<COSXScreen>(
|
||||||
|
this, &COSXScreen::getDropTargetThread));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_fakeDraggingStarted = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
COSXScreen::fakeMouseMove(SInt32 x, SInt32 y) const
|
COSXScreen::getDropTargetThread(void*)
|
||||||
{
|
{
|
||||||
|
char* cstr = NULL;
|
||||||
|
|
||||||
|
// wait for 5 secs for the drop destinaiton string to be filled.
|
||||||
|
UInt32 timeout = ARCH->time() + 5;
|
||||||
|
|
||||||
|
while (ARCH->time() < timeout) {
|
||||||
|
CFStringRef cfstr = getCocoaDropTarget();
|
||||||
|
cstr = CFStringRefToUTF8String(cfstr);
|
||||||
|
CFRelease(cfstr);
|
||||||
|
|
||||||
|
if (cstr != NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ARCH->sleep(.1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cstr != NULL) {
|
||||||
|
LOG((CLOG_DEBUG "drop target: %s", cstr));
|
||||||
|
m_dropTarget = cstr;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG((CLOG_ERR "failed to get drop target"));
|
||||||
|
m_dropTarget.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
delete m_getDropTargetThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
COSXScreen::fakeMouseMove(SInt32 x, SInt32 y)
|
||||||
|
{
|
||||||
|
if (m_fakeDraggingStarted) {
|
||||||
|
// HACK: for some reason the drag icon
|
||||||
|
// does not follow the cursor unless a key
|
||||||
|
// is pressed (except esc key)
|
||||||
|
// TODO: fake this key down properly
|
||||||
|
fakeKeyDown(kKeyControl_L, 8194, 29);
|
||||||
|
}
|
||||||
|
|
||||||
// synthesize event
|
// synthesize event
|
||||||
CGPoint pos;
|
CGPoint pos;
|
||||||
pos.x = x;
|
pos.x = x;
|
||||||
|
@ -671,6 +724,12 @@ COSXScreen::showCursor()
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cursorHidden = false;
|
m_cursorHidden = false;
|
||||||
|
|
||||||
|
if (m_fakeDraggingStarted) {
|
||||||
|
// TODO: use real file extension
|
||||||
|
fakeDragging("txt", 3, m_xCursor, m_yCursor);
|
||||||
|
fakeMouseButton(kButtonLeft, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1409,8 +1468,8 @@ COSXScreen::getScrollSpeedFactor() const
|
||||||
void
|
void
|
||||||
COSXScreen::enableDragTimer(bool enable)
|
COSXScreen::enableDragTimer(bool enable)
|
||||||
{
|
{
|
||||||
UInt32 modifiers;
|
UInt32 modifiers;
|
||||||
MouseTrackingResult res;
|
MouseTrackingResult res;
|
||||||
|
|
||||||
if (enable && m_dragTimer == NULL) {
|
if (enable && m_dragTimer == NULL) {
|
||||||
m_dragTimer = m_events->newTimer(0.01, NULL);
|
m_dragTimer = m_events->newTimer(0.01, NULL);
|
||||||
|
@ -1430,8 +1489,8 @@ void
|
||||||
COSXScreen::handleDrag(const CEvent&, void*)
|
COSXScreen::handleDrag(const CEvent&, void*)
|
||||||
{
|
{
|
||||||
Point p;
|
Point p;
|
||||||
UInt32 modifiers;
|
UInt32 modifiers;
|
||||||
MouseTrackingResult res;
|
MouseTrackingResult res;
|
||||||
|
|
||||||
TrackMouseLocationWithOptions(NULL, 0, 0, &p, &modifiers, &res);
|
TrackMouseLocationWithOptions(NULL, 0, 0, &p, &modifiers, &res);
|
||||||
|
|
||||||
|
@ -1848,10 +1907,16 @@ COSXScreen::handleCGInputEvent(CGEventTapProxy proxy,
|
||||||
case kCGEventOtherMouseUp:
|
case kCGEventOtherMouseUp:
|
||||||
screen->onMouseButton(false, CGEventGetIntegerValueField(event, kCGMouseEventButtonNumber) + 1);
|
screen->onMouseButton(false, CGEventGetIntegerValueField(event, kCGMouseEventButtonNumber) + 1);
|
||||||
break;
|
break;
|
||||||
case kCGEventMouseMoved:
|
case kCGEventLeftMouseDragged: {
|
||||||
case kCGEventLeftMouseDragged:
|
CFStringRef dragInfo = getDraggedFileURL();
|
||||||
|
char* info = CFStringRefToUTF8String(dragInfo);
|
||||||
|
LOG((CLOG_DEBUG "drag info: %s", info));
|
||||||
|
CFRelease(dragInfo);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case kCGEventRightMouseDragged:
|
case kCGEventRightMouseDragged:
|
||||||
case kCGEventOtherMouseDragged:
|
case kCGEventOtherMouseDragged:
|
||||||
|
case kCGEventMouseMoved:
|
||||||
pos = CGEventGetLocation(event);
|
pos = CGEventGetLocation(event);
|
||||||
screen->onMouseMove(pos.x, pos.y);
|
screen->onMouseMove(pos.x, pos.y);
|
||||||
|
|
||||||
|
@ -1942,3 +2007,27 @@ COSXScreen::CMouseButtonState::getFirstButtonDown() const
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
COSXScreen::CFStringRefToUTF8String(CFStringRef aString)
|
||||||
|
{
|
||||||
|
if (aString == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFIndex length = CFStringGetLength(aString);
|
||||||
|
CFIndex maxSize = CFStringGetMaximumSizeForEncoding(
|
||||||
|
length,
|
||||||
|
kCFStringEncodingUTF8);
|
||||||
|
char* buffer = (char*)malloc(maxSize);
|
||||||
|
if (CFStringGetCString(aString, buffer, maxSize, kCFStringEncodingUTF8)) {
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
COSXScreen::fakeDraggingFiles(CString str)
|
||||||
|
{
|
||||||
|
m_fakeDraggingStarted = true;
|
||||||
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ public:
|
||||||
|
|
||||||
// ISecondaryScreen overrides
|
// ISecondaryScreen overrides
|
||||||
virtual void fakeMouseButton(ButtonID id, bool press);
|
virtual void fakeMouseButton(ButtonID id, bool press);
|
||||||
virtual void fakeMouseMove(SInt32 x, SInt32 y) const;
|
virtual void fakeMouseMove(SInt32 x, SInt32 y);
|
||||||
virtual void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const;
|
virtual void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const;
|
||||||
virtual void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const;
|
virtual void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const;
|
||||||
|
|
||||||
|
@ -98,6 +98,10 @@ public:
|
||||||
virtual void setSequenceNumber(UInt32);
|
virtual void setSequenceNumber(UInt32);
|
||||||
virtual bool isPrimary() const;
|
virtual bool isPrimary() const;
|
||||||
|
|
||||||
|
virtual void fakeDraggingFiles(CString str);
|
||||||
|
|
||||||
|
const CString& getDropTarget() const { return m_dropTarget; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// IPlatformScreen overrides
|
// IPlatformScreen overrides
|
||||||
virtual void handleSystemEvent(const CEvent&, void*);
|
virtual void handleSystemEvent(const CEvent&, void*);
|
||||||
|
@ -191,10 +195,16 @@ private:
|
||||||
CGEventType type,
|
CGEventType type,
|
||||||
CGEventRef event,
|
CGEventRef event,
|
||||||
void* refcon);
|
void* refcon);
|
||||||
static CGEventRef handleCGInputEventSecondary(CGEventTapProxy proxy,
|
static CGEventRef handleCGInputEventSecondary(CGEventTapProxy proxy,
|
||||||
CGEventType type,
|
CGEventType type,
|
||||||
CGEventRef event,
|
CGEventRef event,
|
||||||
void* refcon);
|
void* refcon);
|
||||||
|
|
||||||
|
// convert CFString to char*
|
||||||
|
static char* CFStringRefToUTF8String(CFStringRef aString);
|
||||||
|
|
||||||
|
void getDropTargetThread(void*);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct CHotKeyItem {
|
struct CHotKeyItem {
|
||||||
public:
|
public:
|
||||||
|
@ -334,6 +344,10 @@ private:
|
||||||
bool m_autoShowHideCursor;
|
bool m_autoShowHideCursor;
|
||||||
|
|
||||||
IEventQueue* m_events;
|
IEventQueue* m_events;
|
||||||
|
|
||||||
|
bool m_fakeDraggingStarted;
|
||||||
|
CThread* m_getDropTargetThread;
|
||||||
|
CString m_dropTarget;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -45,6 +45,8 @@ public:
|
||||||
newTimer(double duration, bool oneShot) const;
|
newTimer(double duration, bool oneShot) const;
|
||||||
virtual void deleteTimer(CEventQueueTimer*) const;
|
virtual void deleteTimer(CEventQueueTimer*) const;
|
||||||
|
|
||||||
|
virtual void cacheCurrentEventQueueRef() {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void flush();
|
void flush();
|
||||||
|
|
||||||
|
|
|
@ -832,7 +832,7 @@ CXWindowsScreen::fakeMouseButton(ButtonID button, bool press)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CXWindowsScreen::fakeMouseMove(SInt32 x, SInt32 y) const
|
CXWindowsScreen::fakeMouseMove(SInt32 x, SInt32 y)
|
||||||
{
|
{
|
||||||
if (m_xinerama && m_xtestIsXineramaUnaware) {
|
if (m_xinerama && m_xtestIsXineramaUnaware) {
|
||||||
XWarpPointer(m_display, None, m_root, 0, 0, 0, 0, x, y);
|
XWarpPointer(m_display, None, m_root, 0, 0, 0, 0, x, y);
|
||||||
|
|
|
@ -66,7 +66,7 @@ public:
|
||||||
|
|
||||||
// ISecondaryScreen overrides
|
// ISecondaryScreen overrides
|
||||||
virtual void fakeMouseButton(ButtonID id, bool press);
|
virtual void fakeMouseButton(ButtonID id, bool press);
|
||||||
virtual void fakeMouseMove(SInt32 x, SInt32 y) const;
|
virtual void fakeMouseMove(SInt32 x, SInt32 y);
|
||||||
virtual void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const;
|
virtual void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const;
|
||||||
virtual void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const;
|
virtual void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const;
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,7 @@ public:
|
||||||
virtual void screensaver(bool activate) = 0;
|
virtual void screensaver(bool activate) = 0;
|
||||||
virtual void resetOptions() = 0;
|
virtual void resetOptions() = 0;
|
||||||
virtual void setOptions(const COptionsList& options) = 0;
|
virtual void setOptions(const COptionsList& options) = 0;
|
||||||
|
virtual void draggingInfoSending(UInt32 fileCount, const char* data, size_t dataSize) = 0;
|
||||||
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize) = 0;
|
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize) = 0;
|
||||||
virtual CString getName() const;
|
virtual CString getName() const;
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,7 @@ public:
|
||||||
virtual void resetOptions() = 0;
|
virtual void resetOptions() = 0;
|
||||||
virtual void setOptions(const COptionsList& options) = 0;
|
virtual void setOptions(const COptionsList& options) = 0;
|
||||||
virtual void cryptoIv(const UInt8* iv) = 0;
|
virtual void cryptoIv(const UInt8* iv) = 0;
|
||||||
|
virtual void draggingInfoSending(UInt32 fileCount, const char* data, size_t dataSize) = 0;
|
||||||
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize) = 0;
|
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -365,6 +365,13 @@ CClientProxy1_0::cryptoIv(const UInt8* iv)
|
||||||
LOG((CLOG_DEBUG "cryptoIv not supported"));
|
LOG((CLOG_DEBUG "cryptoIv not supported"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CClientProxy1_0::draggingInfoSending(UInt32 fileCount, const char* data, size_t dataSize)
|
||||||
|
{
|
||||||
|
// ignore -- not supported in protocol 1.0
|
||||||
|
LOG((CLOG_DEBUG "draggingInfoSending not supported"));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CClientProxy1_0::fileChunkSending(UInt8 mark, char* data, size_t dataSize)
|
CClientProxy1_0::fileChunkSending(UInt8 mark, char* data, size_t dataSize)
|
||||||
{
|
{
|
||||||
|
|
|
@ -60,6 +60,7 @@ public:
|
||||||
virtual void resetOptions();
|
virtual void resetOptions();
|
||||||
virtual void setOptions(const COptionsList& options);
|
virtual void setOptions(const COptionsList& options);
|
||||||
virtual void cryptoIv(const UInt8* iv);
|
virtual void cryptoIv(const UInt8* iv);
|
||||||
|
virtual void draggingInfoSending(UInt32 fileCount, const char* data, size_t dataSize);
|
||||||
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize);
|
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -40,6 +40,14 @@ CClientProxy1_5::~CClientProxy1_5()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CClientProxy1_5::draggingInfoSending(UInt32 fileCount, const char* data, size_t dataSize)
|
||||||
|
{
|
||||||
|
CString info(data, dataSize);
|
||||||
|
|
||||||
|
CProtocolUtil::writef(getStream(), kMsgDDragInfo, fileCount, &info);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CClientProxy1_5::fileChunkSending(UInt8 mark, char* data, size_t dataSize)
|
CClientProxy1_5::fileChunkSending(UInt8 mark, char* data, size_t dataSize)
|
||||||
{
|
{
|
||||||
|
@ -79,7 +87,7 @@ void
|
||||||
CClientProxy1_5::fileChunkReceived()
|
CClientProxy1_5::fileChunkReceived()
|
||||||
{
|
{
|
||||||
// parse
|
// parse
|
||||||
UInt8 mark;
|
UInt8 mark = 0;
|
||||||
CString content;
|
CString content;
|
||||||
CProtocolUtil::readf(getStream(), kMsgDFileTransfer + 4, &mark, &content);
|
CProtocolUtil::readf(getStream(), kMsgDFileTransfer + 4, &mark, &content);
|
||||||
|
|
||||||
|
@ -113,7 +121,7 @@ CClientProxy1_5::fileChunkReceived()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kFileEnd:
|
case kFileEnd:
|
||||||
m_events->addEvent(CEvent(m_events->forIScreen().fileRecieveComplete(), server));
|
m_events->addEvent(CEvent(m_events->forIScreen().fileRecieveCompleted(), server));
|
||||||
if (CLOG->getFilter() >= kDEBUG2) {
|
if (CLOG->getFilter() >= kDEBUG2) {
|
||||||
LOG((CLOG_DEBUG2 "file data transfer finished"));
|
LOG((CLOG_DEBUG2 "file data transfer finished"));
|
||||||
m_elapsedTime += m_stopwatch.getTime();
|
m_elapsedTime += m_stopwatch.getTime();
|
||||||
|
|
|
@ -29,6 +29,7 @@ public:
|
||||||
CClientProxy1_5(const CString& name, synergy::IStream* adoptedStream, CServer* server, IEventQueue* events);
|
CClientProxy1_5(const CString& name, synergy::IStream* adoptedStream, CServer* server, IEventQueue* events);
|
||||||
~CClientProxy1_5();
|
~CClientProxy1_5();
|
||||||
|
|
||||||
|
virtual void draggingInfoSending(UInt32 fileCount, const char* data, size_t dataSize);
|
||||||
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize);
|
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize);
|
||||||
virtual bool parseMessage(const UInt8* code);
|
virtual bool parseMessage(const UInt8* code);
|
||||||
void fileChunkReceived();
|
void fileChunkReceived();
|
||||||
|
|
|
@ -249,6 +249,12 @@ CPrimaryClient::screensaver(bool)
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CPrimaryClient::draggingInfoSending(UInt32 fileCount, const char* data, size_t dataSize)
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CPrimaryClient::fileChunkSending(UInt8 mark, char* data, size_t dataSize)
|
CPrimaryClient::fileChunkSending(UInt8 mark, char* data, size_t dataSize)
|
||||||
{
|
{
|
||||||
|
|
|
@ -144,6 +144,7 @@ public:
|
||||||
virtual void screensaver(bool activate);
|
virtual void screensaver(bool activate);
|
||||||
virtual void resetOptions();
|
virtual void resetOptions();
|
||||||
virtual void setOptions(const COptionsList& options);
|
virtual void setOptions(const COptionsList& options);
|
||||||
|
virtual void draggingInfoSending(UInt32 fileCount, const char* data, size_t dataSize);
|
||||||
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize);
|
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "CThread.h"
|
#include "CThread.h"
|
||||||
#include "TMethodJob.h"
|
#include "TMethodJob.h"
|
||||||
#include "CFileChunker.h"
|
#include "CFileChunker.h"
|
||||||
|
#include "CDragInformation.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
@ -167,10 +168,10 @@ CServer::CServer(CConfig& config, CPrimaryClient* primaryClient, CScreen* screen
|
||||||
this,
|
this,
|
||||||
new TMethodEventJob<CServer>(this,
|
new TMethodEventJob<CServer>(this,
|
||||||
&CServer::handleFileChunkSendingEvent));
|
&CServer::handleFileChunkSendingEvent));
|
||||||
m_events->adoptHandler(m_events->forIScreen().fileRecieveComplete(),
|
m_events->adoptHandler(m_events->forIScreen().fileRecieveCompleted(),
|
||||||
this,
|
this,
|
||||||
new TMethodEventJob<CServer>(this,
|
new TMethodEventJob<CServer>(this,
|
||||||
&CServer::handleFileRecieveCompleteEvent));
|
&CServer::handleFileRecieveCompletedEvent));
|
||||||
|
|
||||||
// add connection
|
// add connection
|
||||||
addClient(m_primaryClient);
|
addClient(m_primaryClient);
|
||||||
|
@ -1472,9 +1473,9 @@ CServer::handleFileChunkSendingEvent(const CEvent& event, void*)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CServer::handleFileRecieveCompleteEvent(const CEvent& event, void*)
|
CServer::handleFileRecieveCompletedEvent(const CEvent& event, void*)
|
||||||
{
|
{
|
||||||
onFileRecieveComplete();
|
onFileRecieveCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1737,8 +1738,24 @@ CServer::onMouseMovePrimary(SInt32 x, SInt32 y)
|
||||||
|
|
||||||
// should we switch or not?
|
// should we switch or not?
|
||||||
if (isSwitchOkay(newScreen, dir, x, y, xc, yc)) {
|
if (isSwitchOkay(newScreen, dir, x, y, xc, yc)) {
|
||||||
|
if (m_screen->getDraggingStarted() && m_active != newScreen) {
|
||||||
|
CString& dragFileList = m_screen->getDraggingFileDir();
|
||||||
|
size_t size = dragFileList.size() + 1;
|
||||||
|
char* fileList = new char[size];
|
||||||
|
memcpy(fileList, dragFileList.c_str(), size);
|
||||||
|
fileList[size - 1] = '\0';
|
||||||
|
UInt32 fileCount = 1;
|
||||||
|
|
||||||
|
LOG((CLOG_DEBUG2 "sending drag information to client"));
|
||||||
|
LOG((CLOG_DEBUG3 "dragging file list: %s", fileList));
|
||||||
|
LOG((CLOG_DEBUG3 "dragging file list string size: %i", size));
|
||||||
|
newScreen->draggingInfoSending(fileCount, fileList, size);
|
||||||
|
m_screen->setDraggingStarted(false);
|
||||||
|
}
|
||||||
|
|
||||||
// switch screen
|
// switch screen
|
||||||
switchScreen(newScreen, x, y, false);
|
switchScreen(newScreen, x, y, false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1930,7 +1947,7 @@ CServer::onFileChunkSending(const void* data)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CServer::onFileRecieveComplete()
|
CServer::onFileRecieveCompleted()
|
||||||
{
|
{
|
||||||
if (isReceivedFileSizeValid()) {
|
if (isReceivedFileSizeValid()) {
|
||||||
if (!m_fileTransferDes.empty()) {
|
if (!m_fileTransferDes.empty()) {
|
||||||
|
|
|
@ -310,7 +310,7 @@ private:
|
||||||
void handleFakeInputBeginEvent(const CEvent&, void*);
|
void handleFakeInputBeginEvent(const CEvent&, void*);
|
||||||
void handleFakeInputEndEvent(const CEvent&, void*);
|
void handleFakeInputEndEvent(const CEvent&, void*);
|
||||||
void handleFileChunkSendingEvent(const CEvent&, void*);
|
void handleFileChunkSendingEvent(const CEvent&, void*);
|
||||||
void handleFileRecieveCompleteEvent(const CEvent&, void*);
|
void handleFileRecieveCompletedEvent(const CEvent&, void*);
|
||||||
|
|
||||||
// event processing
|
// event processing
|
||||||
void onClipboardChanged(CBaseClientProxy* sender,
|
void onClipboardChanged(CBaseClientProxy* sender,
|
||||||
|
@ -327,7 +327,7 @@ private:
|
||||||
void onMouseMoveSecondary(SInt32 dx, SInt32 dy);
|
void onMouseMoveSecondary(SInt32 dx, SInt32 dy);
|
||||||
void onMouseWheel(SInt32 xDelta, SInt32 yDelta);
|
void onMouseWheel(SInt32 xDelta, SInt32 yDelta);
|
||||||
void onFileChunkSending(const void* data);
|
void onFileChunkSending(const void* data);
|
||||||
void onFileRecieveComplete();
|
void onFileRecieveCompleted();
|
||||||
|
|
||||||
// add client to list and attach event handlers for client
|
// add client to list and attach event handlers for client
|
||||||
bool addClient(CBaseClientProxy*);
|
bool addClient(CBaseClientProxy*);
|
||||||
|
|
|
@ -50,6 +50,10 @@
|
||||||
#include "COSXScreen.h"
|
#include "COSXScreen.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include "COSXDragSimulator.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
@ -531,7 +535,17 @@ CClientApp::mainLoop()
|
||||||
// later. the timer installed by startClient() will take care of
|
// later. the timer installed by startClient() will take care of
|
||||||
// that.
|
// that.
|
||||||
DAEMON_RUNNING(true);
|
DAEMON_RUNNING(true);
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
CThread thread(
|
||||||
|
new TMethodJob<CClientApp>(
|
||||||
|
this, &CClientApp::runEventsLoop,
|
||||||
|
NULL));
|
||||||
|
runCocoaApp();
|
||||||
|
#else
|
||||||
m_events->loop();
|
m_events->loop();
|
||||||
|
#endif
|
||||||
|
|
||||||
DAEMON_RUNNING(false);
|
DAEMON_RUNNING(false);
|
||||||
|
|
||||||
// close down
|
// close down
|
||||||
|
@ -612,3 +626,10 @@ CClientApp::startNode()
|
||||||
m_bye(kExitFailed);
|
m_bye(kExitFailed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CClientApp::runEventsLoop(void*)
|
||||||
|
{
|
||||||
|
m_events->cacheCurrentEventQueueRef();
|
||||||
|
m_events->loop();
|
||||||
|
}
|
||||||
|
|
|
@ -85,6 +85,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool parseArg(const int& argc, const char* const* argv, int& i);
|
virtual bool parseArg(const int& argc, const char* const* argv, int& i);
|
||||||
|
void runEventsLoop(void*);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CClient* s_client;
|
CClient* s_client;
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2013 Bolton Software Ltd.
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file COPYING that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CDragInformation.h"
|
||||||
|
#include "CLog.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
void
|
||||||
|
CDragInformation::parseDragInfo(CDragFileList& dragFileList, UInt32 fileNum, CString data)
|
||||||
|
{
|
||||||
|
size_t startPos = 0;
|
||||||
|
size_t findResult1 = 0;
|
||||||
|
size_t findResult2 = 0;
|
||||||
|
dragFileList.clear();
|
||||||
|
while (fileNum) {
|
||||||
|
findResult1 = data.find('\0', startPos);
|
||||||
|
findResult2 = data.find_last_of("\\", findResult1);
|
||||||
|
|
||||||
|
if (findResult1 == startPos) {
|
||||||
|
//TODO: file number does not match, something goes wrong
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (findResult1 - findResult2 > 1) {
|
||||||
|
dragFileList.push_back(data.substr(findResult2 + 1, findResult1 - findResult2));
|
||||||
|
}
|
||||||
|
startPos = findResult1 + 1;
|
||||||
|
--fileNum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CString
|
||||||
|
CDragInformation::getDragFileExtension(CString fileName)
|
||||||
|
{
|
||||||
|
size_t findResult = -1;
|
||||||
|
findResult = fileName.find_last_of(".", fileName.size());
|
||||||
|
if (findResult != -1) {
|
||||||
|
return fileName.substr(findResult + 1, fileName.size() - findResult - 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2013 Bolton Software Ltd.
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file COPYING that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "stdvector.h"
|
||||||
|
#include "CString.h"
|
||||||
|
#include "BasicTypes.h"
|
||||||
|
|
||||||
|
typedef std::vector<CString> CDragFileList;
|
||||||
|
|
||||||
|
class CDragInformation {
|
||||||
|
public:
|
||||||
|
CDragInformation() { }
|
||||||
|
|
||||||
|
~CDragInformation() { }
|
||||||
|
|
||||||
|
static void parseDragInfo(CDragFileList& dragFileList, UInt32 fileNum, CString data);
|
||||||
|
static CString getDragFileExtension(CString fileName);
|
||||||
|
};
|
|
@ -48,6 +48,7 @@ set(inc
|
||||||
CArgsBase.h
|
CArgsBase.h
|
||||||
IAppUtil.h
|
IAppUtil.h
|
||||||
CFileChunker.h
|
CFileChunker.h
|
||||||
|
CDragInformation.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(src
|
set(src
|
||||||
|
@ -75,6 +76,7 @@ set(src
|
||||||
CAppUtil.cpp
|
CAppUtil.cpp
|
||||||
CArgsBase.cpp
|
CArgsBase.cpp
|
||||||
CFileChunker.cpp
|
CFileChunker.cpp
|
||||||
|
CDragInformation.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#define CPLATFORMSCREEN_H
|
#define CPLATFORMSCREEN_H
|
||||||
|
|
||||||
#include "IPlatformScreen.h"
|
#include "IPlatformScreen.h"
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
//! Base screen implementation
|
//! Base screen implementation
|
||||||
/*!
|
/*!
|
||||||
|
@ -53,7 +54,7 @@ public:
|
||||||
|
|
||||||
// ISecondaryScreen overrides
|
// ISecondaryScreen overrides
|
||||||
virtual void fakeMouseButton(ButtonID id, bool press) = 0;
|
virtual void fakeMouseButton(ButtonID id, bool press) = 0;
|
||||||
virtual void fakeMouseMove(SInt32 x, SInt32 y) const = 0;
|
virtual void fakeMouseMove(SInt32 x, SInt32 y) = 0;
|
||||||
virtual void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const = 0;
|
virtual void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const = 0;
|
||||||
virtual void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const = 0;
|
virtual void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const = 0;
|
||||||
|
|
||||||
|
@ -76,6 +77,8 @@ public:
|
||||||
virtual SInt32 pollActiveGroup() const;
|
virtual SInt32 pollActiveGroup() const;
|
||||||
virtual void pollPressedKeys(KeyButtonSet& pressedKeys) const;
|
virtual void pollPressedKeys(KeyButtonSet& pressedKeys) const;
|
||||||
|
|
||||||
|
virtual void setDraggingStarted(bool started) { m_draggingStarted = started; }
|
||||||
|
virtual bool getDraggingStarted() { return m_draggingStarted; }
|
||||||
virtual CString& getDraggingFileDir() { return m_draggingFileDir; }
|
virtual CString& getDraggingFileDir() { return m_draggingFileDir; }
|
||||||
|
|
||||||
// IPlatformScreen overrides
|
// IPlatformScreen overrides
|
||||||
|
@ -93,6 +96,10 @@ public:
|
||||||
virtual void setSequenceNumber(UInt32) = 0;
|
virtual void setSequenceNumber(UInt32) = 0;
|
||||||
virtual bool isPrimary() const = 0;
|
virtual bool isPrimary() const = 0;
|
||||||
|
|
||||||
|
virtual void fakeDraggingFiles(CString str) { throw std::runtime_error("fakeDraggingFiles not implemented"); }
|
||||||
|
virtual const CString&
|
||||||
|
getDropTarget() const { throw std::runtime_error("getDropTarget not implemented"); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//! Update mouse buttons
|
//! Update mouse buttons
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -415,12 +415,36 @@ CScreen::pollActiveModifiers() const
|
||||||
return m_screen->pollActiveModifiers();
|
return m_screen->pollActiveModifiers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CScreen::getDraggingStarted() const
|
||||||
|
{
|
||||||
|
return m_screen->getDraggingStarted();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CScreen::setDraggingStarted(bool started)
|
||||||
|
{
|
||||||
|
m_screen->setDraggingStarted(started);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CScreen::startDraggingFiles(CString str)
|
||||||
|
{
|
||||||
|
m_screen->fakeDraggingFiles(str);
|
||||||
|
}
|
||||||
|
|
||||||
CString&
|
CString&
|
||||||
CScreen::getDraggingFileDir() const
|
CScreen::getDraggingFileDir() const
|
||||||
{
|
{
|
||||||
return m_screen->getDraggingFileDir();
|
return m_screen->getDraggingFileDir();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CString&
|
||||||
|
CScreen::getDropTarget() const
|
||||||
|
{
|
||||||
|
return m_screen->getDropTarget();
|
||||||
|
}
|
||||||
|
|
||||||
void*
|
void*
|
||||||
CScreen::getEventTarget() const
|
CScreen::getEventTarget() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -219,6 +219,12 @@ public:
|
||||||
*/
|
*/
|
||||||
void fakeInputEnd();
|
void fakeInputEnd();
|
||||||
|
|
||||||
|
//! Change dragging status
|
||||||
|
void setDraggingStarted(bool started);
|
||||||
|
|
||||||
|
//! Fake a files dragging operation
|
||||||
|
void startDraggingFiles(CString str);
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
//@{
|
//@{
|
||||||
|
@ -267,10 +273,18 @@ public:
|
||||||
*/
|
*/
|
||||||
KeyModifierMask pollActiveModifiers() const;
|
KeyModifierMask pollActiveModifiers() const;
|
||||||
|
|
||||||
|
//! Check if dragging has started.
|
||||||
|
|
||||||
|
bool getDraggingStarted() const;
|
||||||
|
|
||||||
//! Get dragging file's directory.
|
//! Get dragging file's directory.
|
||||||
|
|
||||||
CString& getDraggingFileDir() const;
|
CString& getDraggingFileDir() const;
|
||||||
|
|
||||||
|
//! Get drop target directory.
|
||||||
|
|
||||||
|
const CString& getDropTarget() const;
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
// IScreen overrides
|
// IScreen overrides
|
||||||
|
|
|
@ -130,6 +130,9 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void setSequenceNumber(UInt32) = 0;
|
virtual void setSequenceNumber(UInt32) = 0;
|
||||||
|
|
||||||
|
//! Change dragging status
|
||||||
|
virtual void setDraggingStarted(bool started) = 0;
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
//@{
|
//@{
|
||||||
|
@ -162,7 +165,7 @@ public:
|
||||||
|
|
||||||
// ISecondaryScreen overrides
|
// ISecondaryScreen overrides
|
||||||
virtual void fakeMouseButton(ButtonID id, bool press) = 0;
|
virtual void fakeMouseButton(ButtonID id, bool press) = 0;
|
||||||
virtual void fakeMouseMove(SInt32 x, SInt32 y) const = 0;
|
virtual void fakeMouseMove(SInt32 x, SInt32 y) = 0;
|
||||||
virtual void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const = 0;
|
virtual void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const = 0;
|
||||||
virtual void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const = 0;
|
virtual void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const = 0;
|
||||||
|
|
||||||
|
@ -186,6 +189,11 @@ public:
|
||||||
virtual void pollPressedKeys(KeyButtonSet& pressedKeys) const = 0;
|
virtual void pollPressedKeys(KeyButtonSet& pressedKeys) const = 0;
|
||||||
|
|
||||||
virtual CString& getDraggingFileDir() = 0;
|
virtual CString& getDraggingFileDir() = 0;
|
||||||
|
virtual bool getDraggingStarted() = 0;
|
||||||
|
|
||||||
|
virtual void fakeDraggingFiles(CString str) = 0;
|
||||||
|
virtual const CString&
|
||||||
|
getDropTarget() const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//! Handle system event
|
//! Handle system event
|
||||||
|
|
|
@ -44,7 +44,7 @@ public:
|
||||||
/*!
|
/*!
|
||||||
Synthesize a mouse move to the absolute coordinates \c x,y.
|
Synthesize a mouse move to the absolute coordinates \c x,y.
|
||||||
*/
|
*/
|
||||||
virtual void fakeMouseMove(SInt32 x, SInt32 y) const = 0;
|
virtual void fakeMouseMove(SInt32 x, SInt32 y) = 0;
|
||||||
|
|
||||||
//! Fake mouse move
|
//! Fake mouse move
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -46,6 +46,7 @@ const char* kMsgDInfo = "DINF%2i%2i%2i%2i%2i%2i%2i";
|
||||||
const char* kMsgDSetOptions = "DSOP%4I";
|
const char* kMsgDSetOptions = "DSOP%4I";
|
||||||
const char* kMsgDCryptoIv = "DCIV%s";
|
const char* kMsgDCryptoIv = "DCIV%s";
|
||||||
const char* kMsgDFileTransfer = "DFTR%1i%s";
|
const char* kMsgDFileTransfer = "DFTR%1i%s";
|
||||||
|
const char* kMsgDDragInfo = "DDRG%2i%s";
|
||||||
const char* kMsgQInfo = "QINF";
|
const char* kMsgQInfo = "QINF";
|
||||||
const char* kMsgEIncompatible = "EICV%2i%2i";
|
const char* kMsgEIncompatible = "EICV%2i%2i";
|
||||||
const char* kMsgEBusy = "EBSY";
|
const char* kMsgEBusy = "EBSY";
|
||||||
|
|
|
@ -263,6 +263,12 @@ extern const char* kMsgDCryptoIv;
|
||||||
// 2 means the file transfer is finished.
|
// 2 means the file transfer is finished.
|
||||||
extern const char* kMsgDFileTransfer;
|
extern const char* kMsgDFileTransfer;
|
||||||
|
|
||||||
|
// drag infomation: primary <-> secondary
|
||||||
|
// transfer drag infomation. The first 2 bytes are used for storing
|
||||||
|
// the number of dragging objects. Then the following string consists
|
||||||
|
// of each object's directory.
|
||||||
|
extern const char* kMsgDDragInfo;
|
||||||
|
|
||||||
//
|
//
|
||||||
// query codes
|
// query codes
|
||||||
//
|
//
|
||||||
|
|
|
@ -92,16 +92,16 @@ public:
|
||||||
void sendMockData(void* eventTarget);
|
void sendMockData(void* eventTarget);
|
||||||
|
|
||||||
void sendToClient_mockData_handleClientConnected(const CEvent&, void* vlistener);
|
void sendToClient_mockData_handleClientConnected(const CEvent&, void* vlistener);
|
||||||
void sendToClient_mockData_fileRecieveComplete(const CEvent&, void*);
|
void sendToClient_mockData_fileRecieveCompleted(const CEvent&, void*);
|
||||||
|
|
||||||
void sendToClient_mockFile_handleClientConnected(const CEvent&, void* vlistener);
|
void sendToClient_mockFile_handleClientConnected(const CEvent&, void* vlistener);
|
||||||
void sendToClient_mockFile_fileRecieveComplete(const CEvent& event, void*);
|
void sendToClient_mockFile_fileRecieveCompleted(const CEvent& event, void*);
|
||||||
|
|
||||||
void sendToServer_mockData_handleClientConnected(const CEvent&, void* vlistener);
|
void sendToServer_mockData_handleClientConnected(const CEvent&, void* vlistener);
|
||||||
void sendToServer_mockData_fileRecieveComplete(const CEvent& event, void*);
|
void sendToServer_mockData_fileRecieveCompleted(const CEvent& event, void*);
|
||||||
|
|
||||||
void sendToServer_mockFile_handleClientConnected(const CEvent&, void* vlistener);
|
void sendToServer_mockFile_handleClientConnected(const CEvent&, void* vlistener);
|
||||||
void sendToServer_mockFile_fileRecieveComplete(const CEvent& event, void*);
|
void sendToServer_mockFile_fileRecieveCompleted(const CEvent& event, void*);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CTestEventQueue m_events;
|
CTestEventQueue m_events;
|
||||||
|
@ -159,16 +159,16 @@ TEST_F(NetworkTests, sendToClient_mockData)
|
||||||
CClient client(&m_events, "stub", serverAddress, clientSocketFactory, NULL, &clientScreen, cryptoOptions);
|
CClient client(&m_events, "stub", serverAddress, clientSocketFactory, NULL, &clientScreen, cryptoOptions);
|
||||||
|
|
||||||
m_events.adoptHandler(
|
m_events.adoptHandler(
|
||||||
m_events.forIScreen().fileRecieveComplete(), &client,
|
m_events.forIScreen().fileRecieveCompleted(), &client,
|
||||||
new TMethodEventJob<NetworkTests>(
|
new TMethodEventJob<NetworkTests>(
|
||||||
this, &NetworkTests::sendToClient_mockData_fileRecieveComplete));
|
this, &NetworkTests::sendToClient_mockData_fileRecieveCompleted));
|
||||||
|
|
||||||
client.connect();
|
client.connect();
|
||||||
|
|
||||||
m_events.initQuitTimeout(10);
|
m_events.initQuitTimeout(10);
|
||||||
m_events.loop();
|
m_events.loop();
|
||||||
m_events.removeHandler(m_events.forCClientListener().connected(), &listener);
|
m_events.removeHandler(m_events.forCClientListener().connected(), &listener);
|
||||||
m_events.removeHandler(m_events.forIScreen().fileRecieveComplete(), &client);
|
m_events.removeHandler(m_events.forIScreen().fileRecieveCompleted(), &client);
|
||||||
m_events.cleanupQuitTimeout();
|
m_events.cleanupQuitTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,16 +220,16 @@ TEST_F(NetworkTests, sendToClient_mockFile)
|
||||||
CClient client(&m_events, "stub", serverAddress, clientSocketFactory, NULL, &clientScreen, cryptoOptions);
|
CClient client(&m_events, "stub", serverAddress, clientSocketFactory, NULL, &clientScreen, cryptoOptions);
|
||||||
|
|
||||||
m_events.adoptHandler(
|
m_events.adoptHandler(
|
||||||
m_events.forIScreen().fileRecieveComplete(), &client,
|
m_events.forIScreen().fileRecieveCompleted(), &client,
|
||||||
new TMethodEventJob<NetworkTests>(
|
new TMethodEventJob<NetworkTests>(
|
||||||
this, &NetworkTests::sendToClient_mockFile_fileRecieveComplete));
|
this, &NetworkTests::sendToClient_mockFile_fileRecieveCompleted));
|
||||||
|
|
||||||
client.connect();
|
client.connect();
|
||||||
|
|
||||||
m_events.initQuitTimeout(10);
|
m_events.initQuitTimeout(10);
|
||||||
m_events.loop();
|
m_events.loop();
|
||||||
m_events.removeHandler(m_events.forCClientListener().connected(), &listener);
|
m_events.removeHandler(m_events.forCClientListener().connected(), &listener);
|
||||||
m_events.removeHandler(m_events.forIScreen().fileRecieveComplete(), &client);
|
m_events.removeHandler(m_events.forIScreen().fileRecieveCompleted(), &client);
|
||||||
m_events.cleanupQuitTimeout();
|
m_events.cleanupQuitTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,16 +281,16 @@ TEST_F(NetworkTests, sendToServer_mockData)
|
||||||
this, &NetworkTests::sendToServer_mockData_handleClientConnected, &client));
|
this, &NetworkTests::sendToServer_mockData_handleClientConnected, &client));
|
||||||
|
|
||||||
m_events.adoptHandler(
|
m_events.adoptHandler(
|
||||||
m_events.forIScreen().fileRecieveComplete(), &server,
|
m_events.forIScreen().fileRecieveCompleted(), &server,
|
||||||
new TMethodEventJob<NetworkTests>(
|
new TMethodEventJob<NetworkTests>(
|
||||||
this, &NetworkTests::sendToServer_mockData_fileRecieveComplete));
|
this, &NetworkTests::sendToServer_mockData_fileRecieveCompleted));
|
||||||
|
|
||||||
client.connect();
|
client.connect();
|
||||||
|
|
||||||
m_events.initQuitTimeout(10);
|
m_events.initQuitTimeout(10);
|
||||||
m_events.loop();
|
m_events.loop();
|
||||||
m_events.removeHandler(m_events.forCClientListener().connected(), &listener);
|
m_events.removeHandler(m_events.forCClientListener().connected(), &listener);
|
||||||
m_events.removeHandler(m_events.forIScreen().fileRecieveComplete(), &server);
|
m_events.removeHandler(m_events.forIScreen().fileRecieveCompleted(), &server);
|
||||||
m_events.cleanupQuitTimeout();
|
m_events.cleanupQuitTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,16 +342,16 @@ TEST_F(NetworkTests, sendToServer_mockFile)
|
||||||
this, &NetworkTests::sendToServer_mockFile_handleClientConnected, &client));
|
this, &NetworkTests::sendToServer_mockFile_handleClientConnected, &client));
|
||||||
|
|
||||||
m_events.adoptHandler(
|
m_events.adoptHandler(
|
||||||
m_events.forIScreen().fileRecieveComplete(), &server,
|
m_events.forIScreen().fileRecieveCompleted(), &server,
|
||||||
new TMethodEventJob<NetworkTests>(
|
new TMethodEventJob<NetworkTests>(
|
||||||
this, &NetworkTests::sendToServer_mockFile_fileRecieveComplete));
|
this, &NetworkTests::sendToServer_mockFile_fileRecieveCompleted));
|
||||||
|
|
||||||
client.connect();
|
client.connect();
|
||||||
|
|
||||||
m_events.initQuitTimeout(10);
|
m_events.initQuitTimeout(10);
|
||||||
m_events.loop();
|
m_events.loop();
|
||||||
m_events.removeHandler(m_events.forCClientListener().connected(), &listener);
|
m_events.removeHandler(m_events.forCClientListener().connected(), &listener);
|
||||||
m_events.removeHandler(m_events.forIScreen().fileRecieveComplete(), &server);
|
m_events.removeHandler(m_events.forIScreen().fileRecieveCompleted(), &server);
|
||||||
m_events.cleanupQuitTimeout();
|
m_events.cleanupQuitTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,7 +374,7 @@ NetworkTests::sendToClient_mockData_handleClientConnected(const CEvent&, void* v
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
NetworkTests::sendToClient_mockData_fileRecieveComplete(const CEvent& event, void*)
|
NetworkTests::sendToClient_mockData_fileRecieveCompleted(const CEvent& event, void*)
|
||||||
{
|
{
|
||||||
CClient* client = reinterpret_cast<CClient*>(event.getTarget());
|
CClient* client = reinterpret_cast<CClient*>(event.getTarget());
|
||||||
EXPECT_TRUE(client->isReceivedFileSizeValid());
|
EXPECT_TRUE(client->isReceivedFileSizeValid());
|
||||||
|
@ -401,7 +401,7 @@ NetworkTests::sendToClient_mockFile_handleClientConnected(const CEvent&, void* v
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
NetworkTests::sendToClient_mockFile_fileRecieveComplete(const CEvent& event, void*)
|
NetworkTests::sendToClient_mockFile_fileRecieveCompleted(const CEvent& event, void*)
|
||||||
{
|
{
|
||||||
CClient* client = reinterpret_cast<CClient*>(event.getTarget());
|
CClient* client = reinterpret_cast<CClient*>(event.getTarget());
|
||||||
EXPECT_TRUE(client->isReceivedFileSizeValid());
|
EXPECT_TRUE(client->isReceivedFileSizeValid());
|
||||||
|
@ -417,7 +417,7 @@ NetworkTests::sendToServer_mockData_handleClientConnected(const CEvent&, void* v
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
NetworkTests::sendToServer_mockData_fileRecieveComplete(const CEvent& event, void*)
|
NetworkTests::sendToServer_mockData_fileRecieveCompleted(const CEvent& event, void*)
|
||||||
{
|
{
|
||||||
CServer* server = reinterpret_cast<CServer*>(event.getTarget());
|
CServer* server = reinterpret_cast<CServer*>(event.getTarget());
|
||||||
EXPECT_TRUE(server->isReceivedFileSizeValid());
|
EXPECT_TRUE(server->isReceivedFileSizeValid());
|
||||||
|
@ -433,7 +433,7 @@ NetworkTests::sendToServer_mockFile_handleClientConnected(const CEvent&, void* v
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
NetworkTests::sendToServer_mockFile_fileRecieveComplete(const CEvent& event, void*)
|
NetworkTests::sendToServer_mockFile_fileRecieveCompleted(const CEvent& event, void*)
|
||||||
{
|
{
|
||||||
CServer* server = reinterpret_cast<CServer*>(event.getTarget());
|
CServer* server = reinterpret_cast<CServer*>(event.getTarget());
|
||||||
EXPECT_TRUE(server->isReceivedFileSizeValid());
|
EXPECT_TRUE(server->isReceivedFileSizeValid());
|
||||||
|
|
|
@ -61,6 +61,7 @@ public:
|
||||||
MOCK_METHOD0(forIKeyState, IKeyStateEvents&());
|
MOCK_METHOD0(forIKeyState, IKeyStateEvents&());
|
||||||
MOCK_METHOD0(forIPrimaryScreen, IPrimaryScreenEvents&());
|
MOCK_METHOD0(forIPrimaryScreen, IPrimaryScreenEvents&());
|
||||||
MOCK_METHOD0(forIScreen, IScreenEvents&());
|
MOCK_METHOD0(forIScreen, IScreenEvents&());
|
||||||
|
MOCK_METHOD0(cacheCurrentEventQueueRef, void());
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue