feat: Option to change server protocol in GUI

This commit is contained in:
Nick Bolton
2024-10-18 16:13:13 +01:00
parent 512faeea28
commit a5cd0fab9e
14 changed files with 623 additions and 448 deletions

View File

@ -72,15 +72,26 @@ bool ServerConfig::save(const QString &fileName) const
bool ServerConfig::operator==(const ServerConfig &sc) const
{
return m_Screens == sc.m_Screens && m_Columns == sc.m_Columns && m_Rows == sc.m_Rows &&
m_HasHeartbeat == sc.m_HasHeartbeat && m_Heartbeat == sc.m_Heartbeat &&
m_RelativeMouseMoves == sc.m_RelativeMouseMoves && m_Win32KeepForeground == sc.m_Win32KeepForeground &&
m_HasSwitchDelay == sc.m_HasSwitchDelay && m_SwitchDelay == sc.m_SwitchDelay &&
m_HasSwitchDoubleTap == sc.m_HasSwitchDoubleTap && m_SwitchDoubleTap == sc.m_SwitchDoubleTap &&
m_SwitchCornerSize == sc.m_SwitchCornerSize && m_SwitchCorners == sc.m_SwitchCorners &&
m_Hotkeys == sc.m_Hotkeys && m_pAppConfig == sc.m_pAppConfig &&
m_EnableDragAndDrop == sc.m_EnableDragAndDrop && m_DisableLockToScreen == sc.m_DisableLockToScreen &&
m_ClipboardSharing == sc.m_ClipboardSharing && m_ClipboardSharingSize == sc.m_ClipboardSharingSize &&
return m_Screens == sc.m_Screens && //
m_Columns == sc.m_Columns && //
m_Rows == sc.m_Rows && //
m_HasHeartbeat == sc.m_HasHeartbeat && //
m_Heartbeat == sc.m_Heartbeat && //
m_Protocol == sc.m_Protocol && //
m_RelativeMouseMoves == sc.m_RelativeMouseMoves && //
m_Win32KeepForeground == sc.m_Win32KeepForeground && //
m_HasSwitchDelay == sc.m_HasSwitchDelay && //
m_SwitchDelay == sc.m_SwitchDelay && //
m_HasSwitchDoubleTap == sc.m_HasSwitchDoubleTap && //
m_SwitchDoubleTap == sc.m_SwitchDoubleTap && //
m_SwitchCornerSize == sc.m_SwitchCornerSize && //
m_SwitchCorners == sc.m_SwitchCorners && //
m_Hotkeys == sc.m_Hotkeys && //
m_pAppConfig == sc.m_pAppConfig && //
m_EnableDragAndDrop == sc.m_EnableDragAndDrop && //
m_DisableLockToScreen == sc.m_DisableLockToScreen && //
m_ClipboardSharing == sc.m_ClipboardSharing && //
m_ClipboardSharingSize == sc.m_ClipboardSharingSize && //
m_pMainWindow == sc.m_pMainWindow;
}
@ -118,6 +129,7 @@ void ServerConfig::commit()
settings().setValue("hasHeartbeat", hasHeartbeat());
settings().setValue("heartbeat", heartbeat());
settings().setValue("protocol", static_cast<int>(protocol()));
settings().setValue("relativeMouseMoves", relativeMouseMoves());
settings().setValue("win32KeepForeground", win32KeepForeground());
settings().setValue("hasSwitchDelay", hasSwitchDelay());
@ -172,6 +184,7 @@ void ServerConfig::recall()
haveHeartbeat(settings().value("hasHeartbeat", false).toBool());
setHeartbeat(settings().value("heartbeat", 5000).toInt());
setProtocol(static_cast<ServerProtocol>(settings().value("protocol", static_cast<int>(protocol())).toInt()));
setRelativeMouseMoves(settings().value("relativeMouseMoves", false).toBool());
setWin32KeepForeground(settings().value("win32KeepForeground", false).toBool());
haveSwitchDelay(settings().value("hasSwitchDelay", false).toBool());
@ -232,6 +245,8 @@ int ServerConfig::adjacentScreenIndex(int idx, int deltaColumn, int deltaRow) co
QTextStream &operator<<(QTextStream &outStream, const ServerConfig &config)
{
using enum synergy::gui::ServerProtocol;
outStream << "section: screens" << Qt::endl;
foreach (const Screen &s, config.screens())
@ -266,8 +281,15 @@ QTextStream &operator<<(QTextStream &outStream, const ServerConfig &config)
outStream << "section: options" << Qt::endl;
if (config.hasHeartbeat())
outStream << "\t"
<< "heartbeat = " << config.heartbeat() << Qt::endl;
outStream << "\t" << "heartbeat = " << config.heartbeat() << Qt::endl;
if (config.protocol() == kSynergy) {
outStream << "\t" << "protocol = synergy" << Qt::endl;
} else if (config.protocol() == kBarrier) {
outStream << "\t" << "protocol = barrier" << Qt::endl;
} else {
qFatal("unrecognized protocol when writing config");
}
outStream << "\t"
<< "relativeMouseMoves = " << (config.relativeMouseMoves() ? "true" : "false") << Qt::endl;

View File

@ -36,9 +36,25 @@ class ServerConfigDialog;
class MainWindow;
class AppConfig;
namespace synergy::gui {
enum class ServerProtocol
{
kSynergy,
kBarrier
};
// The default protocol was decided by a community vote.
// TODO: Remove this link when the vote concludes:
// https://github.com/deskflow/deskflow/discussions/7742
const auto kDefaultProtocol = ServerProtocol::kSynergy;
} // namespace synergy::gui
class ServerConfig : public ScreenConfig, public deskflow::gui::IServerConfig
{
using QSettingsProxy = deskflow::gui::proxy::QSettingsProxy;
using ServerProtocol = synergy::gui::ServerProtocol;
friend class ServerConfigDialog;
friend QTextStream &operator<<(QTextStream &outStream, const ServerConfig &config);
@ -80,6 +96,10 @@ public:
{
return m_Heartbeat;
}
ServerProtocol protocol() const
{
return m_Protocol;
}
bool relativeMouseMoves() const
{
return m_RelativeMouseMoves;
@ -188,6 +208,10 @@ private:
{
m_Heartbeat = val;
}
void setProtocol(ServerProtocol val)
{
m_Protocol = val;
}
void setRelativeMouseMoves(bool on)
{
m_RelativeMouseMoves = on;
@ -252,6 +276,7 @@ private:
private:
bool m_HasHeartbeat = false;
int m_Heartbeat = 0;
ServerProtocol m_Protocol = synergy::gui::kDefaultProtocol;
bool m_RelativeMouseMoves = false;
bool m_Win32KeepForeground = false;
bool m_HasSwitchDelay = false;

View File

@ -30,6 +30,7 @@
#include <QtGui>
using enum ScreenConfig::SwitchCorner;
using ServerProtocol = synergy::gui::ServerProtocol;
ServerConfigDialog::ServerConfigDialog(QWidget *parent, ServerConfig &config, AppConfig &appConfig)
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint),
@ -51,6 +52,8 @@ ServerConfigDialog::ServerConfigDialog(QWidget *parent, ServerConfig &config, Ap
ui->m_pEditConfigFile->setText(serverConfig().configFile());
ui->m_pCheckBoxUseExternalConfig->setChecked(serverConfig().useExternalConfig());
ui->m_pCheckBoxHeartbeat->setChecked(serverConfig().hasHeartbeat());
ui->m_pRadioProtocolSynergy->setChecked(serverConfig().protocol() == ServerProtocol::kSynergy);
ui->m_pRadioProtocolBarrier->setChecked(serverConfig().protocol() == ServerProtocol::kBarrier);
ui->m_pSpinBoxHeartbeat->setValue(serverConfig().heartbeat());
ui->m_pCheckBoxRelativeMouseMoves->setChecked(serverConfig().relativeMouseMoves());
@ -99,6 +102,8 @@ ServerConfigDialog::ServerConfigDialog(QWidget *parent, ServerConfig &config, Ap
// computers
connect(&m_ScreenSetupModel, &ScreenSetupModel::screensChanged, this, &ServerConfigDialog::onChange);
// Above Qt 6.7 the checkbox signal signature has changed from int to Qt::CheckState
#if QT_VERSION <= QT_VERSION_CHECK(6, 7, 0)
// advanced
connect(ui->m_pCheckBoxSwitchDelay, &QCheckBox::stateChanged, this, [this](const int &v) {
@ -237,6 +242,18 @@ ServerConfigDialog::ServerConfigDialog(QWidget *parent, ServerConfig &config, Ap
onChange();
}
);
connect(ui->m_pRadioProtocolSynergy, &QRadioButton::toggled, this, [this](const bool &v) {
if (v) {
serverConfig().setProtocol(ServerProtocol::kSynergy);
onChange();
}
});
connect(ui->m_pRadioProtocolBarrier, &QRadioButton::toggled, this, [this](const bool &v) {
if (v) {
serverConfig().setProtocol(ServerProtocol::kBarrier);
onChange();
}
});
connect(ui->m_pEditConfigFile, &QLineEdit::textChanged, this, [this]() {
serverConfig().setConfigFile(ui->m_pEditConfigFile->text());

File diff suppressed because it is too large Load Diff

View File

@ -52,7 +52,7 @@ void HelloBack::handleHello(deskflow::IStream *stream, const std::string &client
}
// check versions
LOG_DEBUG("got hello version %s, %d.%d", protocolName.c_str(), serverMajor, serverMinor);
LOG_DEBUG("got hello from %s, protocol v%d.%d", protocolName.c_str(), serverMajor, serverMinor);
const auto helloBackMajor = m_majorVersion;
auto helloBackMinor = m_minorVersion;

View File

@ -28,6 +28,15 @@ String XBadClient::getWhat() const throw()
return "XBadClient";
}
//
// XInvalidProtocol
//
String XInvalidProtocol::getWhat() const throw()
{
return "XInvalidProtocol";
}
//
// XIncompatibleClient
//

View File

@ -35,6 +35,12 @@ Thrown when the client fails to follow the protocol.
*/
XBASE_SUBCLASS_WHAT(XBadClient, XDeskflow);
//! Server protocol error
/*!
Thrown when the server protocol is unrecognized.
*/
XBASE_SUBCLASS_WHAT(XInvalidProtocol, XDeskflow);
//! Incompatible client exception
/*!
Thrown when a client attempting to connect has an incompatible version.

View File

@ -55,6 +55,7 @@ static const OptionID kOptionModifierMapForAltGr = OPTION_CODE("MMFG");
static const OptionID kOptionModifierMapForMeta = OPTION_CODE("MMFM");
static const OptionID kOptionModifierMapForSuper = OPTION_CODE("MMFR");
static const OptionID kOptionHeartbeat = OPTION_CODE("HART");
static const OptionID kOptionProtocol = OPTION_CODE("PROT");
static const OptionID kOptionScreenSwitchCorners = OPTION_CODE("SSCM");
static const OptionID kOptionScreenSwitchCornerSize = OPTION_CODE("SSCS");
static const OptionID kOptionScreenSwitchDelay = OPTION_CODE("SSWT");
@ -98,4 +99,13 @@ enum EScreenSwitchCornerMasks
};
//@}
//! @name Network protocol
//@{
enum class ENetworkProtocol
{
kSynergy,
kBarrier
};
//@}
#undef OPTION_CODE

View File

@ -60,9 +60,10 @@ ClientProxyUnknown::ClientProxyUnknown(deskflow::IStream *stream, double timeout
m_timer = m_events->newOneShotTimer(timeout, this);
addStreamHandlers();
std::string helloMessage = std::string(kSynergyProtocolName).append(kMsgHelloArgs);
const auto protocol = m_server->protocolString();
const auto helloMessage = protocol + kMsgHelloArgs;
LOG((CLOG_DEBUG1 "saying hello"));
LOG_DEBUG("saying hello as %s, protocol v%d.%d", protocol.c_str(), kProtocolMajorVersion, kProtocolMinorVersion);
ProtocolUtil::writef(m_stream, helloMessage.c_str(), kProtocolMajorVersion, kProtocolMinorVersion);
}

View File

@ -21,6 +21,7 @@
#include "base/Event.h"
#include "base/EventTypes.h"
#include "base/String.h"
#include "deskflow/option_types.h"
class ClientProxy;
class EventQueueTimer;

View File

@ -22,7 +22,9 @@
#include "common/stdistream.h"
#include "common/stdostream.h"
#include "deskflow/KeyMap.h"
#include "deskflow/XDeskflow.h"
#include "deskflow/key_types.h"
#include "deskflow/option_types.h"
#include "net/XSocket.h"
#include "server/Server.h"
@ -32,6 +34,9 @@ using namespace deskflow::string;
namespace deskflow::server {
const auto kSynergyProtocolOption = "synergy";
const auto kBarrierProtocolOption = "barrier";
//
// Config
//
@ -675,6 +680,8 @@ void Config::readSectionOptions(ConfigReadContext &s)
}
} else if (name == "heartbeat") {
addOption("", kOptionHeartbeat, s.parseInt(value));
} else if (name == "protocol") {
addOption("", kOptionProtocol, s.parseProtocol(value));
} else if (name == "switchCorners") {
addOption("", kOptionScreenSwitchCorners, s.parseCorners(value));
} else if (name == "switchCornerSize") {
@ -1325,6 +1332,17 @@ String Config::getOptionValue(OptionID id, OptionValue value)
}
return result;
}
if (id == kOptionProtocol) {
using enum ENetworkProtocol;
const auto enumValue = static_cast<ENetworkProtocol>(value);
if (enumValue == kSynergy) {
return kSynergyProtocolOption;
} else if (enumValue == kBarrier) {
return kBarrierProtocolOption;
} else {
throw XInvalidProtocol();
}
}
return "";
}
@ -1822,6 +1840,16 @@ OptionValue ConfigReadContext::parseCorner(const String &arg) const
throw XConfigRead(*this, "invalid argument \"%{1}\"", arg);
}
OptionValue ConfigReadContext::parseProtocol(const String &args) const
{
if (CaselessCmp::equal(args, kSynergyProtocolOption)) {
return static_cast<OptionValue>(ENetworkProtocol::kSynergy);
} else if (CaselessCmp::equal(args, kBarrierProtocolOption)) {
return static_cast<OptionValue>(ENetworkProtocol::kBarrier);
}
throw XConfigRead(*this, "invalid protocol argument \"%{1}\"", args);
}
OptionValue ConfigReadContext::parseCorners(const String &args) const
{
// find first token

View File

@ -537,6 +537,7 @@ public:
OptionValue parseModifierKey(const String &) const;
OptionValue parseCorner(const String &) const;
OptionValue parseCorners(const String &) const;
OptionValue parseProtocol(const String &) const;
Config::Interval parseInterval(const ArgList &args) const;
void parseNameWithArgs(
const String &type, const String &line, const String &delim, String::size_type &index, String &name, ArgList &args

View File

@ -31,6 +31,7 @@
#include "deskflow/PacketStreamFilter.h"
#include "deskflow/Screen.h"
#include "deskflow/StreamChunker.h"
#include "deskflow/XDeskflow.h"
#include "deskflow/option_types.h"
#include "deskflow/protocol_types.h"
#include "mt/Thread.h"
@ -341,6 +342,17 @@ void Server::disconnect()
}
}
std::string Server::protocolString() const
{
using enum ENetworkProtocol;
if (m_protocol == kSynergy) {
return kSynergyProtocolName;
} else if (m_protocol == kBarrier) {
return kBarrierProtocolName;
}
throw XInvalidProtocol();
}
UInt32 Server::getNumClients() const
{
return (SInt32)m_clients.size();
@ -1100,7 +1112,17 @@ void Server::processOptions()
for (Config::ScreenOptions::const_iterator index = options->begin(); index != options->end(); ++index) {
const OptionID id = index->first;
const OptionValue value = index->second;
if (id == kOptionScreenSwitchDelay) {
if (id == kOptionProtocol) {
using enum ENetworkProtocol;
const auto enumValue = static_cast<ENetworkProtocol>(value);
if (enumValue == kSynergy) {
m_protocol = kSynergy;
} else if (enumValue == kBarrier) {
m_protocol = kBarrier;
} else {
throw XInvalidProtocol();
}
} else if (id == kOptionScreenSwitchDelay) {
m_switchWaitDelay = 1.0e-3 * static_cast<double>(value);
if (m_switchWaitDelay < 0.0) {
m_switchWaitDelay = 0.0;

View File

@ -31,6 +31,7 @@
#include "deskflow/clipboard_types.h"
#include "deskflow/key_types.h"
#include "deskflow/mouse_types.h"
#include "deskflow/option_types.h"
#include "server/Config.h"
#include <memory>
@ -192,6 +193,12 @@ public:
//! @name accessors
//@{
//! Get the network protocol
/*!
Returns the network protocol used by the server.
*/
std::string protocolString() const;
//! Get number of connected clients
/*!
Returns the number of connected clients, including the server itself.
@ -422,6 +429,9 @@ private:
UInt32 m_clipboardSeqNum;
};
// used in hello message sent to the client
ENetworkProtocol m_protocol;
// the primary screen client
PrimaryClient *m_primaryClient;