From df3746777b532e2ac75037c3025d8781313aeb9a Mon Sep 17 00:00:00 2001 From: sithlord48 Date: Thu, 18 Jun 2026 16:22:11 -0400 Subject: [PATCH] chore: remove unused wl-clipboard support --- docs/user/configuration.md | 1 - src/lib/common/Settings.h | 3 - src/lib/gui/dialogs/SettingsDialog.cpp | 14 - src/lib/gui/dialogs/SettingsDialog.ui | 23 -- src/lib/platform/CMakeLists.txt | 4 - src/lib/platform/WlClipboard.cpp | 411 -------------------- src/lib/platform/WlClipboard.h | 119 ------ src/lib/platform/WlClipboardCollection.cpp | 138 ------- src/lib/platform/WlClipboardCollection.h | 61 --- src/unittests/platform/CMakeLists.txt | 11 - src/unittests/platform/WlClipboardTests.cpp | 377 ------------------ src/unittests/platform/WlClipboardTests.h | 71 ---- translations/deskflow_es.ts | 8 - translations/deskflow_it.ts | 8 - translations/deskflow_ja.ts | 8 - translations/deskflow_ko.ts | 8 - translations/deskflow_ru.ts | 8 - translations/deskflow_zh_CN.ts | 8 - 18 files changed, 1281 deletions(-) delete mode 100644 src/lib/platform/WlClipboard.cpp delete mode 100644 src/lib/platform/WlClipboard.h delete mode 100644 src/lib/platform/WlClipboardCollection.cpp delete mode 100644 src/lib/platform/WlClipboardCollection.h delete mode 100644 src/unittests/platform/WlClipboardTests.cpp delete mode 100644 src/unittests/platform/WlClipboardTests.h diff --git a/docs/user/configuration.md b/docs/user/configuration.md index 68fabf73e..155848547 100644 --- a/docs/user/configuration.md +++ b/docs/user/configuration.md @@ -77,7 +77,6 @@ This section contains general options it will begin with `[core]` | computerName | string | Name used to identify the computer [default: machine's hostname] | | useHooks | `true` or `false` | If Windows uses hooks or not [default: true] | | language | 639 language | The language to display the GUI in [default: en] | -| wlClipboard | `true` or `false` | When true the wl-clipboard backend will be enabled [default: false] | | enableEnterCommand | `true` or `false` | Should the enter command be triggered when the screen is entered [defaut: false] | | enterCommand | command | A command to run when the screen is entered. | | enableExitCommand | `true` or `false` | Should the exit command be triggered when the screen is exited [defaut: false] | diff --git a/src/lib/common/Settings.h b/src/lib/common/Settings.h index 594585834..e735e05df 100644 --- a/src/lib/common/Settings.h +++ b/src/lib/common/Settings.h @@ -56,7 +56,6 @@ public: inline static const auto Display = QStringLiteral("core/display"); inline static const auto UseHooks = QStringLiteral("core/useHooks"); inline static const auto Language = QStringLiteral("core/language"); - inline static const auto UseWlClipboard = QStringLiteral("core/wlClipboard"); inline static const auto EnableEnterCommand = QStringLiteral("core/enableEnterCommand"); inline static const auto ScreenEnterCommand = QStringLiteral("core/enterCommand"); inline static const auto EnableExitCommand = QStringLiteral("core/enableExitCommand"); @@ -226,7 +225,6 @@ private: , Settings::Core::ComputerName , Settings::Core::Display , Settings::Core::UseHooks - , Settings::Core::UseWlClipboard , Settings::Core::Language , Settings::Daemon::ConfigFile , Settings::Daemon::Elevate @@ -280,7 +278,6 @@ private: , Settings::Gui::ShowVersionInTitle , Settings::Gui::IgnoreMissingKeyboardLayouts , Settings::Core::PreventSleep - , Settings::Core::UseWlClipboard , Settings::Core::EnableEnterCommand , Settings::Core::EnableExitCommand , Settings::Client::DynamicConnectionRetry diff --git a/src/lib/gui/dialogs/SettingsDialog.cpp b/src/lib/gui/dialogs/SettingsDialog.cpp index cb8260d06..abedd70d6 100644 --- a/src/lib/gui/dialogs/SettingsDialog.cpp +++ b/src/lib/gui/dialogs/SettingsDialog.cpp @@ -130,7 +130,6 @@ void SettingsDialog::initConnections() const connect(ui->cbElevateDaemon, &QCheckBox::toggled, this, &SettingsDialog::setButtonBoxEnabledButtons); connect(ui->cbAutoUpdate, &QCheckBox::toggled, this, &SettingsDialog::setButtonBoxEnabledButtons); connect(ui->cbGuiDebug, &QCheckBox::toggled, this, &SettingsDialog::setButtonBoxEnabledButtons); - connect(ui->cbUseWlClipboard, &QCheckBox::toggled, this, &SettingsDialog::setButtonBoxEnabledButtons); connect(ui->cbShowVersion, &QCheckBox::toggled, this, &SettingsDialog::setButtonBoxEnabledButtons); connect(ui->cbRequireClientCert, &QCheckBox::toggled, this, &SettingsDialog::setButtonBoxEnabledButtons); connect(ui->groupLogToFile, &QGroupBox::toggled, this, &SettingsDialog::setButtonBoxEnabledButtons); @@ -242,7 +241,6 @@ void SettingsDialog::accept() Settings::setValue(Settings::Security::CheckPeers, ui->cbRequireClientCert->isChecked()); Settings::setValue(Settings::Core::Language, I18N::nativeTo639Name(ui->comboLanguage->currentText())); Settings::setValue(Settings::Log::GuiDebug, ui->cbGuiDebug->isChecked()); - Settings::setValue(Settings::Core::UseWlClipboard, ui->cbUseWlClipboard->isChecked()); Settings::setValue(Settings::Gui::ShowVersionInTitle, ui->cbShowVersion->isChecked()); Settings::setValue(Settings::Core::EnableEnterCommand, ui->cbRunEnterCommand->isChecked()); Settings::setValue(Settings::Core::EnableExitCommand, ui->cbRunExitCommand->isChecked()); @@ -271,7 +269,6 @@ void SettingsDialog::loadFromConfig() ui->cbElevateDaemon->setChecked(Settings::value(Settings::Daemon::Elevate).toBool()); ui->cbAutoUpdate->setChecked(Settings::value(Settings::Gui::AutoUpdateCheck).toBool()); ui->cbGuiDebug->setChecked(Settings::value(Settings::Log::GuiDebug).toBool()); - ui->cbUseWlClipboard->setChecked(Settings::value(Settings::Core::UseWlClipboard).toBool()); ui->cbShowVersion->setChecked(Settings::value(Settings::Gui::ShowVersionInTitle).toBool()); ui->cbRunEnterCommand->setChecked(Settings::value(Settings::Core::EnableEnterCommand).toBool()); ui->cbRunExitCommand->setChecked(Settings::value(Settings::Core::EnableExitCommand).toBool()); @@ -402,14 +399,6 @@ void SettingsDialog::updateControls() ui->groupService->setVisible(false); } - // wl-clipboard support only works on wayland. - // options should only be available when we are *not* running on wayland. - if (deskflow::platform::isWayland()) { - ui->cbUseWlClipboard->setEnabled(writable); - } else if (ui->widgetWlClipboard->isVisibleTo(ui->tabAdvanced)) { - ui->widgetWlClipboard->setVisible(false); - } - ui->widgetLogFilename->setEnabled(writable && logToFile); updateTlsControls(); @@ -443,7 +432,6 @@ bool SettingsDialog::isModified() const (ui->cbElevateDaemon->isChecked() != Settings::value(Settings::Daemon::Elevate).toBool()) || (ui->cbAutoUpdate->isChecked() != Settings::value(Settings::Gui::AutoUpdateCheck).toBool()) || (ui->cbGuiDebug->isChecked() != Settings::value(Settings::Log::GuiDebug).toBool()) || - (ui->cbUseWlClipboard->isChecked() != Settings::value(Settings::Core::UseWlClipboard).toBool()) || (ui->cbShowVersion->isChecked() != Settings::value(Settings::Gui::ShowVersionInTitle).toBool()) || (ui->rbIconMono->isChecked() != Settings::value(Settings::Gui::SymbolicTrayIcon).toBool()) || (ui->groupService->isChecked() != (processMode == Settings::ProcessMode::Service)) || @@ -479,7 +467,6 @@ bool SettingsDialog::isDefault() const (ui->cbElevateDaemon->isChecked() == Settings::defaultValue(Settings::Daemon::Elevate).toBool()) && (ui->cbAutoUpdate->isChecked() == Settings::defaultValue(Settings::Gui::AutoUpdateCheck).toBool()) && (ui->cbGuiDebug->isChecked() == Settings::defaultValue(Settings::Log::GuiDebug).toBool()) && - (ui->cbUseWlClipboard->isChecked() == Settings::defaultValue(Settings::Core::UseWlClipboard).toBool()) && (ui->cbShowVersion->isChecked() == Settings::defaultValue(Settings::Gui::ShowVersionInTitle).toBool()) && (ui->rbIconMono->isChecked() == Settings::defaultValue(Settings::Gui::SymbolicTrayIcon).toBool()) && (ui->groupService->isChecked() == (processMode == Settings::ProcessMode::Service)) && @@ -508,7 +495,6 @@ void SettingsDialog::resetToDefault() ui->cbElevateDaemon->setChecked(Settings::defaultValue(Settings::Daemon::Elevate).toBool()); ui->cbAutoUpdate->setChecked(Settings::defaultValue(Settings::Gui::AutoUpdateCheck).toBool()); ui->cbGuiDebug->setChecked(Settings::defaultValue(Settings::Log::GuiDebug).toBool()); - ui->cbUseWlClipboard->setChecked(Settings::defaultValue(Settings::Core::UseWlClipboard).toBool()); ui->cbShowVersion->setChecked(Settings::defaultValue(Settings::Gui::ShowVersionInTitle).toBool()); ui->cbRunEnterCommand->setChecked(Settings::defaultValue(Settings::Core::EnableEnterCommand).toBool()); ui->cbRunExitCommand->setChecked(Settings::defaultValue(Settings::Core::EnableExitCommand).toBool()); diff --git a/src/lib/gui/dialogs/SettingsDialog.ui b/src/lib/gui/dialogs/SettingsDialog.ui index ae33488fc..95cad931b 100644 --- a/src/lib/gui/dialogs/SettingsDialog.ui +++ b/src/lib/gui/dialogs/SettingsDialog.ui @@ -807,29 +807,6 @@ - - - - - - - Enable wl-clipboard support - - - - - - - <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> - - - true - - - - - - diff --git a/src/lib/platform/CMakeLists.txt b/src/lib/platform/CMakeLists.txt index a71be51e7..e8b686978 100644 --- a/src/lib/platform/CMakeLists.txt +++ b/src/lib/platform/CMakeLists.txt @@ -151,10 +151,6 @@ elseif(UNIX) EiKeyState.h EiScreen.cpp EiScreen.h - WlClipboardCollection.cpp - WlClipboardCollection.h - WlClipboard.cpp - WlClipboard.h ) # The Portal sources also require EI. if(LIBPORTAL_FOUND) diff --git a/src/lib/platform/WlClipboard.cpp b/src/lib/platform/WlClipboard.cpp deleted file mode 100644 index 2277e1c52..000000000 --- a/src/lib/platform/WlClipboard.cpp +++ /dev/null @@ -1,411 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * SPDX-FileCopyrightText: (C) 2025 Deskflow Developers - * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception - */ - -#include "platform/WlClipboard.h" - -#include "base/Log.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace { - -inline static const auto s_copyApp = QStringLiteral("wl-copy"); -inline static const auto s_pasteApp = QStringLiteral("wl-paste"); - -// wl-clipboard args -inline static const auto s_listTypes = QStringLiteral("--list-types"); -inline static const auto s_isPrimary = QStringLiteral("--primary"); -inline static const auto s_noNewLine = QStringLiteral("-n"); -inline static const auto s_readType = QStringLiteral("-t%1"); - -// MIME types for different clipboard formats -inline static const auto s_mimeTypeText = QStringLiteral("text/plain;charset=utf-8"); -inline static const auto s_mimeTypeHtml = QStringLiteral("text/html"); -inline static const auto s_mimeTypeBmp = QStringLiteral("image/bmp"); - -// Additional HTML MIME type variants -const char *const s_mimeTypeHtmlUtf8 = "text/html;charset=UTF-8"; -const char *const s_mimeTypeHtmlWindows = "HTML Format"; - -// Command timeout (milliseconds) -const int kCacheValidityMs = 100; -const int kMonitorIntervalMs = 1000; -const int kMaxConsecutiveErrors = 5; -} // namespace - -WlClipboard::WlClipboard(ClipboardID id) : m_id(id), m_useClipboard(id == kClipboardClipboard) -{ - // Initialize cached data - for (int i = 0; i < static_cast(Format::TotalFormats); ++i) { - m_cachedAvailable[i] = false; - } -} - -WlClipboard::~WlClipboard() -{ - stopMonitoring(); - for (auto &cmd : m_runningWlCopies) { - cmd->close(); - cmd->waitForFinished(100); - } - m_runningWlCopies.clear(); -} - -ClipboardID WlClipboard::getID() const -{ - return m_id; -} - -bool WlClipboard::isAvailable() -{ - return !QStandardPaths::findExecutable(s_copyApp).isEmpty() && !QStandardPaths::findExecutable(s_pasteApp).isEmpty(); -} - -bool WlClipboard::isEnabled() -{ - return Settings::value(Settings::Core::UseWlClipboard).toBool(); -} - -void WlClipboard::startMonitoring() -{ - if (m_monitoring) { - return; - } - m_stopMonitoring = false; - m_monitoring = true; - m_monitorThread = std::make_unique(&WlClipboard::monitorClipboard, this); -} - -void WlClipboard::stopMonitoring() -{ - if (!m_monitoring) { - return; - } - - m_stopMonitoring = true; - m_monitoring = false; - - if (m_monitorThread && m_monitorThread->joinable()) { - m_monitorThread->join(); - } - m_monitorThread.reset(); -} - -bool WlClipboard::hasChanged() const -{ - return m_hasChanged.load(); -} - -bool WlClipboard::empty() -{ - if (!m_open) { - return false; - } - auto cmd = new QProcess(this); - cmd->setProgram(s_copyApp); - m_runningWlCopies.append(cmd); - connect(cmd, &QProcess::finished, this, [&] { m_runningWlCopies.removeAll(cmd); }); - - QStringList args = {s_noNewLine, ""}; - if (!m_useClipboard) - args.prepend(s_isPrimary); - - cmd->setArguments(args); - cmd->start(); - bool success = cmd->waitForStarted(100); - - if (success) { - // Update ownership and cache only if command succeeded - std::scoped_lock lock(m_cacheMutex); - updateOwnership(true); - invalidateCache(); - } - - return success; -} - -void WlClipboard::add(Format format, const std::string &data) -{ - if (!m_open) { - return; - } - - if (format == Format::HTML) { - return; - } - - auto mimeType = formatToMimeType(format); - if (mimeType.isEmpty()) { - LOG_WARN("unsupported clipboard format: %d", format); - return; - } - - auto cmd = new QProcess(this); - cmd->setProgram(s_copyApp); - - m_runningWlCopies.append(cmd); - connect(cmd, &QProcess::finished, this, [&] { m_runningWlCopies.removeAll(cmd); }); - - QStringList args = {s_noNewLine, s_readType.arg(mimeType), QString::fromStdString(data)}; - if (!m_useClipboard) - args.prepend(s_isPrimary); - - cmd->setArguments(args); - cmd->start(); - - if (cmd->waitForStarted(100)) { - std::scoped_lock lock(m_cacheMutex); - updateOwnership(true); - invalidateCache(); - } -} - -bool WlClipboard::open(Time time) const -{ - if (m_open) { - LOG_DEBUG("failed to open clipboard: already opened"); - return false; - } - - m_open = true; - m_time = time; - - return true; -} - -void WlClipboard::close() const -{ - if (!m_open) { - return; - } - - LOG_DEBUG("close clipboard"); - - m_open = false; - const_cast(this)->invalidateCache(); -} - -IClipboard::Time WlClipboard::getTime() const -{ - return m_time; -} - -bool WlClipboard::has(Format format) const -{ - if (!m_open) { - return false; - } - - std::scoped_lock lock(m_cacheMutex); - - // Check cache validity - Time currentTime = getCurrentTime(); - if (m_cached && (currentTime - m_cachedTime) < kCacheValidityMs) { - return m_cachedAvailable[static_cast(format)]; - } - - if (const auto availableTypes = getAvailableMimeTypes(); availableTypes.isEmpty()) { - // No types available - mark all formats as unavailable - for (int i = 0; i < static_cast(Format::TotalFormats); ++i) { - m_cachedAvailable[i] = false; - m_cachedData[i].clear(); - } - } else { - using enum IClipboard::Format; - // Check each format against available types - for (int i = 0; i < static_cast(TotalFormats); ++i) { - auto currentFormat = static_cast(i); - const auto mimeType = formatToMimeType(currentFormat); - - m_cachedAvailable[i] = false; - if (!mimeType.isEmpty()) { - for (const auto &available : availableTypes) { - if (available == mimeType || (currentFormat == Text && available == QStringLiteral("text/plain")) || - (currentFormat == HTML && available.startsWith(QStringLiteral("text/html")))) { - m_cachedAvailable[i] = true; - break; - } - } - } - } - } - - m_cached = true; - m_cachedTime = currentTime; - - return m_cachedAvailable[static_cast(format)]; -} - -std::string WlClipboard::get(Format format) const -{ - if (!m_open) { - return std::string(); - } - - std::scoped_lock lock(m_cacheMutex); - - // Return cached data if available and valid - if (m_cached && m_cachedAvailable[static_cast(format)] && !m_cachedData[static_cast(format)].empty()) { - return m_cachedData[static_cast(format)]; - } - - auto mimeType = formatToMimeType(format); - if (mimeType.isEmpty()) { - return std::string(); - } - - QProcess cmd; - cmd.setProgram(s_pasteApp); - - QStringList args = {s_noNewLine, s_readType.arg(mimeType)}; - if (!m_useClipboard) - args.append(s_isPrimary); - - cmd.setArguments(args); - cmd.start(); - cmd.waitForFinished(); - - auto data = cmd.readAll().toStdString(); - - // Update cache - m_cachedData[static_cast(format)] = data; - m_cachedAvailable[static_cast(format)] = !data.empty(); - m_cached = true; - m_cachedTime = getCurrentTime(); - - return data; -} - -QString WlClipboard::formatToMimeType(Format format) const -{ - switch (format) { - using enum IClipboard::Format; - case Text: - return s_mimeTypeText; - case HTML: - return s_mimeTypeHtml; - case Bitmap: - return s_mimeTypeBmp; - default: - return {}; - } -} - -IClipboard::Format WlClipboard::mimeTypeToFormat(const QString &mimeType) const -{ - using enum IClipboard::Format; - if (mimeType == s_mimeTypeText || mimeType == QStringLiteral("text/plain")) { - return Text; - } - if (mimeType == s_mimeTypeHtml || mimeType == s_mimeTypeHtmlUtf8 || mimeType == s_mimeTypeHtmlWindows || - mimeType.contains("text/html")) { - return HTML; - } - if (mimeType == s_mimeTypeBmp) { - return Bitmap; - } - return Text; // Default fallback -} - -QStringList WlClipboard::getAvailableMimeTypes() const -{ - QProcess cmd; - cmd.setProgram(s_pasteApp); - - QStringList args = {s_listTypes}; - if (!m_useClipboard) - args.append(s_isPrimary); - - cmd.setArguments(args); - cmd.start(); - cmd.waitForFinished(); - - const static QChar newLine = QLatin1Char('\n'); - return QString::fromLocal8Bit(cmd.readAll()).split(newLine); -} - -void WlClipboard::monitorClipboard() -{ - QStringList lastTypes; - int consecutiveErrors = 0; - - while (!m_stopMonitoring) { - std::this_thread::sleep_for(std::chrono::milliseconds(kMonitorIntervalMs)); - try { - // Check if clipboard content has changed by comparing available types - const auto currentTypes = getAvailableMimeTypes(); - - // Reset error counter on successful operation - consecutiveErrors = 0; - - if (currentTypes != lastTypes) { - m_hasChanged = true; - lastTypes = currentTypes; - - // Clear cache when clipboard changes - std::scoped_lock lock(m_cacheMutex); - invalidateCache(); - updateOwnership(false); - } - } catch (const std::exception &e) { - LOG_WARN("clipboard monitoring error: %s", e.what()); - if (++consecutiveErrors >= kMaxConsecutiveErrors) { - LOG_ERR("too many consecutive errors in clipboard monitoring, stopping"); - break; - } - } catch (...) { - LOG_WARN("clipboard monitoring unknown error"); - if (++consecutiveErrors >= kMaxConsecutiveErrors) { - LOG_ERR("too many consecutive errors in clipboard monitoring, stopping"); - break; - } - } - } -} - -IClipboard::Time WlClipboard::getCurrentTime() const -{ - return static_cast