feat: remove drag and drop support, its broken on all platforms
This commit is contained in:
committed by
Chris Rizzitello
parent
55a7fa3266
commit
5365e34f08
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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)) {
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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();
|
||||
}
|
||||
@ -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;
|
||||
};
|
||||
@ -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"));
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
};
|
||||
@ -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);
|
||||
}
|
||||
@ -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);
|
||||
};
|
||||
@ -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
|
||||
/*!
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
};
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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)
|
||||
}
|
||||
44
src/lib/platform/OSXCocoaApp.m
Normal file
44
src/lib/platform/OSXCocoaApp.m
Normal 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];
|
||||
}
|
||||
@ -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];
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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;
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user