diff --git a/src/lib/gui/CMakeLists.txt b/src/lib/gui/CMakeLists.txt
index 0dea497d8..5e841c54c 100644
--- a/src/lib/gui/CMakeLists.txt
+++ b/src/lib/gui/CMakeLists.txt
@@ -54,6 +54,8 @@ add_library(${target} STATIC
core/CommandProcess.h
core/CoreProcess.cpp
core/CoreProcess.h
+ core/NetworkMonitor.cpp
+ core/NetworkMonitor.h
core/ServerConnection.cpp
core/ServerConnection.h
core/ServerMessage.cpp
diff --git a/src/lib/gui/MainWindow.cpp b/src/lib/gui/MainWindow.cpp
index b8c49b8ef..8b4bb9f54 100644
--- a/src/lib/gui/MainWindow.cpp
+++ b/src/lib/gui/MainWindow.cpp
@@ -86,7 +86,9 @@ MainWindow::MainWindow()
m_actionSettings{new QAction(this)},
m_actionStartCore{new QAction(this)},
m_actionRestartCore{new QAction(this)},
- m_actionStopCore{new QAction(this)}
+ m_actionStopCore{new QAction(this)},
+ m_networkMonitor{new NetworkMonitor(this)},
+ m_currentIPValid(true)
{
ui->setupUi(this);
@@ -165,6 +167,11 @@ MainWindow::MainWindow()
}
MainWindow::~MainWindow()
{
+ // Stop network monitoring
+ if (m_networkMonitor) {
+ m_networkMonitor->stopMonitoring();
+ }
+
m_guiDupeChecker->close();
m_coreProcess.cleanup();
}
@@ -198,8 +205,6 @@ void MainWindow::setupControls()
ui->btnConfigureServer->setIcon(QIcon::fromTheme(QStringLiteral("configure")));
- updateNetworkInfo();
-
if (Settings::value(Settings::Core::LastVersion).toString() != kVersion) {
Settings::setValue(Settings::Core::LastVersion, kVersion);
}
@@ -334,6 +339,8 @@ void MainWindow::connectSlots()
connect(ui->btnEditName, &QPushButton::clicked, this, &MainWindow::showHostNameEditor);
connect(ui->lineEditName, &QLineEdit::editingFinished, this, &MainWindow::setHostName);
+
+ connect(m_networkMonitor, &NetworkMonitor::ipAddressesChanged, this, &MainWindow::updateIpLabel);
}
void MainWindow::toggleLogVisible(bool visible)
@@ -425,6 +432,12 @@ void MainWindow::coreProcessError(CoreProcess::Error error)
void MainWindow::startCore()
{
+ // Save current IP state when server starts
+ if (m_coreProcess.mode() == CoreMode::Server) {
+ m_serverStartIPs = m_networkMonitor->getAvailableIPv4Addresses();
+ m_serverStartSuggestedIP = m_networkMonitor->getSuggestedIPv4Address();
+ }
+
m_coreProcess.start();
m_actionStartCore->setVisible(false);
m_actionRestartCore->setVisible(true);
@@ -521,7 +534,6 @@ void MainWindow::coreModeToggled()
void MainWindow::updateModeControls(bool serverMode)
{
- ui->lblIpAddresses->setVisible(serverMode);
ui->serverOptions->setVisible(serverMode);
ui->clientOptions->setVisible(!serverMode);
ui->lblNoMode->setVisible(false);
@@ -534,6 +546,15 @@ void MainWindow::updateModeControls(bool serverMode)
updateModeControlLabels();
toggleCanRunCore((!serverMode && !ui->lineHostname->text().isEmpty()) || serverMode);
+
+ ui->lblIpAddresses->setVisible(serverMode);
+ if (serverMode) {
+ // Initialize network monitoring
+ updateNetworkInfo();
+ m_networkMonitor->startMonitoring();
+ } else {
+ m_networkMonitor->stopMonitoring();
+ }
}
void MainWindow::updateModeControlLabels()
@@ -590,43 +611,7 @@ void MainWindow::updateSecurityIcon(bool visible)
void MainWindow::updateNetworkInfo()
{
- static const auto colorText = QStringLiteral(R"(%2)");
-
- QStringList ipList;
- QString suggestedAddress;
-
- bool hinted = false;
-
- const auto addresses = QNetworkInterface::allAddresses();
- for (const auto &address : addresses) {
- if (address.protocol() == QAbstractSocket::IPv4Protocol && address != QHostAddress(QHostAddress::LocalHost) &&
- !address.isInSubnet(QHostAddress::parseSubnet("169.254.0.0/16"))) {
- // usually 192.168.x.x is a useful ip for the user, so indicate
- // this by coloring it in the "link" color
- if (!hinted && address.isInSubnet(QHostAddress::parseSubnet("192.168/16"))) {
- suggestedAddress = address.toString();
- ipList.append(colorText.arg(palette().link().color().name(), suggestedAddress));
- hinted = true;
- } else {
- ipList.append(address.toString());
- }
- }
- }
-
- if (ipList.isEmpty()) {
- ui->lblIpAddresses->setText(colorText.arg(palette().linkVisited().color().name(), tr("No IP Detected")));
- ui->lblIpAddresses->setToolTip(tr("Unable to detect an IP address. Check your network connection is active."));
- return;
- }
-
- ui->lblIpAddresses->setText(tr("Suggested IP: %1").arg(suggestedAddress.isEmpty() ? ipList.first() : suggestedAddress)
- );
-
- if (auto toolTipBase = tr("
If connecting via the hostname fails, try %1
"); ipList.count() < 2) {
- ui->lblIpAddresses->setToolTip(toolTipBase.arg(tr("the suggested IP.")));
- } else {
- ui->lblIpAddresses->setToolTip(toolTipBase.arg(tr("one of the following IPs: %1").arg(ipList.join(" "))));
- }
+ updateIpLabel(m_networkMonitor->getAvailableIPv4Addresses());
}
void MainWindow::serverConnectionConfigureClient(const QString &clientName)
@@ -915,10 +900,12 @@ void MainWindow::updateStatus()
break;
case Stopped:
+ updateNetworkInfo();
setStatus(tr("%1 is not running").arg(kAppName));
break;
case Started: {
+ updateNetworkInfo();
switch (connection) {
using enum CoreConnectionState;
@@ -1258,3 +1245,92 @@ void MainWindow::handleNewClientPromptRequest(const QString &clientName, bool us
bool result = deskflow::gui::messages::showNewClientPrompt(this, clientName, usePeerAuth);
m_serverConnection.handleNewClientResult(clientName, result);
}
+
+void MainWindow::updateIpLabel(const QList &addresses)
+{
+ if (m_coreProcess.mode() != CoreMode::Server) {
+ return;
+ }
+
+ static const auto colorText = QStringLiteral(R"(%2)");
+
+ if (addresses.isEmpty()) {
+ ui->lblIpAddresses->setText(colorText.arg(palette().linkVisited().color().name(), tr("No IP Detected")));
+ ui->lblIpAddresses->setToolTip(tr("Unable to detect an IP address. Check your network connection is active."));
+ return;
+ }
+
+ // Get all available IPs for tooltip
+ QStringList ipList;
+ for (const auto &address : addresses) {
+ ipList.append(address.toString());
+ }
+
+ QString labelText;
+ QString toolTipText;
+
+ // If we have a fixed IP we will use it
+ if (const auto ip = Settings::value(Settings::Core::Interface).toString(); !ip.isEmpty()) {
+ labelText = tr("Using IP: ");
+ toolTipText = tr("Selected as the interface in settings.");
+ if (ipList.contains(ip, Qt::CaseInsensitive)) {
+ labelText.append(ip);
+ } else {
+ labelText.append(colorText.arg(palette().linkVisited().color().name(), ip));
+ toolTipText.append(tr("\nInterface is not active. Unable to start server."));
+ }
+ } else {
+ labelText = tr("Suggested IP: ");
+ toolTipText = tr("
If connecting via the hostname fails, try %1
");
+ static auto s_toolTipSuggestIP = tr("the suggested IP.");
+ static auto s_toolTipIpList = tr("one of the following IPs: %1");
+
+ // Determine which IP to show and tooltip based on server state
+ if (m_coreProcess.isStarted()) {
+ // ipList should only include valid ip from servers start
+ ipList.clear();
+ for (const auto &address : std::as_const(m_serverStartIPs)) {
+ if (addresses.contains(address))
+ ipList.append(address.toString());
+ }
+
+ QString suggestedIP = m_serverStartSuggestedIP.toString();
+ if ((suggestedIP != m_currentIpAddress.toString()) || !addresses.contains(m_serverStartSuggestedIP)) {
+ m_currentIPValid = false;
+ for (const auto &address : std::as_const(m_serverStartIPs)) {
+ if (addresses.contains(address)) {
+ suggestedIP = address.toString();
+ m_currentIpAddress = address;
+ m_currentIPValid = true;
+ break;
+ }
+ }
+ } else {
+ m_currentIPValid = true;
+ }
+
+ if (m_currentIPValid) {
+ labelText.append(suggestedIP);
+ } else {
+ labelText.append(colorText.arg(palette().linkVisited().color().name(), suggestedIP));
+ toolTipText.append(tr("\nA bound IP is now invalid, you may need to restart the server."));
+ }
+ } else {
+ // Server is not running - update normally
+ const auto suggestedIp = m_networkMonitor->getSuggestedIPv4Address();
+ QString displayIP = !suggestedIp.isNull() ? suggestedIp.toString() : ipList.first();
+ m_currentIpAddress = !suggestedIp.isNull() ? suggestedIp : QHostAddress();
+ m_currentIPValid = !suggestedIp.isNull();
+ labelText.append(displayIP);
+ }
+
+ if (ipList.count() < 2) {
+ toolTipText = toolTipText.arg(s_toolTipSuggestIP);
+ } else {
+ toolTipText = toolTipText.arg(s_toolTipIpList.arg(ipList.join(" ")));
+ }
+ }
+
+ ui->lblIpAddresses->setText(labelText);
+ ui->lblIpAddresses->setToolTip(toolTipText);
+}
diff --git a/src/lib/gui/MainWindow.h b/src/lib/gui/MainWindow.h
index 9aad00b30..6b99b34d6 100644
--- a/src/lib/gui/MainWindow.h
+++ b/src/lib/gui/MainWindow.h
@@ -8,6 +8,7 @@
#pragma once
+#include
#include
#include
#include
@@ -20,6 +21,7 @@
#include "config/ServerConfig.h"
#include "gui/core/ClientConnection.h"
#include "gui/core/CoreProcess.h"
+#include "gui/core/NetworkMonitor.h"
#include "gui/core/ServerConnection.h"
#include "gui/core/WaylandWarnings.h"
#include "net/Fingerprint.h"
@@ -58,6 +60,7 @@ class MainWindow : public QMainWindow
{
using CoreMode = Settings::CoreMode;
using CoreProcess = deskflow::gui::CoreProcess;
+ using NetworkMonitor = deskflow::gui::NetworkMonitor;
Q_OBJECT
@@ -152,6 +155,8 @@ private:
void toggleCanRunCore(bool enableButtons);
void remoteHostChanged(const QString &newRemoteHost);
void handleNewClientPromptRequest(const QString &clientName, bool usePeerAuth);
+ void updateIpLabel(const QList &addresses);
+
/**
* @brief showClientError
* @param error Error Type
@@ -218,4 +223,13 @@ private:
QAction *m_actionStartCore = nullptr;
QAction *m_actionRestartCore = nullptr;
QAction *m_actionStopCore = nullptr;
+
+ // Network monitoring
+ NetworkMonitor *m_networkMonitor = nullptr;
+ QHostAddress m_currentIpAddress;
+
+ // Server IP strategy optimization
+ QList m_serverStartIPs;
+ QHostAddress m_serverStartSuggestedIP;
+ bool m_currentIPValid;
};
diff --git a/src/lib/gui/core/NetworkMonitor.cpp b/src/lib/gui/core/NetworkMonitor.cpp
new file mode 100644
index 000000000..002c45e3b
--- /dev/null
+++ b/src/lib/gui/core/NetworkMonitor.cpp
@@ -0,0 +1,143 @@
+/*
+ * Deskflow -- mouse and keyboard sharing utility
+ * SPDX-FileCopyrightText: (C) 2025 Deskflow Developers
+ * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
+ */
+
+#include "NetworkMonitor.h"
+
+#include
+#include
+#include
+#include
+#include
+
+namespace deskflow::gui {
+
+bool NetworkMonitor::isVirtualInterface(const QString &interfaceName) const
+{
+ // Common virtual network interface patterns
+ static const QStringList virtualPatterns = {
+ QStringLiteral("vboxnet"), // VirtualBox host-only networks
+ QStringLiteral("vmnet"), // VMware virtual networks
+ QStringLiteral("docker"), // Docker bridge networks
+ QStringLiteral("virbr"), // libvirt bridge networks
+ QStringLiteral("veth"), // Virtual ethernet
+ QStringLiteral("br-"), // Bridge interfaces (some are virtual)
+ QStringLiteral("tun"), // Tunnel interfaces
+ QStringLiteral("tap"), // TAP interfaces
+ QStringLiteral("utun"), // User tunnel (macOS)
+ QStringLiteral("awdl"), // Apple Wireless Direct Link
+ QStringLiteral("p2p"), // Peer-to-peer
+ QStringLiteral("llw"), // Link-local wireless
+ QStringLiteral("anpi"), // Apple network interface
+ };
+
+ return virtualPatterns.contains(interfaceName, Qt::CaseInsensitive);
+}
+
+NetworkMonitor::NetworkMonitor(QObject *parent) : QObject(parent), m_checkTimer(new QTimer(this)), m_isMonitoring(false)
+{
+ connect(m_checkTimer, &QTimer::timeout, this, &NetworkMonitor::updateNetworkState);
+}
+
+void NetworkMonitor::startMonitoring(int intervalMs)
+{
+ if (m_isMonitoring) {
+ return;
+ }
+
+ updateNetworkState();
+
+ m_checkTimer->start(intervalMs);
+ m_isMonitoring = true;
+}
+
+void NetworkMonitor::stopMonitoring()
+{
+ if (!m_isMonitoring) {
+ return;
+ }
+
+ m_checkTimer->stop();
+ m_isMonitoring = false;
+}
+
+QList NetworkMonitor::getAvailableIPv4Addresses() const
+{
+ QList physicalIPs;
+ QList virtualIPs;
+ QSet uniqueAddresses;
+
+ const auto allInterfaces = QNetworkInterface::allInterfaces();
+ for (const auto &interface : allInterfaces) {
+ if (!(interface.flags() & QNetworkInterface::IsUp) || !(interface.flags() & QNetworkInterface::IsRunning) ||
+ (interface.flags() & QNetworkInterface::IsLoopBack)) {
+ continue;
+ }
+
+ const bool isVirtual = isVirtualInterface(interface.name());
+ const auto addressEntries = interface.addressEntries();
+
+ for (const auto &entry : addressEntries) {
+ const QHostAddress address = entry.ip();
+
+ if (address.protocol() != QAbstractSocket::IPv4Protocol ||
+ address.isInSubnet(QHostAddress::parseSubnet(QStringLiteral("169.254/16"))) || address.isLoopback() ||
+ uniqueAddresses.contains(address)) {
+ continue;
+ }
+
+ uniqueAddresses.insert(address);
+
+ if (isVirtual) {
+ virtualIPs.append(address);
+ } else {
+ physicalIPs.append(address);
+ }
+ }
+ }
+
+ auto physicalComparator = [](const QHostAddress &a, const QHostAddress &b) {
+ static const auto localIpFilter = QStringLiteral("192.168/16");
+ if (a.isInSubnet(QHostAddress::parseSubnet(localIpFilter)) !=
+ b.isInSubnet(QHostAddress::parseSubnet(localIpFilter))) {
+ return true;
+ }
+ return a.toIPv4Address() < b.toIPv4Address();
+ };
+
+ std::sort(physicalIPs.begin(), physicalIPs.end(), physicalComparator);
+
+ std::sort(virtualIPs.begin(), virtualIPs.end(), [](const QHostAddress &a, const QHostAddress &b) {
+ return a.toIPv4Address() < b.toIPv4Address();
+ });
+
+ auto result = physicalIPs;
+ result.append(virtualIPs);
+
+ return result;
+}
+
+QHostAddress NetworkMonitor::getSuggestedIPv4Address() const
+{
+ const auto addresses = getAvailableIPv4Addresses();
+ if (addresses.isEmpty())
+ return QHostAddress();
+ return addresses.first();
+}
+
+void NetworkMonitor::setIpAddresses(const QList &newAddresses)
+{
+ if (newAddresses == m_lastAddresses)
+ return;
+ m_lastAddresses = newAddresses;
+ Q_EMIT ipAddressesChanged(m_lastAddresses);
+}
+
+void NetworkMonitor::updateNetworkState()
+{
+ setIpAddresses(getAvailableIPv4Addresses());
+}
+
+} // namespace deskflow::gui
diff --git a/src/lib/gui/core/NetworkMonitor.h b/src/lib/gui/core/NetworkMonitor.h
new file mode 100644
index 000000000..2ef4b059c
--- /dev/null
+++ b/src/lib/gui/core/NetworkMonitor.h
@@ -0,0 +1,88 @@
+/*
+ * Deskflow -- mouse and keyboard sharing utility
+ * SPDX-FileCopyrightText: (C) 2025 Deskflow Developers
+ * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
+ */
+
+#pragma once
+
+#include
+#include
+#include
+
+class QTimer;
+namespace deskflow::gui {
+
+/**
+ * @brief Monitor network activity changes and provide IP address updates
+ *
+ * The NetworkMonitor class monitors IP address changes
+ * It periodically checks network status and emits signals when changes are detected.
+ */
+class NetworkMonitor : public QObject
+{
+ Q_OBJECT
+
+public:
+ /**
+ * @brief Construct a new NetworkMonitor object
+ * @param parent Parent QObject
+ */
+ explicit NetworkMonitor(QObject *parent = nullptr);
+
+ /**
+ * @brief Destroy the NetworkMonitor object
+ */
+ ~NetworkMonitor() override = default;
+
+ /**
+ * @brief Start network monitoring
+ * @param intervalMs Check interval in milliseconds, default 3000ms (3 seconds)
+ */
+ void startMonitoring(int intervalMs = 3000);
+
+ /**
+ * @brief Stop network monitoring
+ */
+ void stopMonitoring();
+
+ /**
+ * @brief Get list of all available IPv4 addresses (excluding local and link-local addresses)
+ * @return IPv4 address list
+ */
+ QList getAvailableIPv4Addresses() const;
+
+ /**
+ * @brief Get recommended IP address (192.168.x.x preferred)
+ * @return Recommended IP address, returns null if none available
+ */
+ QHostAddress getSuggestedIPv4Address() const;
+
+Q_SIGNALS:
+ /**
+ * @brief Emitted when IP addresses change
+ * @param addresses New IP address list
+ */
+ void ipAddressesChanged(const QList &addresses);
+
+private:
+ void setIpAddresses(const QList &newAddresses);
+
+ /**
+ * @brief Check if a network interface is virtual
+ * @param interfaceName Network interface name
+ * @return true if it's a virtual interface
+ */
+ bool isVirtualInterface(const QString &interfaceName) const;
+
+ /**
+ * @brief Update current network status
+ */
+ void updateNetworkState();
+
+ QTimer *m_checkTimer; ///< Timer for periodic network checks
+ QList m_lastAddresses; ///< Last known IP addresses
+ bool m_isMonitoring; ///< Flag indicating if monitoring is active
+};
+
+} // namespace deskflow::gui
diff --git a/src/lib/gui/dialogs/SettingsDialog.cpp b/src/lib/gui/dialogs/SettingsDialog.cpp
index 49b5d23fc..b9733f013 100644
--- a/src/lib/gui/dialogs/SettingsDialog.cpp
+++ b/src/lib/gui/dialogs/SettingsDialog.cpp
@@ -14,6 +14,7 @@
#include "common/Settings.h"
#include "gui/Messages.h"
#include "gui/TlsUtility.h"
+#include "gui/core/NetworkMonitor.h"
#include
#include
@@ -49,6 +50,16 @@ SettingsDialog::SettingsDialog(QWidget *parent, const IServerConfig &serverConfi
// the developer was looking at, and it's easy to accidentally save that.
ui->tabWidget->setCurrentIndex(0);
+ // Populate the list of IP addresses
+ NetworkMonitor networkMonitor(this);
+ const auto addresses = networkMonitor.getAvailableIPv4Addresses();
+ for (const auto &address : addresses) {
+ QString ipString = address.toString();
+ if (ui->comboInterface->findText(ipString) == -1) {
+ ui->comboInterface->addItem(ipString, ipString);
+ }
+ }
+
loadFromConfig();
adjustSize();
@@ -160,7 +171,7 @@ void SettingsDialog::updateText()
void SettingsDialog::accept()
{
Settings::setValue(Settings::Core::Port, ui->sbPort->value());
- Settings::setValue(Settings::Core::Interface, ui->lineInterface->text());
+ Settings::setValue(Settings::Core::Interface, ui->comboInterface->currentData());
Settings::setValue(Settings::Log::Level, ui->comboLogLevel->currentIndex());
Settings::setValue(Settings::Log::ToFile, ui->cbLogToFile->isChecked());
Settings::setValue(Settings::Log::File, ui->lineLogFilename->text());
@@ -194,7 +205,6 @@ void SettingsDialog::accept()
void SettingsDialog::loadFromConfig()
{
ui->sbPort->setValue(Settings::value(Settings::Core::Port).toInt());
- ui->lineInterface->setText(Settings::value(Settings::Core::Interface).toString());
ui->comboLogLevel->setCurrentIndex(Settings::value(Settings::Log::Level).toInt());
ui->cbLogToFile->setChecked(Settings::value(Settings::Log::ToFile).toBool());
ui->lineLogFilename->setText(Settings::value(Settings::Log::File).toString());
@@ -222,6 +232,10 @@ void SettingsDialog::loadFromConfig()
ui->lblDebugWarning->setVisible(Settings::value(Settings::Log::Level).toInt() > 4);
+ ui->comboInterface->setCurrentText(Settings::value(Settings::Core::Interface).toString());
+ if (ui->comboInterface->currentIndex() < 0)
+ ui->comboInterface->setCurrentIndex(0);
+
qDebug() << "load from config done";
updateControls();
}
@@ -289,7 +303,7 @@ void SettingsDialog::updateControls()
ui->buttonBox->button(QDialogButtonBox::Save)->setEnabled(writable);
ui->sbPort->setEnabled(writable);
- ui->lineInterface->setEnabled(writable);
+ ui->comboInterface->setEnabled(writable);
ui->comboLogLevel->setEnabled(writable);
ui->cbLogToFile->setEnabled(writable);
ui->cbAutoHide->setEnabled(writable);
diff --git a/src/lib/gui/dialogs/SettingsDialog.ui b/src/lib/gui/dialogs/SettingsDialog.ui
index 8bce0d9a4..dcc6fe24a 100644
--- a/src/lib/gui/dialogs/SettingsDialog.ui
+++ b/src/lib/gui/dialogs/SettingsDialog.ui
@@ -393,10 +393,12 @@
-
-
- true
-
+
+
+
+ Automatic
+
+
@@ -733,7 +735,7 @@
btnTlsRegenCertcbRequireClientCertsbPort
- lineInterface
+ comboInterfacecbLogToFilelineLogFilenamebtnBrowseLog
diff --git a/translations/deskflow_es.ts b/translations/deskflow_es.ts
index b95e67c10..5f0dd175f 100644
--- a/translations/deskflow_es.ts
+++ b/translations/deskflow_es.ts
@@ -420,8 +420,16 @@ Do you want to connect to the server?
No se puede detectar una dirección IP. Compruebe que su conexión de red esté activa.
- Suggested IP: %1
- IP sugerida: %1
+ Using IP:
+ Usando IP:
+
+
+ Selected as the interface in settings.
+ Seleccionado como la interfaz en la configuración.
+
+
+ Suggested IP:
+ IP sugerida: <p>If connecting via the hostname fails, try %1</p>
@@ -435,6 +443,12 @@ Do you want to connect to the server?
one of the following IPs:<br/>%1una de las siguientes IP:<br/>%1
+
+
+A bound IP is now invalid, you may need to restart the server.
+
+La dirección IP asignada ahora no es válida; es posible que deba reiniciar el servidor.
+ &File&Archivo
@@ -459,6 +473,12 @@ Do you want to connect to the server?
invalid certificate, generating a new onecertificado no válido, generando uno nuevo
+
+
+Interface is not active. Unable to start server.
+
+La interfaz no está activa. No se puede iniciar el servidor.
+ %1 will retry in a moment...%1 lo intentará nuevamente en un momento...
@@ -1287,6 +1307,10 @@ Al habilitar esta opción, se deshabilitará la interfaz gráfica de usuario (GU
<html><head/><body><p>Requires the wl-clipboard package</p><p>When using wl-clipboard v2.2.1, there is a focus stealing bug that may make Deskflow harder to use. This has been fixed when using the wl-clipboard master branch, unless your Compositor lacks wlroots-data-control protocol support.</p></body></html><html><head/><body><p>Requiere el paquete wl-clipboard</p><p>Al usar wl-clipboard v2.2.1, existe un error que provoca la pérdida del foco y que puede dificultar el uso de Deskflow. Este error se ha corregido al usar la rama principal de wl-clipboard, a menos que su Compositor no sea compatible con el protocolo wlroots-data-control.</p></body></html>
+
+ Automatic
+ Automática
+ i18n
diff --git a/translations/deskflow_it.ts b/translations/deskflow_it.ts
index 34b47f4da..85a4fd859 100644
--- a/translations/deskflow_it.ts
+++ b/translations/deskflow_it.ts
@@ -408,8 +408,16 @@ Vuoi connetterti al server?
Impossibile rilevare un indirizzo IP. Controlla che la tua connessione di rete sia attiva.
- Suggested IP: %1
- IP suggerito: %1
+ Using IP:
+ Utilizzo dell'indirizzo IP:
+
+
+ Selected as the interface in settings.
+ Selezionata come interfaccia nelle impostazioni.
+
+
+ Suggested IP:
+ IP suggerito: <p>If connecting via the hostname fails, try %1</p>
@@ -423,6 +431,12 @@ Vuoi connetterti al server?
one of the following IPs:<br/>%1uno dei seguenti IP:<br/>%1
+
+
+A bound IP is now invalid, you may need to restart the server.
+
+L'indirizzo IP associato non è più valido, potrebbe essere necessario riavviare il server.
+ &File&File
@@ -467,6 +481,12 @@ Nomi validi:
invalid certificate, generating a new onecertificato non valido, ne viene generato uno nuovo
+
+
+Interface is not active. Unable to start server.
+
+L'interfaccia non è attiva. Impossibile avviare il server.
+ %1 will retry in a moment...%1 riproverà tra un momento...
@@ -1287,6 +1307,10 @@ L'abilitazione di questa impostazione disabiliterà l'interfaccia graf
<html><head/><body><p>Requires the wl-clipboard package</p><p>When using wl-clipboard v2.2.1, there is a focus stealing bug that may make Deskflow harder to use. This has been fixed when using the wl-clipboard master branch, unless your Compositor lacks wlroots-data-control protocol support.</p></body></html><html><head/><body><p>Richiede il pacchetto wl-clipboard</p><p>Quando si utilizza wl-clipboard v2.2.1, si verifica un bug di furto del focus che potrebbe rendere Deskflow più difficile da usare. Questo problema è stato risolto quando si utilizza il ramo master di wl-clipboard, a meno che il proprio compositore non supporti il protocollo wlroots-data-control.</p></body></html>
+
+ Automatic
+ Automatica
+ i18n
diff --git a/translations/deskflow_ja.ts b/translations/deskflow_ja.ts
index fbea4c3d8..90dff3231 100644
--- a/translations/deskflow_ja.ts
+++ b/translations/deskflow_ja.ts
@@ -372,8 +372,12 @@ Do you want to connect to the server?
IPアドレスが見つかりません。ネットワーク接続を確認してください。
- Suggested IP: %1
- 推奨IPアドレス: %1
+ Using IP:
+ IPアドレスを使用する:
+
+
+ Selected as the interface in settings.
+ 設定でインターフェースとして選択されています。<p>If connecting via the hostname fails, try %1</p>
@@ -387,6 +391,12 @@ Do you want to connect to the server?
one of the following IPs:<br/>%1以下のIPアドレスのいずれか:<br/>%1
+
+
+A bound IP is now invalid, you may need to restart the server.
+
+割り当て済みのIPアドレスが無効になりました。サーバーを再起動する必要があるかもしれません。
+ %1 is starting...%1 は起動処理中です…
@@ -531,6 +541,16 @@ Valid names:
クライアント:
%1
+
+
+Interface is not active. Unable to start server.
+
+インターフェースがアクティブではありません。サーバーを起動できません。
+
+
+ Suggested IP:
+ 推奨IPアドレス:
+ The Core executable could not be successfully started, although it does exist. Please check if you have sufficient permissions to run this program.コア実行ファイルは存在していますが、起動できませんでした。このプログラムを実行するのに十分な権限があることを確認してください。
@@ -1288,6 +1308,10 @@ Enabling this setting will disable the server config GUI.
<html><head/><body><p>Requires the wl-clipboard package</p><p>When using wl-clipboard v2.2.1, there is a focus stealing bug that may make Deskflow harder to use. This has been fixed when using the wl-clipboard master branch, unless your Compositor lacks wlroots-data-control protocol support.</p></body></html><html><head/><body><p>wl-clipboard パッケージが必要です。</p><p>wl-clipboard v2.2.1 を使用すると、フォーカス盗用のバグにより Deskflow の使い勝手が悪くなる可能性があります。この問題は wl-clipboard のマスターブランチで修正されていますが、使用しているコンポジターが wlroots-data-control プロトコルに対応している必要があります。</p></body></html>
+
+ Automatic
+ 自動
+ i18n
diff --git a/translations/deskflow_ru.ts b/translations/deskflow_ru.ts
index 8637879bb..2e9d31c37 100644
--- a/translations/deskflow_ru.ts
+++ b/translations/deskflow_ru.ts
@@ -374,8 +374,12 @@ Do you want to connect to the server?
Не получаеться найти Ip адресc. Проверте подключение к сети.
- Suggested IP: %1
- Ваш (рекомендованый) IP адресс: %1
+ Using IP:
+ Использование IP-адреса:
+
+
+ Selected as the interface in settings.
+ Выбран в качестве интерфейса в настройках.<p>If connecting via the hostname fails, try %1</p>
@@ -389,6 +393,12 @@ Do you want to connect to the server?
one of the following IPs:<br/>%1один из следующих IP-адресов:<br/>%1
+
+
+A bound IP is now invalid, you may need to restart the server.
+
+Привязанный IP-адрес теперь недействителен, возможно, потребуется перезапустить сервер.
+ %1 is starting...%1 запускается...
@@ -535,6 +545,16 @@ Valid names:
Клиент:
%1
+
+
+Interface is not active. Unable to start server.
+
+Интерфейс неактивен. Невозможно запустить сервер.
+
+
+ Suggested IP:
+ Ваш (рекомендованый) IP адресс:
+ The Core executable could not be successfully started, although it does exist. Please check if you have sufficient permissions to run this program.Не удалось запустить исполняемый файл Core, хотя он существует. Проверьте, есть ли у вас достаточные права для запуска этой программы.
@@ -1292,6 +1312,10 @@ Enabling this setting will disable the server config GUI.
<html><head/><body><p>Requires the wl-clipboard package</p><p>When using wl-clipboard v2.2.1, there is a focus stealing bug that may make Deskflow harder to use. This has been fixed when using the wl-clipboard master branch, unless your Compositor lacks wlroots-data-control protocol support.</p></body></html><html><head/><body><p>Для этого необходим пакет wl-clipboard.</p><p>Когда ты используешь wl-clipboard v2.2.1. Возникает ошибка перехвата фокуса, которая мешает использовать deskflowю. Это фиксется если использовать wl-clipboard из ветки master, если только ваш Compositor не поддерживает протокол wlroots-data-control.</p></body></html>
+
+ Automatic
+ Автоматический
+ i18n
diff --git a/translations/deskflow_zh_CN.ts b/translations/deskflow_zh_CN.ts
index fb328d505..9b1d9fc58 100644
--- a/translations/deskflow_zh_CN.ts
+++ b/translations/deskflow_zh_CN.ts
@@ -372,8 +372,12 @@ Do you want to connect to the server?
无法检测到 IP 地址。请检查您的网络连接是否正常。
- Suggested IP: %1
- 建议 IP:%1
+ Using IP:
+ 使用IP地址:
+
+
+ Selected as the interface in settings.
+ 在设置中选择为接口。<p>If connecting via the hostname fails, try %1</p>
@@ -387,6 +391,12 @@ Do you want to connect to the server?
one of the following IPs:<br/>%1以下 IP 地址之一:<br/>%1
+
+
+A bound IP is now invalid, you may need to restart the server.
+
+绑定的IP地址现在无效,您可能需要重启服务器。
+ %1 is starting...%1 正在启动...
@@ -531,6 +541,16 @@ Valid names:
客户端:
%1
+
+
+Interface is not active. Unable to start server.
+
+接口未激活。无法启动服务器。
+
+
+ Suggested IP:
+ 建议 IP:
+ The Core executable could not be successfully started, although it does exist. Please check if you have sufficient permissions to run this program.Core 可执行文件虽然存在,但无法成功启动。请检查您是否拥有运行此程序的足够权限。
@@ -1288,6 +1308,10 @@ Enabling this setting will disable the server config GUI.
<html><head/><body><p>Requires the wl-clipboard package</p><p>When using wl-clipboard v2.2.1, there is a focus stealing bug that may make Deskflow harder to use. This has been fixed when using the wl-clipboard master branch, unless your Compositor lacks wlroots-data-control protocol support.</p></body></html><html><head/><body><p>需要 wl-clipboard 包</p><p>使用 wl-clipboard v2.2.1 时存在一个焦点抢夺 Bug,可能导致 Deskflow 使用不便。该问题已在 wl-clipboard 的 master 分支中修复,除非您的合成器不支持 wlroots-data-control 协议。</p></body></html>
+
+ Automatic
+ 自动的
+ i18n