From 682966fec0bd3393b55078229194004e73558556 Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Mon, 30 Mar 2026 19:38:03 +0100 Subject: [PATCH] feat(ipc): Handle missing keyboard layouts with IPC --- src/lib/client/ServerProxy.cpp | 20 ++++++---------- src/lib/client/ServerProxy.h | 1 - src/lib/common/Settings.h | 3 +++ src/lib/deskflow/languages/LanguageManager.h | 2 ++ src/lib/gui/MainWindow.cpp | 25 ++++++++++++++++++++ src/lib/gui/MainWindow.h | 1 + src/lib/gui/core/CoreProcess.cpp | 2 ++ src/lib/gui/core/CoreProcess.h | 1 + translations/deskflow_es.ts | 12 ++++++++++ translations/deskflow_it.ts | 12 ++++++++++ translations/deskflow_ja.ts | 12 ++++++++++ translations/deskflow_ko.ts | 12 ++++++++++ translations/deskflow_ru.ts | 12 ++++++++++ translations/deskflow_zh_CN.ts | 12 ++++++++++ 14 files changed, 113 insertions(+), 14 deletions(-) diff --git a/src/lib/client/ServerProxy.cpp b/src/lib/client/ServerProxy.cpp index 600f05697..c23cd6a0d 100644 --- a/src/lib/client/ServerProxy.cpp +++ b/src/lib/client/ServerProxy.cpp @@ -18,6 +18,7 @@ #include "deskflow/ProtocolTypes.h" #include "deskflow/ProtocolUtil.h" #include "deskflow/StreamChunker.h" +#include "deskflow/ipc/CoreIpc.h" #include "io/IStream.h" #include @@ -139,7 +140,12 @@ ServerProxy::ConnectionResult ServerProxy::parseHandshakeMessage(const uint8_t * // handshake is complete m_parser = &ServerProxy::parseMessage; - checkMissedLanguages(); + + if (const auto missedKeyboardLayouts = m_languageManager.getMissedLanguages(); !missedKeyboardLayouts.empty()) { + LOG_WARN("server layouts missing on this computer: %s", missedKeyboardLayouts.c_str()); + ipcSendToClient("missingKeyboardLayouts", QString::fromStdString(missedKeyboardLayouts)); + } + m_client->handshakeComplete(); } @@ -844,15 +850,3 @@ void ServerProxy::setActiveServerLanguage(const std::string_view &language) LOG_DEBUG1("active server language is empty"); } } - -void ServerProxy::checkMissedLanguages() const -{ - auto missedLanguages = m_languageManager.getMissedLanguages(); - if (!missedLanguages.empty()) { - LOG( - (CLOG_WARN "You need to install these languages on this computer and restart " - "Deskflow to enable support for multiple languages: %s", - missedLanguages.c_str()) - ); - } -} diff --git a/src/lib/client/ServerProxy.h b/src/lib/client/ServerProxy.h index 2c638b8ca..595356640 100644 --- a/src/lib/client/ServerProxy.h +++ b/src/lib/client/ServerProxy.h @@ -98,7 +98,6 @@ private: void secureInputNotification(); void setServerLanguages(); void setActiveServerLanguage(const std::string_view &language); - void checkMissedLanguages() const; private: using MessageParser = ConnectionResult (ServerProxy::*)(const uint8_t *); diff --git a/src/lib/common/Settings.h b/src/lib/common/Settings.h index 5e7ee0f0e..59295066a 100644 --- a/src/lib/common/Settings.h +++ b/src/lib/common/Settings.h @@ -85,6 +85,7 @@ public: inline static const auto ShownFirstConnectedMessage = QStringLiteral("gui/shownFirstConnectedMessage"); inline static const auto ShownServerFirstStartMessage = QStringLiteral("gui/shownServerFirstStartMessage"); inline static const auto ShowVersionInTitle = QStringLiteral("gui/showVersionInTitle"); + inline static const auto IgnoreMissingKeyboardLayouts = QStringLiteral("gui/ignoreMissingKeyboardLayouts"); }; struct Log { @@ -243,6 +244,7 @@ private: , Settings::Gui::ShownFirstConnectedMessage , Settings::Gui::ShownServerFirstStartMessage , Settings::Gui::ShowVersionInTitle + , Settings::Gui::IgnoreMissingKeyboardLayouts , Settings::Security::Certificate , Settings::Security::CheckPeers , Settings::Security::KeySize @@ -258,6 +260,7 @@ private: , Settings::Gui::ShownFirstConnectedMessage , Settings::Gui::ShownServerFirstStartMessage , Settings::Gui::ShowVersionInTitle + , Settings::Gui::IgnoreMissingKeyboardLayouts , Settings::Core::PreventSleep , Settings::Core::UseWlClipboard , Settings::Core::EnableEnterCommand diff --git a/src/lib/deskflow/languages/LanguageManager.h b/src/lib/deskflow/languages/LanguageManager.h index 3cd1f19fa..4aef2db60 100644 --- a/src/lib/deskflow/languages/LanguageManager.h +++ b/src/lib/deskflow/languages/LanguageManager.h @@ -11,6 +11,8 @@ namespace deskflow::languages { +// TODO: rename class and namespace; "languages" is a misnomer. These are keyboard +// _layouts_ (Windows/X11) or input sources (macOS), not spoken "languages". class LanguageManager { std::vector m_remoteLanguages; diff --git a/src/lib/gui/MainWindow.cpp b/src/lib/gui/MainWindow.cpp index bd8b7177a..7d2622a0b 100644 --- a/src/lib/gui/MainWindow.cpp +++ b/src/lib/gui/MainWindow.cpp @@ -31,6 +31,7 @@ #include "net/FingerprintDatabase.h" #include "widgets/StatusBar.h" +#include #include #include #include @@ -272,6 +273,7 @@ void MainWindow::connectSlots() connect(&m_coreProcess, &CoreProcess::connectionRefused, this, &MainWindow::handleConnectionRefused); connect(&m_coreProcess, &CoreProcess::retryIn, this, &MainWindow::updateTimeoutDelay); connect(&m_coreProcess, &CoreProcess::peerFingerprint, this, &MainWindow::handlePeerFingerprint); + connect(&m_coreProcess, &CoreProcess::missingKeyboardLayouts, this, &MainWindow::handleMissingKeyboardLayouts); if (Settings::value(Settings::Gui::AutoStartCore).toBool()) { connect(ui->btnToggleCore, &QPushButton::clicked, m_actionStopCore, &QAction::trigger, Qt::UniqueConnection); @@ -802,6 +804,29 @@ void MainWindow::handleConnectionRefused(deskflow::core::ConnectionRefusal reaso m_clientErrorVisible = false; } +void MainWindow::handleMissingKeyboardLayouts(const QString &layouts) +{ + if (Settings::value(Settings::Gui::IgnoreMissingKeyboardLayouts).toBool()) + return; + + QMessageBox msgBox(this); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setWindowTitle(tr("Missing Keyboard Layouts")); + msgBox.setText(tr("

Keyboard layout support requires matching layouts on all computers. " + "The following layouts from the other computer are not installed on this computer:

" + "

%1

" + "

Please install them to enable support for these layouts.

") + .arg(layouts)); + + auto *checkBox = new QCheckBox(tr("Don't show this again"), &msgBox); + msgBox.setCheckBox(checkBox); + msgBox.exec(); + + if (checkBox->isChecked()) { + Settings::setValue(Settings::Gui::IgnoreMissingKeyboardLayouts, true); + } +} + void MainWindow::handlePeerFingerprint(const QString &fingerprint) { const auto sha256Text = QString(fingerprint).remove(':'); diff --git a/src/lib/gui/MainWindow.h b/src/lib/gui/MainWindow.h index fbac2fcc8..1ec5d97f6 100644 --- a/src/lib/gui/MainWindow.h +++ b/src/lib/gui/MainWindow.h @@ -119,6 +119,7 @@ private: void handleUnrecognisedClient(const QString &clientName); void handleConnectionRefused(deskflow::core::ConnectionRefusal reason); void handlePeerFingerprint(const QString &fingerprint); + void handleMissingKeyboardLayouts(const QString &layouts); void closeEvent(QCloseEvent *event) override; void secureSocket(bool secureSocket); void connectSlots(); diff --git a/src/lib/gui/core/CoreProcess.cpp b/src/lib/gui/core/CoreProcess.cpp index 935f36081..ef634dfef 100644 --- a/src/lib/gui/core/CoreProcess.cpp +++ b/src/lib/gui/core/CoreProcess.cpp @@ -564,6 +564,8 @@ void CoreProcess::onCoreIpcMessageReceived(const QString &command, const QString Q_EMIT retryIn(args.toInt()); } else if (command == "peerFingerprint") { Q_EMIT peerFingerprint(args); + } else if (command == "missingKeyboardLayouts") { + Q_EMIT missingKeyboardLayouts(args); } } diff --git a/src/lib/gui/core/CoreProcess.h b/src/lib/gui/core/CoreProcess.h index 45cfa34be..71cebca01 100644 --- a/src/lib/gui/core/CoreProcess.h +++ b/src/lib/gui/core/CoreProcess.h @@ -93,6 +93,7 @@ Q_SIGNALS: void connectionRefused(deskflow::core::ConnectionRefusal reason); void retryIn(int seconds); void peerFingerprint(const QString &fingerprint); + void missingKeyboardLayouts(const QString &layouts); private Q_SLOTS: void onProcessFinished(int exitCode, QProcess::ExitStatus); diff --git a/translations/deskflow_es.ts b/translations/deskflow_es.ts index 05dc0f82f..f4d9e94c4 100644 --- a/translations/deskflow_es.ts +++ b/translations/deskflow_es.ts @@ -559,6 +559,18 @@ Additionally, check you are able to %1 the server config file: %2 Además, verifique que puede %1 el archivo de configuración del servidor: %2 + + Don't show this again + + + + Missing Keyboard Layouts + + + + <p>Keyboard layout support requires matching layouts on all computers. The following layouts from the other computer are not installed on this computer:</p><p><b>%1</b></p><p>Please install them to enable support for these layouts.</p> + + NewScreenWidget diff --git a/translations/deskflow_it.ts b/translations/deskflow_it.ts index f58928c6c..7620a3856 100644 --- a/translations/deskflow_it.ts +++ b/translations/deskflow_it.ts @@ -559,6 +559,18 @@ Additionally, check you are able to %1 the server config file: %2 Inoltre, verifica di poter %1 il file di configurazione del server: %2 + + Don't show this again + + + + Missing Keyboard Layouts + + + + <p>Keyboard layout support requires matching layouts on all computers. The following layouts from the other computer are not installed on this computer:</p><p><b>%1</b></p><p>Please install them to enable support for these layouts.</p> + + NewScreenWidget diff --git a/translations/deskflow_ja.ts b/translations/deskflow_ja.ts index 1484e003d..decc3c314 100644 --- a/translations/deskflow_ja.ts +++ b/translations/deskflow_ja.ts @@ -559,6 +559,18 @@ Additionally, check you are able to %1 the server config file: %2 また、サーバー設定ファイルを%1できることを確認してください: %2 + + Don't show this again + + + + Missing Keyboard Layouts + + + + <p>Keyboard layout support requires matching layouts on all computers. The following layouts from the other computer are not installed on this computer:</p><p><b>%1</b></p><p>Please install them to enable support for these layouts.</p> + + NewScreenWidget diff --git a/translations/deskflow_ko.ts b/translations/deskflow_ko.ts index e96f0cdbb..b1e1bdecf 100644 --- a/translations/deskflow_ko.ts +++ b/translations/deskflow_ko.ts @@ -559,6 +559,18 @@ Additionally, check you are able to %1 the server config file: %2 또한 서버 구성 파일을 %1할 수 있는지 확인하세요: %2 + + Don't show this again + + + + Missing Keyboard Layouts + + + + <p>Keyboard layout support requires matching layouts on all computers. The following layouts from the other computer are not installed on this computer:</p><p><b>%1</b></p><p>Please install them to enable support for these layouts.</p> + + NewScreenWidget diff --git a/translations/deskflow_ru.ts b/translations/deskflow_ru.ts index 0f6f316aa..de4223837 100644 --- a/translations/deskflow_ru.ts +++ b/translations/deskflow_ru.ts @@ -559,6 +559,18 @@ Additionally, check you are able to %1 the server config file: %2 Также убедитесь, что вы можете %1 файл конфигурации сервера: %2 + + Don't show this again + + + + Missing Keyboard Layouts + + + + <p>Keyboard layout support requires matching layouts on all computers. The following layouts from the other computer are not installed on this computer:</p><p><b>%1</b></p><p>Please install them to enable support for these layouts.</p> + + NewScreenWidget diff --git a/translations/deskflow_zh_CN.ts b/translations/deskflow_zh_CN.ts index cd9fdf2c0..30a3384a8 100644 --- a/translations/deskflow_zh_CN.ts +++ b/translations/deskflow_zh_CN.ts @@ -559,6 +559,18 @@ Additionally, check you are able to %1 the server config file: %2 另外,请检查您是否能够%1服务器配置文件:%2 + + Don't show this again + + + + Missing Keyboard Layouts + + + + <p>Keyboard layout support requires matching layouts on all computers. The following layouts from the other computer are not installed on this computer:</p><p><b>%1</b></p><p>Please install them to enable support for these layouts.</p> + + NewScreenWidget