From 2d2b9f9d46b2d53890d154da75f8f7d81f865e6b Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Tue, 16 Jun 2026 19:09:55 +0100 Subject: [PATCH 01/14] Add support for Rocky Linux in CI matrix and dependency installation --- .github/matrix.yml | 12 +++++++++++ scripts/install_deps.sh | 48 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/.github/matrix.yml b/.github/matrix.yml index aa538cabd..442ac0aad 100644 --- a/.github/matrix.yml +++ b/.github/matrix.yml @@ -67,6 +67,18 @@ target: runs-on: ubuntu-latest container: fedora:42 + - name: rocky-8-x86_64 + runs-on: ubuntu-latest + container: rockylinux:8 + + - name: rocky-9-x86_64 + runs-on: ubuntu-latest + container: rockylinux:9 + + - name: rocky-10-x86_64 + runs-on: ubuntu-latest + container: rockylinux:10 + - name: opensuse-tumbleweed-x86_64 runs-on: ubuntu-latest container: opensuse/tumbleweed:latest diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh index 894a711ed..0a9736157 100755 --- a/scripts/install_deps.sh +++ b/scripts/install_deps.sh @@ -28,6 +28,7 @@ install_linux_deps() { echo "Detected Linux: ${os}" case "${os}" in *debian*) install_debian_deps ;; + *rhel*) install_rhel_deps ;; *fedora*) install_fedora_deps ;; *suse*) install_suse_deps ;; *arch*) install_arch_deps ;; @@ -132,6 +133,53 @@ install_fedora_deps() { cli11-devel } +install_rhel_deps() { + dnf install -y 'dnf-command(config-manager)' + dnf install -y epel-release + + # The -devel packages live in the CodeReady Builder repo (powertools on el8, crb on el9+). + dnf config-manager --set-enabled powertools 2>/dev/null \ + || dnf config-manager --set-enabled crb 2>/dev/null || true + + . /etc/os-release || true + + # el8 has no Qt6 and a pre-C++20 compiler, so it needs Qt5 and a gcc-toolset; + # el9+ build against Qt6 like the other distros. + if [ "${VERSION_ID%%.*}" = "8" ]; then + dnf install -y \ + cmake \ + make \ + ninja-build \ + gcc-toolset-13 \ + rpm-build \ + openssl-devel \ + glib2-devel \ + gdk-pixbuf2-devel \ + libXtst-devel \ + libnotify-devel \ + libxkbfile-devel \ + qt5-qtbase-devel \ + qt5-qttools-devel \ + gtk3-devel + else + dnf install -y \ + cmake \ + make \ + ninja-build \ + gcc-c++ \ + rpm-build \ + openssl-devel \ + glib2-devel \ + gdk-pixbuf2-devel \ + libXtst-devel \ + libnotify-devel \ + libxkbfile-devel \ + qt6-qtbase-devel \ + qt6-qttools-devel \ + gtk3-devel + fi +} + install_suse_deps() { zypper refresh zypper --non-interactive --no-gpg-checks install -y --force-resolution \ From b97d5d809aead872ef6d3c29569c242aef5f02e9 Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Tue, 16 Jun 2026 20:13:08 +0100 Subject: [PATCH 02/14] Refactor Qt package handling to support version flexibility and remove Rocky Linux 10 from CI matrix --- .github/matrix.yml | 4 ---- cmake/Libraries.cmake | 7 ++++--- ext/synergy-extra | 2 +- scripts/install_deps.sh | 5 ++--- src/apps/deskflow-daemon/CMakeLists.txt | 8 ++++---- src/gui/CMakeLists.txt | 10 +++++----- src/lib/arch/CMakeLists.txt | 4 ++-- src/lib/deskflow/CMakeLists.txt | 4 ++-- src/lib/gui/CMakeLists.txt | 6 +++--- src/lib/platform/CMakeLists.txt | 4 ++-- 10 files changed, 25 insertions(+), 29 deletions(-) diff --git a/.github/matrix.yml b/.github/matrix.yml index 442ac0aad..0222a8dc4 100644 --- a/.github/matrix.yml +++ b/.github/matrix.yml @@ -75,10 +75,6 @@ target: runs-on: ubuntu-latest container: rockylinux:9 - - name: rocky-10-x86_64 - runs-on: ubuntu-latest - container: rockylinux:10 - - name: opensuse-tumbleweed-x86_64 runs-on: ubuntu-latest container: opensuse/tumbleweed:latest diff --git a/cmake/Libraries.cmake b/cmake/Libraries.cmake index d008c2ba7..c6cf9c0ac 100644 --- a/cmake/Libraries.cmake +++ b/cmake/Libraries.cmake @@ -25,7 +25,8 @@ macro(configure_libs) configure_windows_libs() endif() - find_package(Qt6 REQUIRED COMPONENTS Core Widgets Network) + find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Widgets Network) + find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Widgets Network) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) @@ -540,11 +541,11 @@ endmacro() macro(configure_qt) find_package( - Qt6 + Qt${QT_VERSION_MAJOR} COMPONENTS Core Widgets Network Xml REQUIRED) - message(STATUS "Qt version: ${Qt6_VERSION}") + message(STATUS "Qt version: ${Qt${QT_VERSION_MAJOR}_VERSION}") set(GUI_RES_DIR ${DESKFLOW_RES_DIR}/gui) set(GUI_QRC_FILE ${GUI_RES_DIR}/app.qrc) diff --git a/ext/synergy-extra b/ext/synergy-extra index 706bdf4d8..a615c9d78 160000 --- a/ext/synergy-extra +++ b/ext/synergy-extra @@ -1 +1 @@ -Subproject commit 706bdf4d815643c0db722389b67a273a365d2225 +Subproject commit a615c9d780b4d32d8cf4d56c074ae79dc2315402 diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh index 0a9736157..ac06beccc 100755 --- a/scripts/install_deps.sh +++ b/scripts/install_deps.sh @@ -144,7 +144,8 @@ install_rhel_deps() { . /etc/os-release || true # el8 has no Qt6 and a pre-C++20 compiler, so it needs Qt5 and a gcc-toolset; - # el9+ build against Qt6 like the other distros. + # el9+ build against Qt6. qttools is skipped (the build has no translations, and + # on el9 EPEL's qt6-linguist has an unsatisfiable LLVM dependency). if [ "${VERSION_ID%%.*}" = "8" ]; then dnf install -y \ cmake \ @@ -159,7 +160,6 @@ install_rhel_deps() { libnotify-devel \ libxkbfile-devel \ qt5-qtbase-devel \ - qt5-qttools-devel \ gtk3-devel else dnf install -y \ @@ -175,7 +175,6 @@ install_rhel_deps() { libnotify-devel \ libxkbfile-devel \ qt6-qtbase-devel \ - qt6-qttools-devel \ gtk3-devel fi } diff --git a/src/apps/deskflow-daemon/CMakeLists.txt b/src/apps/deskflow-daemon/CMakeLists.txt index d549a1941..d8a168502 100644 --- a/src/apps/deskflow-daemon/CMakeLists.txt +++ b/src/apps/deskflow-daemon/CMakeLists.txt @@ -35,10 +35,10 @@ if(WIN32) platform app ${libs} - Qt6::Core) - - find_package(Qt6 REQUIRED COMPONENTS Widgets) - get_target_property(WINDEPLOYQT_EXE Qt6::windeployqt IMPORTED_LOCATION) + Qt${QT_VERSION_MAJOR}::Core) + + find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets) + get_target_property(WINDEPLOYQT_EXE Qt${QT_VERSION_MAJOR}::windeployqt IMPORTED_LOCATION) add_custom_command(TARGET ${DAEMON_BINARY_NAME} POST_BUILD COMMAND ${WINDEPLOYQT_EXE} --no-compiler-runtime diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 0064323e2..45d047e16 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -52,9 +52,9 @@ target_link_libraries( ${target} ${DESKFLOW_GUI_HOOK_LIB} gui - Qt6::Core - Qt6::Widgets - Qt6::Network) + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Widgets + Qt${QT_VERSION_MAJOR}::Network) if(WIN32) set_target_properties(${target} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:LIBCMT") @@ -110,8 +110,8 @@ elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") elseif(WIN32) - find_package(Qt6 REQUIRED COMPONENTS Widgets) - get_target_property(WINDEPLOYQT_EXE Qt6::windeployqt IMPORTED_LOCATION) + find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets) + get_target_property(WINDEPLOYQT_EXE Qt${QT_VERSION_MAJOR}::windeployqt IMPORTED_LOCATION) add_custom_command(TARGET ${GUI_BINARY_NAME} POST_BUILD COMMAND ${WINDEPLOYQT_EXE} --force-openssl diff --git a/src/lib/arch/CMakeLists.txt b/src/lib/arch/CMakeLists.txt index 51be8a212..7972f8458 100644 --- a/src/lib/arch/CMakeLists.txt +++ b/src/lib/arch/CMakeLists.txt @@ -43,7 +43,7 @@ if(UNIX) target_link_libraries(arch ${CMAKE_DL_LIBS} ${libs}) if(NOT APPLE) - find_package(Qt6 COMPONENTS DBus) - target_link_libraries(arch Qt6::DBus) + find_package(Qt${QT_VERSION_MAJOR} COMPONENTS DBus) + target_link_libraries(arch Qt${QT_VERSION_MAJOR}::DBus) endif() endif() diff --git a/src/lib/deskflow/CMakeLists.txt b/src/lib/deskflow/CMakeLists.txt index 25b478a49..0b522f425 100644 --- a/src/lib/deskflow/CMakeLists.txt +++ b/src/lib/deskflow/CMakeLists.txt @@ -43,7 +43,7 @@ add_library(${lib_name} STATIC ${sources}) if(WIN32) - target_link_libraries(${lib_name} PRIVATE Qt6::Core Qt6::Network) + target_link_libraries(${lib_name} PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network) elseif(UNIX) @@ -62,7 +62,7 @@ elseif(UNIX) ${tomlplusplus_lib}) if(NOT APPLE) - target_link_libraries(${lib_name} PRIVATE Qt6::Xml) + target_link_libraries(${lib_name} PRIVATE Qt${QT_VERSION_MAJOR}::Xml) find_package(PkgConfig) if(PKG_CONFIG_FOUND) diff --git a/src/lib/gui/CMakeLists.txt b/src/lib/gui/CMakeLists.txt index e11d0841e..9f010c86d 100644 --- a/src/lib/gui/CMakeLists.txt +++ b/src/lib/gui/CMakeLists.txt @@ -44,6 +44,6 @@ add_library(${target} STATIC ${sources} ${ui_files} ${qrc_file}) target_link_libraries( ${target} ${DESKFLOW_GUI_HOOK_LIB} - Qt6::Core - Qt6::Widgets - Qt6::Network) + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Widgets + Qt${QT_VERSION_MAJOR}::Network) diff --git a/src/lib/platform/CMakeLists.txt b/src/lib/platform/CMakeLists.txt index 778d6feb2..2a04ec476 100644 --- a/src/lib/platform/CMakeLists.txt +++ b/src/lib/platform/CMakeLists.txt @@ -91,9 +91,9 @@ if(UNIX) ${libs}) if(NOT APPLE) - find_package(Qt6 COMPONENTS DBus) + find_package(Qt${QT_VERSION_MAJOR} COMPONENTS DBus) - target_link_libraries(platform Qt6::DBus) + target_link_libraries(platform Qt${QT_VERSION_MAJOR}::DBus) if(${LIBXKBCOMMON_VERSION} VERSION_GREATER_EQUAL "1.10") target_compile_definitions(platform PRIVATE HAVE_XKB_KEYMAP_MOD_GET_MASK=1) From 7e6fac1364f7b713e5d84807f13cfd88231c2c4a Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Tue, 16 Jun 2026 20:33:48 +0100 Subject: [PATCH 03/14] Enhance RHEL dependency installation and CI integration for target-specific builds --- .github/actions/install-deps/action.yml | 26 +++++++++++++++++++++++++ .github/workflows/ci.yml | 2 ++ scripts/install_deps.sh | 12 ++++++++++-- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/.github/actions/install-deps/action.yml b/.github/actions/install-deps/action.yml index 640be5575..0e0d4608d 100644 --- a/.github/actions/install-deps/action.yml +++ b/.github/actions/install-deps/action.yml @@ -2,6 +2,7 @@ # SPDX-License-Identifier: MIT name: "Install dependencies" +description: "Install build dependencies for Synergy." inputs: working-directory: @@ -11,6 +12,10 @@ inputs: description: "The version of Qt to install on macOS and Windows." required: false default: "6.9.3" + target-name: + description: "The name of the build target (e.g. rocky-8-x86_64)." + required: false + default: "" outputs: vcpkg-cmake-config: @@ -41,6 +46,27 @@ runs: working-directory: ${{ inputs.working-directory }} run: ./scripts/install_deps.py + # el8/el9 ship cmake 3.20 (below our 3.22 minimum); el8 also has no C++20 + # compiler. Put a newer cmake (and on el8 the gcc-toolset) on PATH for the build. + - name: Setup RHEL toolchain + if: ${{ startsWith(inputs.target-name, 'rocky') }} + shell: bash + run: | + . /etc/os-release + + cmake_version=3.28.3 + curl -fsSL "https://github.com/Kitware/CMake/releases/download/v${cmake_version}/cmake-${cmake_version}-linux-x86_64.tar.gz" \ + | tar -xz -C /opt + echo "/opt/cmake-${cmake_version}-linux-x86_64/bin" >> "$GITHUB_PATH" + + if [ "${VERSION_ID%%.*}" = "8" ]; then + toolset=/opt/rh/gcc-toolset-13/root/usr + echo "${toolset}/bin" >> "$GITHUB_PATH" + echo "CC=${toolset}/bin/gcc" >> "$GITHUB_ENV" + echo "CXX=${toolset}/bin/g++" >> "$GITHUB_ENV" + echo "LD_LIBRARY_PATH=${toolset}/lib64" >> "$GITHUB_ENV" + fi + - name: Install Qt (macOS) if: ${{ runner.os == 'macOS' }} uses: jurplel/install-qt-action@v4 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c10c9de33..2918f40b8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -183,6 +183,8 @@ jobs: id: install-deps if: ${{ !steps.vars.outputs.is-flatpak }} uses: ./.github/actions/install-deps + with: + target-name: ${{ matrix.target.name }} - name: Build id: build diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh index ac06beccc..b6d69743d 100755 --- a/scripts/install_deps.sh +++ b/scripts/install_deps.sh @@ -151,6 +151,8 @@ install_rhel_deps() { cmake \ make \ ninja-build \ + tar \ + gzip \ gcc-toolset-13 \ rpm-build \ openssl-devel \ @@ -160,12 +162,16 @@ install_rhel_deps() { libnotify-devel \ libxkbfile-devel \ qt5-qtbase-devel \ - gtk3-devel + gtk3-devel \ + gtest-devel \ + gmock-devel else dnf install -y \ cmake \ make \ ninja-build \ + tar \ + gzip \ gcc-c++ \ rpm-build \ openssl-devel \ @@ -175,7 +181,9 @@ install_rhel_deps() { libnotify-devel \ libxkbfile-devel \ qt6-qtbase-devel \ - gtk3-devel + gtk3-devel \ + gtest-devel \ + gmock-devel fi } From ead4e81fc9335e18ed263d79b61e593aacf918ea Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Tue, 16 Jun 2026 20:39:16 +0100 Subject: [PATCH 04/14] Import lib.env within the run function to prevent circular import issues --- scripts/lib/cmd_utils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/lib/cmd_utils.py b/scripts/lib/cmd_utils.py index 26fbaa958..aca9c5ad3 100644 --- a/scripts/lib/cmd_utils.py +++ b/scripts/lib/cmd_utils.py @@ -15,7 +15,6 @@ import subprocess import sys -import lib.env as env try: import colorama # type: ignore @@ -90,6 +89,9 @@ def run( print_cmd (bool): Print the command before running it (false by default for security) """ + # Imported here, not at module top, to avoid a circular import with lib.env. + import lib.env as env + is_list_cmd = isinstance(command, list) # create string version of list command, only for debugging purposes From 9139d4be16d33a794f7f6ecd032714f25b79a162 Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Tue, 16 Jun 2026 23:55:56 +0100 Subject: [PATCH 05/14] Refactor dependency installation for RHEL: add Python 3.11 and pip, reorganize setup steps for clarity --- .github/actions/install-deps/action.yml | 38 ++++++++++++++----------- scripts/install_deps.sh | 2 ++ 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/.github/actions/install-deps/action.yml b/.github/actions/install-deps/action.yml index 0e0d4608d..df64aceb0 100644 --- a/.github/actions/install-deps/action.yml +++ b/.github/actions/install-deps/action.yml @@ -32,22 +32,9 @@ runs: working-directory: ${{ inputs.working-directory }} run: ./scripts/install_deps.sh ${args} - # HACK: Needed for GTest on Windows (installed bia Meson). - - name: Install Meson deps (Windows) - if: ${{ runner.os == 'Windows' }} - shell: pwsh - working-directory: ${{ inputs.working-directory }} - run: python ./scripts/install_deps.py - - # Installs some Python deps (e.g. pip, etc) and the venv needed for the package step. - - name: Setup Python env (Linux & macOS) - if: ${{ runner.os == 'Linux' || runner.os == 'macOS' }} - shell: bash - working-directory: ${{ inputs.working-directory }} - run: ./scripts/install_deps.py - - # el8/el9 ship cmake 3.20 (below our 3.22 minimum); el8 also has no C++20 - # compiler. Put a newer cmake (and on el8 the gcc-toolset) on PATH for the build. + # el8/el9 ship cmake 3.20 (below our 3.22 minimum); el8 also has no C++20 compiler + # and only Python 3.6. Set up a newer cmake/compiler/python before the Python env + # and build steps that need them. - name: Setup RHEL toolchain if: ${{ startsWith(inputs.target-name, 'rocky') }} shell: bash @@ -65,8 +52,27 @@ runs: echo "CC=${toolset}/bin/gcc" >> "$GITHUB_ENV" echo "CXX=${toolset}/bin/g++" >> "$GITHUB_ENV" echo "LD_LIBRARY_PATH=${toolset}/lib64" >> "$GITHUB_ENV" + + # el8's python3 is 3.6; the build scripts need >= 3.9, so expose python3.11 as python3. + mkdir -p /opt/python-shim + ln -sf /usr/bin/python3.11 /opt/python-shim/python3 + echo "/opt/python-shim" >> "$GITHUB_PATH" fi + # HACK: Needed for GTest on Windows (installed bia Meson). + - name: Install Meson deps (Windows) + if: ${{ runner.os == 'Windows' }} + shell: pwsh + working-directory: ${{ inputs.working-directory }} + run: python ./scripts/install_deps.py + + # Installs some Python deps (e.g. pip, etc) and the venv needed for the package step. + - name: Setup Python env (Linux & macOS) + if: ${{ runner.os == 'Linux' || runner.os == 'macOS' }} + shell: bash + working-directory: ${{ inputs.working-directory }} + run: ./scripts/install_deps.py + - name: Install Qt (macOS) if: ${{ runner.os == 'macOS' }} uses: jurplel/install-qt-action@v4 diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh index b6d69743d..5241aa074 100755 --- a/scripts/install_deps.sh +++ b/scripts/install_deps.sh @@ -153,6 +153,8 @@ install_rhel_deps() { ninja-build \ tar \ gzip \ + python3.11 \ + python3.11-pip \ gcc-toolset-13 \ rpm-build \ openssl-devel \ From 20229fca4b1316529c73c111dcb3f1edc5fdc668 Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Wed, 17 Jun 2026 00:10:17 +0100 Subject: [PATCH 06/14] Add OpenSSL compatibility definition for SSL_OP_IGNORE_UNEXPECTED_EOF in SslApi and SecureSocket --- src/lib/arch/unix/ArchSystemUnix.cpp | 1 + src/lib/net/InverseSockets/SslApi.cpp | 5 +++++ src/lib/net/SecureSocket.cpp | 5 +++++ 3 files changed, 11 insertions(+) diff --git a/src/lib/arch/unix/ArchSystemUnix.cpp b/src/lib/arch/unix/ArchSystemUnix.cpp index 4203d78e1..d395248d5 100644 --- a/src/lib/arch/unix/ArchSystemUnix.cpp +++ b/src/lib/arch/unix/ArchSystemUnix.cpp @@ -21,6 +21,7 @@ #include "base/Log.h" #include +#include #include #include #include diff --git a/src/lib/net/InverseSockets/SslApi.cpp b/src/lib/net/InverseSockets/SslApi.cpp index 968531e89..d5fc17888 100644 --- a/src/lib/net/InverseSockets/SslApi.cpp +++ b/src/lib/net/InverseSockets/SslApi.cpp @@ -8,6 +8,11 @@ #include #include +// SSL_OP_IGNORE_UNEXPECTED_EOF was added in OpenSSL 3.0; older versions behave this way by default. +#ifndef SSL_OP_IGNORE_UNEXPECTED_EOF +#define SSL_OP_IGNORE_UNEXPECTED_EOF 0 +#endif + namespace deskflow { namespace ssl { diff --git a/src/lib/net/SecureSocket.cpp b/src/lib/net/SecureSocket.cpp index 3c1b559f7..214654e03 100644 --- a/src/lib/net/SecureSocket.cpp +++ b/src/lib/net/SecureSocket.cpp @@ -35,6 +35,11 @@ #include #include +// SSL_OP_IGNORE_UNEXPECTED_EOF was added in OpenSSL 3.0; older versions behave this way by default. +#ifndef SSL_OP_IGNORE_UNEXPECTED_EOF +#define SSL_OP_IGNORE_UNEXPECTED_EOF 0 +#endif + // // SecureSocket // From a276431abe2fc44d01f6a90fcef84547f462f4a2 Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Wed, 17 Jun 2026 00:19:01 +0100 Subject: [PATCH 07/14] Add QTextStream include to Hotkey and Logger for text stream operations --- src/gui/src/Hotkey.cpp | 1 + src/lib/gui/Logger.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/gui/src/Hotkey.cpp b/src/gui/src/Hotkey.cpp index e0eca537e..610b73bb5 100644 --- a/src/gui/src/Hotkey.cpp +++ b/src/gui/src/Hotkey.cpp @@ -19,6 +19,7 @@ #include "Hotkey.h" #include +#include Hotkey::Hotkey() : m_KeySequence(), m_Actions() { diff --git a/src/lib/gui/Logger.cpp b/src/lib/gui/Logger.cpp index 11b46ea94..d6498db1c 100644 --- a/src/lib/gui/Logger.cpp +++ b/src/lib/gui/Logger.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #if defined(Q_OS_WIN) From 553051313ce58b553b82f6f1e57b3a2c7c1150a4 Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Wed, 17 Jun 2026 00:31:06 +0100 Subject: [PATCH 08/14] Add QDebug include to multiple source files for enhanced debugging capabilities --- src/lib/gui/config/Settings.cpp | 1 + src/lib/gui/core/CoreProcess.cpp | 1 + src/lib/gui/diagnostic.cpp | 1 + src/lib/gui/proxy/QSettingsProxy.cpp | 1 + src/lib/gui/tls/TlsCertificate.cpp | 1 + 5 files changed, 5 insertions(+) diff --git a/src/lib/gui/config/Settings.cpp b/src/lib/gui/config/Settings.cpp index e4e5a3c26..63827f40b 100644 --- a/src/lib/gui/config/Settings.cpp +++ b/src/lib/gui/config/Settings.cpp @@ -22,6 +22,7 @@ #include "proxy/QSettingsProxy.h" #include +#include #include #include diff --git a/src/lib/gui/core/CoreProcess.cpp b/src/lib/gui/core/CoreProcess.cpp index c8dd631af..98d5da5d8 100644 --- a/src/lib/gui/core/CoreProcess.cpp +++ b/src/lib/gui/core/CoreProcess.cpp @@ -22,6 +22,7 @@ #endif #include +#include #include #include #include diff --git a/src/lib/gui/diagnostic.cpp b/src/lib/gui/diagnostic.cpp index 9d29e1794..a130d0f39 100644 --- a/src/lib/gui/diagnostic.cpp +++ b/src/lib/gui/diagnostic.cpp @@ -21,6 +21,7 @@ #include "paths.h" #include +#include #include #include #include diff --git a/src/lib/gui/proxy/QSettingsProxy.cpp b/src/lib/gui/proxy/QSettingsProxy.cpp index b8ee6d270..e03849983 100644 --- a/src/lib/gui/proxy/QSettingsProxy.cpp +++ b/src/lib/gui/proxy/QSettingsProxy.cpp @@ -21,6 +21,7 @@ #include "gui/Logger.h" #include +#include #include #include #include diff --git a/src/lib/gui/tls/TlsCertificate.cpp b/src/lib/gui/tls/TlsCertificate.cpp index b4ad1dbad..6ab162c0e 100644 --- a/src/lib/gui/tls/TlsCertificate.cpp +++ b/src/lib/gui/tls/TlsCertificate.cpp @@ -20,6 +20,7 @@ #include "TlsFingerprint.h" #include +#include #include #include #include From c5a0942ecee288790cf11a199f72d68c0a1e7a0e Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Wed, 17 Jun 2026 01:20:24 +0100 Subject: [PATCH 09/14] Refactor signal connection in QProcessProxy::create for clarity --- src/lib/gui/proxy/QProcessProxy.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/gui/proxy/QProcessProxy.cpp b/src/lib/gui/proxy/QProcessProxy.cpp index a0b96b271..fb78ca3ba 100644 --- a/src/lib/gui/proxy/QProcessProxy.cpp +++ b/src/lib/gui/proxy/QProcessProxy.cpp @@ -23,7 +23,9 @@ void QProcessProxy::create() { m_pProcess = std::make_unique(); - connect(m_pProcess.get(), &QProcess::finished, this, [this](int exitCode, QProcess::ExitStatus exitStatus) { + connect( + m_pProcess.get(), static_cast(&QProcess::finished), this, + [this](int exitCode, QProcess::ExitStatus exitStatus) { emit finished(exitCode, exitStatus); }); From af472b706762f01bad65c314b92a1dd6d61d695c Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Wed, 17 Jun 2026 01:26:45 +0100 Subject: [PATCH 10/14] Update subproject commit reference for synergy-extra --- ext/synergy-extra | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/synergy-extra b/ext/synergy-extra index a615c9d78..bf5b87aee 160000 --- a/ext/synergy-extra +++ b/ext/synergy-extra @@ -1 +1 @@ -Subproject commit a615c9d780b4d32d8cf4d56c074ae79dc2315402 +Subproject commit bf5b87aee64f3503954fb409d60c358ad534435d From b43fb0d923572ef8d1cf097bf67080e1b055ebe7 Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Wed, 17 Jun 2026 10:06:55 +0100 Subject: [PATCH 11/14] Skip test builds for Rocky Linux 8 in CI and action workflows --- .github/actions/build/action.yml | 5 +++++ .github/workflows/ci.yml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 32c46f96b..7874dadae 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -47,6 +47,11 @@ runs: cmake_args="$cmake_args -DUSE_TOMLPLUSPLUS=OFF -DUSE_CLI11=OFF" + # el8's EPEL GoogleTest predates MOCK_METHOD, so skip the test build there. + if [[ "${{ inputs.target-name }}" == rocky-8-* ]]; then + cmake_args="$cmake_args -DBUILD_TESTS=OFF" + fi + cmake_args_input=$(echo "${{ inputs.cmake-args }}" | tr '\n' ' ') cmake_args="$cmake_args $cmake_args_input" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2918f40b8..71f643f86 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -203,7 +203,7 @@ jobs: ${{ steps.install-deps.outputs.vcpkg-cmake-config }} - name: Tests - if: ${{ !steps.vars.outputs.is-flatpak }} + if: ${{ !steps.vars.outputs.is-flatpak && !startsWith(matrix.target.name, 'rocky-8') }} uses: ./.github/actions/run-tests timeout-minutes: 2 with: From 9cd703dd380df0eeeb1d1e12fd6e5d3cbd5ecd7c Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Wed, 17 Jun 2026 11:23:19 +0100 Subject: [PATCH 12/14] Replace Qt::endl with '\n' in QTextStream outputs for consistency --- src/gui/src/ServerConfig.cpp | 42 ++++++++++++------------ src/lib/gui/Logger.cpp | 2 +- src/lib/gui/config/Screen.cpp | 14 ++++---- src/test/integtests/gui/dotenv_tests.cpp | 6 ++-- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/gui/src/ServerConfig.cpp b/src/gui/src/ServerConfig.cpp index 39d2aa8e6..7c1289d31 100644 --- a/src/gui/src/ServerConfig.cpp +++ b/src/gui/src/ServerConfig.cpp @@ -239,81 +239,81 @@ int ServerConfig::adjacentScreenIndex(int idx, int deltaColumn, int deltaRow) co QTextStream &operator<<(QTextStream &outStream, const ServerConfig &config) { - outStream << "section: screens" << Qt::endl; + outStream << "section: screens" << '\n'; foreach (const Screen &s, config.screens()) if (!s.isNull()) s.writeScreensSection(outStream); - outStream << "end" << Qt::endl << Qt::endl; + outStream << "end" << '\n' << '\n'; - outStream << "section: aliases" << Qt::endl; + outStream << "section: aliases" << '\n'; foreach (const Screen &s, config.screens()) if (!s.isNull()) s.writeAliasesSection(outStream); - outStream << "end" << Qt::endl << Qt::endl; + outStream << "end" << '\n' << '\n'; - outStream << "section: links" << Qt::endl; + outStream << "section: links" << '\n'; for (int i = 0; i < config.screens().size(); i++) if (!config.screens()[i].isNull()) { - outStream << "\t" << config.screens()[i].name() << ":" << Qt::endl; + outStream << "\t" << config.screens()[i].name() << ":" << '\n'; for (unsigned int j = 0; j < sizeof(neighbourDirs) / sizeof(neighbourDirs[0]); j++) { int idx = config.adjacentScreenIndex(i, neighbourDirs[j].x, neighbourDirs[j].y); if (idx != -1 && !config.screens()[idx].isNull()) - outStream << "\t\t" << neighbourDirs[j].name << " = " << config.screens()[idx].name() << Qt::endl; + outStream << "\t\t" << neighbourDirs[j].name << " = " << config.screens()[idx].name() << '\n'; } } - outStream << "end" << Qt::endl << Qt::endl; + outStream << "end" << '\n' << '\n'; - outStream << "section: options" << Qt::endl; + outStream << "section: options" << '\n'; if (config.hasHeartbeat()) outStream << "\t" - << "heartbeat = " << config.heartbeat() << Qt::endl; + << "heartbeat = " << config.heartbeat() << '\n'; outStream << "\t" - << "relativeMouseMoves = " << (config.relativeMouseMoves() ? "true" : "false") << Qt::endl; + << "relativeMouseMoves = " << (config.relativeMouseMoves() ? "true" : "false") << '\n'; outStream << "\t" - << "win32KeepForeground = " << (config.win32KeepForeground() ? "true" : "false") << Qt::endl; + << "win32KeepForeground = " << (config.win32KeepForeground() ? "true" : "false") << '\n'; outStream << "\t" - << "disableLockToScreen = " << (config.disableLockToScreen() ? "true" : "false") << Qt::endl; + << "disableLockToScreen = " << (config.disableLockToScreen() ? "true" : "false") << '\n'; outStream << "\t" - << "clipboardSharing = " << (config.clipboardSharing() ? "true" : "false") << Qt::endl; + << "clipboardSharing = " << (config.clipboardSharing() ? "true" : "false") << '\n'; outStream << "\t" - << "clipboardSharingSize = " << config.clipboardSharingSize() << Qt::endl; + << "clipboardSharingSize = " << config.clipboardSharingSize() << '\n'; if (!config.getClientAddress().isEmpty()) { outStream << "\t" - << "clientAddress = " << config.getClientAddress() << Qt::endl; + << "clientAddress = " << config.getClientAddress() << '\n'; } if (config.hasSwitchDelay()) outStream << "\t" - << "switchDelay = " << config.switchDelay() << Qt::endl; + << "switchDelay = " << config.switchDelay() << '\n'; if (config.hasSwitchDoubleTap()) outStream << "\t" - << "switchDoubleTap = " << config.switchDoubleTap() << Qt::endl; + << "switchDoubleTap = " << config.switchDoubleTap() << '\n'; outStream << "\t" << "switchCorners = none "; for (int i = 0; i < config.switchCorners().size(); i++) if (config.switchCorners()[i]) outStream << "+" << config.switchCornerName(i) << " "; - outStream << Qt::endl; + outStream << '\n'; outStream << "\t" - << "switchCornerSize = " << config.switchCornerSize() << Qt::endl; + << "switchCornerSize = " << config.switchCornerSize() << '\n'; foreach (const Hotkey &hotkey, config.hotkeys()) outStream << hotkey; - outStream << "end" << Qt::endl << Qt::endl; + outStream << "end" << '\n' << '\n'; return outStream; } diff --git a/src/lib/gui/Logger.cpp b/src/lib/gui/Logger.cpp index d6498db1c..be9239f32 100644 --- a/src/lib/gui/Logger.cpp +++ b/src/lib/gui/Logger.cpp @@ -53,7 +53,7 @@ QString printLine(FILE *out, const QString &type, const QString &message, const // stdout/stderr and Windows debug output all expect a terminated line. QString terminatedLogLine = logLine; QTextStream terminatedStream(&terminatedLogLine); - terminatedStream << Qt::endl; + terminatedStream << '\n'; #if defined(Q_OS_WIN) // Debug output is viewable using either VS Code, Visual Studio, DebugView, or diff --git a/src/lib/gui/config/Screen.cpp b/src/lib/gui/config/Screen.cpp index f19899064..d2882a3b8 100644 --- a/src/lib/gui/config/Screen.cpp +++ b/src/lib/gui/config/Screen.cpp @@ -92,24 +92,24 @@ void Screen::saveSettings(QSettingsProxy &settings) const QTextStream &Screen::writeScreensSection(QTextStream &outStream) const { - outStream << "\t" << name() << ":" << Qt::endl; + outStream << "\t" << name() << ":" << '\n'; for (int i = 0; i < modifiers().size(); i++) if (modifier(i) != i) - outStream << "\t\t" << modifierName(i) << " = " << modifierName(modifier(i)) << Qt::endl; + outStream << "\t\t" << modifierName(i) << " = " << modifierName(modifier(i)) << '\n'; for (int i = 0; i < fixes().size(); i++) - outStream << "\t\t" << fixName(i) << " = " << (fixes()[i] ? "true" : "false") << Qt::endl; + outStream << "\t\t" << fixName(i) << " = " << (fixes()[i] ? "true" : "false") << '\n'; outStream << "\t\t" << "switchCorners = none "; for (int i = 0; i < switchCorners().size(); i++) if (switchCorners()[i]) outStream << "+" << switchCornerName(i) << " "; - outStream << Qt::endl; + outStream << '\n'; outStream << "\t\t" - << "switchCornerSize = " << switchCornerSize() << Qt::endl; + << "switchCornerSize = " << switchCornerSize() << '\n'; return outStream; } @@ -117,10 +117,10 @@ QTextStream &Screen::writeScreensSection(QTextStream &outStream) const QTextStream &Screen::writeAliasesSection(QTextStream &outStream) const { if (!aliases().isEmpty()) { - outStream << "\t" << name() << ":" << Qt::endl; + outStream << "\t" << name() << ":" << '\n'; foreach (const QString &alias, aliases()) - outStream << "\t\t" << alias << Qt::endl; + outStream << "\t\t" << alias << '\n'; } return outStream; diff --git a/src/test/integtests/gui/dotenv_tests.cpp b/src/test/integtests/gui/dotenv_tests.cpp index fd1d8165e..acd3a278e 100644 --- a/src/test/integtests/gui/dotenv_tests.cpp +++ b/src/test/integtests/gui/dotenv_tests.cpp @@ -45,9 +45,9 @@ TEST(dotenv_tests, dotenv_envFileWithEntry_loadsEnvVar) const QString entry = key + " = " + value; QTextStream out(&file); - out << " # Comment" << Qt::endl; - out << "FOOBAR" << Qt::endl; - out << entry << Qt::endl; + out << " # Comment" << '\n'; + out << "FOOBAR" << '\n'; + out << entry << '\n'; file.close(); deskflow::gui::dotenv(envFile); From 4d6e1591de51a02314389044e4ebf49492fce0aa Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Wed, 17 Jun 2026 11:38:11 +0100 Subject: [PATCH 13/14] Add conditional view option methods for Qt 6 compatibility in ScreenSetupView --- src/gui/src/ScreenSetupView.cpp | 14 +++++++++++++- src/gui/src/ScreenSetupView.h | 4 ++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/gui/src/ScreenSetupView.cpp b/src/gui/src/ScreenSetupView.cpp index d7a283202..8a7dc993f 100644 --- a/src/gui/src/ScreenSetupView.cpp +++ b/src/gui/src/ScreenSetupView.cpp @@ -145,10 +145,22 @@ void ScreenSetupView::startDrag(Qt::DropActions) } } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) void ScreenSetupView::initViewItemOption(QStyleOptionViewItem *option) const { option->showDecorationSelected = true; option->decorationPosition = QStyleOptionViewItem::Top; option->displayAlignment = Qt::AlignCenter; option->textElideMode = Qt::ElideMiddle; -} \ No newline at end of file +} +#else +QStyleOptionViewItem ScreenSetupView::viewOptions() const +{ + QStyleOptionViewItem option = QTableView::viewOptions(); + option.showDecorationSelected = true; + option.decorationPosition = QStyleOptionViewItem::Top; + option.displayAlignment = Qt::AlignCenter; + option.textElideMode = Qt::ElideMiddle; + return option; +} +#endif \ No newline at end of file diff --git a/src/gui/src/ScreenSetupView.h b/src/gui/src/ScreenSetupView.h index 10f672a60..7dcbcd3af 100644 --- a/src/gui/src/ScreenSetupView.h +++ b/src/gui/src/ScreenSetupView.h @@ -47,7 +47,11 @@ class ScreenSetupView : public QTableView void dragEnterEvent(QDragEnterEvent *event) override; void dragMoveEvent(QDragMoveEvent *event) override; void startDrag(Qt::DropActions supportedActions) override; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) void initViewItemOption(QStyleOptionViewItem *option) const override; +#else + QStyleOptionViewItem viewOptions() const override; +#endif void scrollTo(const QModelIndex &, ScrollHint) override { } From 83466bce483f54ddafb5735763820eaca6fc08eb Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Wed, 17 Jun 2026 11:58:06 +0100 Subject: [PATCH 14/14] Fix dragMoveEvent to support Qt 6 position handling --- src/gui/src/ScreenSetupView.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gui/src/ScreenSetupView.cpp b/src/gui/src/ScreenSetupView.cpp index 8a7dc993f..2f9aca9d4 100644 --- a/src/gui/src/ScreenSetupView.cpp +++ b/src/gui/src/ScreenSetupView.cpp @@ -99,7 +99,11 @@ void ScreenSetupView::dragMoveEvent(QDragMoveEvent *event) event->setDropAction(Qt::MoveAction); event->accept(); } else { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) const auto &point = event->position().toPoint(); +#else + const auto &point = event->pos(); +#endif int col = columnAt(point.x()); int row = rowAt(point.y());