feat: add switchToNextScreen hotkey to cycle through computers

This commit is contained in:
Kris
2025-08-29 09:26:16 -04:00
committed by Chris Rizzitello
parent 398c9726f3
commit 104d2facdb
9 changed files with 111 additions and 7 deletions

View File

@ -432,6 +432,9 @@ Actions are two lists of individual actions separated by commas. The two lists a
* `switchInDirection(dir)`
: 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
Valid key names are:

View File

@ -1,5 +1,6 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2025 Deskflow Developers
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
* SPDX-FileCopyrightText: (C) 2008 Volker Lanz <vl@fidra.de>
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
@ -42,6 +43,7 @@ public:
keystroke,
switchToScreen,
switchInDirection,
switchToNextScreen,
lockCursorToScreen,
restartAllConnections,
mouseDown,
@ -162,11 +164,17 @@ private:
inline static const QString m_commandTemplate = QStringLiteral("(%1)");
inline static const QStringList m_actionTypeNames{
QStringLiteral("keyDown"), QStringLiteral("keyUp"),
QStringLiteral("keystroke"), QStringLiteral("switchToScreen"),
QStringLiteral("switchInDirection"), QStringLiteral("lockCursorToScreen"),
QStringLiteral("restartServer"), QStringLiteral("mouseDown"),
QStringLiteral("mouseUp"), QStringLiteral("mousebutton")
QStringLiteral("keyDown"),
QStringLiteral("keyUp"),
QStringLiteral("keystroke"),
QStringLiteral("switchToScreen"),
QStringLiteral("switchInDirection"),
QStringLiteral("switchToNextScreen"),
QStringLiteral("lockCursorToScreen"),
QStringLiteral("restartServer"),
QStringLiteral("mouseDown"),
QStringLiteral("mouseUp"),
QStringLiteral("mousebutton")
};
inline static const QStringList m_switchDirectionNames{

View File

@ -1,6 +1,7 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* 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) 2008 Volker Lanz <vl@fidra.de>
* 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 SwitchTo = 3;
inline static const auto SwitchInDirection = 4;
inline static const auto ModifyCursorLock = 5;
inline static const auto RestartServer = 6;
inline static const auto SwitchToNextScreen = 5;
inline static const auto ModifyCursorLock = 6;
inline static const auto RestartServer = 7;
};
ActionDialog(QWidget *parent, const ServerConfig &config, Hotkey &hotkey, Action &action);

View File

@ -63,6 +63,11 @@
<string>Switch in a direction</string>
</property>
</item>
<item>
<property name="text">
<string>Switch to next computer</string>
</property>
</item>
<item>
<property name="text">
<string>Modify the cursor lock</string>

View File

@ -1,5 +1,6 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2025 Deskflow Developers
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
* 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);
}
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") {
if (args.size() > 1) {
throw ServerConfigReadException(s, "syntax for action: lockCursorToScreen([{off|on|toggle}])");

View File

@ -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)
: m_mode(mode),
m_events(events)

View File

@ -211,6 +211,21 @@ public:
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
class KeyboardBroadcastAction : public Action
{

View File

@ -28,6 +28,7 @@
#include "server/PrimaryClient.h"
#ifdef _WIN32
#include <algorithm>
#include <array>
#endif
#include <cmath>
@ -110,6 +111,9 @@ Server::Server(
m_events->addHandler(EventTypes::ServerSwitchInDirection, m_inputFilter, [this](const auto &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) {
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)
{
const auto *info = (KeyboardBroadcastInfo *)event.getData();

View File

@ -306,6 +306,7 @@ private:
void handleClientCloseTimeout(BaseClientProxy *client);
void handleSwitchToScreenEvent(const Event &event);
void handleSwitchInDirectionEvent(const Event &event);
void handleToggleScreenEvent(const Event &event);
void handleKeyboardBroadcastEvent(const Event &event);
void handleLockCursorToScreenEvent(const Event &event);