used a hidden drop window to get drag filename
This commit is contained in:
parent
7b8cdb6b38
commit
b85a9b628e
|
@ -0,0 +1,178 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2014 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 "platform/MSWindowsDropTarget.h"
|
||||||
|
|
||||||
|
#include "base/Log.h"
|
||||||
|
#include "common/common.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <Shlobj.h>
|
||||||
|
|
||||||
|
void getDropData(IDataObject *pDataObject);
|
||||||
|
|
||||||
|
CMSWindowsDropTarget* CMSWindowsDropTarget::s_instance = NULL;
|
||||||
|
|
||||||
|
CMSWindowsDropTarget::CMSWindowsDropTarget() :
|
||||||
|
m_refCount(1),
|
||||||
|
m_allowDrop(false)
|
||||||
|
{
|
||||||
|
s_instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMSWindowsDropTarget::~CMSWindowsDropTarget()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CMSWindowsDropTarget&
|
||||||
|
CMSWindowsDropTarget::instance()
|
||||||
|
{
|
||||||
|
assert(s_instance != NULL);
|
||||||
|
return *s_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT
|
||||||
|
CMSWindowsDropTarget::DragEnter(IDataObject* dataObject, DWORD keyState, POINTL point, DWORD* effect)
|
||||||
|
{
|
||||||
|
// check if data object contain drop
|
||||||
|
m_allowDrop = queryDataObject(dataObject);
|
||||||
|
if (m_allowDrop) {
|
||||||
|
getDropData(dataObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
*effect = DROPEFFECT_NONE;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT
|
||||||
|
CMSWindowsDropTarget::DragOver(DWORD keyState, POINTL point, DWORD* effect)
|
||||||
|
{
|
||||||
|
*effect = DROPEFFECT_NONE;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT
|
||||||
|
CMSWindowsDropTarget::DragLeave(void)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT
|
||||||
|
CMSWindowsDropTarget::Drop(IDataObject* dataObject, DWORD keyState, POINTL point, DWORD* effect)
|
||||||
|
{
|
||||||
|
*effect = DROPEFFECT_NONE;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CMSWindowsDropTarget::queryDataObject(IDataObject* dataObject)
|
||||||
|
{
|
||||||
|
// check if it supports CF_HDROP using a HGLOBAL
|
||||||
|
FORMATETC fmtetc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||||
|
|
||||||
|
return dataObject->QueryGetData(&fmtetc) == S_OK ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsDropTarget::setDraggingFilename(char* const filename)
|
||||||
|
{
|
||||||
|
m_dragFilename = filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
CMSWindowsDropTarget::getDraggingFilename()
|
||||||
|
{
|
||||||
|
return m_dragFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsDropTarget::clearDraggingFilename()
|
||||||
|
{
|
||||||
|
m_dragFilename.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
getDropData(IDataObject* dataObject)
|
||||||
|
{
|
||||||
|
// construct a FORMATETC object
|
||||||
|
FORMATETC fmtEtc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||||
|
STGMEDIUM stgMed;
|
||||||
|
|
||||||
|
// See if the dataobject contains any DROP stored as a HGLOBAL
|
||||||
|
if(dataObject->QueryGetData(&fmtEtc) == S_OK) {
|
||||||
|
if(dataObject->GetData(&fmtEtc, &stgMed) == S_OK) {
|
||||||
|
// get data here
|
||||||
|
PVOID data = GlobalLock(stgMed.hGlobal);
|
||||||
|
|
||||||
|
// data object global handler contains:
|
||||||
|
// DROPFILESfilename1 filename2 two spaces as the end
|
||||||
|
// TODO: get multiple filenames
|
||||||
|
wchar_t* wcData = (wchar_t*)((LPBYTE)data + sizeof(DROPFILES));
|
||||||
|
|
||||||
|
// convert wchar to char
|
||||||
|
char* filename = new char[wcslen(wcData) + 1];
|
||||||
|
filename[wcslen(wcData)] = '\0';
|
||||||
|
wcstombs(filename, wcData, wcslen(wcData));
|
||||||
|
|
||||||
|
CMSWindowsDropTarget::instance().setDraggingFilename(filename);
|
||||||
|
|
||||||
|
GlobalUnlock(stgMed.hGlobal);
|
||||||
|
|
||||||
|
// release the data using the COM API
|
||||||
|
ReleaseStgMedium(&stgMed);
|
||||||
|
|
||||||
|
delete[] filename;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT __stdcall
|
||||||
|
CMSWindowsDropTarget::QueryInterface (REFIID iid, void ** object)
|
||||||
|
{
|
||||||
|
if (iid == IID_IDropTarget || iid == IID_IUnknown) {
|
||||||
|
AddRef();
|
||||||
|
*object = this;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*object = 0;
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG __stdcall
|
||||||
|
CMSWindowsDropTarget::AddRef(void)
|
||||||
|
{
|
||||||
|
return InterlockedIncrement(&m_refCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG __stdcall
|
||||||
|
CMSWindowsDropTarget::Release(void)
|
||||||
|
{
|
||||||
|
LONG count = InterlockedDecrement(&m_refCount);
|
||||||
|
|
||||||
|
if (count == 0) {
|
||||||
|
delete this;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2014 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 <string>
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <oleidl.h>
|
||||||
|
|
||||||
|
class CMSWindowsScreen;
|
||||||
|
|
||||||
|
class CMSWindowsDropTarget : public IDropTarget {
|
||||||
|
public:
|
||||||
|
CMSWindowsDropTarget();
|
||||||
|
~CMSWindowsDropTarget();
|
||||||
|
|
||||||
|
// IUnknown implementation
|
||||||
|
HRESULT __stdcall QueryInterface(REFIID iid, void** object);
|
||||||
|
ULONG __stdcall AddRef(void);
|
||||||
|
ULONG __stdcall Release(void);
|
||||||
|
|
||||||
|
// IDropTarget implementation
|
||||||
|
HRESULT __stdcall DragEnter(IDataObject* dataObject, DWORD keyState, POINTL point, DWORD* effect);
|
||||||
|
HRESULT __stdcall DragOver(DWORD keyState, POINTL point, DWORD* effect);
|
||||||
|
HRESULT __stdcall DragLeave(void);
|
||||||
|
HRESULT __stdcall Drop(IDataObject* dataObject, DWORD keyState, POINTL point, DWORD* effect);
|
||||||
|
|
||||||
|
void setDraggingFilename(char* const);
|
||||||
|
std::string getDraggingFilename();
|
||||||
|
void clearDraggingFilename();
|
||||||
|
|
||||||
|
static CMSWindowsDropTarget&
|
||||||
|
instance();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool queryDataObject(IDataObject* dataObject);
|
||||||
|
|
||||||
|
long m_refCount;
|
||||||
|
bool m_allowDrop;
|
||||||
|
std::string m_dragFilename;
|
||||||
|
|
||||||
|
static CMSWindowsDropTarget*
|
||||||
|
s_instance;
|
||||||
|
};
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "platform/MSWindowsScreen.h"
|
#include "platform/MSWindowsScreen.h"
|
||||||
|
|
||||||
|
#include "platform/MSWindowsDropTarget.h"
|
||||||
#include "client/Client.h"
|
#include "client/Client.h"
|
||||||
#include "platform/MSWindowsClipboard.h"
|
#include "platform/MSWindowsClipboard.h"
|
||||||
#include "platform/MSWindowsDesks.h"
|
#include "platform/MSWindowsDesks.h"
|
||||||
|
@ -118,7 +119,9 @@ CMSWindowsScreen::CMSWindowsScreen(
|
||||||
m_keyState(NULL),
|
m_keyState(NULL),
|
||||||
m_hasMouse(GetSystemMetrics(SM_MOUSEPRESENT) != 0),
|
m_hasMouse(GetSystemMetrics(SM_MOUSEPRESENT) != 0),
|
||||||
m_showingMouse(false),
|
m_showingMouse(false),
|
||||||
m_events(events)
|
m_events(events),
|
||||||
|
m_dropWindow(NULL),
|
||||||
|
m_dropWindowSize(20)
|
||||||
{
|
{
|
||||||
assert(s_windowInstance != NULL);
|
assert(s_windowInstance != NULL);
|
||||||
assert(s_screen == NULL);
|
assert(s_screen == NULL);
|
||||||
|
@ -157,6 +160,11 @@ CMSWindowsScreen::CMSWindowsScreen(
|
||||||
else {
|
else {
|
||||||
LOG((CLOG_ERR "failed to get desktop path, no drop target available, error=%d", GetLastError()));
|
LOG((CLOG_ERR "failed to get desktop path, no drop target available, error=%d", GetLastError()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OleInitialize(0);
|
||||||
|
m_dropWindow = createDropWindow(m_class, "DropWindow");
|
||||||
|
m_dropTarget = new CMSWindowsDropTarget();
|
||||||
|
RegisterDragDrop(m_dropWindow, m_dropTarget);
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
delete m_keyState;
|
delete m_keyState;
|
||||||
|
@ -190,6 +198,11 @@ CMSWindowsScreen::~CMSWindowsScreen()
|
||||||
destroyWindow(m_window);
|
destroyWindow(m_window);
|
||||||
destroyClass(m_class);
|
destroyClass(m_class);
|
||||||
|
|
||||||
|
RevokeDragDrop(m_dropWindow);
|
||||||
|
m_dropTarget->Release();
|
||||||
|
OleUninitialize();
|
||||||
|
destroyWindow(m_dropWindow);
|
||||||
|
|
||||||
s_screen = NULL;
|
s_screen = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,32 +358,33 @@ CMSWindowsScreen::leave()
|
||||||
m_isOnScreen = false;
|
m_isOnScreen = false;
|
||||||
forceShowCursor();
|
forceShowCursor();
|
||||||
|
|
||||||
if (isDraggingStarted()) {
|
if (isDraggingStarted() && !m_isPrimary) {
|
||||||
CString& draggingFilename = getDraggingFilename();
|
m_sendDragThread = new CThread(
|
||||||
size_t size = draggingFilename.size();
|
new TMethodJob<CMSWindowsScreen>(
|
||||||
|
this,
|
||||||
|
&CMSWindowsScreen::sendDragThread));
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_isPrimary) {
|
return true;
|
||||||
// TODO: fake these keys properly
|
}
|
||||||
fakeKeyDown(kKeyEscape, 8192, 1);
|
|
||||||
fakeKeyUp(1);
|
|
||||||
|
|
||||||
fakeMouseButton(kButtonLeft, false);
|
void
|
||||||
|
CMSWindowsScreen::sendDragThread(void*)
|
||||||
|
{
|
||||||
|
CString& draggingFilename = getDraggingFilename();
|
||||||
|
size_t size = draggingFilename.size();
|
||||||
|
|
||||||
if (draggingFilename.empty() == false) {
|
if (draggingFilename.empty() == false) {
|
||||||
CClientApp& app = CClientApp::instance();
|
CClientApp& app = CClientApp::instance();
|
||||||
CClient* client = app.getClientPtr();
|
CClient* client = app.getClientPtr();
|
||||||
UInt32 fileCount = 1;
|
UInt32 fileCount = 1;
|
||||||
LOG((CLOG_DEBUG "send dragging info to server: %s", draggingFilename.c_str()));
|
LOG((CLOG_DEBUG "send dragging info to server: %s", draggingFilename.c_str()));
|
||||||
client->draggingInfoSending(fileCount, draggingFilename, size);
|
client->draggingInfoSending(fileCount, draggingFilename, size);
|
||||||
LOG((CLOG_DEBUG "send dragging file to server"));
|
LOG((CLOG_DEBUG "send dragging file to server"));
|
||||||
client->sendFileToServer(draggingFilename.c_str());
|
client->sendFileToServer(draggingFilename.c_str());
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_draggingStarted = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
m_draggingStarted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -858,6 +872,29 @@ CMSWindowsScreen::createWindow(ATOM windowClass, const char* name) const
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HWND
|
||||||
|
CMSWindowsScreen::createDropWindow(ATOM windowClass, const char* name) const
|
||||||
|
{
|
||||||
|
HWND window = CreateWindowEx(
|
||||||
|
WS_EX_TOPMOST |
|
||||||
|
WS_EX_TRANSPARENT |
|
||||||
|
WS_EX_ACCEPTFILES,
|
||||||
|
reinterpret_cast<LPCTSTR>(m_class),
|
||||||
|
name,
|
||||||
|
WS_POPUP,
|
||||||
|
0, 0, m_dropWindowSize, m_dropWindowSize,
|
||||||
|
NULL, NULL,
|
||||||
|
s_windowInstance,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (window == NULL) {
|
||||||
|
LOG((CLOG_ERR "failed to create drop window: %d", GetLastError()));
|
||||||
|
throw XScreenOpenFailure();
|
||||||
|
}
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CMSWindowsScreen::destroyWindow(HWND hwnd) const
|
CMSWindowsScreen::destroyWindow(HWND hwnd) const
|
||||||
{
|
{
|
||||||
|
@ -1801,9 +1838,48 @@ CString&
|
||||||
CMSWindowsScreen::getDraggingFilename()
|
CMSWindowsScreen::getDraggingFilename()
|
||||||
{
|
{
|
||||||
if (m_draggingStarted) {
|
if (m_draggingStarted) {
|
||||||
char filename[MAX_PATH];
|
m_dropTarget->clearDraggingFilename();
|
||||||
m_shellEx.getDraggingFilename(filename);
|
m_draggingFilename.clear();
|
||||||
m_draggingFilename = filename;
|
|
||||||
|
int halfSize = m_dropWindowSize / 2;
|
||||||
|
|
||||||
|
SInt32 xPos = m_isPrimary ? m_xCursor : m_xCenter;
|
||||||
|
SInt32 yPos = m_isPrimary ? m_yCursor : m_yCenter;
|
||||||
|
xPos = (xPos - halfSize) < 0 ? 0 : xPos - halfSize;
|
||||||
|
yPos = (yPos - halfSize) < 0 ? 0 : yPos - halfSize;
|
||||||
|
SetWindowPos(
|
||||||
|
m_dropWindow,
|
||||||
|
HWND_TOPMOST,
|
||||||
|
xPos,
|
||||||
|
yPos,
|
||||||
|
m_dropWindowSize,
|
||||||
|
m_dropWindowSize,
|
||||||
|
SWP_SHOWWINDOW);
|
||||||
|
|
||||||
|
// TODO: fake these keys properly
|
||||||
|
fakeKeyDown(kKeyEscape, 8192, 1);
|
||||||
|
fakeKeyUp(1);
|
||||||
|
fakeMouseButton(kButtonLeft, false);
|
||||||
|
|
||||||
|
CString filename;
|
||||||
|
DOUBLE timeout = ARCH->time() + .5f;
|
||||||
|
while (ARCH->time() < timeout) {
|
||||||
|
ARCH->sleep(.05f);
|
||||||
|
filename = m_dropTarget->getDraggingFilename();
|
||||||
|
if (!filename.empty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowWindow(m_dropWindow, SW_HIDE);
|
||||||
|
|
||||||
|
if (!filename.empty()) {
|
||||||
|
m_draggingFilename = filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_draggingFilename.empty()) {
|
||||||
|
LOG((CLOG_DEBUG "failed to get drag file name from OLE"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_draggingFilename;
|
return m_draggingFilename;
|
||||||
|
|
|
@ -34,6 +34,7 @@ class CMSWindowsDesks;
|
||||||
class CMSWindowsKeyState;
|
class CMSWindowsKeyState;
|
||||||
class CMSWindowsScreenSaver;
|
class CMSWindowsScreenSaver;
|
||||||
class CThread;
|
class CThread;
|
||||||
|
class CMSWindowsDropTarget;
|
||||||
|
|
||||||
//! Implementation of IPlatformScreen for Microsoft Windows
|
//! Implementation of IPlatformScreen for Microsoft Windows
|
||||||
class CMSWindowsScreen : public CPlatformScreen {
|
class CMSWindowsScreen : public CPlatformScreen {
|
||||||
|
@ -135,6 +136,7 @@ private:
|
||||||
ATOM createDeskWindowClass(bool isPrimary) const;
|
ATOM createDeskWindowClass(bool isPrimary) const;
|
||||||
void destroyClass(ATOM windowClass) const;
|
void destroyClass(ATOM windowClass) const;
|
||||||
HWND createWindow(ATOM windowClass, const char* name) const;
|
HWND createWindow(ATOM windowClass, const char* name) const;
|
||||||
|
HWND createDropWindow(ATOM windowClass, const char* name) const;
|
||||||
void destroyWindow(HWND) const;
|
void destroyWindow(HWND) const;
|
||||||
|
|
||||||
// convenience function to send events
|
// convenience function to send events
|
||||||
|
@ -216,6 +218,9 @@ private: // HACK
|
||||||
bool isModifierRepeat(KeyModifierMask oldState,
|
bool isModifierRepeat(KeyModifierMask oldState,
|
||||||
KeyModifierMask state, WPARAM wParam) const;
|
KeyModifierMask state, WPARAM wParam) const;
|
||||||
|
|
||||||
|
// send drag info and data back to server
|
||||||
|
void sendDragThread(void*);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct CHotKeyItem {
|
struct CHotKeyItem {
|
||||||
public:
|
public:
|
||||||
|
@ -325,4 +330,11 @@ private:
|
||||||
IEventQueue* m_events;
|
IEventQueue* m_events;
|
||||||
|
|
||||||
CString m_desktopPath;
|
CString m_desktopPath;
|
||||||
|
|
||||||
|
CMSWindowsDropTarget*
|
||||||
|
m_dropTarget;
|
||||||
|
HWND m_dropWindow;
|
||||||
|
const int m_dropWindowSize;
|
||||||
|
|
||||||
|
CThread* m_sendDragThread;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2102,6 +2102,11 @@ COSXScreen::getDraggingFilename()
|
||||||
CString fileList(info);
|
CString fileList(info);
|
||||||
m_draggingFilename = fileList;
|
m_draggingFilename = fileList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fake a escape key down and up then left mouse button up
|
||||||
|
fakeKeyDown(kKeyEscape, 8192, 1);
|
||||||
|
fakeKeyUp(1);
|
||||||
|
fakeMouseButton(kButtonLeft, false);
|
||||||
}
|
}
|
||||||
return m_draggingFilename;
|
return m_draggingFilename;
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,9 @@ CServer::CServer(
|
||||||
m_sendFileThread(NULL),
|
m_sendFileThread(NULL),
|
||||||
m_writeToDropDirThread(NULL),
|
m_writeToDropDirThread(NULL),
|
||||||
m_ignoreFileTransfer(false),
|
m_ignoreFileTransfer(false),
|
||||||
m_enableDragDrop(enableDragDrop)
|
m_enableDragDrop(enableDragDrop),
|
||||||
|
m_getDragInfoThread(NULL),
|
||||||
|
m_waitDragInfoThread(true)
|
||||||
{
|
{
|
||||||
// must have a primary client and it must have a canonical name
|
// must have a primary client and it must have a canonical name
|
||||||
assert(m_primaryClient != NULL);
|
assert(m_primaryClient != NULL);
|
||||||
|
@ -1658,6 +1660,9 @@ CServer::onMouseDown(ButtonID id)
|
||||||
|
|
||||||
// relay
|
// relay
|
||||||
m_active->mouseDown(id);
|
m_active->mouseDown(id);
|
||||||
|
|
||||||
|
// reset this variable back to default value true
|
||||||
|
m_waitDragInfoThread = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1759,46 +1764,76 @@ 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_enableDragDrop && m_screen->isDraggingStarted() && m_active != newScreen) {
|
if (m_enableDragDrop
|
||||||
CString& dragFileList = m_screen->getDraggingFilename();
|
&& m_screen->isDraggingStarted()
|
||||||
size_t size = dragFileList.size() + 1;
|
&& m_active != newScreen
|
||||||
char* fileList = NULL;
|
&& m_waitDragInfoThread) {
|
||||||
UInt32 fileCount = 1;
|
if (m_getDragInfoThread == NULL) {
|
||||||
if (dragFileList.empty() == false) {
|
m_getDragInfoThread = new CThread(
|
||||||
fileList = new char[size];
|
new TMethodJob<CServer>(
|
||||||
memcpy(fileList, dragFileList.c_str(), size);
|
this,
|
||||||
fileList[size - 1] = '\0';
|
&CServer::getDragInfoThread));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_getDragInfoThread == NULL) {
|
||||||
|
// switch screen
|
||||||
|
switchScreen(newScreen, x, y, false);
|
||||||
|
|
||||||
|
// send drag file info to client if there is any
|
||||||
|
if (m_dragFileList.size() > 0) {
|
||||||
|
sendDragInfo(newScreen);
|
||||||
|
m_dragFileList.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// fake a escape key down and up then left mouse button up
|
m_waitDragInfoThread = true;
|
||||||
m_screen->keyDown(kKeyEscape, 8192, 1);
|
|
||||||
m_screen->keyUp(kKeyEscape, 8192, 1);
|
return true;
|
||||||
m_screen->mouseUp(kButtonLeft);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CServer::getDragInfoThread(void*)
|
||||||
|
{
|
||||||
|
m_dragFileList.clear();
|
||||||
|
CString& dragFileList = m_screen->getDraggingFilename();
|
||||||
|
if (!dragFileList.empty()) {
|
||||||
|
m_dragFileList.push_back(dragFileList);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
|
// on mac it seems that after faking a LMB up, system would signal back
|
||||||
// on mac it seems that after faking a LMB up, system would signal back
|
// to synergy a mouse up event, which doesn't happen on windows. as a
|
||||||
// to synergy a mouse up event, which doesn't happen on windows. as a
|
// result, synergy would send dragging file to client twice. This variable
|
||||||
// result, synergy would send dragging file to client twice. This variable
|
// is used to ignore the first file sending.
|
||||||
// is used to ignore the first file sending.
|
m_ignoreFileTransfer = true;
|
||||||
m_ignoreFileTransfer = true;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (dragFileList.empty() == false) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// switch screen
|
m_waitDragInfoThread = false;
|
||||||
switchScreen(newScreen, x, y, false);
|
m_getDragInfoThread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
void
|
||||||
}
|
CServer::sendDragInfo(CBaseClientProxy* newScreen)
|
||||||
else {
|
{
|
||||||
return false;
|
// TODO: support multiple files dragging
|
||||||
|
CString& dragFile = m_dragFileList.at(0);
|
||||||
|
size_t size = dragFile.size() + 1;
|
||||||
|
char* fileList = NULL;
|
||||||
|
UInt32 fileCount = 1;
|
||||||
|
if (dragFile.empty() == false) {
|
||||||
|
fileList = new char[size];
|
||||||
|
memcpy(fileList, dragFile.c_str(), size);
|
||||||
|
fileList[size - 1] = '\0';
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -365,6 +365,12 @@ private:
|
||||||
// thread function for writing file to drop directory
|
// thread function for writing file to drop directory
|
||||||
void writeToDropDirThread(void*);
|
void writeToDropDirThread(void*);
|
||||||
|
|
||||||
|
// thread function for getting drag filename
|
||||||
|
void getDragInfoThread(void*);
|
||||||
|
|
||||||
|
// send drag info to new client screen
|
||||||
|
void sendDragInfo(CBaseClientProxy* newScreen);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool m_mock;
|
bool m_mock;
|
||||||
|
|
||||||
|
@ -472,4 +478,7 @@ private:
|
||||||
CString m_dragFileExt;
|
CString m_dragFileExt;
|
||||||
bool m_ignoreFileTransfer;
|
bool m_ignoreFileTransfer;
|
||||||
bool m_enableDragDrop;
|
bool m_enableDragDrop;
|
||||||
|
|
||||||
|
CThread* m_getDragInfoThread;
|
||||||
|
bool m_waitDragInfoThread;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue