feat: remove drag and drop support, its broken on all platforms

This commit is contained in:
sithlord48
2025-05-04 21:47:44 -04:00
committed by Chris Rizzitello
parent 55a7fa3266
commit 5365e34f08
41 changed files with 64 additions and 1989 deletions

View File

@ -227,15 +227,6 @@ enum class EventTypes : uint32_t
/// This event is sent whenever a clipboard chunk is transferred.
ClipboardSending,
/// This event is sent whenever a file chunk is transferred.
FileChunkSending,
/// This event is sent whenever file has been received.
FileReceiveCompleted,
/// This event is a keepalive event.
FileKeepAlive,
/// Start libEI
EIConnected,
/// Stop libEi

View File

@ -15,8 +15,6 @@
#include "base/TMethodJob.h"
#include "client/ServerProxy.h"
#include "deskflow/AppUtil.h"
#include "deskflow/DropHelper.h"
#include "deskflow/FileChunk.h"
#include "deskflow/IPlatformScreen.h"
#include "deskflow/PacketStreamFilter.h"
#include "deskflow/ProtocolTypes.h"
@ -63,8 +61,6 @@ Client::Client(
m_suspended(false),
m_connectOnResume(false),
m_events(events),
m_sendFileThread(nullptr),
m_writeToDropDirThread(nullptr),
m_useSecureNetwork(args.m_enableCrypto),
m_args(args),
m_enableClipboard(true),
@ -81,15 +77,6 @@ Client::Client(
EventTypes::ScreenResume, getEventTarget(), new TMethodEventJob<Client>(this, &Client::handleResume)
);
if (m_args.m_enableDragDrop) {
m_events->adoptHandler(
EventTypes::FileChunkSending, this, new TMethodEventJob<Client>(this, &Client::handleFileChunkSending)
);
m_events->adoptHandler(
EventTypes::FileReceiveCompleted, this, new TMethodEventJob<Client>(this, &Client::handleFileReceiveCompleted)
);
}
m_pHelloBack = std::make_unique<HelloBack>(std::make_shared<HelloBack::Deps>(
[this]() {
sendConnectionFailedEvent("got invalid hello message from server");
@ -241,11 +228,6 @@ void Client::enter(int32_t xAbs, int32_t yAbs, uint32_t, KeyModifierMask mask, b
m_active = true;
m_screen->mouseMove(xAbs, yAbs);
m_screen->enter(mask);
if (m_sendFileThread) {
StreamChunker::interruptFile();
m_sendFileThread.reset(nullptr);
}
}
bool Client::leave()
@ -422,16 +404,6 @@ void Client::sendConnectionFailedEvent(const char *msg)
m_events->addEvent(event);
}
void Client::sendFileChunk(const void *data)
{
auto *chunk = static_cast<FileChunk *>(const_cast<void *>(data));
LOG((CLOG_DEBUG1 "send file chunk"));
assert(m_server != nullptr);
// relay
m_server->fileChunkSending(chunk->m_chunk[0], &chunk->m_chunk[1], chunk->m_dataSize);
}
void Client::setupConnecting()
{
assert(m_stream != nullptr);
@ -686,24 +658,6 @@ void Client::handleResume(const Event &, void *)
}
}
void Client::handleFileChunkSending(const Event &event, void *)
{
sendFileChunk(event.getDataObject());
}
void Client::handleFileReceiveCompleted(const Event &event, void *)
{
onFileReceiveCompleted();
}
void Client::onFileReceiveCompleted()
{
if (isReceivedFileSizeValid()) {
auto method = new TMethodJob<Client>(this, &Client::writeToDropDirThread);
m_writeToDropDirThread.reset(new Thread(method));
}
}
void Client::bindNetworkInterface(IDataSocket *socket) const
{
try {
@ -725,60 +679,3 @@ void Client::handleStopRetry(const Event &, void *)
{
m_args.m_restartable = false;
}
void Client::writeToDropDirThread(void *)
{
LOG((CLOG_DEBUG "starting write to drop dir thread"));
while (m_screen->isFakeDraggingStarted()) {
ARCH->sleep(.1f);
}
DropHelper::writeToDir(m_screen->getDropTarget(), m_dragFileList, m_receivedFileData);
}
void Client::dragInfoReceived(uint32_t fileNum, std::string data)
{
// TODO: fix duplicate function from CServer
if (!m_args.m_enableDragDrop) {
LOG((CLOG_DEBUG "drag drop not enabled, ignoring drag info."));
return;
}
DragInformation::parseDragInfo(m_dragFileList, fileNum, data);
m_screen->startDraggingFiles(m_dragFileList);
}
bool Client::isReceivedFileSizeValid()
{
return m_expectedFileSize == m_receivedFileData.size();
}
void Client::sendFileToServer(const char *filename)
{
if (m_sendFileThread) {
StreamChunker::interruptFile();
}
auto data = static_cast<void *>(const_cast<char *>(filename));
auto method = new TMethodJob<Client>(this, &Client::sendFileThread, data);
m_sendFileThread.reset(new Thread(method));
}
void Client::sendFileThread(void *filename)
{
try {
auto *name = static_cast<char *>(filename);
StreamChunker::sendFile(name, m_events, this);
} catch (std::runtime_error &error) {
LOG((CLOG_ERR "failed sending file chunks: %s", error.what()));
}
m_sendFileThread.reset(nullptr);
}
void Client::sendDragInfo(uint32_t fileCount, std::string &info, size_t size)
{
m_server->sendDragInfo(fileCount, info.c_str(), size);
}

View File

@ -13,7 +13,6 @@
#include "base/EventTypes.h"
#include "deskflow/ClientArgs.h"
#include "deskflow/Clipboard.h"
#include "deskflow/DragInformation.h"
#include "deskflow/INode.h"
#include "mt/CondVar.h"
#include "net/NetworkAddress.h"
@ -97,15 +96,6 @@ public:
*/
virtual void handshakeComplete();
//! Received drag information
void dragInfoReceived(uint32_t fileNum, std::string data);
//! Create a new thread and use it to send file to Server
void sendFileToServer(const char *filename);
//! Send dragging file information back to server
void sendDragInfo(uint32_t fileCount, std::string &info, size_t size);
//@}
//! @name accessors
//@{
@ -130,27 +120,6 @@ public:
*/
NetworkAddress getServerAddress() const;
//! Return true if received file size is valid
bool isReceivedFileSizeValid();
//! Return expected file size
size_t &getExpectedFileSize()
{
return m_expectedFileSize;
}
//! Return received file data
std::string &getReceivedFileData()
{
return m_receivedFileData;
}
//! Return drag file list
DragFileList getDragFileList()
{
return m_dragFileList;
}
//! Return last resolved adresses count
size_t getLastResolvedAddressesCount() const
{
@ -188,9 +157,6 @@ private:
void sendClipboard(ClipboardID);
void sendEvent(EventTypes, void *);
void sendConnectionFailedEvent(const char *msg);
void sendFileChunk(const void *data);
void sendFileThread(void *);
void writeToDropDirThread(void *);
void setupConnecting();
void setupConnection();
void setupScreen();
@ -211,10 +177,7 @@ private:
void handleHello(const Event &, void *);
void handleSuspend(const Event &event, void *);
void handleResume(const Event &event, void *);
void handleFileChunkSending(const Event &, void *);
void handleFileReceiveCompleted(const Event &, void *);
void handleStopRetry(const Event &, void *);
void onFileReceiveCompleted();
void sendClipboardThread(void *);
void bindNetworkInterface(IDataSocket *socket) const;
@ -238,13 +201,6 @@ private:
IClipboard::Time m_timeClipboard[kClipboardEnd];
std::string m_dataClipboard[kClipboardEnd];
IEventQueue *m_events;
std::size_t m_expectedFileSize;
std::string m_receivedFileData;
DragFileList m_dragFileList;
std::string m_dragFileExt;
using AutoThread = std::unique_ptr<Thread>;
AutoThread m_sendFileThread;
AutoThread m_writeToDropDirThread;
bool m_useSecureNetwork;
bool m_enableClipboard;
size_t m_maximumClipboardSize;

View File

@ -15,7 +15,6 @@
#include "deskflow/AppUtil.h"
#include "deskflow/Clipboard.h"
#include "deskflow/ClipboardChunk.h"
#include "deskflow/FileChunk.h"
#include "deskflow/OptionTypes.h"
#include "deskflow/ProtocolTypes.h"
#include "deskflow/ProtocolUtil.h"
@ -314,11 +313,7 @@ ServerProxy::EResult ServerProxy::parseMessage(const uint8_t *code)
setOptions();
}
else if (memcmp(code, kMsgDFileTransfer, 4) == 0) {
fileChunkReceived();
} else if (memcmp(code, kMsgDDragInfo, 4) == 0) {
dragInfoReceived();
} else if (memcmp(code, kMsgDSecureInputNotification, 4) == 0) {
else if (memcmp(code, kMsgDSecureInputNotification, 4) == 0) {
secureInputNotification();
}
@ -818,46 +813,11 @@ void ServerProxy::infoAcknowledgment()
m_ignoreMouse = false;
}
void ServerProxy::fileChunkReceived()
{
int result = FileChunk::assemble(m_stream, m_client->getReceivedFileData(), m_client->getExpectedFileSize());
if (result == kFinish) {
m_events->addEvent(Event(EventTypes::FileReceiveCompleted, m_client));
} else if (result == kStart) {
if (m_client->getDragFileList().size() > 0) {
std::string filename = m_client->getDragFileList().at(0).getFilename();
LOG((CLOG_DEBUG "start receiving %s", filename.c_str()));
}
}
}
void ServerProxy::dragInfoReceived()
{
// parse
uint32_t fileNum = 0;
std::string content;
ProtocolUtil::readf(m_stream, kMsgDDragInfo + 4, &fileNum, &content);
m_client->dragInfoReceived(fileNum, content);
}
void ServerProxy::handleClipboardSendingEvent(const Event &event, void *)
{
ClipboardChunk::send(m_stream, event.getDataObject());
}
void ServerProxy::fileChunkSending(uint8_t mark, char *data, size_t dataSize)
{
FileChunk::send(m_stream, mark, data, dataSize);
}
void ServerProxy::sendDragInfo(uint32_t fileCount, const char *info, size_t size)
{
std::string data(info, size);
ProtocolUtil::writef(m_stream, kMsgDDragInfo, fileCount, &data);
}
void ServerProxy::secureInputNotification()
{
std::string app;

View File

@ -51,12 +51,6 @@ public:
//@}
// sending file chunk to server
void fileChunkSending(uint8_t mark, char *data, size_t dataSize);
// sending dragging information to server
void sendDragInfo(uint32_t fileCount, const char *info, size_t size);
#ifdef TEST_ENV
void handleDataForTest()
{
@ -109,8 +103,6 @@ private:
void setOptions();
void queryInfo();
void infoAcknowledgment();
void fileChunkReceived();
void dragInfoReceived();
void handleClipboardSendingEvent(const Event &, void *);
void secureInputNotification();
void setServerLanguages();

View File

@ -21,16 +21,13 @@
#include "base/IEventQueue.h"
#endif
#if WINAPI_CARBON
#include "platform/OSXDragSimulator.h"
#endif
#include <iostream>
#include <stdexcept>
#include <stdio.h>
#include <vector>
#if WINAPI_CARBON
#include "platform/OSXCocoaApp.h"
#include <ApplicationServices/ApplicationServices.h>
#endif

View File

@ -183,27 +183,6 @@ bool ArgParser::parseGenericArgs(int argc, const char *const *argv, int &i)
// HACK: stop error happening when using portable (deskflowp)
} else if (isArg(i, argc, argv, nullptr, "--client")) {
// HACK: stop error happening when using portable (deskflowp)
} else if (isArg(i, argc, argv, nullptr, "--enable-drag-drop")) {
bool useDragDrop = true;
#ifdef WINAPI_XWINDOWS
useDragDrop = false;
LOG((CLOG_INFO "ignoring --enable-drag-drop, not supported on linux."));
#endif
#ifdef WINAPI_MSWINDOWS
if (!IsWindowsVistaOrGreater()) {
useDragDrop = false;
LOG((CLOG_INFO "ignoring --enable-drag-drop, not supported below vista."));
}
#endif
if (useDragDrop) {
argsBase().m_enableDragDrop = true;
}
} else if (isArg(i, argc, argv, nullptr, "--enable-crypto")) {
argsBase().m_enableCrypto = true;
} else if (isArg(i, argc, argv, nullptr, "--tls-cert", 1)) {

View File

@ -59,9 +59,6 @@ public:
/// @brief Should the app add a tray icon
bool m_disableTray = false;
/// @brief Should drag drop support be enabled
bool m_enableDragDrop = false;
/// @brief Will cause the application to exit with OK code when set to true
bool m_shouldExitOk = false;

View File

@ -86,12 +86,6 @@ add_library(${lib_name} STATIC ${PLATFORM_CODE}
DaemonApp.cpp
DaemonApp.h
DisplayInvalidException.h
DragInformation.cpp
DragInformation.h
DropHelper.cpp
DropHelper.h
FileChunk.cpp
FileChunk.h
IApp.h
IAppUtil.h
IClient.h

View File

@ -46,7 +46,7 @@
#if WINAPI_CARBON
#include "base/TMethodJob.h"
#include "mt/Thread.h"
#include "platform/OSXDragSimulator.h"
#include "platform/OSXCocoaApp.h"
#include "platform/OSXScreen.h"
#endif
@ -244,7 +244,6 @@ void ClientApp::handleScreenError(const Event &, void *)
deskflow::Screen *ClientApp::openClientScreen()
{
deskflow::Screen *screen = createScreen();
screen->setEnableDragDrop(argsBase().m_enableDragDrop);
m_events->adoptHandler(
EventTypes::ScreenError, screen->getEventTarget(),
new TMethodEventJob<ClientApp>(this, &ClientApp::handleScreenError)

View File

@ -1,133 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2013 - 2016 Symless Ltd.
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#include "deskflow/DragInformation.h"
#include "base/Log.h"
#include <fstream>
#include <sstream>
#include <stdexcept>
using namespace std;
DragInformation::DragInformation() : m_filename(), m_filesize(0)
{
}
void DragInformation::parseDragInfo(DragFileList &dragFileList, uint32_t fileNum, std::string data)
{
size_t startPos = 0;
size_t findResult1 = 0;
size_t findResult2 = 0;
dragFileList.clear();
std::string slash("\\");
if (data.find("/", startPos) != std::string::npos) {
slash = "/";
}
uint32_t index = 0;
while (index < fileNum) {
findResult1 = data.find(',', startPos);
findResult2 = data.find_last_of(slash, findResult1);
if (findResult1 == startPos) {
// TODO: file number does not match, something goes wrong
break;
}
// set filename
if (findResult1 - findResult2 > 1) {
std::string filename = data.substr(findResult2 + 1, findResult1 - findResult2 - 1);
DragInformation di;
di.setFilename(filename);
dragFileList.push_back(di);
}
startPos = findResult1 + 1;
// set filesize
findResult2 = data.find(',', startPos);
if (findResult2 - findResult1 > 1) {
std::string filesize = data.substr(findResult1 + 1, findResult2 - findResult1 - 1);
size_t size = stringToNum(filesize);
dragFileList.at(index).setFilesize(size);
}
startPos = findResult1 + 1;
++index;
}
LOG((CLOG_DEBUG "drag info received, total drag file number: %i", dragFileList.size()));
for (size_t i = 0; i < dragFileList.size(); ++i) {
LOG((CLOG_DEBUG "dragging file %i name: %s", i + 1, dragFileList.at(i).getFilename().c_str()));
}
}
std::string DragInformation::getDragFileExtension(std::string filename)
{
size_t findResult = std::string::npos;
findResult = filename.find_last_of(".", filename.size());
if (findResult != std::string::npos) {
return filename.substr(findResult + 1, filename.size() - findResult - 1);
} else {
return "";
}
}
int DragInformation::setupDragInfo(DragFileList &fileList, std::string &output)
{
auto size = static_cast<int>(fileList.size());
for (int i = 0; i < size; ++i) {
output.append(fileList.at(i).getFilename());
output.append(",");
std::string filesize = getFileSize(fileList.at(i).getFilename());
output.append(filesize);
output.append(",");
}
return size;
}
bool DragInformation::isFileValid(std::string filename)
{
bool result = false;
std::fstream file(filename.c_str(), ios::in | ios::binary);
if (file.is_open()) {
result = true;
}
file.close();
return result;
}
size_t DragInformation::stringToNum(std::string &str)
{
istringstream iss(str.c_str());
size_t size;
iss >> size;
return size;
}
std::string DragInformation::getFileSize(std::string &filename)
{
std::fstream file(filename.c_str(), ios::in | ios::binary);
if (!file.is_open()) {
throw std::runtime_error("failed to get file size");
}
// check file size
file.seekg(0, std::ios::end);
auto size = (size_t)file.tellg();
stringstream ss;
ss << size;
file.close();
return ss.str();
}

View File

@ -1,56 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2013 - 2016 Symless Ltd.
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#pragma once
#include "base/EventTypes.h"
#include <string>
#include <vector>
class DragInformation;
using DragFileList = std::vector<DragInformation>;
class DragInformation
{
public:
DragInformation();
~DragInformation() = default;
std::string &getFilename()
{
return m_filename;
}
void setFilename(std::string &name)
{
m_filename = name;
}
size_t getFilesize()
{
return m_filesize;
}
void setFilesize(size_t size)
{
m_filesize = size;
}
static void parseDragInfo(DragFileList &dragFileList, uint32_t fileNum, std::string data);
static std::string getDragFileExtension(std::string filename);
// helper function to setup drag info
// example: filename1,filesize1,filename2,filesize2,
// return file count
static int setupDragInfo(DragFileList &fileList, std::string &output);
static bool isFileValid(std::string filename);
private:
static size_t stringToNum(std::string &str);
static std::string getFileSize(std::string &filename);
private:
std::string m_filename;
size_t m_filesize;
};

View File

@ -1,40 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2014 - 2016 Symless Ltd.
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#include "deskflow/DropHelper.h"
#include "base/Log.h"
#include <fstream>
void DropHelper::writeToDir(const std::string &destination, DragFileList &fileList, std::string &data)
{
LOG((CLOG_DEBUG "dropping file, files=%i target=%s", fileList.size(), destination.c_str()));
if (!destination.empty() && fileList.size() > 0) {
std::fstream file;
std::string dropTarget = destination;
#ifdef SYSAPI_WIN32
dropTarget.append("\\");
#else
dropTarget.append("/");
#endif
dropTarget.append(fileList.at(0).getFilename());
file.open(dropTarget.c_str(), std::ios::out | std::ios::binary);
if (!file.is_open()) {
LOG((CLOG_ERR "drop file failed: can not open %s", dropTarget.c_str()));
}
file.write(data.c_str(), data.size());
file.close();
LOG((CLOG_DEBUG "%s is saved to %s", fileList.at(0).getFilename().c_str(), destination.c_str()));
fileList.clear();
} else {
LOG((CLOG_ERR "drop file failed: drop target is empty"));
}
}

View File

@ -1,15 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2014 - 2016 Symless Ltd.
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#pragma once
#include "deskflow/DragInformation.h"
class DropHelper
{
public:
static void writeToDir(const std::string &destination, DragFileList &fileList, std::string &data);
};

View File

@ -1,140 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2015 - 2016 Symless Ltd.
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#include "deskflow/FileChunk.h"
#include "base/Log.h"
#include "base/Stopwatch.h"
#include "base/String.h"
#include "deskflow/ProtocolTypes.h"
#include "deskflow/ProtocolUtil.h"
#include "io/IStream.h"
static const uint16_t kIntervalThreshold = 1;
FileChunk::FileChunk(size_t size) : Chunk(size)
{
m_dataSize = size - FILE_CHUNK_META_SIZE;
}
FileChunk *FileChunk::start(const std::string &size)
{
size_t sizeLength = size.size();
auto *start = new FileChunk(sizeLength + FILE_CHUNK_META_SIZE);
char *chunk = start->m_chunk;
chunk[0] = kDataStart;
memcpy(&chunk[1], size.c_str(), sizeLength);
chunk[sizeLength + 1] = '\0';
return start;
}
FileChunk *FileChunk::data(uint8_t *data, size_t dataSize)
{
auto *chunk = new FileChunk(dataSize + FILE_CHUNK_META_SIZE);
char *chunkData = chunk->m_chunk;
chunkData[0] = kDataChunk;
memcpy(&chunkData[1], data, dataSize);
chunkData[dataSize + 1] = '\0';
return chunk;
}
FileChunk *FileChunk::end()
{
auto *end = new FileChunk(FILE_CHUNK_META_SIZE);
char *chunk = end->m_chunk;
chunk[0] = kDataEnd;
chunk[1] = '\0';
return end;
}
int FileChunk::assemble(deskflow::IStream *stream, std::string &dataReceived, size_t &expectedSize)
{
// parse
uint8_t mark = 0;
std::string content;
static size_t receivedDataSize;
static double elapsedTime;
static Stopwatch stopwatch;
if (!ProtocolUtil::readf(stream, kMsgDFileTransfer + 4, &mark, &content)) {
return kError;
}
switch (mark) {
case kDataStart:
dataReceived.clear();
expectedSize = deskflow::string::stringToSizeType(content);
receivedDataSize = 0;
elapsedTime = 0;
stopwatch.reset();
if (CLOG->getFilter() >= kDEBUG2) {
LOG((CLOG_DEBUG2 "recv file size=%s", content.c_str()));
stopwatch.start();
}
return kStart;
case kDataChunk:
dataReceived.append(content);
if (CLOG->getFilter() >= kDEBUG2) {
LOG((CLOG_DEBUG2 "recv file chunk size=%i", content.size()));
double interval = stopwatch.getTime();
receivedDataSize += content.size();
LOG((CLOG_DEBUG2 "recv file interval=%f s", interval));
if (interval >= kIntervalThreshold) {
double averageSpeed = receivedDataSize / interval / 1000;
LOG((CLOG_DEBUG2 "recv file average speed=%f kb/s", averageSpeed));
receivedDataSize = 0;
elapsedTime += interval;
stopwatch.reset();
}
}
return kNotFinish;
case kDataEnd:
if (expectedSize != dataReceived.size()) {
LOG((CLOG_ERR "corrupted clipboard data, expected size=%d actual size=%d", expectedSize, dataReceived.size()));
return kError;
}
if (CLOG->getFilter() >= kDEBUG2) {
LOG((CLOG_DEBUG2 "file transfer finished"));
elapsedTime += stopwatch.getTime();
double averageSpeed = expectedSize / elapsedTime / 1000;
LOG((CLOG_DEBUG2 "file transfer finished: total time consumed=%f s", elapsedTime));
LOG((CLOG_DEBUG2 "file transfer finished: total data received=%i kb", expectedSize / 1000));
LOG((CLOG_DEBUG2 "file transfer finished: total average speed=%f kb/s", averageSpeed));
}
return kFinish;
}
return kError;
}
void FileChunk::send(deskflow::IStream *stream, uint8_t mark, char *data, size_t dataSize)
{
std::string chunk(data, dataSize);
switch (mark) {
case kDataStart:
LOG((CLOG_DEBUG2 "sending file chunk start: size=%s", data));
break;
case kDataChunk:
LOG((CLOG_DEBUG2 "sending file chunk: size=%i", chunk.size()));
break;
case kDataEnd:
LOG((CLOG_DEBUG2 "sending file finished"));
break;
}
ProtocolUtil::writef(stream, kMsgDFileTransfer, mark, &chunk);
}

View File

@ -1,30 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2015 - 2016 Symless Ltd.
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#pragma once
#include "common/Common.h"
#include "deskflow/Chunk.h"
#include <string>
#define FILE_CHUNK_META_SIZE 2
namespace deskflow {
class IStream;
};
class FileChunk : public Chunk
{
public:
FileChunk(size_t size);
static FileChunk *start(const std::string &size);
static FileChunk *data(uint8_t *data, size_t dataSize);
static FileChunk *end();
static int assemble(deskflow::IStream *stream, std::string &dataCached, size_t &expectedSize);
static void send(deskflow::IStream *stream, uint8_t mark, char *data, size_t dataSize);
};

View File

@ -8,7 +8,6 @@
#pragma once
#include "deskflow/ClipboardTypes.h"
#include "deskflow/DragInformation.h"
#include "deskflow/IKeyState.h"
#include "deskflow/IPrimaryScreen.h"
#include "deskflow/IScreen.h"
@ -127,9 +126,6 @@ public:
*/
virtual void setSequenceNumber(uint32_t) = 0;
//! Change dragging status
virtual void setDraggingStarted(bool started) = 0;
//! Determine the name of the app causing a secure input state
/*!
On MacOS check which app causes a secure input state to be enabled. No
@ -189,14 +185,6 @@ public:
int32_t pollActiveGroup() const override = 0;
void pollPressedKeys(KeyButtonSet &pressedKeys) const override = 0;
virtual std::string &getDraggingFilename() = 0;
virtual void clearDraggingFilename() = 0;
virtual bool isDraggingStarted() = 0;
virtual bool isFakeDraggingStarted() = 0;
virtual void fakeDraggingFiles(DragFileList fileList) = 0;
virtual const std::string &getDropTarget() const = 0;
protected:
//! Handle system event
/*!

View File

@ -11,8 +11,6 @@
PlatformScreen::PlatformScreen(IEventQueue *events, deskflow::ClientScrollDirection scrollDirection)
: IPlatformScreen(events),
m_draggingStarted(false),
m_fakeDraggingStarted(false),
m_clientScrollDirection(scrollDirection)
{
}
@ -85,14 +83,6 @@ void PlatformScreen::pollPressedKeys(KeyButtonSet &pressedKeys) const
getKeyState()->pollPressedKeys(pressedKeys);
}
bool PlatformScreen::isDraggingStarted()
{
if (App::instance().argsBase().m_enableDragDrop) {
return m_draggingStarted;
}
return false;
}
int32_t PlatformScreen::mapClientScrollDirection(int32_t x) const
{
return (x * m_clientScrollDirection);

View File

@ -8,7 +8,6 @@
#pragma once
#include "deskflow/ClientArgs.h"
#include "deskflow/DragInformation.h"
#include "deskflow/IPlatformScreen.h"
#include <stdexcept>
@ -65,23 +64,6 @@ public:
int32_t pollActiveGroup() const override;
void pollPressedKeys(KeyButtonSet &pressedKeys) const override;
void setDraggingStarted(bool started) override
{
m_draggingStarted = started;
}
bool isDraggingStarted() override;
bool isFakeDraggingStarted() override
{
return m_fakeDraggingStarted;
}
std::string &getDraggingFilename() override
{
return m_draggingFilename;
}
void clearDraggingFilename() override
{
}
// IPlatformScreen overrides
void enable() override = 0;
void disable() override = 0;
@ -98,15 +80,6 @@ public:
void setSequenceNumber(uint32_t) override = 0;
bool isPrimary() const override = 0;
void fakeDraggingFiles(DragFileList fileList) override
{
throw std::runtime_error("fakeDraggingFiles not implemented");
}
const std::string &getDropTarget() const override
{
throw std::runtime_error("getDropTarget not implemented");
}
protected:
//! Update mouse buttons
/*!
@ -132,11 +105,6 @@ protected:
*/
virtual int32_t mapClientScrollDirection(int32_t) const;
protected:
std::string m_draggingFilename;
bool m_draggingStarted;
bool m_fakeDraggingStarted;
private:
/*!
* \brief m_clientScrollDirection

View File

@ -26,8 +26,7 @@ Screen::Screen(IPlatformScreen *platformScreen, IEventQueue *events)
m_entered(m_isPrimary),
m_fakeInput(false),
m_events(events),
m_mock(false),
m_enableDragDrop(false)
m_mock(false)
{
assert(m_screen != nullptr);
@ -325,17 +324,9 @@ bool Screen::isLockedToScreen() const
uint32_t buttonID = 0;
if (m_screen->isAnyMouseButtonDown(buttonID)) {
if (buttonID != kButtonLeft) {
LOG((CLOG_DEBUG "locked by mouse buttonID: %d", buttonID));
}
if (m_enableDragDrop) {
return (buttonID == kButtonLeft) ? false : true;
} else {
return true;
}
LOG((CLOG_DEBUG "locked by mouse buttonID: %d", buttonID));
return true;
}
// not locked
return false;
}
@ -364,46 +355,6 @@ KeyModifierMask Screen::pollActiveModifiers() const
return m_screen->pollActiveModifiers();
}
bool Screen::isDraggingStarted() const
{
return m_screen->isDraggingStarted();
}
bool Screen::isFakeDraggingStarted() const
{
return m_screen->isFakeDraggingStarted();
}
void Screen::setDraggingStarted(bool started)
{
m_screen->setDraggingStarted(started);
}
void Screen::startDraggingFiles(DragFileList &fileList)
{
m_screen->fakeDraggingFiles(fileList);
}
void Screen::setEnableDragDrop(bool enabled)
{
m_enableDragDrop = enabled;
}
std::string &Screen::getDraggingFilename() const
{
return m_screen->getDraggingFilename();
}
void Screen::clearDraggingFilename()
{
m_screen->clearDraggingFilename();
}
const std::string &Screen::getDropTarget() const
{
return m_screen->getDropTarget();
}
void *Screen::getEventTarget() const
{
return m_screen;

View File

@ -8,12 +8,13 @@
#pragma once
#include "deskflow/ClipboardTypes.h"
#include "deskflow/DragInformation.h"
#include "deskflow/IScreen.h"
#include "deskflow/KeyTypes.h"
#include "deskflow/MouseTypes.h"
#include "deskflow/OptionTypes.h"
#include <string>
class IClipboard;
class IPlatformScreen;
class IEventQueue;
@ -216,14 +217,6 @@ public:
*/
void fakeInputEnd();
//! Change dragging status
void setDraggingStarted(bool started);
//! Fake a files dragging operation
void startDraggingFiles(DragFileList &fileList);
void setEnableDragDrop(bool enabled);
//! Determine the name of the app causing a secure input state
/*!
On MacOS check which app causes a secure input state to be enabled. No
@ -279,21 +272,6 @@ public:
*/
KeyModifierMask pollActiveModifiers() const;
//! Test if file is dragged on primary screen
bool isDraggingStarted() const;
//! Test if file is dragged on secondary screen
bool isFakeDraggingStarted() const;
//! Get the filename of the file being dragged
std::string &getDraggingFilename() const;
//! Clear the filename of the file that was dragged
void clearDraggingFilename();
//! Get the drop target directory
const std::string &getDropTarget() const;
//@}
// IScreen overrides
@ -341,7 +319,6 @@ private:
IEventQueue *m_events;
bool m_mock;
bool m_enableDragDrop;
};
} // namespace deskflow

View File

@ -49,7 +49,7 @@
#if WINAPI_CARBON
#include "base/TMethodJob.h"
#include "mt/Thread.h"
#include "platform/OSXDragSimulator.h"
#include "platform/OSXCocoaApp.h"
#include "platform/OSXScreen.h"
#endif
@ -429,7 +429,6 @@ bool ServerApp::initServer()
deskflow::Screen *ServerApp::openServerScreen()
{
deskflow::Screen *screen = createScreen();
screen->setEnableDragDrop(argsBase().m_enableDragDrop);
m_events->adoptHandler(
EventTypes::ScreenError, screen->getEventTarget(),
new TMethodEventJob<ServerApp>(this, &ServerApp::handleScreenError)

View File

@ -13,10 +13,7 @@
#include "base/Stopwatch.h"
#include "base/String.h"
#include "deskflow/ClipboardChunk.h"
#include "deskflow/FileChunk.h"
#include "deskflow/ProtocolTypes.h"
#include "mt/Lock.h"
#include "mt/Mutex.h"
#include <fstream>
#include <stdexcept>
@ -25,74 +22,6 @@ using namespace std;
static const size_t g_chunkSize = 512 * 1024; // 512kb
bool StreamChunker::s_isChunkingFile = false;
bool StreamChunker::s_interruptFile = false;
Mutex *StreamChunker::s_interruptMutex = nullptr;
void StreamChunker::sendFile(char *filename, IEventQueue *events, void *eventTarget)
{
s_isChunkingFile = true;
std::fstream file(static_cast<char *>(filename), std::ios::in | std::ios::binary);
if (!file.is_open()) {
throw runtime_error("failed to open file");
}
// check file size
file.seekg(0, std::ios::end);
auto size = (size_t)file.tellg();
// send first message (file size)
std::string fileSize = deskflow::string::sizeTypeToString(size);
FileChunk *sizeMessage = FileChunk::start(fileSize);
events->addEvent(Event(EventTypes::FileChunkSending, eventTarget, sizeMessage));
// send chunk messages with a fixed chunk size
size_t sentLength = 0;
size_t chunkSize = g_chunkSize;
file.seekg(0, std::ios::beg);
while (true) {
if (s_interruptFile) {
s_interruptFile = false;
LOG((CLOG_DEBUG "file transmission interrupted"));
break;
}
events->addEvent(Event(EventTypes::FileKeepAlive, eventTarget));
// make sure we don't read too much from the mock data.
if (sentLength + chunkSize > size) {
chunkSize = size - sentLength;
}
auto *chunkData = new char[chunkSize];
file.read(chunkData, chunkSize);
auto *data = reinterpret_cast<uint8_t *>(chunkData);
FileChunk *fileChunk = FileChunk::data(data, chunkSize);
delete[] chunkData;
events->addEvent(Event(EventTypes::FileChunkSending, eventTarget, fileChunk));
sentLength += chunkSize;
file.seekg(sentLength, std::ios::beg);
if (sentLength == size) {
break;
}
}
// send last message
FileChunk *end = FileChunk::end();
events->addEvent(Event(EventTypes::FileChunkSending, eventTarget, end));
file.close();
s_isChunkingFile = false;
}
void StreamChunker::sendClipboard(
std::string &data, size_t size, ClipboardID id, uint32_t sequence, IEventQueue *events, void *eventTarget
)
@ -108,8 +37,6 @@ void StreamChunker::sendClipboard(
size_t chunkSize = g_chunkSize;
while (true) {
events->addEvent(Event(EventTypes::FileKeepAlive, eventTarget));
// make sure we don't read too much from the mock data.
if (sentLength + chunkSize > size) {
chunkSize = size - sentLength;
@ -133,11 +60,3 @@ void StreamChunker::sendClipboard(
LOG((CLOG_DEBUG "sent clipboard size=%d", sentLength));
}
void StreamChunker::interruptFile()
{
if (s_isChunkingFile) {
s_interruptFile = true;
LOG((CLOG_INFO "previous dragged file has become invalid"));
}
}

View File

@ -11,19 +11,11 @@
#include <string>
class IEventQueue;
class Mutex;
class StreamChunker
{
public:
static void sendFile(char *filename, IEventQueue *events, void *eventTarget);
static void sendClipboard(
std::string &data, size_t size, ClipboardID id, uint32_t sequence, IEventQueue *events, void *eventTarget
);
static void interruptFile();
private:
static bool s_isChunkingFile;
static bool s_interruptFile;
static Mutex *s_interruptMutex;
};

View File

@ -32,8 +32,6 @@ if(WIN32)
MSWindowsDebugOutputter.h
MSWindowsDesks.cpp
MSWindowsDesks.h
MSWindowsDropTarget.cpp
MSWindowsDropTarget.h
MSWindowsEventQueueBuffer.cpp
MSWindowsEventQueueBuffer.h
MSWindowsHook.cpp
@ -76,10 +74,8 @@ elseif(APPLE)
OSXClipboardUTF8Converter.h
OSXClipboardUTF16Converter.cpp
OSXClipboardUTF16Converter.h
OSXDragSimulator.h
OSXDragSimulator.m
OSXDragView.h
OSXDragView.m
OSXCocoaApp.h
OSXCocoaApp.m
OSXEventQueueBuffer.cpp
OSXEventQueueBuffer.h
OSXKeyState.cpp

View File

@ -1,150 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2014 - 2016 Symless Ltd.
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#include "platform/MSWindowsDropTarget.h"
#include "base/Log.h"
#include "common/Common.h"
#include <Shlobj.h>
#include <stdio.h>
void getDropData(IDataObject *pDataObject);
MSWindowsDropTarget *MSWindowsDropTarget::s_instance = nullptr;
MSWindowsDropTarget::MSWindowsDropTarget() : m_refCount(1), m_allowDrop(false)
{
s_instance = this;
}
MSWindowsDropTarget &MSWindowsDropTarget::instance()
{
assert(s_instance != nullptr);
return *s_instance;
}
HRESULT
MSWindowsDropTarget::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
MSWindowsDropTarget::DragOver(DWORD keyState, POINTL point, DWORD *effect)
{
*effect = DROPEFFECT_NONE;
return S_OK;
}
HRESULT
MSWindowsDropTarget::DragLeave(void)
{
return S_OK;
}
HRESULT
MSWindowsDropTarget::Drop(IDataObject *dataObject, DWORD keyState, POINTL point, DWORD *effect)
{
*effect = DROPEFFECT_NONE;
return S_OK;
}
bool MSWindowsDropTarget::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 MSWindowsDropTarget::setDraggingFilename(char *const filename)
{
m_dragFilename = filename;
}
std::string MSWindowsDropTarget::getDraggingFilename()
{
return m_dragFilename;
}
void MSWindowsDropTarget::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));
MSWindowsDropTarget::instance().setDraggingFilename(filename);
GlobalUnlock(stgMed.hGlobal);
// release the data using the COM API
ReleaseStgMedium(&stgMed);
delete[] filename;
}
}
}
HRESULT __stdcall MSWindowsDropTarget::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 MSWindowsDropTarget::AddRef(void)
{
return InterlockedIncrement(&m_refCount);
}
ULONG __stdcall MSWindowsDropTarget::Release(void)
{
LONG count = InterlockedDecrement(&m_refCount);
if (count == 0) {
delete this;
return 0;
} else {
return count;
}
}

View File

@ -1,47 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2014 - 2016 Symless Ltd.
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#pragma once
#include <string>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <oleidl.h>
class MSWindowsScreen;
class MSWindowsDropTarget : public IDropTarget
{
public:
MSWindowsDropTarget();
~MSWindowsDropTarget() = default;
// 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 MSWindowsDropTarget &instance();
private:
bool queryDataObject(IDataObject *dataObject);
long m_refCount;
bool m_allowDrop;
std::string m_dragFilename;
static MSWindowsDropTarget *s_instance;
};

View File

@ -25,7 +25,6 @@
#include "mt/Thread.h"
#include "platform/MSWindowsClipboard.h"
#include "platform/MSWindowsDesks.h"
#include "platform/MSWindowsDropTarget.h"
#include "platform/MSWindowsEventQueueBuffer.h"
#include "platform/MSWindowsKeyState.h"
#include "platform/MSWindowsScreenSaver.h"
@ -114,9 +113,7 @@ MSWindowsScreen::MSWindowsScreen(
m_keyState(nullptr),
m_hasMouse(GetSystemMetrics(SM_MOUSEPRESENT) != 0),
m_showingMouse(false),
m_events(events),
m_dropWindow(nullptr),
m_dropWindowSize(20)
m_events(events)
{
assert(s_windowInstance != nullptr);
assert(s_screen == nullptr);
@ -143,23 +140,11 @@ MSWindowsScreen::MSWindowsScreen(
LOG((CLOG_DEBUG "screen shape: %d,%d %dx%d %s", m_x, m_y, m_w, m_h, m_multimon ? "(multi-monitor)" : ""));
LOG((CLOG_DEBUG "window is 0x%08x", m_window));
// SHGetFolderPath is deprecated in vista, but use it for xp support.
char desktopPath[MAX_PATH];
if (SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_DESKTOP, nullptr, 0, desktopPath))) {
m_desktopPath = std::string(desktopPath);
LOG((CLOG_DEBUG "using desktop for file drag-drop target: %s", m_desktopPath.c_str()));
} else {
LOG((CLOG_DEBUG "unable to use desktop as file drag-drop target, code=%d", GetLastError()));
}
if (App::instance().argsBase().m_preventSleep) {
m_powerManager.disableSleep();
}
OleInitialize(0);
m_dropWindow = createDropWindow(m_class, "DropWindow");
m_dropTarget = new MSWindowsDropTarget();
RegisterDragDrop(m_dropWindow, m_dropTarget);
} catch (...) {
delete m_keyState;
delete m_desks;
@ -193,10 +178,7 @@ MSWindowsScreen::~MSWindowsScreen()
destroyWindow(m_window);
destroyClass(m_class);
RevokeDragDrop(m_dropWindow);
m_dropTarget->Release();
OleUninitialize();
destroyWindow(m_dropWindow);
s_screen = nullptr;
}
@ -359,28 +341,6 @@ void MSWindowsScreen::leave()
// now off screen
m_isOnScreen = false;
forceShowCursor();
if (isDraggingStarted() && !m_isPrimary) {
m_sendDragThread = new Thread(new TMethodJob<MSWindowsScreen>(this, &MSWindowsScreen::sendDragThread));
}
}
void MSWindowsScreen::sendDragThread(void *)
{
std::string &draggingFilename = getDraggingFilename();
size_t size = draggingFilename.size();
if (draggingFilename.empty() == false) {
ClientApp &app = ClientApp::instance();
Client *client = app.getClientPtr();
uint32_t fileCount = 1;
LOG((CLOG_DEBUG "send dragging info to server: %s", draggingFilename.c_str()));
client->sendDragInfo(fileCount, draggingFilename, size);
LOG((CLOG_DEBUG "send dragging file to server"));
client->sendFileToServer(draggingFilename.c_str());
}
m_draggingStarted = false;
}
bool MSWindowsScreen::setClipboard(ClipboardID, const IClipboard *src)
@ -762,22 +722,13 @@ void MSWindowsScreen::fakeMouseButton(ButtonID id, bool press)
m_desks->fakeMouseButton(id, press);
if (id == kButtonLeft) {
if (press) {
m_buttons[kButtonLeft] = true;
} else {
m_buttons[kButtonLeft] = false;
m_fakeDraggingStarted = false;
m_draggingStarted = false;
}
m_buttons[kButtonLeft] = press;
}
}
void MSWindowsScreen::fakeMouseMove(int32_t x, int32_t y)
{
m_desks->fakeMouseMove(x, y);
if (m_buttons[kButtonLeft]) {
m_draggingStarted = true;
}
}
void MSWindowsScreen::fakeMouseRelativeMove(int32_t dx, int32_t dy) const
@ -887,21 +838,6 @@ HWND MSWindowsScreen::createWindow(ATOM windowClass, const char *name) const
return window;
}
HWND MSWindowsScreen::createDropWindow(ATOM windowClass, const char *name) const
{
HWND window = CreateWindowEx(
WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_ACCEPTFILES, MAKEINTATOM(m_class), name, WS_POPUP, 0, 0,
m_dropWindowSize, m_dropWindowSize, nullptr, nullptr, s_windowInstance, nullptr
);
if (window == nullptr) {
LOG((CLOG_ERR "failed to create drop window: %d", GetLastError()));
throw XScreenOpenFailure();
}
return window;
}
void MSWindowsScreen::destroyWindow(HWND hwnd) const
{
if (hwnd != nullptr) {
@ -1266,18 +1202,7 @@ bool MSWindowsScreen::onMouseButton(WPARAM wParam, LPARAM lParam)
// keep our shadow key state up to date
if (button >= kButtonLeft && button <= kButtonExtra0 + 1) {
if (pressed) {
m_buttons[button] = true;
if (button == kButtonLeft) {
m_draggingFilename.clear();
LOG((CLOG_DEBUG2 "dragging filename is cleared"));
}
} else {
m_buttons[button] = false;
if (m_draggingStarted && button == kButtonLeft) {
m_draggingStarted = false;
}
}
m_buttons[button] = pressed;
}
// ignore message if posted prior to last mark change
@ -1328,13 +1253,8 @@ bool MSWindowsScreen::onMouseMove(int32_t mx, int32_t my)
saveMousePosition(mx, my);
if (m_isOnScreen) {
// motion on primary screen
sendEvent(EventTypes::PrimaryScreenMotionOnPrimary, MotionInfo::alloc(m_xCursor, m_yCursor));
if (m_buttons[kButtonLeft] == true && m_draggingStarted == false) {
m_draggingStarted = true;
}
} else {
// the motion is on the secondary screen, so we warp mouse back to
// center on the server screen. if we don't do this, then the mouse
@ -1776,63 +1696,6 @@ bool MSWindowsScreen::HotKeyItem::operator<(const HotKeyItem &x) const
return (m_keycode < x.m_keycode || (m_keycode == x.m_keycode && m_mask < x.m_mask));
}
void MSWindowsScreen::fakeDraggingFiles(DragFileList fileList)
{
// possible design flaw: this function stops a "not implemented"
// exception from being thrown.
}
std::string &MSWindowsScreen::getDraggingFilename()
{
if (m_draggingStarted) {
m_dropTarget->clearDraggingFilename();
m_draggingFilename.clear();
int halfSize = m_dropWindowSize / 2;
int32_t xPos = m_isPrimary ? m_xCursor : m_xCenter;
int32_t 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, AppUtil::instance().getCurrentLanguageCode());
fakeKeyUp(1);
fakeMouseButton(kButtonLeft, false);
std::string 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()) {
if (DragInformation::isFileValid(filename)) {
m_draggingFilename = filename;
} else {
LOG((CLOG_DEBUG "drag file name is invalid: %s", filename.c_str()));
}
}
if (m_draggingFilename.empty()) {
LOG((CLOG_WARN "failed to get drag file name from OLE"));
}
}
return m_draggingFilename;
}
const std::string &MSWindowsScreen::getDropTarget() const
{
return m_desktopPath;
}
std::string MSWindowsScreen::getSecureInputApp() const
{
// ignore on Windows

View File

@ -8,7 +8,6 @@
#pragma once
#include "deskflow/ClientArgs.h"
#include "deskflow/DragInformation.h"
#include "deskflow/PlatformScreen.h"
#include "mt/CondVar.h"
#include "mt/Mutex.h"
@ -125,9 +124,6 @@ public:
void setOptions(const OptionsList &options) override;
void setSequenceNumber(uint32_t) override;
bool isPrimary() const override;
void fakeDraggingFiles(DragFileList fileList) override;
std::string &getDraggingFilename() override;
const std::string &getDropTarget() const override;
std::string getSecureInputApp() const override;
protected:
@ -147,7 +143,6 @@ private:
ATOM createDeskWindowClass(bool isPrimary) const;
void destroyClass(ATOM windowClass) const;
HWND createWindow(ATOM windowClass, const char *name) const;
HWND createDropWindow(ATOM windowClass, const char *name) const;
void destroyWindow(HWND) const;
// convenience function to send events
@ -233,9 +228,6 @@ private: // HACK
// check if it is a modifier key repeating message
bool isModifierRepeat(KeyModifierMask oldState, KeyModifierMask state, WPARAM wParam) const;
// send drag info and data back to server
void sendDragThread(void *);
private:
struct HotKeyItem
{
@ -346,12 +338,6 @@ private:
std::string m_desktopPath;
MSWindowsDropTarget *m_dropTarget;
HWND m_dropWindow;
const int m_dropWindowSize;
Thread *m_sendDragThread;
PrimaryKeyDownList m_primaryKeyDownList;
MSWindowsPowerManager m_powerManager;
};

View File

@ -16,8 +16,6 @@ extern "C"
#endif
void runCocoaApp();
void stopCocoaLoop();
void fakeDragging(const char *str, int cursorX, int cursorY);
CFStringRef getCocoaDropTarget();
#if defined(__cplusplus)
}

View File

@ -0,0 +1,44 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2013 - 2016 Symless Ltd.
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#import "platform/OSXCocoaApp.h"
#import <Cocoa/Cocoa.h>
#import <CoreData/CoreData.h>
#import <Foundation/Foundation.h>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
NSWindow *dummyWindow = NULL;
void runCocoaApp()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[NSApplication sharedApplication];
NSWindow *window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 3, 3)
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
[window setTitle:@""];
[window setAlphaValue:0.1];
[window makeKeyAndOrderFront:nil];
dummyWindow = window;
NSLog(@"starting cocoa loop");
[NSApp run];
NSLog(@"cocoa: release");
[pool release];
}
void stopCocoaLoop()
{
[NSApp stop:dummyWindow];
}

View File

@ -1,92 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2013 - 2016 Symless Ltd.
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#import "platform/OSXDragSimulator.h"
#import "platform/OSXDragView.h"
#import <Cocoa/Cocoa.h>
#import <CoreData/CoreData.h>
#import <Foundation/Foundation.h>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
NSWindow *g_dragWindow = NULL;
OSXDragView *g_dragView = NULL;
NSString *g_ext = NULL;
void runCocoaApp()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[NSApplication sharedApplication];
NSWindow *window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 3, 3)
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
[window setTitle:@""];
[window setAlphaValue:0.1];
[window makeKeyAndOrderFront:nil];
OSXDragView *dragView = [[OSXDragView alloc] initWithFrame:NSMakeRect(0, 0, 3, 3)];
g_dragWindow = window;
g_dragView = dragView;
[window setContentView:dragView];
NSLog(@"starting cocoa loop");
[NSApp run];
NSLog(@"cocoa: release");
[pool release];
}
void stopCocoaLoop()
{
[NSApp stop:g_dragWindow];
}
void fakeDragging(const char *str, int cursorX, int cursorY)
{
g_ext = [NSString stringWithUTF8String:str];
dispatch_async(dispatch_get_main_queue(), ^{
NSRect screen = [[NSScreen mainScreen] frame];
NSLog(@"screen size: witdh = %f height = %f", screen.size.width, screen.size.height);
NSLog(@"mouseLocation: %d %d", cursorX, cursorY);
int newPosX = 0;
int newPosY = 0;
newPosX = cursorX - 1;
newPosY = screen.size.height - cursorY - 1;
NSRect rect = NSMakeRect(newPosX, newPosY, 3, 3);
NSLog(@"newPosX: %d", newPosX);
NSLog(@"newPosY: %d", newPosY);
[g_dragWindow setFrame:rect display:NO];
[g_dragWindow makeKeyAndOrderFront:nil];
[NSApp activateIgnoringOtherApps:YES];
[g_dragView setFileExt:g_ext];
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
CGEventRef down =
CGEventCreateMouseEvent(source, kCGEventLeftMouseDown, CGPointMake(cursorX, cursorY), kCGMouseButtonLeft);
CGEventPost(kCGHIDEventTap, down);
CFRelease(down);
CFRelease(source);
});
}
CFStringRef getCocoaDropTarget()
{
// HACK: sleep, wait for cocoa drop target updated first
usleep(1000000);
return [g_dragView getDropTarget];
}

View File

@ -1,24 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2013 - 2016 Symless Ltd.
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#pragma once
#import <Cocoa/Cocoa.h>
#ifdef MAC_OS_X_VERSION_10_7
@interface OSXDragView : NSView <NSDraggingSource, NSDraggingInfo> {
NSMutableString *m_dropTarget;
NSString *m_dragFileExt;
}
- (CFStringRef)getDropTarget;
- (void)clearDropTarget;
- (void)setFileExt:(NSString *)ext;
@end
#endif

View File

@ -1,149 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2013 - 2016 Symless Ltd.
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#import "platform/OSXDragView.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#pragma clang diagnostic ignored "-Wobjc-protocol-property-synthesis"
#pragma clang diagnostic ignored "-Wprotocol"
@implementation OSXDragView
@dynamic draggingFormation;
@dynamic animatesToDestination;
@dynamic numberOfValidItemsForDrop;
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
m_dropTarget = [[NSMutableString alloc] initWithCapacity:0];
m_dragFileExt = [[NSMutableString alloc] initWithCapacity:0];
return self;
}
- (void)drawRect:(NSRect)dirtyRect
{
}
- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
{
return YES;
}
- (void)mouseDown:(NSEvent *)theEvent
{
NSLog(@"cocoa mouse down");
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:m_dragFileExt]
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:@""];
}
- (void)setFileExt:(NSString *)ext
{
[ext retain];
[m_dragFileExt release];
m_dragFileExt = ext;
NSLog(@"drag file ext: %@", m_dragFileExt);
}
- (NSWindow *)draggingDestinationWindow
{
return nil;
}
- (NSDragOperation)draggingSourceOperationMask
{
return NSDragOperationCopy;
}
- (NSPoint)draggingLocation
{
NSPoint point;
return point;
}
- (NSPoint)draggedImageLocation
{
NSPoint point;
return point;
}
- (NSImage *)draggedImage
{
return nil;
}
- (NSPasteboard *)draggingPasteboard
{
return nil;
}
- (id)draggingSource
{
return nil;
}
- (NSInteger)draggingSequenceNumber
{
return 0;
}
- (void)slideDraggedImageTo:(NSPoint)screenPoint
{
}
- (NSDragOperation)draggingSession:(NSDraggingSession *)session
sourceOperationMaskForDraggingContext:(NSDraggingContext)context
{
return NSDragOperationCopy;
}
- (void)enumerateDraggingItemsWithOptions:(NSDraggingItemEnumerationOptions)enumOpts
forView:(NSView *)view
classes:(NSArray *)classArray
searchOptions:(NSDictionary *)searchOptions
usingBlock:(void (^)(NSDraggingItem *draggingItem, NSInteger idx, BOOL *stop))block
{
}
@end

View File

@ -8,7 +8,6 @@
#pragma once
#include "base/EventTypes.h"
#include "deskflow/DragInformation.h"
#include "deskflow/PlatformScreen.h"
#include "platform/OSXClipboard.h"
#include "platform/OSXPowerManager.h"
@ -94,14 +93,8 @@ public:
void setOptions(const OptionsList &options) override;
void setSequenceNumber(uint32_t) override;
bool isPrimary() const override;
void fakeDraggingFiles(DragFileList fileList) override;
std::string &getDraggingFilename() override;
std::string getSecureInputApp() const override;
const std::string &getDropTarget() const override
{
return m_dropTarget;
}
void waitForCarbonLoop() const;
protected:
@ -154,12 +147,6 @@ private:
// get the current scroll wheel speed
double getScrollSpeed() const;
// enable/disable drag handling for buttons 3 and up
void enableDragTimer(bool enable);
// drag timer handler
void handleDrag(const Event &, void *);
// clipboard check timer handler
void handleClipboardCheck(const Event &, void *);
@ -190,8 +177,6 @@ private:
// convert CFString to char*
static char *CFStringRefToUTF8String(CFStringRef aString);
void getDropTargetThread(void *);
private:
struct HotKeyItem
{
@ -266,9 +251,6 @@ private:
std::vector<MouseButtonEventMapType> MouseButtonEventMap;
bool m_cursorHidden;
int32_t m_dragNumButtonsDown;
Point m_dragLastPoint;
EventQueueTimer *m_dragTimer;
// keyboard stuff
OSXKeyState *m_keyState;

View File

@ -23,7 +23,6 @@
#include "mt/Mutex.h"
#include "mt/Thread.h"
#include "platform/OSXClipboard.h"
#include "platform/OSXDragSimulator.h"
#include "platform/OSXEventQueueBuffer.h"
#include "platform/OSXKeyState.h"
#include "platform/OSXMediaKeySupport.h"
@ -85,8 +84,6 @@ OSXScreen::OSXScreen(
m_cursorPosValid(false),
MouseButtonEventMap(NumButtonIDs),
m_cursorHidden(false),
m_dragNumButtonsDown(0),
m_dragTimer(nullptr),
m_keyState(nullptr),
m_sequenceNumber(0),
m_screensaver(nullptr),
@ -109,7 +106,6 @@ OSXScreen::OSXScreen(
m_lastSingleClickXCursor(0),
m_lastSingleClickYCursor(0),
m_events(events),
m_getDropTargetThread(nullptr),
m_impl(nullptr)
{
m_displayID = CGMainDisplayID();
@ -548,55 +544,10 @@ void OSXScreen::fakeMouseButton(ButtonID id, bool press)
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
if (!press && (id == kButtonLeft)) {
if (m_fakeDraggingStarted) {
auto method = new TMethodJob<OSXScreen>(this, &OSXScreen::getDropTargetThread);
m_getDropTargetThread.reset(new Thread(method));
}
m_draggingStarted = false;
}
}
void OSXScreen::getDropTargetThread(void *)
{
// wait for 5 secs for the drop destinaiton string to be filled.
uint32_t timeout = ARCH->time() + 5;
m_dropTarget.clear();
while (ARCH->time() < timeout) {
CFStringRef cfstr = getCocoaDropTarget();
char *cstr = CFStringRefToUTF8String(cfstr);
CFRelease(cfstr);
if (cstr != nullptr) {
LOG((CLOG_DEBUG "drop target: %s", cstr));
m_dropTarget = cstr;
free(cstr);
break;
}
ARCH->sleep(.1f);
}
if (m_dropTarget.empty()) {
LOG((CLOG_ERR "failed to get drop target"));
}
m_fakeDraggingStarted = false;
}
void OSXScreen::fakeMouseMove(int32_t x, int32_t y)
{
if (m_fakeDraggingStarted) {
m_buttonState.set(0, kMouseButtonDown);
}
// index 0 means left mouse button
if (m_buttonState.test(0)) {
m_draggingStarted = true;
}
// synthesize event
CGPoint pos;
pos.x = x;
@ -761,10 +712,6 @@ void OSXScreen::disable()
}
// FIXME -- allow system to enter power saving mode
// disable drag handling
m_dragNumButtonsDown = 0;
enableDragTimer(false);
// uninstall clipboard timer
if (m_clipboardTimer != nullptr) {
m_events->removeHandler(EventTypes::Timer, m_clipboardTimer);
@ -808,31 +755,6 @@ void OSXScreen::leave()
{
hideCursor();
if (isDraggingStarted()) {
std::string &fileList = getDraggingFilename();
if (!m_isPrimary) {
if (fileList.empty() == false) {
ClientApp &app = ClientApp::instance();
Client *client = app.getClientPtr();
DragInformation di;
di.setFilename(fileList);
DragFileList dragFileList;
dragFileList.push_back(di);
std::string info;
uint32_t fileCount = DragInformation::setupDragInfo(dragFileList, info);
client->sendDragInfo(fileCount, info, info.size());
LOG((CLOG_DEBUG "send dragging file to server"));
// TODO: what to do with multiple file or even
// a folder
client->sendFileToServer(fileList.c_str());
}
}
m_draggingStarted = false;
}
if (m_isPrimary) {
avoidHesitatingCursor();
}
@ -1011,9 +933,6 @@ bool OSXScreen::onMouseMove(CGFloat mx, CGFloat my)
if (m_isOnScreen) {
// motion on primary screen
sendEvent(EventTypes::PrimaryScreenMotionOnPrimary, MotionInfo::alloc(m_xCursor, m_yCursor));
if (m_buttonState.test(0)) {
m_draggingStarted = true;
}
} else {
// motion on secondary screen. warp mouse back to
// center.
@ -1070,37 +989,6 @@ bool OSXScreen::onMouseButton(bool pressed, uint16_t macButton)
}
}
// handle drags with any button other than button 1 or 2
if (macButton > 2) {
if (pressed) {
// one more button
if (m_dragNumButtonsDown++ == 0) {
enableDragTimer(true);
}
} else {
// one less button
if (--m_dragNumButtonsDown == 0) {
enableDragTimer(false);
}
}
}
if (macButton == kButtonLeft) {
EMouseButtonState state = pressed ? kMouseButtonDown : kMouseButtonUp;
m_buttonState.set(kButtonLeft - 1, state);
if (pressed) {
m_draggingFilename.clear();
LOG((CLOG_DEBUG2 "dragging file directory is cleared"));
} else {
if (m_fakeDraggingStarted) {
auto method = new TMethodJob<OSXScreen>(this, &OSXScreen::getDropTargetThread);
m_getDropTargetThread.reset(new Thread(method));
}
m_draggingStarted = false;
}
}
return true;
}
@ -1358,38 +1246,6 @@ double OSXScreen::getScrollSpeed() const
return scaling;
}
void OSXScreen::enableDragTimer(bool enable)
{
if (enable && m_dragTimer == nullptr) {
m_dragTimer = m_events->newTimer(0.01, nullptr);
m_events->adoptHandler(
EventTypes::Timer, m_dragTimer, new TMethodEventJob<OSXScreen>(this, &OSXScreen::handleDrag)
);
CGEventRef event = CGEventCreate(nullptr);
CGPoint mouse = CGEventGetLocation(event);
m_dragLastPoint.h = (short)mouse.x;
m_dragLastPoint.v = (short)mouse.y;
CFRelease(event);
} else if (!enable && m_dragTimer != nullptr) {
m_events->removeHandler(EventTypes::Timer, m_dragTimer);
m_events->deleteTimer(m_dragTimer);
m_dragTimer = nullptr;
}
}
void OSXScreen::handleDrag(const Event &, void *)
{
CGEventRef event = CGEventCreate(nullptr);
CGPoint p = CGEventGetLocation(event);
CFRelease(event);
if ((short)p.x != m_dragLastPoint.h || (short)p.y != m_dragLastPoint.v) {
m_dragLastPoint.h = (short)p.x;
m_dragLastPoint.v = (short)p.y;
onMouseMove((int32_t)p.x, (int32_t)p.y);
}
}
void OSXScreen::updateButtons()
{
uint32_t buttons = GetCurrentButtonState();
@ -1888,40 +1744,6 @@ char *OSXScreen::CFStringRefToUTF8String(CFStringRef aString)
return buffer;
}
void OSXScreen::fakeDraggingFiles(DragFileList fileList)
{
m_fakeDraggingStarted = true;
std::string fileExt;
if (fileList.size() == 1) {
fileExt = DragInformation::getDragFileExtension(fileList.at(0).getFilename());
}
fakeDragging(fileExt.c_str(), m_xCursor, m_yCursor);
}
std::string &OSXScreen::getDraggingFilename()
{
if (m_draggingStarted) {
m_draggingFilename.clear();
CFStringRef dragInfo = getDraggedFileURL();
char *info = CFStringRefToUTF8String(dragInfo);
CFRelease(dragInfo);
if (info != nullptr) {
LOG((CLOG_DEBUG "drag info: %s", info));
m_draggingFilename = info;
free(info);
}
// fake a escape key down and up then left mouse button up
fakeKeyDown(kKeyEscape, 8192, 1, AppUtil::instance().getCurrentLanguageCode());
fakeKeyUp(1);
fakeMouseButton(kButtonLeft, false);
}
return m_draggingFilename;
}
void OSXScreen::waitForCarbonLoop() const
{
if (*m_carbonLoopReady) {

View File

@ -8,7 +8,6 @@
#include "base/Log.h"
#include "base/TMethodEventJob.h"
#include "deskflow/FileChunk.h"
#include "deskflow/ProtocolUtil.h"
#include "deskflow/StreamChunker.h"
#include "io/IStream.h"
@ -24,28 +23,17 @@ ClientProxy1_5::ClientProxy1_5(const std::string &name, deskflow::IStream *strea
: ClientProxy1_4(name, stream, server, events),
m_events(events)
{
m_events->adoptHandler(
EventTypes::FileKeepAlive, this,
new TMethodEventJob<ClientProxy1_3>(this, &ClientProxy1_3::handleKeepAlive, nullptr)
);
}
ClientProxy1_5::~ClientProxy1_5()
{
m_events->removeHandler(EventTypes::FileKeepAlive, this);
// do nothing
}
void ClientProxy1_5::sendDragInfo(uint32_t fileCount, const char *info, size_t size)
{
std::string data(info, size);
ProtocolUtil::writef(getStream(), kMsgDDragInfo, fileCount, &data);
// do nothing
}
void ClientProxy1_5::fileChunkSending(uint8_t mark, char *data, size_t dataSize)
{
FileChunk::send(getStream(), mark, data, dataSize);
// do nothing
}
bool ClientProxy1_5::parseMessage(const uint8_t *code)
@ -63,25 +51,10 @@ bool ClientProxy1_5::parseMessage(const uint8_t *code)
void ClientProxy1_5::fileChunkReceived()
{
Server *server = getServer();
int result = FileChunk::assemble(getStream(), server->getReceivedFileData(), server->getExpectedFileSize());
if (result == kFinish) {
m_events->addEvent(Event(EventTypes::FileReceiveCompleted, server));
} else if (result == kStart) {
if (server->getFakeDragFileList().size() > 0) {
std::string filename = server->getFakeDragFileList().at(0).getFilename();
LOG((CLOG_DEBUG "start receiving %s", filename.c_str()));
}
}
// do nothing
}
void ClientProxy1_5::dragInfoReceived()
{
// parse
uint32_t fileNum = 0;
std::string content;
ProtocolUtil::readf(getStream(), kMsgDDragInfo + 4, &fileNum, &content);
m_server->dragInfoReceived(fileNum, content);
// do nothing
}

View File

@ -21,7 +21,7 @@ public:
ClientProxy1_5(const std::string &name, deskflow::IStream *adoptedStream, Server *server, IEventQueue *events);
ClientProxy1_5(ClientProxy1_5 const &) = delete;
ClientProxy1_5(ClientProxy1_5 &&) = delete;
~ClientProxy1_5() override;
~ClientProxy1_5() override = default;
ClientProxy1_5 &operator=(ClientProxy1_5 const &) = delete;
ClientProxy1_5 &operator=(ClientProxy1_5 &&) = delete;

View File

@ -13,8 +13,6 @@
#include "base/TMethodEventJob.h"
#include "base/TMethodJob.h"
#include "deskflow/AppUtil.h"
#include "deskflow/DropHelper.h"
#include "deskflow/FileChunk.h"
#include "deskflow/IPlatformScreen.h"
#include "deskflow/OptionTypes.h"
#include "deskflow/PacketStreamFilter.h"
@ -73,14 +71,9 @@ Server::Server(
m_lockedToScreen(false),
m_screen(screen),
m_events(events),
m_sendFileThread(nullptr),
m_writeToDropDirThread(nullptr),
m_ignoreFileTransfer(false),
m_disableLockToScreen(false),
m_enableClipboard(true),
m_maximumClipboardSize(INT_MAX),
m_sendDragInfoThread(nullptr),
m_waitDragInfoThread(true),
m_args(args)
{
// must have a primary client and it must have a canonical name
@ -165,16 +158,6 @@ Server::Server(
new TMethodEventJob<Server>(this, &Server::handleFakeInputEndEvent)
);
if (m_args.m_enableDragDrop) {
m_events->adoptHandler(
EventTypes::FileChunkSending, this, new TMethodEventJob<Server>(this, &Server::handleFileChunkSendingEvent)
);
m_events->adoptHandler(
EventTypes::FileReceiveCompleted, this,
new TMethodEventJob<Server>(this, &Server::handleFileReceiveCompletedEvent)
);
}
// add connection
addClient(m_primaryClient);
@ -1444,16 +1427,6 @@ void Server::handleFakeInputEndEvent(const Event &, void *)
m_primaryClient->fakeInputEnd();
}
void Server::handleFileChunkSendingEvent(const Event &event, void *)
{
onFileChunkSending(event.getDataObject());
}
void Server::handleFileReceiveCompletedEvent(const Event &event, void *)
{
onFileReceiveCompleted();
}
void Server::onClipboardChanged(BaseClientProxy *sender, ClipboardID id, uint32_t seqNum)
{
ClipboardInfo &clipboard = m_clipboards[id];
@ -1616,9 +1589,6 @@ void Server::onMouseDown(ButtonID id)
// relay
m_active->mouseDown(id);
// reset this variable back to default value true
m_waitDragInfoThread = true;
}
void Server::onMouseUp(ButtonID id)
@ -1628,23 +1598,6 @@ void Server::onMouseUp(ButtonID id)
// relay
m_active->mouseUp(id);
if (m_ignoreFileTransfer) {
m_ignoreFileTransfer = false;
return;
}
if (m_args.m_enableDragDrop) {
if (!m_screen->isOnScreen()) {
std::string &file = m_screen->getDraggingFilename();
if (!file.empty()) {
sendFileToClient(file.c_str());
}
}
// always clear dragging filename
m_screen->clearDraggingFilename();
}
}
bool Server::onMouseMovePrimary(int32_t x, int32_t y)
@ -1727,17 +1680,8 @@ bool Server::onMouseMovePrimary(int32_t x, int32_t y)
// should we switch or not?
if (isSwitchOkay(newScreen, dir, x, y, xc, yc)) {
if (m_args.m_enableDragDrop && m_screen->isDraggingStarted() && m_active != newScreen && m_waitDragInfoThread) {
if (!m_sendDragInfoThread) {
m_sendDragInfoThread.reset(new Thread(new TMethodJob<Server>(this, &Server::sendDragInfoThread, newScreen)));
}
return false;
}
// switch screen
switchScreen(newScreen, x, y, false);
m_waitDragInfoThread = true;
return true;
}
}
@ -1745,48 +1689,6 @@ bool Server::onMouseMovePrimary(int32_t x, int32_t y)
return false;
}
void Server::sendDragInfoThread(void *arg)
{
auto *newScreen = static_cast<BaseClientProxy *>(arg);
m_dragFileList.clear();
std::string &dragFileList = m_screen->getDraggingFilename();
if (!dragFileList.empty()) {
DragInformation di;
di.setFilename(dragFileList);
m_dragFileList.push_back(di);
}
#if defined(__APPLE__)
// on mac it seems that after faking a LMB up, system would signal back
// to deskflow a mouse up event, which doesn't happen on windows. as a
// result, deskflow would send dragging file to client twice. This variable
// is used to ignore the first file sending.
m_ignoreFileTransfer = true;
#endif
// send drag file info to client if there is any
if (m_dragFileList.size() > 0) {
sendDragInfo(newScreen);
m_dragFileList.clear();
}
m_waitDragInfoThread = false;
m_sendDragInfoThread.reset(nullptr);
}
void Server::sendDragInfo(BaseClientProxy *newScreen)
{
std::string infoString;
uint32_t fileCount = DragInformation::setupDragInfo(m_dragFileList, infoString);
if (fileCount > 0) {
LOG((CLOG_DEBUG2 "sending drag information to client"));
LOG((CLOG_DEBUG3 "dragging file list: %s", infoString.c_str()));
LOG((CLOG_DEBUG3 "dragging file list string size: %i", infoString.size()));
newScreen->sendDragInfo(fileCount, infoString.c_str(), infoString.size());
}
}
void Server::onMouseMoveSecondary(int32_t dx, int32_t dy)
{
LOG((CLOG_DEBUG2 "onMouseMoveSecondary initial %+d,%+d", dx, dy));
@ -1925,11 +1827,6 @@ void Server::onMouseMoveSecondary(int32_t dx, int32_t dy)
} while (false);
if (jump) {
if (m_sendFileThread) {
StreamChunker::interruptFile();
m_sendFileThread.reset(nullptr);
}
int32_t newX = m_x;
int32_t newY = m_y;
@ -1971,36 +1868,6 @@ void Server::onMouseWheel(int32_t xDelta, int32_t yDelta)
m_active->mouseWheel(xDelta, yDelta);
}
void Server::onFileChunkSending(const void *data)
{
auto *chunk = static_cast<FileChunk *>(const_cast<void *>(data));
LOG((CLOG_DEBUG1 "sending file chunk"));
assert(m_active != nullptr);
// relay
m_active->fileChunkSending(chunk->m_chunk[0], &chunk->m_chunk[1], chunk->m_dataSize);
}
void Server::onFileReceiveCompleted()
{
if (isReceivedFileSizeValid()) {
auto method = new TMethodJob<Server>(this, &Server::writeToDropDirThread);
m_writeToDropDirThread.reset(new Thread(method));
}
}
void Server::writeToDropDirThread(void *)
{
LOG((CLOG_DEBUG "starting write to drop dir thread"));
while (m_screen->isFakeDraggingStarted()) {
ARCH->sleep(.1f);
}
DropHelper::writeToDir(m_screen->getDropTarget(), m_fakeDragFileList, m_receivedFileData);
}
bool Server::addClient(BaseClientProxy *client)
{
std::string name = getName(client);
@ -2241,44 +2108,3 @@ Server::KeyboardBroadcastInfo *Server::KeyboardBroadcastInfo::alloc(State state,
std::copy(screens.c_str(), screens.c_str() + screens.size() + 1, info->m_screens);
return info;
}
bool Server::isReceivedFileSizeValid()
{
return m_expectedFileSize == m_receivedFileData.size();
}
void Server::sendFileToClient(const char *filename)
{
if (m_sendFileThread != nullptr) {
StreamChunker::interruptFile();
}
auto data = static_cast<void *>(const_cast<char *>(filename));
auto method = new TMethodJob<Server>(this, &Server::sendFileThread, data);
m_sendFileThread.reset(new Thread(method));
}
void Server::sendFileThread(void *data)
{
try {
auto *filename = static_cast<char *>(data);
LOG((CLOG_DEBUG "sending file to client, filename=%s", filename));
StreamChunker::sendFile(filename, m_events, this);
} catch (std::runtime_error &error) {
LOG((CLOG_ERR "failed sending file chunks, error: %s", error.what()));
}
m_sendFileThread.reset(nullptr);
}
void Server::dragInfoReceived(uint32_t fileNum, std::string content)
{
if (!m_args.m_enableDragDrop) {
LOG((CLOG_DEBUG "drag drop not enabled, ignoring drag info."));
return;
}
DragInformation::parseDragInfo(m_fakeDragFileList, fileNum, content);
m_screen->startDraggingFiles(m_fakeDragFileList);
}

View File

@ -12,7 +12,6 @@
#include "base/Stopwatch.h"
#include "deskflow/Clipboard.h"
#include "deskflow/ClipboardTypes.h"
#include "deskflow/DragInformation.h"
#include "deskflow/INode.h"
#include "deskflow/KeyTypes.h"
#include "deskflow/MouseTypes.h"
@ -167,12 +166,6 @@ public:
*/
void disconnect();
//! Create a new thread and use it to send file to client
void sendFileToClient(const char *filename);
//! Received dragging information from client
void dragInfoReceived(uint32_t fileNum, std::string content);
//! Store ClientListener pointer
void setListener(ClientListener *p)
{
@ -201,27 +194,6 @@ public:
*/
void getClients(std::vector<std::string> &list) const;
//! Return true if received file size is valid
bool isReceivedFileSizeValid();
//! Return expected file data size
size_t &getExpectedFileSize()
{
return m_expectedFileSize;
}
//! Return received file data
std::string &getReceivedFileData()
{
return m_receivedFileData;
}
//! Return fake drag file list
DragFileList getFakeDragFileList()
{
return m_fakeDragFileList;
}
//@}
private:
@ -348,8 +320,6 @@ private:
void handleLockCursorToScreenEvent(const Event &, void *);
void handleFakeInputBeginEvent(const Event &, void *);
void handleFakeInputEndEvent(const Event &, void *);
void handleFileChunkSendingEvent(const Event &, void *);
void handleFileReceiveCompletedEvent(const Event &, void *);
// event processing
void onClipboardChanged(BaseClientProxy *sender, ClipboardID id, uint32_t seqNum);
@ -362,8 +332,6 @@ private:
bool onMouseMovePrimary(int32_t x, int32_t y);
void onMouseMoveSecondary(int32_t dx, int32_t dy);
void onMouseWheel(int32_t xDelta, int32_t yDelta);
void onFileChunkSending(const void *data);
void onFileReceiveCompleted();
// add client to list and attach event handlers for client
bool addClient(BaseClientProxy *);
@ -388,18 +356,6 @@ private:
// force the cursor off of \p client
void forceLeaveClient(BaseClientProxy *client);
// thread funciton for sending file
void sendFileThread(void *);
// thread function for writing file to drop directory
void writeToDropDirThread(void *);
// thread function for sending drag information
void sendDragInfoThread(void *);
// send drag info to new client screen
void sendDragInfo(BaseClientProxy *newScreen);
public:
bool m_mock;
@ -500,23 +456,10 @@ private:
IEventQueue *m_events;
// file transfer
using AutoThread = std::unique_ptr<Thread>;
size_t m_expectedFileSize;
std::string m_receivedFileData;
DragFileList m_dragFileList;
DragFileList m_fakeDragFileList;
AutoThread m_sendFileThread;
AutoThread m_writeToDropDirThread;
std::string m_dragFileExt;
bool m_ignoreFileTransfer;
bool m_disableLockToScreen;
bool m_enableClipboard;
size_t m_maximumClipboardSize;
AutoThread m_sendDragInfoThread;
bool m_waitDragInfoThread;
ClientListener *m_clientListener;
deskflow::ServerArgs m_args;
};

View File

@ -204,31 +204,3 @@ TEST_F(GenericArgsParsingTests, parseGenericArgs_versionCmd_showVersion)
EXPECT_EQ(true, g_versionShowed);
EXPECT_EQ(1, i);
}
#ifndef WINAPI_XWINDOWS
TEST_F(GenericArgsParsingTests, parseGenericArgs_dragDropCmdOnNonLinux_enableDragDropTrue)
{
int i = 1;
const int argc = 2;
const char *kDragDropCmd[argc] = {"stub", "--enable-drag-drop"};
m_argParser->parseGenericArgs(argc, kDragDropCmd, i);
EXPECT_EQ(true, argsBase.m_enableDragDrop);
EXPECT_EQ(1, i);
}
#endif
#ifdef WINAPI_XWINDOWS
TEST_F(GenericArgsParsingTests, parseGenericArgs_dragDropCmdOnLinux_enableDragDropFalse)
{
int i = 1;
const int argc = 2;
const char *kDragDropCmd[argc] = {"stub", "--enable-drag-drop"};
m_argParser->parseGenericArgs(argc, kDragDropCmd, i);
EXPECT_FALSE(argsBase.m_enableDragDrop);
EXPECT_EQ(1, i);
}
#endif