feat: add switchToNextScreen hotkey to cycle through computers
This commit is contained in:
parent
398c9726f3
commit
104d2facdb
9 changed files with 111 additions and 7 deletions
|
|
@ -432,6 +432,9 @@ Actions are two lists of individual actions separated by commas. The two lists a
|
||||||
* `switchInDirection(dir)`
|
* `switchInDirection(dir)`
|
||||||
: Switch to the screen in the direction ''dir'', which may be one of ''left'', ''right'', ''up'' or ''down''.
|
: Switch to the screen in the direction ''dir'', which may be one of ''left'', ''right'', ''up'' or ''down''.
|
||||||
|
|
||||||
|
* `switchToNextScreen()`
|
||||||
|
: Cycle to the next screen in the configuration order. If at the last screen, cycles back to the first screen.
|
||||||
|
|
||||||
##### Keynames
|
##### Keynames
|
||||||
Valid key names are:
|
Valid key names are:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
* Deskflow -- mouse and keyboard sharing utility
|
||||||
|
* SPDX-FileCopyrightText: (C) 2025 Deskflow Developers
|
||||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||||
* SPDX-FileCopyrightText: (C) 2008 Volker Lanz <vl@fidra.de>
|
* SPDX-FileCopyrightText: (C) 2008 Volker Lanz <vl@fidra.de>
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
|
|
@ -42,6 +43,7 @@ public:
|
||||||
keystroke,
|
keystroke,
|
||||||
switchToScreen,
|
switchToScreen,
|
||||||
switchInDirection,
|
switchInDirection,
|
||||||
|
switchToNextScreen,
|
||||||
lockCursorToScreen,
|
lockCursorToScreen,
|
||||||
restartAllConnections,
|
restartAllConnections,
|
||||||
mouseDown,
|
mouseDown,
|
||||||
|
|
@ -162,11 +164,17 @@ private:
|
||||||
|
|
||||||
inline static const QString m_commandTemplate = QStringLiteral("(%1)");
|
inline static const QString m_commandTemplate = QStringLiteral("(%1)");
|
||||||
inline static const QStringList m_actionTypeNames{
|
inline static const QStringList m_actionTypeNames{
|
||||||
QStringLiteral("keyDown"), QStringLiteral("keyUp"),
|
QStringLiteral("keyDown"),
|
||||||
QStringLiteral("keystroke"), QStringLiteral("switchToScreen"),
|
QStringLiteral("keyUp"),
|
||||||
QStringLiteral("switchInDirection"), QStringLiteral("lockCursorToScreen"),
|
QStringLiteral("keystroke"),
|
||||||
QStringLiteral("restartServer"), QStringLiteral("mouseDown"),
|
QStringLiteral("switchToScreen"),
|
||||||
QStringLiteral("mouseUp"), QStringLiteral("mousebutton")
|
QStringLiteral("switchInDirection"),
|
||||||
|
QStringLiteral("switchToNextScreen"),
|
||||||
|
QStringLiteral("lockCursorToScreen"),
|
||||||
|
QStringLiteral("restartServer"),
|
||||||
|
QStringLiteral("mouseDown"),
|
||||||
|
QStringLiteral("mouseUp"),
|
||||||
|
QStringLiteral("mousebutton")
|
||||||
};
|
};
|
||||||
|
|
||||||
inline static const QStringList m_switchDirectionNames{
|
inline static const QStringList m_switchDirectionNames{
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
* Deskflow -- mouse and keyboard sharing utility
|
||||||
* SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello <sithlord48@gmail.com>
|
* SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello <sithlord48@gmail.com>
|
||||||
|
* SPDX-FileCopyrightText: (C) 2025 Deskflow Developers
|
||||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||||
* SPDX-FileCopyrightText: (C) 2008 Volker Lanz <vl@fidra.de>
|
* SPDX-FileCopyrightText: (C) 2008 Volker Lanz <vl@fidra.de>
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
|
|
@ -31,8 +32,9 @@ public:
|
||||||
inline static const auto ToggleKey = 2;
|
inline static const auto ToggleKey = 2;
|
||||||
inline static const auto SwitchTo = 3;
|
inline static const auto SwitchTo = 3;
|
||||||
inline static const auto SwitchInDirection = 4;
|
inline static const auto SwitchInDirection = 4;
|
||||||
inline static const auto ModifyCursorLock = 5;
|
inline static const auto SwitchToNextScreen = 5;
|
||||||
inline static const auto RestartServer = 6;
|
inline static const auto ModifyCursorLock = 6;
|
||||||
|
inline static const auto RestartServer = 7;
|
||||||
};
|
};
|
||||||
|
|
||||||
ActionDialog(QWidget *parent, const ServerConfig &config, Hotkey &hotkey, Action &action);
|
ActionDialog(QWidget *parent, const ServerConfig &config, Hotkey &hotkey, Action &action);
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,11 @@
|
||||||
<string>Switch in a direction</string>
|
<string>Switch in a direction</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Switch to next computer</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Modify the cursor lock</string>
|
<string>Modify the cursor lock</string>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
* Deskflow -- mouse and keyboard sharing utility
|
||||||
|
* SPDX-FileCopyrightText: (C) 2025 Deskflow Developers
|
||||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
|
|
@ -1061,6 +1062,14 @@ void Config::parseAction(
|
||||||
action = new InputFilter::SwitchInDirectionAction(m_events, direction);
|
action = new InputFilter::SwitchInDirectionAction(m_events, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (name == "switchToNextScreen") {
|
||||||
|
if (args.size() != 0) {
|
||||||
|
throw ServerConfigReadException(s, "syntax for action: switchToNextScreen");
|
||||||
|
}
|
||||||
|
|
||||||
|
action = new InputFilter::SwitchToNextScreenAction(m_events);
|
||||||
|
}
|
||||||
|
|
||||||
else if (name == "lockCursorToScreen") {
|
else if (name == "lockCursorToScreen") {
|
||||||
if (args.size() > 1) {
|
if (args.size() > 1) {
|
||||||
throw ServerConfigReadException(s, "syntax for action: lockCursorToScreen([{off|on|toggle}])");
|
throw ServerConfigReadException(s, "syntax for action: lockCursorToScreen([{off|on|toggle}])");
|
||||||
|
|
|
||||||
|
|
@ -336,6 +336,28 @@ void InputFilter::SwitchInDirectionAction::perform(const Event &event)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InputFilter::SwitchToNextScreenAction::SwitchToNextScreenAction(IEventQueue *events) : m_events(events)
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
InputFilter::Action *InputFilter::SwitchToNextScreenAction::clone() const
|
||||||
|
{
|
||||||
|
return new SwitchToNextScreenAction(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string InputFilter::SwitchToNextScreenAction::format() const
|
||||||
|
{
|
||||||
|
return "switchToNextScreen()";
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputFilter::SwitchToNextScreenAction::perform(const Event &event)
|
||||||
|
{
|
||||||
|
m_events->addEvent(
|
||||||
|
Event(EventTypes::ServerToggleScreen, event.getTarget(), nullptr, Event::EventFlags::DeliverImmediately)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
InputFilter::KeyboardBroadcastAction::KeyboardBroadcastAction(IEventQueue *events, Mode mode)
|
InputFilter::KeyboardBroadcastAction::KeyboardBroadcastAction(IEventQueue *events, Mode mode)
|
||||||
: m_mode(mode),
|
: m_mode(mode),
|
||||||
m_events(events)
|
m_events(events)
|
||||||
|
|
|
||||||
|
|
@ -211,6 +211,21 @@ public:
|
||||||
IEventQueue *m_events;
|
IEventQueue *m_events;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// SwitchToNextScreenAction
|
||||||
|
class SwitchToNextScreenAction : public Action
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit SwitchToNextScreenAction(IEventQueue *events);
|
||||||
|
|
||||||
|
// Action overrides
|
||||||
|
Action *clone() const override;
|
||||||
|
std::string format() const override;
|
||||||
|
void perform(const Event &) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
IEventQueue *m_events;
|
||||||
|
};
|
||||||
|
|
||||||
// KeyboardBroadcastAction
|
// KeyboardBroadcastAction
|
||||||
class KeyboardBroadcastAction : public Action
|
class KeyboardBroadcastAction : public Action
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
#include "server/PrimaryClient.h"
|
#include "server/PrimaryClient.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#endif
|
#endif
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
@ -110,6 +111,9 @@ Server::Server(
|
||||||
m_events->addHandler(EventTypes::ServerSwitchInDirection, m_inputFilter, [this](const auto &e) {
|
m_events->addHandler(EventTypes::ServerSwitchInDirection, m_inputFilter, [this](const auto &e) {
|
||||||
handleSwitchInDirectionEvent(e);
|
handleSwitchInDirectionEvent(e);
|
||||||
});
|
});
|
||||||
|
m_events->addHandler(EventTypes::ServerToggleScreen, m_inputFilter, [this](const auto &e) {
|
||||||
|
handleToggleScreenEvent(e);
|
||||||
|
});
|
||||||
m_events->addHandler(EventTypes::ServerKeyboardBroadcast, m_inputFilter, [this](const auto &e) {
|
m_events->addHandler(EventTypes::ServerKeyboardBroadcast, m_inputFilter, [this](const auto &e) {
|
||||||
handleKeyboardBroadcastEvent(e);
|
handleKeyboardBroadcastEvent(e);
|
||||||
});
|
});
|
||||||
|
|
@ -1330,6 +1334,41 @@ void Server::handleSwitchInDirectionEvent(const Event &event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Server::handleToggleScreenEvent(const Event &event)
|
||||||
|
{
|
||||||
|
// Get the list of connected screens in config order
|
||||||
|
std::vector<std::string> screens;
|
||||||
|
getClients(screens);
|
||||||
|
|
||||||
|
if (screens.size() < 2) {
|
||||||
|
LOG_ERR("not enough screens to toggle");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the current active screen
|
||||||
|
std::string currentScreen = getName(m_active);
|
||||||
|
auto it = std::ranges::find(screens, currentScreen);
|
||||||
|
if (it == screens.end()) {
|
||||||
|
LOG_ERR("current screen not found in list");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the next screen
|
||||||
|
auto nextIt = it + 1;
|
||||||
|
if (nextIt == screens.end()) {
|
||||||
|
nextIt = screens.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the client for the next screen
|
||||||
|
ClientList::const_iterator clientIt = m_clients.find(*nextIt);
|
||||||
|
if (clientIt == m_clients.end()) {
|
||||||
|
LOG_ERR("next screen not active");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
jumpToScreen(clientIt->second);
|
||||||
|
}
|
||||||
|
|
||||||
void Server::handleKeyboardBroadcastEvent(const Event &event)
|
void Server::handleKeyboardBroadcastEvent(const Event &event)
|
||||||
{
|
{
|
||||||
const auto *info = (KeyboardBroadcastInfo *)event.getData();
|
const auto *info = (KeyboardBroadcastInfo *)event.getData();
|
||||||
|
|
|
||||||
|
|
@ -306,6 +306,7 @@ private:
|
||||||
void handleClientCloseTimeout(BaseClientProxy *client);
|
void handleClientCloseTimeout(BaseClientProxy *client);
|
||||||
void handleSwitchToScreenEvent(const Event &event);
|
void handleSwitchToScreenEvent(const Event &event);
|
||||||
void handleSwitchInDirectionEvent(const Event &event);
|
void handleSwitchInDirectionEvent(const Event &event);
|
||||||
|
void handleToggleScreenEvent(const Event &event);
|
||||||
void handleKeyboardBroadcastEvent(const Event &event);
|
void handleKeyboardBroadcastEvent(const Event &event);
|
||||||
void handleLockCursorToScreenEvent(const Event &event);
|
void handleLockCursorToScreenEvent(const Event &event);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue