Compare commits
258 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f781ac9855 | |||
| d6087cc5bd | |||
| 6e9694b5d8 | |||
| 201df59cb7 | |||
| bcfc77fde6 | |||
| 245a522188 | |||
| fdf1df1a30 | |||
| 84b433853a | |||
| e225a357fd | |||
| 54fac87ed2 | |||
| 56a665cd18 | |||
| cb8c6fe9d9 | |||
| 239a265e18 | |||
| ee53d28af7 | |||
| 91fd139a49 | |||
| 7f1a234d06 | |||
| db20c4b0c7 | |||
| 7bd3fc1eb5 | |||
| 8fde0d764e | |||
| e1eb4ebf98 | |||
| 4b06160f84 | |||
| 2160f7826f | |||
| 7f6a68bb2f | |||
| 95521c53d6 | |||
| 446847f4fb | |||
| 37bc70896b | |||
| f9c8d08ff7 | |||
| 55c611f754 | |||
| 541e30f406 | |||
| 4b24b5b38d | |||
| df8500178b | |||
| 378fdae140 | |||
| 31e95ad2dc | |||
| 8b5a61f07f | |||
| 516f803eb4 | |||
| c1a7b836ce | |||
| 9530b9c6ba | |||
| 9df2a2c28d | |||
| 133545d03f | |||
| 75e852d95f | |||
| 9c44653fff | |||
| 2adee7c460 | |||
| 6f6e9cddb7 | |||
| fdd9b1bb6d | |||
| b2ff6aa938 | |||
| 5e4188b2fe | |||
| a3875bf71c | |||
| f3930d9520 | |||
| f66a50dab7 | |||
| 68ebc88293 | |||
| 83c8d295d4 | |||
| 07219ed431 | |||
| da5f3c0be1 | |||
| a23e35c522 | |||
| eb74d8ca99 | |||
| 65b6fe7ca3 | |||
| 9b6615328b | |||
| 7fb87b32f5 | |||
| 8508805f5d | |||
| 385a610da2 | |||
| e00058a332 | |||
| 45b6ff19e7 | |||
| 1798d7e4e6 | |||
| 854787e6b3 | |||
| 498ffe85c3 | |||
| cd3f9b2e7d | |||
| 42b16efdb9 | |||
| 003f87db9e | |||
| 86dca27e4c | |||
| 26fa6860e4 | |||
| d9798a9b2b | |||
| 70a2554370 | |||
| 13c325eb3f | |||
| a3ad66dfb0 | |||
| c9d1a50bb0 | |||
| cb3e516206 | |||
| de2e3fb9ce | |||
| 3bad718bb7 | |||
| 40c10766f3 | |||
| bf09df835d | |||
| 4a16804d27 | |||
| 5e1aa9eb5d | |||
| 3c86d9dc83 | |||
| 099262d8ce | |||
| d9e6ec4b70 | |||
| d7b20fad5c | |||
| 6e6a88af87 | |||
| ce17167248 | |||
| 656ad6402b | |||
| 329742a411 | |||
| 4df982dd6f | |||
| b1010751ba | |||
| 4238441018 | |||
| a13bd3d0bd | |||
| 516e612282 | |||
| bfd4bbd8f4 | |||
| 1c4ec6ec41 | |||
| 2ef23b8206 | |||
| ecf70f09f3 | |||
| 397c652e1c | |||
| 1666a30b94 | |||
| 827d020d16 | |||
| 0138372871 | |||
| 9e78cb55aa | |||
| 38cc678ad2 | |||
| e624e6f174 | |||
| 96b50b7d1c | |||
| ffbe2cf885 | |||
| b1b8720781 | |||
| 8609cbc20a | |||
| 7fe862b715 | |||
| 377272e917 | |||
| b051c5ae60 | |||
| 38f00da704 | |||
| dcd2c62880 | |||
| b7f29d76c3 | |||
| 55601debe0 | |||
| 6c8eca6c41 | |||
| 6444e2c208 | |||
| b3ce7c41d3 | |||
| 6963c28219 | |||
| 99ed548495 | |||
| d37bda6edb | |||
| 73de5e964e | |||
| 27451d3425 | |||
| 613f3651ea | |||
| 0e3cee6287 | |||
| 6056e5850b | |||
| 1b01a010ed | |||
| 7faf76c7df | |||
| 55f513941b | |||
| 9e74100960 | |||
| 531b988dd1 | |||
| 5647121dd8 | |||
| c1af4c3b71 | |||
| dd895ed99f | |||
| 7771dcd04c | |||
| d537a23fda | |||
| f7b98465fa | |||
| ed1bf01306 | |||
| 80f814a2da | |||
| 5355c9080b | |||
| 16517ca541 | |||
| e8ea9f53ee | |||
| 7da8c54924 | |||
| 3683db0db9 | |||
| cd0aa6496a | |||
| c583252b03 | |||
| 2c433eddd7 | |||
| 5ee39c9b00 | |||
| c1642b8d9d | |||
| f2c16c4432 | |||
| 37b4e4b57f | |||
| b502a6b848 | |||
| fe0ddf85e4 | |||
| 6990477504 | |||
| e05b35dda4 | |||
| f50e4e850b | |||
| 3cd3d7b1ff | |||
| 5a7284fd6a | |||
| 362b2e1477 | |||
| 7bf716b232 | |||
| 554178b658 | |||
| af17b14224 | |||
| 1e9f92c93f | |||
| 8bb325a2d2 | |||
| 8606dc8618 | |||
| 6362948e15 | |||
| 085a70d5a5 | |||
| 93abf4217b | |||
| 88b0a7d2e1 | |||
| 5fa70d0d0a | |||
| d01c07cab8 | |||
| 6834862413 | |||
| 4273fe2318 | |||
| 266a4a5edf | |||
| 5e6381c88a | |||
| 9aa1d6b79d | |||
| d45d6baacb | |||
| a887ac066c | |||
| 787a48424e | |||
| b20d6361d6 | |||
| b833ca7a45 | |||
| 43eab1f04c | |||
| dc9e104f8c | |||
| f456aab196 | |||
| de3b9d8e2e | |||
| b7960eecb4 | |||
| 03f142977f | |||
| 5360fb3c89 | |||
| 4eb7ea3491 | |||
| 5642879a21 | |||
| 737328d7b0 | |||
| bee0f84556 | |||
| 2721de220a | |||
| 4c6195cc5d | |||
| 1e46bd2727 | |||
| 54ecdad101 | |||
| 51a749b109 | |||
| 788f6c3eb2 | |||
| e01c595071 | |||
| bcd90434a2 | |||
| 698fd3f83c | |||
| 2a53d4f187 | |||
| 53487e757b | |||
| ef315183f3 | |||
| 8b1e8dfd9f | |||
| b73aceee7d | |||
| 3b811a1bd0 | |||
| a099276e4e | |||
| 38f8159e9d | |||
| 87fb06781c | |||
| b9017de881 | |||
| 24d1d4e620 | |||
| 3bcc1e11ed | |||
| d26c75a784 | |||
| 5b091dee56 | |||
| 3344644d2e | |||
| 39e7f60c5a | |||
| 57d1e42eca | |||
| cd45164e40 | |||
| 0ed583a7fe | |||
| 751c869435 | |||
| 4cfeadf0be | |||
| 402baf3bde | |||
| d199130b43 | |||
| 758c1044b5 | |||
| 6e8952c8a0 | |||
| bb38ad0766 | |||
| bc96ddebdd | |||
| 80606ef040 | |||
| 836d9b9a2b | |||
| f2063f9e05 | |||
| a74d792b5b | |||
| 256ba2411b | |||
| 0a23e62093 | |||
| e38a8e6b15 | |||
| 6f022ff700 | |||
| 265c2c2a2c | |||
| 1594b8e760 | |||
| 029cb8fc0b | |||
| 8e236e7e5c | |||
| 38b2798bb7 | |||
| d580dfba57 | |||
| da4237f349 | |||
| a78d1acc71 | |||
| 24d5b26da2 | |||
| 9c81f1c045 | |||
| 899a49d09a | |||
| 3a4bf35e22 | |||
| 495331108b | |||
| a7ce936d68 | |||
| f6ccd2a25b | |||
| 5d310be807 | |||
| bd674f546b | |||
| cc821f750d | |||
| 2485e993a4 | |||
| b5d12b8aa5 |
20
.github/actions/install-dependencies/action.yml
vendored
20
.github/actions/install-dependencies/action.yml
vendored
@ -37,30 +37,26 @@ runs:
|
||||
apt update -qqq > /dev/null
|
||||
apt install -qqq cmake build-essential ninja-build \
|
||||
xorg-dev libx11-dev libxtst-dev libssl-dev \
|
||||
libglib2.0-dev libgdk-pixbuf-2.0-dev libnotify-dev \
|
||||
libxkbfile-dev qt6-base-dev qt6-tools-dev \
|
||||
libgtk-3-dev libgtest-dev libgmock-dev libpugixml-dev \
|
||||
libglib2.0-dev libxkbfile-dev qt6-base-dev qt6-tools-dev \
|
||||
libgtk-3-dev libgtest-dev libgmock-dev \
|
||||
libei-dev libportal-dev libtomlplusplus-dev libcli11-dev -y >/dev/null
|
||||
elif [ ${{inputs.like}} == "fedora" ]; then
|
||||
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 gtest-devel gmock-devel pugixml-devel \
|
||||
libXtst-devel libxkbfile-devel qt6-qtbase-devel qt6-qttools-devel \
|
||||
gtk3-devel gtest-devel gmock-devel \
|
||||
libei-devel libportal-devel tomlplusplus-devel \
|
||||
cli11-devel
|
||||
elif [ ${{inputs.like}} == "suse" ]; then
|
||||
zypper refresh
|
||||
zypper install -y --force-resolution \
|
||||
cmake make ninja gcc-c++ rpm-build libopenssl-devel \
|
||||
glib2-devel gdk-pixbuf-devel libXtst-devel libnotify-devel \
|
||||
libxkbfile-devel qt6-base-devel qt6-tools-devel gtk3-devel \
|
||||
googletest-devel googlemock-devel pugixml-devel libei-devel \
|
||||
glib2-devel libXtst-devel libxkbfile-devel qt6-base-devel qt6-tools-devel gtk3-devel \
|
||||
googletest-devel googlemock-devel libei-devel \
|
||||
libportal-devel tomlplusplus-devel cli11-devel
|
||||
elif [ ${{ inputs.like }} == "arch" ]; then
|
||||
pacman -Syu --noconfirm base-devel cmake ninja \
|
||||
gcc openssl glib2 gdk-pixbuf2 libxtst libnotify \
|
||||
libxkbfile gtest pugixml libei libportal \
|
||||
gcc openssl glib2 libxtst libxkbfile gtest libei libportal \
|
||||
qt6-base qt6-tools gtk3 tomlplusplus cli11
|
||||
else
|
||||
echo "Unknown like"
|
||||
@ -91,7 +87,7 @@ runs:
|
||||
id: vcpkg
|
||||
uses: johnwason/vcpkg-action@v6
|
||||
with:
|
||||
pkgs: wintoast gtest pkgconf openssl
|
||||
pkgs: gtest openssl
|
||||
extra-args: --classic
|
||||
triplet: x64-windows-release
|
||||
token: ${{ github.token }}
|
||||
|
||||
2
.github/actions/lint-check/action.yml
vendored
2
.github/actions/lint-check/action.yml
vendored
@ -5,7 +5,7 @@ runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Install Dependencies
|
||||
run: pipx install --global clang_format
|
||||
run: pipx install --global clang-format==20.1.0
|
||||
shell: bash
|
||||
|
||||
- name: Run format command
|
||||
|
||||
@ -18,7 +18,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# Fallback for when git can not be found
|
||||
set(DESKFLOW_VERSION_MAJOR 1)
|
||||
set(DESKFLOW_VERSION_MINOR 20)
|
||||
set(DESKFLOW_VERSION_MINOR 21)
|
||||
set(DESKFLOW_VERSION_PATCH 0)
|
||||
set(DESKFLOW_VERSION_TWEAK 0)
|
||||
|
||||
@ -95,6 +95,22 @@ set(REQUIRED_LIBEI_VERSION 1.3)
|
||||
set(REQUIRED_LIBPORTAL_VERSION 0.8)
|
||||
set(REQUIRED_QT_VERSION 6.7.0)
|
||||
|
||||
if (MSVC)
|
||||
# On Windows, require that the same MSVC runtime is used as on the host.
|
||||
# Mitigates things like access violations caused by accidental ABI-compatibility breakage.
|
||||
set(REQUIRED_MSVC_RUNTIME_MAJOR 14)
|
||||
cmake_host_system_information(
|
||||
RESULT REQUIRED_MSVC_RUNTIME_MINOR
|
||||
QUERY WINDOWS_REGISTRY
|
||||
"HKLM/SOFTWARE/Microsoft/VisualStudio/${REQUIRED_MSVC_RUNTIME_MAJOR}.0/VC/Runtimes/x64"
|
||||
VALUE "Minor")
|
||||
if (REQUIRED_MSVC_RUNTIME_MINOR)
|
||||
message(STATUS "MSVC runtime: ${REQUIRED_MSVC_RUNTIME_MAJOR}.${REQUIRED_MSVC_RUNTIME_MINOR}")
|
||||
else()
|
||||
message(FATAL_ERROR "MSVC runtime registry entry not found")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Control debug item visibility
|
||||
# When not set logging is forced to DEBUG and show code locations
|
||||
# Also exposes a test menu
|
||||
|
||||
@ -1,61 +0,0 @@
|
||||
MICROSOFT SOFTWARE LICENSE TERMS
|
||||
|
||||
MICROSOFT VISUAL C++ 2015 - 2022 RUNTIME
|
||||
|
||||
These license terms are an agreement between Microsoft Corporation (or based on where you live, one of its affiliates) and you. They apply to the software named above. The terms also apply to any Microsoft services or updates for the software, except to the extent those have different terms.
|
||||
|
||||
IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE RIGHTS BELOW.
|
||||
|
||||
1. INSTALLATION AND USE RIGHTS.
|
||||
|
||||
You may install and use any number of copies of the software.
|
||||
|
||||
2. TERMS FOR SPECIFIC COMPONENTS.
|
||||
|
||||
a. Microsoft Platforms. The software may include components from Microsoft Windows; Microsoft Windows Server; Microsoft SQL Server; Microsoft Exchange; Microsoft Office; and Microsoft SharePoint. These components are governed by separate agreements and their own product support policies, as described in the Microsoft “Licenses” folder accompanying the software, except that, if license terms for those components are also included in the associated installation directory, those license terms control.
|
||||
|
||||
b. Third Party Components. The software may include third party components with separate legal notices or governed by other agreements, as may be described in the notices file(s) accompanying the software.
|
||||
|
||||
3. SCOPE OF LICENSE. The software is licensed, not sold. This agreement only gives you some rights to use the software. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you may use the software only as expressly permitted in this agreement. In doing so, you must comply with any technical limitations in the software that only allow you to use it in certain ways. You may not
|
||||
|
||||
· work around any technical limitations in the software;
|
||||
|
||||
· reverse engineer, decompile or disassemble the software, or otherwise attempt to derive the source code for the software except, and only to the extent required by third party licensing terms governing the use of certain open source components that may be included in the software;
|
||||
|
||||
· remove, minimize, block or modify any notices of Microsoft or its suppliers in the software;
|
||||
|
||||
· use the software in any way that is against the law;
|
||||
|
||||
· share, publish, rent or lease the software; or
|
||||
|
||||
· provide the software as a stand-alone offering or combined with any of your applications for others to use, or transfer the software or this agreement to any third party.
|
||||
|
||||
4. EXPORT RESTRICTIONS. You must comply with all domestic and international export laws and regulations that apply to the software, which include restrictions on destinations, end users, and end use. For further information on export restrictions, visit www.microsoft.com/exporting.
|
||||
|
||||
5. SUPPORT SERVICES. Because this software is “as is,” we may not provide support services for it.
|
||||
|
||||
6. ENTIRE AGREEMENT. This agreement, and the terms for supplements, updates, Internet-based services and support services that you use, are the entire agreement for the software and support services.
|
||||
|
||||
7. APPLICABLE LAW. If you acquired the software in the United States, Washington law applies to interpretation of and claims for breach of this agreement, and the laws of the state where you live apply to all other claims. If you acquired the software in any other country, its laws apply.
|
||||
|
||||
8. CONSUMER RIGHTS; REGIONAL VARIATIONS. This agreement describes certain legal rights. You may have other rights, including consumer rights, under the laws of your state or country. Separate and apart from your relationship with Microsoft, you may also have rights with respect to the party from which you acquired the software. This agreement does not change those other rights if the laws of your state or country do not permit it to do so. For example, if you acquired the software in one of the below regions, or mandatory country law applies, then the following provisions apply to you:
|
||||
|
||||
a. Australia. You have statutory guarantees under the Australian Consumer Law and nothing in this agreement is intended to affect those rights.
|
||||
|
||||
b. Canada. If you acquired this software in Canada, you may stop receiving updates by turning off the automatic update feature, disconnecting your device from the Internet (if and when you re-connect to the Internet, however, the software will resume checking for and installing updates), or uninstalling the software. The product documentation, if any, may also specify how to turn off updates for your specific device or software.
|
||||
|
||||
c. Germany and Austria.
|
||||
|
||||
(i) Warranty. The properly licensed software will perform substantially as described in any Microsoft materials that accompany the software. However, Microsoft gives no contractual guarantee in relation to the licensed software.
|
||||
|
||||
(ii) Limitation of Liability. In case of intentional conduct, gross negligence, claims based on the Product Liability Act, as well as, in case of death or personal or physical injury, Microsoft is liable according to the statutory law.
|
||||
|
||||
Subject to the foregoing clause (ii), Microsoft will only be liable for slight negligence if Microsoft is in breach of such material contractual obligations, the fulfillment of which facilitate the due performance of this agreement, the breach of which would endanger the purpose of this agreement and the compliance with which a party may constantly trust in (so-called "cardinal obligations"). In other cases of slight negligence, Microsoft will not be liable for slight negligence.
|
||||
|
||||
9. DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED “AS-IS.” YOU BEAR THE RISK OF USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES OR CONDITIONS. TO THE EXTENT PERMITTED UNDER YOUR LOCAL LAWS, MICROSOFT EXCLUDES THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
|
||||
10. LIMITATION ON AND EXCLUSION OF DAMAGES. YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES.
|
||||
|
||||
This limitation applies to (a) anything related to the software, services, content (including code) on third party Internet sites, or third party applications; and (b) claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law.
|
||||
|
||||
It also applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your country may not allow the exclusion or limitation of incidental, consequential or other damages.
|
||||
@ -64,7 +64,12 @@ For instructions on building Deskflow, use the wiki page: [Building](https://git
|
||||
|
||||
We support all major operating systems, including Windows, macOS, Linux, and Unix-like BSD-derived.
|
||||
|
||||
Windows 10 or higher is required.
|
||||
> [!NOTE]
|
||||
> On Windows, you will need to install the
|
||||
> [Microsoft Visual C++ Redistributable](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170#latest-microsoft-visual-c-redistributable-version).
|
||||
> Download latest: [`vc_redist.x64.exe`](https://aka.ms/vs/17/release/vc_redist.x64.exe)
|
||||
|
||||
Windows 10 or higher is required.
|
||||
|
||||
macOS 12 or higher is required.
|
||||
|
||||
|
||||
@ -127,12 +127,6 @@ precedence = "override"
|
||||
SPDX-FileCopyrightText = "Deskflow Developers"
|
||||
SPDX-License-Identifier = "MIT"
|
||||
|
||||
[[annotations]]
|
||||
path = "deploy/windows/Microsoft_VC142_CRT_x64.msm"
|
||||
precedence = "override"
|
||||
SPDX-FileCopyrightText = "Microsoft"
|
||||
SPDX-License-Identifier = "LicenseRef-Microsoft-vc-redist"
|
||||
|
||||
[[annotations]]
|
||||
path = "src/apps/deskflow-client/deskflow-client.exe.manifest"
|
||||
precedence = "override"
|
||||
|
||||
@ -8,10 +8,9 @@ macro(configure_libs)
|
||||
if(UNIX)
|
||||
configure_unix_libs()
|
||||
elseif(WIN32)
|
||||
find_package(Python REQUIRED QUIET)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /D _BIND_TO_CURRENT_VCLIBS_VERSION=1")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD /O2 /Ob2")
|
||||
list(APPEND libs Wtsapi32 Userenv Wininet comsuppw Shlwapi)
|
||||
list(APPEND libs Wtsapi32 Userenv Wininet comsuppw Shlwapi version)
|
||||
add_definitions(
|
||||
/DWIN32
|
||||
/D_WINDOWS
|
||||
@ -21,6 +20,9 @@ macro(configure_libs)
|
||||
endif()
|
||||
|
||||
find_package(Qt6 ${REQUIRED_QT_VERSION} REQUIRED COMPONENTS Core Widgets Network)
|
||||
if(UNIX AND NOT APPLE)
|
||||
find_package(Qt6 ${REQUIRED_QT_VERSION} REQUIRED COMPONENTS DBus Xml)
|
||||
endif()
|
||||
|
||||
# Define the location of Qt deployment tool
|
||||
if(WIN32)
|
||||
@ -33,19 +35,12 @@ macro(configure_libs)
|
||||
find_program(DEPLOYQT macdeployqt)
|
||||
endif()
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
message(STATUS "Qt version: ${Qt6_VERSION}")
|
||||
|
||||
# TODO SSL check can happen in lib/net when don't have to deploy it any longer on windows
|
||||
|
||||
# Apple has to use static libraries because "Use of the Apple-provided OpenSSL
|
||||
# libraries by apps is strongly discouraged."
|
||||
# https://developer.apple.com/library/archive/documentation/Security/Conceptual/cryptoservices/SecureNetworkCommunicationAPIs/SecureNetworkCommunicationAPIs.html
|
||||
if(APPLE)
|
||||
set(OPENSSL_USE_STATIC_LIBS TRUE)
|
||||
endif()
|
||||
|
||||
find_package(OpenSSL ${REQUIRED_OPENSSL_VERSION} REQUIRED COMPONENTS SSL Crypto)
|
||||
|
||||
option(ENABLE_COVERAGE "Enable test coverage" OFF)
|
||||
if(ENABLE_COVERAGE)
|
||||
message(STATUS "Enabling code coverage")
|
||||
@ -94,20 +89,11 @@ macro(configure_unix_libs)
|
||||
include(CheckSymbolExists)
|
||||
include(CheckCSourceCompiles)
|
||||
|
||||
check_include_file_cxx(istream HAVE_ISTREAM)
|
||||
check_include_file_cxx(ostream HAVE_OSTREAM)
|
||||
check_include_file_cxx(sstream HAVE_SSTREAM)
|
||||
|
||||
check_include_files(locale.h HAVE_LOCALE_H)
|
||||
check_include_files(sys/select.h HAVE_SYS_SELECT_H)
|
||||
check_include_files(sys/socket.h HAVE_SYS_SOCKET_H)
|
||||
check_include_files(sys/time.h HAVE_SYS_TIME_H)
|
||||
check_include_files(sys/utsname.h HAVE_SYS_UTSNAME_H)
|
||||
check_include_files(unistd.h HAVE_UNISTD_H)
|
||||
check_include_files(wchar.h HAVE_WCHAR_H)
|
||||
|
||||
check_function_exists(getpwuid_r HAVE_GETPWUID_R)
|
||||
check_function_exists(gmtime_r HAVE_GMTIME_R)
|
||||
check_function_exists(nanosleep HAVE_NANOSLEEP)
|
||||
check_function_exists(sigwait HAVE_POSIX_SIGWAIT)
|
||||
check_function_exists(inet_aton HAVE_INET_ATON)
|
||||
@ -163,34 +149,16 @@ macro(configure_unix_libs)
|
||||
configure_xorg_libs()
|
||||
|
||||
include(FindPkgConfig)
|
||||
|
||||
find_package(PkgConfig)
|
||||
if(PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(LIBXKBCOMMON REQUIRED xkbcommon)
|
||||
pkg_check_modules(GLIB2 REQUIRED glib-2.0 gio-2.0)
|
||||
pkg_check_modules(GLIB2 REQUIRED glib-2.0)
|
||||
find_library(LIBM m)
|
||||
include_directories(${LIBXKBCOMMON_INCLUDE_DIRS} ${GLIB2_INCLUDE_DIRS}
|
||||
${LIBM_INCLUDE_DIRS})
|
||||
else()
|
||||
message(WARNING "pkg-config not found, skipping wayland libraries")
|
||||
endif()
|
||||
|
||||
|
||||
find_package(pugixml REQUIRED)
|
||||
|
||||
find_package(PkgConfig)
|
||||
if(PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(lib_glib REQUIRED IMPORTED_TARGET glib-2.0)
|
||||
pkg_search_module(PC_GDKPIXBUF gdk-pixbuf-2.0)
|
||||
|
||||
include_directories(${PC_GDKPIXBUF_INCLUDE_DIRS})
|
||||
|
||||
pkg_check_modules(lib_gdkpixbuf REQUIRED IMPORTED_TARGET gdk-pixbuf-2.0)
|
||||
pkg_check_modules(lib_notify REQUIRED IMPORTED_TARGET libnotify)
|
||||
|
||||
add_definitions(-DHAVE_GDK_PIXBUF=1 -DHAVE_LIBNOTIFY=1)
|
||||
else()
|
||||
message(WARNING "pkg-config not found, skipping libnotify and gdk-pixbuf")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# For config.h, set some static values; it may be a good idea to make these
|
||||
@ -205,8 +173,8 @@ macro(configure_unix_libs)
|
||||
# Unix only: For config.h, save the results based on a template (config.h.in).
|
||||
# Note that this won't work on Windows because filenames are not case sensitive,
|
||||
# and we have header files named "Config.h" (upper case 'C').
|
||||
configure_file(${CMAKE_SOURCE_DIR}/src/lib/config.h.in
|
||||
${CMAKE_BINARY_DIR}/src/lib/config.h @ONLY)
|
||||
configure_file(${CMAKE_SOURCE_DIR}/src/lib/Config.h.in
|
||||
${CMAKE_BINARY_DIR}/src/lib/Config.h @ONLY)
|
||||
|
||||
add_definitions(-DSYSAPI_UNIX=1 -DHAVE_CONFIG_H)
|
||||
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
"Hadzhylov",
|
||||
"Hetu",
|
||||
"HINSTANCE",
|
||||
"HKLM",
|
||||
"hotspots",
|
||||
"Hutterer",
|
||||
"ifdef",
|
||||
@ -65,6 +66,7 @@
|
||||
"qobject",
|
||||
"qputenv",
|
||||
"readf",
|
||||
"Redist",
|
||||
"Regen",
|
||||
"Repology",
|
||||
"Rizzitello",
|
||||
|
||||
@ -22,9 +22,7 @@ depends=(
|
||||
'libxtst'
|
||||
'libxinerama'
|
||||
'libxkbcommon-x11'
|
||||
'libnotify'
|
||||
'hicolor-icon-theme'
|
||||
'pugixml'
|
||||
'qt6-base'
|
||||
'qt6-tools'
|
||||
'libei'
|
||||
|
||||
@ -23,17 +23,6 @@ cleanup:
|
||||
- /share/gir-1.0
|
||||
- /lib/girepository-1.0
|
||||
modules:
|
||||
- name: python3-attrs
|
||||
buildsystem: simple
|
||||
build-commands:
|
||||
- pip3 install --verbose --exists-action=i --no-index --find-links="file://${PWD}"
|
||||
--prefix=${FLATPAK_DEST} --no-build-isolation attrs
|
||||
sources:
|
||||
- type: file
|
||||
url: https://files.pythonhosted.org/packages/e0/44/827b2a91a5816512fcaf3cc4ebc465ccd5d598c45cefa6703fcf4a79018f/attrs-23.2.0-py3-none-any.whl
|
||||
sha256: 99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1
|
||||
cleanup:
|
||||
- '*'
|
||||
- name: python3-Jinja2
|
||||
buildsystem: simple
|
||||
build-commands:
|
||||
@ -57,8 +46,8 @@ modules:
|
||||
sources:
|
||||
- type: git
|
||||
url: https://gitlab.freedesktop.org/libinput/libei
|
||||
tag: 1.3.0
|
||||
commit: 997b7c0f37faea4f8bae59613c8f27370925d5b0
|
||||
tag: 1.4.0
|
||||
commit: 5d6d8e6590df210b75559a889baa9459c68d9366
|
||||
- name: libportal
|
||||
buildsystem: meson
|
||||
config-opts:
|
||||
@ -70,15 +59,8 @@ modules:
|
||||
sources:
|
||||
- type: git
|
||||
url: https://github.com/flatpak/libportal.git
|
||||
tag: 0.8.1
|
||||
commit: 26c15008cbe579f57f89468384f8efc033f25f6f
|
||||
- name: puixml
|
||||
buildsystem: cmake-ninja
|
||||
sources:
|
||||
- type: git
|
||||
url: https://github.com/zeux/pugixml
|
||||
tag: v1.14
|
||||
commit: db78afc2b7d8f043b4bc6b185635d949ea2ed2a8
|
||||
tag: 0.9.1
|
||||
commit: 8f5dc8d192f6e31dafe69e35219e3b707bde71ce
|
||||
- name: cli11
|
||||
buildsystem: cmake-ninja
|
||||
config-opts:
|
||||
|
||||
@ -42,7 +42,33 @@
|
||||
</branding>
|
||||
<content_rating type="oars-1.0" />
|
||||
<releases>
|
||||
<release version="1.20.0" date="2025-3-03" urgency="high">
|
||||
<release version="1.21.0" date="2025-03-27" urgency="high">
|
||||
<description>
|
||||
<p>This stable release removes some dependencies, additionally fixes several bugs. For the full changelog see the release page.</p>
|
||||
<ul>
|
||||
<li>Cleanup unused classes</li>
|
||||
<li>New Settings class</li>
|
||||
<li>Remove need for pugixml</li>
|
||||
<li>Remove need for libNotify</li>
|
||||
<li>Remove need for gio</li>
|
||||
<li>Remove need for gitkpixbuf</li>
|
||||
<li>Fix issues with windows installer when msvc is missing</li>
|
||||
</ul>
|
||||
</description>
|
||||
<url>https://github.com/deskflow/deskflow/releases/tag/v1.21.0</url>
|
||||
</release>
|
||||
<release version="1.20.1" date="2025-03-07" urgency="low">
|
||||
<description>
|
||||
<p>This stable release introduces a Windows dependency requirement and fixes a macOS bug.</p>
|
||||
<ul>
|
||||
<li>Fix: macOS menu bar icon invisible when menu bar is light</li>
|
||||
<li>Feature: Add Windows installer check for Visual C++ Redistributable</li>
|
||||
<li>Feature: Prevent Windows binaries running if MSVC runtime too old</li>
|
||||
</ul>
|
||||
</description>
|
||||
<url>https://github.com/deskflow/deskflow/releases/tag/v1.20.1</url>
|
||||
</release>
|
||||
<release version="1.20.0" date="2025-03-03" urgency="high">
|
||||
<description>
|
||||
<p>This stable release fixes a few security issues, additionally fixes several bugs and adds a few new features. For the full changelog see the release page.</p>
|
||||
<ul>
|
||||
@ -56,9 +82,9 @@
|
||||
<li>Win32: Fix clear settings</li>
|
||||
</ul>
|
||||
</description>
|
||||
<url>https://github.com/deskflow/deskflow/releases/tag/v1.20.0</url>
|
||||
<url>https://github.com/deskflow/deskflow/releases/tag/v1.20.0</url>
|
||||
</release>
|
||||
<release version="1.19.0" date="2025-1-31" urgency="high">
|
||||
<release version="1.19.0" date="2025-01-31" urgency="high">
|
||||
<description>
|
||||
<p>This stable release fixes several bugs and adds a few new features. For the full changelog see the release page.</p>
|
||||
<ul>
|
||||
@ -76,7 +102,7 @@
|
||||
<li>Lots of Internal Cleanup</li>
|
||||
</ul>
|
||||
</description>
|
||||
<url>https://github.com/deskflow/deskflow/releases/tag/v1.19.0</url>
|
||||
<url>https://github.com/deskflow/deskflow/releases/tag/v1.19.0</url>
|
||||
</release>
|
||||
<release version="1.18.0" date="2024-12-26" urgency="high">
|
||||
<description>
|
||||
@ -95,7 +121,7 @@
|
||||
<li>Update the windows clipboard format listener to monitor the clipboard</li>
|
||||
</ul>
|
||||
</description>
|
||||
<url>https://github.com/deskflow/deskflow/releases/tag/v1.18.0</url>
|
||||
<url>https://github.com/deskflow/deskflow/releases/tag/v1.18.0</url>
|
||||
</release>
|
||||
<release version="1.17.2" date="2024-11-20" urgency="medium">
|
||||
<description>
|
||||
@ -149,9 +175,9 @@
|
||||
<li>ci: build flatpaks</li>
|
||||
</ul>
|
||||
</description>
|
||||
<url>https://github.com/deskflow/deskflow/releases/tag/v1.17.2</url>
|
||||
<url>https://github.com/deskflow/deskflow/releases/tag/v1.17.2</url>
|
||||
</release>
|
||||
<release version="1.17.1" date="2024-11-7" urgency="high">
|
||||
<release version="1.17.1" date="2024-11-07" urgency="high">
|
||||
<description>
|
||||
<p>This stable release has a very long changelog some notable ones are.</p>
|
||||
<ul>
|
||||
@ -266,7 +292,7 @@
|
||||
<li>ci: adjust pacakge script to use the names we would like when in cpack</li>
|
||||
</ul>
|
||||
</description>
|
||||
<url>https://github.com/deskflow/deskflow/releases/tag/v1.17.1</url>
|
||||
<url>https://github.com/deskflow/deskflow/releases/tag/v1.17.1</url>
|
||||
</release>
|
||||
<release version="1.17.0" date="2024-10-02" urgency="low">
|
||||
<description>
|
||||
@ -316,7 +342,7 @@
|
||||
<li>Use sonarsource/sonarcloud-github-c-cpp</li>
|
||||
</ul>
|
||||
</description>
|
||||
<url>https://github.com/deskflow/deskflow/releases/tag/v1.17.0</url>
|
||||
<url>https://github.com/deskflow/deskflow/releases/tag/v1.17.0</url>
|
||||
</release>
|
||||
</releases>
|
||||
</component>
|
||||
|
||||
Binary file not shown.
@ -46,7 +46,6 @@ list(APPEND CPACK_WIX_EXTENSIONS "WixToolset.Util.wixext" "WixToolset.Firewall.w
|
||||
list(APPEND CPACK_WIX_CUSTOM_XMLNS "util=http://wixtoolset.org/schemas/v4/wxs/util" "firewall=http://wixtoolset.org/schemas/v4/wxs/firewall")
|
||||
|
||||
# The patch has to know the full path of our msm file
|
||||
set(CPACK_WIX_MSM_FILE "${MY_DIR}/Microsoft_VC142_CRT_x64.msm")
|
||||
configure_file(
|
||||
${MY_DIR}/wix-patch.xml.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/wix-patch.xml @ONLY
|
||||
@ -54,3 +53,18 @@ configure_file(
|
||||
|
||||
# This patch set ups filewall rules, the service and msm module
|
||||
set(CPACK_WIX_PATCH_FILE "${CMAKE_CURRENT_BINARY_DIR}/wix-patch.xml")
|
||||
|
||||
# Creates a DLL that can be used by our MSI for custom actions.
|
||||
configure_file(
|
||||
${MY_DIR}/wix-custom.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/wix-custom.h @ONLY
|
||||
)
|
||||
add_library(
|
||||
wix-custom SHARED
|
||||
${MY_DIR}/wix-custom.cpp
|
||||
)
|
||||
target_include_directories(wix-custom PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set_target_properties(wix-custom PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
)
|
||||
target_link_libraries(wix-custom PRIVATE Msi)
|
||||
|
||||
72
deploy/windows/wix-custom.cpp
Normal file
72
deploy/windows/wix-custom.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2025 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "wix-custom.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
|
||||
// Include after Windows.h
|
||||
#include <MsiQuery.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
namespace {
|
||||
// Warning: DLL will crash with error code 1603 if we exceed this.
|
||||
const auto kLogLineMax = 1024;
|
||||
|
||||
// Prefixes log messages with the app name so they're easier to find/filter.
|
||||
const std::string kLogPrefix = std::string(kAppId) + " installer: ";
|
||||
|
||||
// Note: Resized to log line max when used.
|
||||
static std::string s_logMessageBuffer; // NOSONAR - Must be mutable.
|
||||
} // namespace
|
||||
|
||||
// This log output can be viewed by using the DebugView program.
|
||||
#define MS_LOG_DEBUG(message, ...) \
|
||||
s_logMessageBuffer.resize(kLogLineMax); \
|
||||
sprintf(s_logMessageBuffer.data(), message, __VA_ARGS__); \
|
||||
OutputDebugStringA((kLogPrefix + s_logMessageBuffer + "\n").c_str())
|
||||
|
||||
extern "C" __declspec(dllexport) UINT __stdcall CheckVCRedist(MSIHANDLE hInstall)
|
||||
{
|
||||
const auto kKeyName = TEXT("SOFTWARE\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes\\x64");
|
||||
const auto kValueName = TEXT("Minor");
|
||||
const auto kProperty = "VC_REDIST_VERSION_OK";
|
||||
|
||||
MS_LOG_DEBUG("checking for msvc redist v%d.%d", kWindowsRuntimeMajor, kWindowsRuntimeMinor);
|
||||
|
||||
HKEY hKey;
|
||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, kKeyName, 0, KEY_READ, &hKey) != ERROR_SUCCESS) {
|
||||
MS_LOG_DEBUG("msvc redist registry key not found");
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
MS_LOG_DEBUG("msvc redist registry key found, querying minor version");
|
||||
|
||||
DWORD minorVersion = 0;
|
||||
DWORD size = sizeof(DWORD);
|
||||
RegQueryValueEx(hKey, kValueName, nullptr, nullptr, (LPBYTE)&minorVersion, &size);
|
||||
RegCloseKey(hKey);
|
||||
|
||||
MS_LOG_DEBUG("msvc redist minor version: %lu", minorVersion);
|
||||
|
||||
if (minorVersion < kWindowsRuntimeMinor) {
|
||||
MS_LOG_DEBUG("msvc redist minor version %lu too low, expected >= %d", minorVersion, kWindowsRuntimeMinor);
|
||||
// Returning success allows the installer will show a friendly error message.
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
MS_LOG_DEBUG("msvc redist version ok, setting: %s", kProperty);
|
||||
if (MsiSetProperty(hInstall, kProperty, "ok") != ERROR_SUCCESS) {
|
||||
MS_LOG_DEBUG("failed to set property: %s", kProperty);
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
MS_LOG_DEBUG("msvc redist version check successful");
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
14
deploy/windows/wix-custom.h.in
Normal file
14
deploy/windows/wix-custom.h.in
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2025 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
const auto kAppId = "@CMAKE_PROJECT_NAME@";
|
||||
|
||||
// clang-format off
|
||||
const auto kWindowsRuntimeMajor = @REQUIRED_MSVC_RUNTIME_MAJOR@;
|
||||
const auto kWindowsRuntimeMinor = @REQUIRED_MSVC_RUNTIME_MINOR@;
|
||||
// clang-format on
|
||||
@ -1,26 +1,73 @@
|
||||
<CPackWiXPatch>
|
||||
<CPackWiXFragment Id="CM_CP_deskflow_daemon.exe">
|
||||
<ServiceInstall Description="Controls the Deskflow foreground processes." DisplayName="Deskflow" ErrorControl="normal" Id="ServiceInstall" Name="Deskflow" Start="auto" Type="ownProcess">
|
||||
<util:ServiceConfig FirstFailureActionType="restart" ResetPeriodInDays="1" RestartServiceDelayInSeconds="1" SecondFailureActionType="restart" ThirdFailureActionType="restart"/>
|
||||
<ServiceInstall
|
||||
Id="ServiceInstall"
|
||||
Name="Deskflow"
|
||||
DisplayName="Deskflow"
|
||||
Description="Runs the Core process on secure desktops (UAC prompts, login screen, etc)."
|
||||
ErrorControl="normal"
|
||||
Start="auto"
|
||||
Type="ownProcess">
|
||||
<util:ServiceConfig
|
||||
ResetPeriodInDays="1"
|
||||
RestartServiceDelayInSeconds="1"
|
||||
FirstFailureActionType="restart"
|
||||
SecondFailureActionType="restart"
|
||||
ThirdFailureActionType="none"
|
||||
/>
|
||||
</ServiceInstall>
|
||||
<ServiceControl Id="ServiceControl" Name="Deskflow" Remove="uninstall" Start="install" Stop="both"/>
|
||||
</CPackWiXFragment>
|
||||
|
||||
<CPackWiXFragment Id="CM_CP_deskflow_server.exe">
|
||||
<firewall:FirewallException Id="ServerFirewallException" Name="Deskflow Server" Program="[INSTALL_ROOT]deskflow-server.exe" Scope="any"/>
|
||||
</CPackWiXFragment>
|
||||
|
||||
<CPackWiXFragment Id="CM_CP_deskflow_client.exe">
|
||||
<firewall:FirewallException Id="ClientFirewallException" Name="Deskflow Client" Program="[INSTALL_ROOT]deskflow-client.exe" Scope="any"/>
|
||||
</CPackWiXFragment>
|
||||
|
||||
<CPackWiXFragment Id="#PRODUCT">
|
||||
<StandardDirectory Id="TARGETDIR">
|
||||
<Merge Id="VCRedist" SourceFile="@CPACK_WIX_MSM_FILE@" DiskId="1" Language="0"/>
|
||||
</StandardDirectory >
|
||||
<Feature Id="VCRedist" Title="Visual C++ Runtime" AllowAbsent="no" AllowAdvertise="yes" Display="hidden" InstallDefault="local" TypicalDefault="install">
|
||||
<MergeRef Id="VCRedist" Primary="yes"/>
|
||||
</Feature>
|
||||
<CustomAction Id="Run_Deskflow" ExeCommand="Deskflow" FileRef="CM_FP_deskflow.exe" Return="asyncNoWait"/>
|
||||
<Property Id="VC_REDIST_INSTALLED">
|
||||
<RegistrySearch
|
||||
Id="FindVCRedist"
|
||||
Root="HKLM"
|
||||
Key="SOFTWARE\Microsoft\VisualStudio\@REQUIRED_MSVC_RUNTIME_MAJOR@.0\VC\Runtimes\x64"
|
||||
Name="Installed"
|
||||
Type="raw" />
|
||||
</Property>
|
||||
|
||||
<Binary Id="CustomDLL" SourceFile="@CMAKE_CURRENT_BINARY_DIR@/wix-custom.dll" />
|
||||
|
||||
<CustomAction
|
||||
Id="CheckVCRedist"
|
||||
BinaryRef="CustomDLL"
|
||||
DllEntry="CheckVCRedist"
|
||||
Execute="immediate" />
|
||||
|
||||
<CustomAction
|
||||
Id="ShowVCRedistError"
|
||||
Error="Microsoft Visual C++ Redistributable v@REQUIRED_MSVC_RUNTIME_MAJOR@.@REQUIRED_MSVC_RUNTIME_MINOR@ or later is required. Please download and install the latest version and then restart the installation. See our documentation for instructions." />
|
||||
|
||||
<CustomAction
|
||||
Id="RunDeskflow"
|
||||
ExeCommand="Deskflow"
|
||||
FileRef="CM_FP_deskflow.exe"
|
||||
Return="asyncNoWait" />
|
||||
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action="Run_Deskflow" OnExit="success" Condition="NOT Installed"/>
|
||||
<Custom
|
||||
Action="CheckVCRedist"
|
||||
Before="InstallInitialize"
|
||||
Condition="NOT Installed AND VC_REDIST_INSTALLED" />
|
||||
<Custom
|
||||
Action="ShowVCRedistError"
|
||||
Before="InstallInitialize"
|
||||
Condition="NOT Installed AND (NOT VC_REDIST_INSTALLED OR NOT VC_REDIST_VERSION_OK)" />
|
||||
<Custom
|
||||
Action="RunDeskflow"
|
||||
OnExit="success"
|
||||
Condition="NOT Installed" />
|
||||
</InstallExecuteSequence>
|
||||
</CPackWiXFragment>
|
||||
</CPackWiXPatch>
|
||||
|
||||
@ -18,6 +18,8 @@
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
#if SYSAPI_WIN32
|
||||
ArchMiscWindows::guardRuntimeVersion();
|
||||
|
||||
// record window instance for tray icon, etc
|
||||
ArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL));
|
||||
#endif
|
||||
|
||||
@ -8,14 +8,12 @@ if(WIN32)
|
||||
set(target ${CMAKE_PROJECT_NAME}-daemon)
|
||||
|
||||
# Generate rc file
|
||||
set(EXE_DESCRIPTION "Windows service to run ${CMAKE_PROJECT_NAME} in secure desktops (UAC prompts, login screen, etc)")
|
||||
set(EXE_DESCRIPTION "${CMAKE_PROJECT_PROPER_NAME} Daemon for handling secure desktops (UAC prompts, login screen, etc)")
|
||||
set(EXE_ICON "IDI_DESKFLOW ICON DISCARDABLE \"${CMAKE_SOURCE_DIR}/src/apps/res/deskflow.ico\"")
|
||||
configure_file(${CMAKE_SOURCE_DIR}/src/apps/res/windows.rc.in ${target}.rc)
|
||||
|
||||
add_executable(${target} WIN32 ${target}.cpp ${CMAKE_CURRENT_BINARY_DIR}/${target}.rc)
|
||||
|
||||
find_package(Qt6 COMPONENTS Core Network)
|
||||
|
||||
target_link_libraries(
|
||||
${target}
|
||||
arch
|
||||
@ -25,6 +23,7 @@ if(WIN32)
|
||||
net
|
||||
platform
|
||||
app
|
||||
common
|
||||
${libs}
|
||||
Qt6::Core)
|
||||
|
||||
|
||||
@ -5,15 +5,12 @@
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "arch/Arch.h"
|
||||
#include "base/Log.h"
|
||||
#include "common/constants.h"
|
||||
#include "deskflow/DaemonApp.h"
|
||||
#include "deskflow/ipc/DaemonIpcServer.h"
|
||||
|
||||
#include "arch/Arch.h"
|
||||
#include "base/EventQueue.h"
|
||||
#include "base/Log.h"
|
||||
#include "common/Settings.h"
|
||||
#include "deskflow/DaemonApp.h"
|
||||
#include "deskflow/ipc/DaemonIpcServer.h"
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
|
||||
@ -24,16 +21,19 @@
|
||||
|
||||
#endif
|
||||
|
||||
#include <QCommandLineParser>
|
||||
#include <QCoreApplication>
|
||||
#include <QThread>
|
||||
|
||||
using namespace deskflow::core;
|
||||
|
||||
void handleError(const char *message);
|
||||
void handleError(const char *message = "Unrecognized error.");
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
#if SYSAPI_WIN32
|
||||
ArchMiscWindows::guardRuntimeVersion();
|
||||
|
||||
// Save window instance for later use, e.g. `GetModuleFileName` which is used when installing the daemon.
|
||||
ArchMiscWindows::setInstanceWin32(GetModuleHandle(nullptr));
|
||||
#endif
|
||||
@ -44,79 +44,86 @@ int main(int argc, char **argv)
|
||||
Log log;
|
||||
EventQueue events;
|
||||
|
||||
LOG((CLOG_PRINT "%s daemon (v%s)", kAppName, kVersion));
|
||||
// Daemon deliberately does not have a parent, as it will be moved to a new thread.
|
||||
DaemonApp daemon(events);
|
||||
|
||||
auto &daemon = DaemonApp::instance();
|
||||
DaemonApp::InitResult initResult;
|
||||
try {
|
||||
initResult = daemon.init(&events, argc, argv);
|
||||
} catch (std::exception &e) {
|
||||
handleError(e.what());
|
||||
return kExitFailed;
|
||||
} catch (...) {
|
||||
handleError("Unrecognized error.");
|
||||
return kExitFailed;
|
||||
QCoreApplication app(argc, argv);
|
||||
QCoreApplication::setApplicationName(QStringLiteral("%1 Daemon").arg(kAppName));
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
|
||||
const auto foregroundOption = QCommandLineOption({"f", "foreground"}, "Run in the foreground (show console)");
|
||||
parser.addOption(foregroundOption);
|
||||
|
||||
const auto installOption = QCommandLineOption({"i", "install"}, "Install as a Windows service");
|
||||
parser.addOption(installOption);
|
||||
|
||||
const auto uninstallOption = QCommandLineOption({"u", "uninstall"}, "Uninstall the Windows service");
|
||||
parser.addOption(uninstallOption);
|
||||
|
||||
parser.process(app);
|
||||
|
||||
if (parser.isSet(foregroundOption)) {
|
||||
daemon.setForeground();
|
||||
}
|
||||
|
||||
switch (initResult) {
|
||||
using enum DaemonApp::InitResult;
|
||||
// Depends on whether foreground option was set.
|
||||
daemon.initLogging();
|
||||
|
||||
case StartDaemon: {
|
||||
LOG_INFO("starting daemon");
|
||||
QCoreApplication app(argc, argv);
|
||||
// Important: Log the app name and version number to the log file daemon app has initialized
|
||||
// logging as it creates the file logger. Logging before would only log to stdout which is not
|
||||
// useful for troubleshooting Windows services.
|
||||
// It's important to write the version number to the log file so we can be certain the old daemon
|
||||
// was uninstalled, since sometimes Windows services can get stuck and fail to be removed.
|
||||
LOG_PRINT("%s v%s", QCoreApplication::applicationName().toStdString().c_str(), kDisplayVersion);
|
||||
|
||||
// Default log level to system setting (found in Registry).
|
||||
auto logLevel = Settings::value(Settings::Daemon::LogLevel).toString().toStdString();
|
||||
if (logLevel != "") {
|
||||
CLOG->setFilter(logLevel.c_str());
|
||||
LOG_DEBUG("log level: %s", logLevel.c_str());
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
// Show warning if not running as admin as daemon will behave differently.
|
||||
if (!ArchMiscWindows::isProcessElevated()) {
|
||||
LOG_WARN("not running as admin, some features may not work");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (parser.isSet(installOption)) {
|
||||
daemon.install();
|
||||
return kExitSuccess;
|
||||
} else if (parser.isSet(uninstallOption)) {
|
||||
daemon.uninstall();
|
||||
return kExitSuccess;
|
||||
}
|
||||
|
||||
const auto ipcServer =
|
||||
new ipc::DaemonIpcServer(&app, DaemonApp::logFilename().toStdString().c_str()); // NOSONAR - Qt managed
|
||||
ipcServer->listen();
|
||||
daemon.connectIpcServer(ipcServer);
|
||||
|
||||
QThread daemonThread;
|
||||
daemon.moveToThread(&daemonThread);
|
||||
|
||||
QObject::connect(&daemonThread, &QThread::started, [&daemon, &daemonThread]() {
|
||||
LOG_DEBUG("daemon thread started");
|
||||
daemon.run();
|
||||
daemonThread.quit();
|
||||
LOG_DEBUG("daemon thread finished");
|
||||
});
|
||||
QObject::connect(&daemonThread, &QThread::finished, &app, &QCoreApplication::quit);
|
||||
daemon.run(daemonThread);
|
||||
|
||||
ipc::DaemonIpcServer ipcServer(&app, QString::fromStdString(daemon.logFilename()));
|
||||
|
||||
// Use direct connection as the daemon app is on it's own thread, and so is on a different event loop.
|
||||
QObject::connect(
|
||||
&ipcServer, &ipc::DaemonIpcServer::logLevelChanged, &daemon, &DaemonApp::saveLogLevel, //
|
||||
Qt::DirectConnection
|
||||
);
|
||||
QObject::connect(
|
||||
&ipcServer, &ipc::DaemonIpcServer::elevateModeChanged, &daemon, &DaemonApp::setElevate, //
|
||||
Qt::DirectConnection
|
||||
);
|
||||
QObject::connect(
|
||||
&ipcServer, &ipc::DaemonIpcServer::commandChanged, &daemon, &DaemonApp::setCommand, //
|
||||
Qt::DirectConnection
|
||||
);
|
||||
QObject::connect(
|
||||
&ipcServer, &ipc::DaemonIpcServer::startProcessRequested, &daemon, &DaemonApp::applyWatchdogCommand, //
|
||||
Qt::DirectConnection
|
||||
);
|
||||
QObject::connect(
|
||||
&ipcServer, &ipc::DaemonIpcServer::stopProcessRequested, &daemon, &DaemonApp::clearWatchdogCommand, //
|
||||
Qt::DirectConnection
|
||||
);
|
||||
QObject::connect(
|
||||
&ipcServer, &ipc::DaemonIpcServer::clearSettingsRequested, &daemon, &DaemonApp::clearSettings, //
|
||||
Qt::DirectConnection
|
||||
);
|
||||
|
||||
daemonThread.start();
|
||||
const auto exitCode = QCoreApplication::exec();
|
||||
daemonThread.wait();
|
||||
|
||||
LOG_DEBUG("daemon exited, code: %d", exitCode);
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
case FatalError:
|
||||
} catch (std::exception &e) {
|
||||
handleError(e.what());
|
||||
return kExitFailed;
|
||||
} catch (...) {
|
||||
handleError();
|
||||
return kExitFailed;
|
||||
|
||||
default:
|
||||
return kExitSuccess;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -8,10 +8,6 @@ else()
|
||||
set(target deskflow)
|
||||
endif()
|
||||
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
if(WIN32)
|
||||
@ -52,6 +48,8 @@ add_executable(${target} WIN32 MACOSX_BUNDLE
|
||||
Action.h
|
||||
DataDownloader.cpp
|
||||
DataDownloader.h
|
||||
Diagnostic.cpp
|
||||
Diagnostic.h
|
||||
Hotkey.cpp
|
||||
Hotkey.h
|
||||
KeySequence.cpp
|
||||
@ -60,13 +58,11 @@ add_executable(${target} WIN32 MACOSX_BUNDLE
|
||||
MainWindow.cpp
|
||||
MainWindow.h
|
||||
MainWindow.ui
|
||||
ProcessorArch.h
|
||||
QUtility.cpp
|
||||
QUtility.h
|
||||
ScreenSetupModel.cpp
|
||||
ScreenSetupModel.h
|
||||
ServerConfig.cpp
|
||||
ServerConfig.h
|
||||
StyleUtils.h
|
||||
VersionChecker.cpp
|
||||
VersionChecker.h
|
||||
dialogs/AboutDialog.cpp
|
||||
@ -92,6 +88,24 @@ add_executable(${target} WIN32 MACOSX_BUNDLE
|
||||
dialogs/SettingsDialog.cpp
|
||||
dialogs/SettingsDialog.h
|
||||
dialogs/SettingsDialog.ui
|
||||
validators/AliasValidator.cpp
|
||||
validators/AliasValidator.h
|
||||
validators/ComputerNameValidator.cpp
|
||||
validators/ComputerNameValidator.h
|
||||
validators/EmptyStringValidator.cpp
|
||||
validators/EmptyStringValidator.h
|
||||
validators/IStringValidator.cpp
|
||||
validators/IStringValidator.h
|
||||
validators/LineEditValidator.cpp
|
||||
validators/LineEditValidator.h
|
||||
validators/ScreenDuplicationsValidator.cpp
|
||||
validators/ScreenDuplicationsValidator.h
|
||||
validators/ScreenNameValidator.cpp
|
||||
validators/ScreenNameValidator.h
|
||||
validators/SpacesValidator.cpp
|
||||
validators/SpacesValidator.h
|
||||
validators/ValidationError.cpp
|
||||
validators/ValidationError.h
|
||||
widgets/FingerprintPreview.h
|
||||
widgets/FingerprintPreview.cpp
|
||||
widgets/KeySequenceWidget.cpp
|
||||
@ -107,6 +121,7 @@ add_executable(${target} WIN32 MACOSX_BUNDLE
|
||||
target_link_libraries(
|
||||
${target}
|
||||
gui
|
||||
common
|
||||
Qt6::Core
|
||||
Qt6::Widgets
|
||||
Qt6::Network)
|
||||
|
||||
@ -4,12 +4,11 @@
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "diagnostic.h"
|
||||
#include "Diagnostic.h"
|
||||
|
||||
#include "config/ConfigScopes.h"
|
||||
#include "paths.h"
|
||||
#include "common/Settings.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QProcess>
|
||||
|
||||
@ -27,23 +26,19 @@ void restart()
|
||||
QProcess::startDetached(program, arguments);
|
||||
|
||||
qDebug("exiting current process");
|
||||
QApplication::exit();
|
||||
QCoreApplication::exit();
|
||||
}
|
||||
|
||||
void clearSettings(ConfigScopes &scopes, bool enableRestart)
|
||||
void clearSettings(bool enableRestart)
|
||||
{
|
||||
qDebug("clearing settings");
|
||||
scopes.clear();
|
||||
Settings::proxy().clear();
|
||||
|
||||
// save but do not emit saving signal which will prevent the current state of
|
||||
// the app config and server configs from being applied.
|
||||
scopes.save(false);
|
||||
Settings::save(false);
|
||||
|
||||
auto configDir = paths::configDir();
|
||||
qDebug("removing config dir: %s", qPrintable(configDir.absolutePath()));
|
||||
configDir.removeRecursively();
|
||||
|
||||
auto profileDir = paths::coreProfileDir();
|
||||
auto profileDir = QDir(Settings::settingsPath());
|
||||
qDebug("removing profile dir: %s", qPrintable(profileDir.absolutePath()));
|
||||
profileDir.removeRecursively();
|
||||
|
||||
@ -6,10 +6,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gui/config/ConfigScopes.h"
|
||||
|
||||
namespace deskflow::gui::diagnostic {
|
||||
|
||||
void clearSettings(ConfigScopes &scopes, bool enableRestart);
|
||||
void clearSettings(bool enableRestart);
|
||||
|
||||
}
|
||||
@ -9,28 +9,27 @@
|
||||
#include "MainWindow.h"
|
||||
#include "ui_MainWindow.h"
|
||||
|
||||
#include "Diagnostic.h"
|
||||
#include "StyleUtils.h"
|
||||
|
||||
#include "dialogs/AboutDialog.h"
|
||||
#include "dialogs/FingerprintDialog.h"
|
||||
#include "dialogs/ServerConfigDialog.h"
|
||||
#include "dialogs/SettingsDialog.h"
|
||||
|
||||
#include "base/String.h"
|
||||
#include "common/constants.h"
|
||||
#include "common/Settings.h"
|
||||
#include "common/UrlConstants.h"
|
||||
#include "gui/Logger.h"
|
||||
#include "gui/config/ConfigScopes.h"
|
||||
#include "gui/constants.h"
|
||||
#include "gui/Messages.h"
|
||||
#include "gui/Styles.h"
|
||||
#include "gui/core/CoreProcess.h"
|
||||
#include "gui/diagnostic.h"
|
||||
#include "gui/ipc/DaemonIpcClient.h"
|
||||
#include "gui/messages.h"
|
||||
#include "gui/string_utils.h"
|
||||
#include "gui/style_utils.h"
|
||||
#include "gui/styles.h"
|
||||
#include "net/FingerprintDatabase.h"
|
||||
#include "platform/wayland.h"
|
||||
#include "platform/Wayland.h"
|
||||
|
||||
#if defined(Q_OS_LINUX)
|
||||
#include "config.h"
|
||||
#include "Config.h"
|
||||
#endif
|
||||
|
||||
#include <QApplication>
|
||||
@ -56,19 +55,16 @@
|
||||
|
||||
using namespace deskflow::gui;
|
||||
|
||||
using CoreMode = CoreProcess::Mode;
|
||||
using CoreConnectionState = CoreProcess::ConnectionState;
|
||||
using CoreProcessState = CoreProcess::ProcessState;
|
||||
|
||||
MainWindow::MainWindow(ConfigScopes &configScopes, AppConfig &appConfig)
|
||||
MainWindow::MainWindow()
|
||||
: ui{std::make_unique<Ui::MainWindow>()},
|
||||
m_configScopes(configScopes),
|
||||
m_appConfig(appConfig),
|
||||
m_serverConfig(appConfig, *this),
|
||||
m_coreProcess(appConfig, m_serverConfig),
|
||||
m_serverConnection(this, appConfig, m_serverConfig, m_serverConfigDialogState),
|
||||
m_clientConnection(this, appConfig),
|
||||
m_tlsUtility(appConfig),
|
||||
m_serverConfig(*this),
|
||||
m_coreProcess(m_serverConfig),
|
||||
m_serverConnection(this, m_serverConfig),
|
||||
m_clientConnection(this),
|
||||
m_tlsUtility(this),
|
||||
m_trayIcon{new QSystemTrayIcon(this)},
|
||||
m_guiDupeChecker{new QLocalServer(this)},
|
||||
m_daemonIpcClient{new ipc::DaemonIpcClient(this)},
|
||||
@ -83,12 +79,9 @@ MainWindow::MainWindow(ConfigScopes &configScopes, AppConfig &appConfig)
|
||||
m_actionQuit{new QAction(tr("&Quit"), this)},
|
||||
m_actionTrayQuit{new QAction(tr("&Quit"), this)},
|
||||
m_actionRestore{new QAction(tr("&Open Deskflow"), this)},
|
||||
m_actionSave{new QAction(tr("Save configuration &as..."), this)},
|
||||
m_actionSettings{new QAction(tr("Preferences"), this)},
|
||||
m_actionStartCore{new QAction(tr("&Start"), this)},
|
||||
m_actionStopCore{new QAction(tr("S&top"), this)},
|
||||
m_actionTestCriticalError{new QAction(tr("Test Critical Error"), this)},
|
||||
m_actionTestFatalError{new QAction(tr("Test Fatal Error"), this)}
|
||||
m_actionStopCore{new QAction(tr("S&top"), this)}
|
||||
{
|
||||
const auto themeName = QStringLiteral("deskflow-%1").arg(iconMode());
|
||||
if (QIcon::themeName().isEmpty())
|
||||
@ -120,9 +113,6 @@ MainWindow::MainWindow(ConfigScopes &configScopes, AppConfig &appConfig)
|
||||
m_actionSettings->setMenuRole(QAction::PreferencesRole);
|
||||
m_actionSettings->setIcon(QIcon::fromTheme(QStringLiteral("configure")));
|
||||
|
||||
m_actionSave->setShortcut(QKeySequence(tr("Ctrl+Alt+S")));
|
||||
m_actionSave->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::DocumentSaveAs));
|
||||
|
||||
m_actionStartCore->setShortcut(QKeySequence(tr("Ctrl+S")));
|
||||
m_actionStartCore->setIcon(QIcon::fromTheme(QStringLiteral("system-run")));
|
||||
|
||||
@ -146,25 +136,23 @@ MainWindow::MainWindow(ConfigScopes &configScopes, AppConfig &appConfig)
|
||||
|
||||
setupTrayIcon();
|
||||
|
||||
m_configScopes.signalReady();
|
||||
|
||||
updateScreenName();
|
||||
applyConfig();
|
||||
restoreWindow();
|
||||
|
||||
qDebug().noquote() << "active settings path:" << m_configScopes.activeFilePath();
|
||||
qDebug().noquote() << "active settings path:" << Settings::settingsPath();
|
||||
|
||||
updateSize();
|
||||
|
||||
// Force generation of SHA256 for the localhost
|
||||
if (m_appConfig.tlsEnabled()) {
|
||||
if (!QFile::exists(localFingerprintDb())) {
|
||||
if (Settings::value(Settings::Security::TlsEnabled).toBool()) {
|
||||
if (!QFile::exists(Settings::tlsLocalDb())) {
|
||||
regenerateLocalFingerprints();
|
||||
return;
|
||||
}
|
||||
|
||||
deskflow::FingerprintDatabase db;
|
||||
db.read(localFingerprintDb().toStdString());
|
||||
db.read(Settings::tlsLocalDb().toStdString());
|
||||
if (db.fingerprints().size() != kTlsDbSize) {
|
||||
regenerateLocalFingerprints();
|
||||
}
|
||||
@ -179,36 +167,33 @@ MainWindow::~MainWindow()
|
||||
|
||||
void MainWindow::restoreWindow()
|
||||
{
|
||||
const auto &windowSize = m_appConfig.mainWindowSize();
|
||||
if (windowSize.has_value()) {
|
||||
qDebug() << "restoring main window size";
|
||||
m_expandedSize = windowSize.value();
|
||||
}
|
||||
|
||||
const auto &windowPosition = m_appConfig.mainWindowPosition();
|
||||
if (windowPosition.has_value()) {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
for (auto screen : QGuiApplication::screens()) {
|
||||
auto geo = screen->geometry();
|
||||
x = std::min(geo.x(), x);
|
||||
y = std::min(geo.y(), y);
|
||||
w = std::max(geo.x() + geo.width(), w);
|
||||
h = std::max(geo.y() + geo.height(), h);
|
||||
}
|
||||
const QSize totalScreenSize(w, h);
|
||||
const QPoint point = windowPosition.value();
|
||||
if (point.x() < totalScreenSize.width() && point.y() < totalScreenSize.height()) {
|
||||
qDebug() << "restoring main window position";
|
||||
move(point);
|
||||
}
|
||||
} else {
|
||||
const auto windowGeometry = Settings::value(Settings::Gui::WindowGeometry).toRect();
|
||||
if (!windowGeometry.isValid()) {
|
||||
// center main window in middle of screen
|
||||
const auto screen = QGuiApplication::primaryScreen();
|
||||
QRect screenGeometry = screen->geometry();
|
||||
move(screenGeometry.center() - rect().center());
|
||||
return;
|
||||
}
|
||||
|
||||
m_expandedSize = windowGeometry.size();
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
const auto screens = QGuiApplication::screens();
|
||||
for (auto screen : screens) {
|
||||
auto geo = screen->geometry();
|
||||
x = std::min(geo.x(), x);
|
||||
y = std::min(geo.y(), y);
|
||||
w = std::max(geo.x() + geo.width(), w);
|
||||
h = std::max(geo.y() + geo.height(), h);
|
||||
}
|
||||
const QRect screensGeometry(x, y, w, h);
|
||||
if (screensGeometry.contains(windowGeometry)) {
|
||||
qDebug() << "restoring main window position";
|
||||
move(windowGeometry.topLeft());
|
||||
}
|
||||
}
|
||||
|
||||
@ -218,15 +203,16 @@ void MainWindow::setupControls()
|
||||
|
||||
secureSocket(false);
|
||||
|
||||
ui->btnConfigureServer->setIcon(QIcon::fromTheme(QStringLiteral("configure")));
|
||||
ui->lblIpAddresses->setText(tr("This computer's IP addresses: %1").arg(getIPAddresses()));
|
||||
|
||||
if (m_appConfig.lastVersion() != kVersion) {
|
||||
m_appConfig.setLastVersion(kVersion);
|
||||
if (Settings::value(Settings::Core::LastVersion).toString() != kVersion) {
|
||||
Settings::setValue(Settings::Core::LastVersion, kVersion);
|
||||
}
|
||||
|
||||
// Setup the log toggle, set its initial state to closed
|
||||
ui->btnToggleLog->setStyleSheet(kStyleFlatButton);
|
||||
if (m_appConfig.logExpanded()) {
|
||||
if (Settings::value(Settings::Gui::LogExpanded).toBool()) {
|
||||
ui->btnToggleLog->setArrowType(Qt::DownArrow);
|
||||
ui->textLog->setVisible(true);
|
||||
ui->btnToggleLog->click();
|
||||
@ -236,11 +222,13 @@ void MainWindow::setupControls()
|
||||
|
||||
ui->serverOptions->setVisible(false);
|
||||
ui->clientOptions->setVisible(false);
|
||||
ui->rbModeClient->setChecked(m_appConfig.clientGroupChecked());
|
||||
ui->rbModeServer->setChecked(m_appConfig.serverGroupChecked());
|
||||
|
||||
if (m_appConfig.clientGroupChecked() || m_appConfig.serverGroupChecked())
|
||||
updateModeControls(m_appConfig.serverGroupChecked());
|
||||
const auto coreMode = Settings::value(Settings::Core::CoreMode).value<Settings::CoreMode>();
|
||||
ui->rbModeClient->setChecked(coreMode == Settings::CoreMode::Client);
|
||||
ui->rbModeServer->setChecked(coreMode == Settings::CoreMode::Server);
|
||||
|
||||
if (coreMode != Settings::CoreMode::None)
|
||||
updateModeControls(coreMode == Settings::CoreMode::Server);
|
||||
|
||||
ui->lineEditName->setValidator(new QRegularExpressionValidator(m_nameRegEx, this));
|
||||
ui->lineEditName->setVisible(false);
|
||||
@ -292,11 +280,8 @@ void MainWindow::connectSlots()
|
||||
|
||||
connect(this, &MainWindow::shown, this, &MainWindow::firstShown, Qt::QueuedConnection);
|
||||
|
||||
connect(&m_configScopes, &ConfigScopes::saving, this, &MainWindow::configScopesSaving, Qt::DirectConnection);
|
||||
|
||||
connect(&m_appConfig, &AppConfig::tlsChanged, this, &MainWindow::appConfigTlsChanged);
|
||||
connect(&m_appConfig, &AppConfig::screenNameChanged, this, &MainWindow::updateScreenName);
|
||||
connect(&m_appConfig, &AppConfig::logLevelChanged, &m_coreProcess, &CoreProcess::applyLogLevel);
|
||||
connect(Settings::instance(), &Settings::serverSettingsChanged, this, &MainWindow::serverConfigSaving);
|
||||
connect(Settings::instance(), &Settings::settingsChanged, this, &MainWindow::settingsChanged);
|
||||
|
||||
connect(&m_coreProcess, &CoreProcess::starting, this, &MainWindow::coreProcessStarting, Qt::DirectConnection);
|
||||
connect(&m_coreProcess, &CoreProcess::error, this, &MainWindow::coreProcessError);
|
||||
@ -313,12 +298,9 @@ void MainWindow::connectSlots()
|
||||
connect(m_actionQuit, &QAction::triggered, this, &MainWindow::close);
|
||||
connect(m_actionTrayQuit, &QAction::triggered, this, &MainWindow::close);
|
||||
connect(m_actionRestore, &QAction::triggered, this, &MainWindow::showAndActivate);
|
||||
connect(m_actionSave, &QAction::triggered, this, &MainWindow::saveConfig);
|
||||
connect(m_actionSettings, &QAction::triggered, this, &MainWindow::openSettings);
|
||||
connect(m_actionStartCore, &QAction::triggered, this, &MainWindow::startCore);
|
||||
connect(m_actionStopCore, &QAction::triggered, this, &MainWindow::stopCore);
|
||||
connect(m_actionTestFatalError, &QAction::triggered, this, &MainWindow::testFatalError);
|
||||
connect(m_actionTestCriticalError, &QAction::triggered, this, &MainWindow::testCriticalError);
|
||||
|
||||
connect(&m_versionChecker, &VersionChecker::updateFound, this, &MainWindow::versionCheckerUpdateFound);
|
||||
|
||||
@ -339,6 +321,7 @@ void MainWindow::connectSlots()
|
||||
connect(ui->lineHostname, &QLineEdit::returnPressed, ui->btnConnect, &QPushButton::click);
|
||||
connect(ui->lineHostname, &QLineEdit::textChanged, &m_coreProcess, &deskflow::gui::CoreProcess::setAddress);
|
||||
|
||||
connect(ui->btnSaveServerConfig, &QPushButton::clicked, this, &MainWindow::saveServerConfig);
|
||||
connect(ui->btnConfigureServer, &QPushButton::clicked, this, [this] { showConfigureServer(""); });
|
||||
connect(ui->lblComputerName, &QLabel::linkActivated, this, &MainWindow::openSettings);
|
||||
connect(m_btnFingerprint, &QToolButton::clicked, this, &MainWindow::showMyFingerprint);
|
||||
@ -361,16 +344,14 @@ void MainWindow::toggleLogVisible(bool visible)
|
||||
{
|
||||
if (visible) {
|
||||
ui->btnToggleLog->setArrowType(Qt::DownArrow);
|
||||
ui->textLog->setVisible(true);
|
||||
m_appConfig.setLogExpanded(true);
|
||||
} else {
|
||||
ui->btnToggleLog->setArrowType(Qt::RightArrow);
|
||||
m_expandedSize = size();
|
||||
ui->textLog->setVisible(false);
|
||||
m_appConfig.setLogExpanded(false);
|
||||
}
|
||||
// 1 ms delay is to make sure we have left the function before calling updateSize
|
||||
QTimer::singleShot(1, this, &MainWindow::updateSize);
|
||||
ui->textLog->setVisible(visible);
|
||||
Settings::setValue(Settings::Gui::LogExpanded, visible);
|
||||
// 15 ms delay is to make sure we have left the function before calling updateSize
|
||||
QTimer::singleShot(15, this, &MainWindow::updateSize);
|
||||
}
|
||||
|
||||
void MainWindow::firstShown()
|
||||
@ -386,17 +367,30 @@ void MainWindow::firstShown()
|
||||
QTimer::singleShot(kCriticalDialogDelay, this, &messages::raiseCriticalDialog);
|
||||
}
|
||||
|
||||
void MainWindow::configScopesSaving()
|
||||
void MainWindow::settingsChanged(const QString &key)
|
||||
{
|
||||
m_serverConfig.commit();
|
||||
if (key == Settings::Log::Level) {
|
||||
m_coreProcess.applyLogLevel();
|
||||
return;
|
||||
}
|
||||
|
||||
if (key == Settings::Core::ScreenName)
|
||||
updateScreenName();
|
||||
|
||||
if ((key == Settings::Security::Certificate) || (key == Settings::Security::KeySize) ||
|
||||
(key == Settings::Security::TlsEnabled) || (key == Settings::Security::CheckPeers)) {
|
||||
const auto certificate = Settings::value(Settings::Security::Certificate).toString();
|
||||
if (m_tlsUtility.isEnabled() && !QFile::exists(certificate)) {
|
||||
m_tlsUtility.generateCertificate();
|
||||
}
|
||||
updateSecurityIcon(m_lblSecurityStatus->isVisible());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::appConfigTlsChanged()
|
||||
void MainWindow::serverConfigSaving()
|
||||
{
|
||||
if (m_tlsUtility.isEnabled() && !QFile::exists(m_appConfig.tlsCertPath())) {
|
||||
m_tlsUtility.generateCertificate();
|
||||
}
|
||||
updateSecurityIcon(m_lblSecurityStatus->isVisible());
|
||||
m_serverConfig.commit();
|
||||
}
|
||||
|
||||
void MainWindow::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
|
||||
@ -409,7 +403,7 @@ void MainWindow::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
|
||||
void MainWindow::versionCheckerUpdateFound(const QString &version)
|
||||
{
|
||||
m_btnUpdate->setVisible(true);
|
||||
m_btnUpdate->setToolTip(tr("A new version v%1 is avilable").arg(version));
|
||||
m_btnUpdate->setToolTip(tr("A new version v%1 is available").arg(version));
|
||||
}
|
||||
|
||||
void MainWindow::coreProcessError(CoreProcess::Error error)
|
||||
@ -441,16 +435,6 @@ void MainWindow::stopCore()
|
||||
m_coreProcess.stop();
|
||||
}
|
||||
|
||||
void MainWindow::testFatalError() const
|
||||
{
|
||||
qFatal() << "test fatal error";
|
||||
}
|
||||
|
||||
void MainWindow::testCriticalError() const
|
||||
{
|
||||
qCritical() << "test critical error";
|
||||
}
|
||||
|
||||
void MainWindow::clearSettings()
|
||||
{
|
||||
if (!messages::showClearSettings(this)) {
|
||||
@ -462,15 +446,15 @@ void MainWindow::clearSettings()
|
||||
m_coreProcess.clearSettings();
|
||||
|
||||
m_saveOnExit = false;
|
||||
diagnostic::clearSettings(m_configScopes, true);
|
||||
diagnostic::clearSettings(true);
|
||||
}
|
||||
|
||||
bool MainWindow::saveConfig()
|
||||
bool MainWindow::saveServerConfig()
|
||||
{
|
||||
QString fileName = QFileDialog::getSaveFileName(this, tr("Save configuration as..."));
|
||||
QString fileName = QFileDialog::getSaveFileName(this, tr("Save server configuration as..."));
|
||||
|
||||
if (!fileName.isEmpty() && !m_serverConfig.save(fileName)) {
|
||||
QMessageBox::warning(this, tr("Save failed"), tr("Could not save configuration to file."));
|
||||
QMessageBox::warning(this, tr("Save failed"), tr("Could not save server configuration to file."));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -495,10 +479,10 @@ void MainWindow::openGetNewVersionUrl() const
|
||||
|
||||
void MainWindow::openSettings()
|
||||
{
|
||||
auto dialog = SettingsDialog(this, m_appConfig, m_serverConfig, m_coreProcess);
|
||||
auto dialog = SettingsDialog(this, m_serverConfig, m_coreProcess);
|
||||
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
m_configScopes.save();
|
||||
Settings::save();
|
||||
|
||||
applyConfig();
|
||||
|
||||
@ -516,28 +500,26 @@ void MainWindow::resetCore()
|
||||
|
||||
void MainWindow::updateSize()
|
||||
{
|
||||
if (m_appConfig.logExpanded()) {
|
||||
setMaximumHeight(16777215);
|
||||
setMaximumWidth(16777215);
|
||||
if (Settings::value(Settings::Gui::LogExpanded).toBool()) {
|
||||
setMaximumSize(16777215, 16777215);
|
||||
resize(m_expandedSize);
|
||||
} else {
|
||||
adjustSize();
|
||||
// Prevent Resize with log collapsed
|
||||
setMaximumHeight(height());
|
||||
setMaximumWidth(width());
|
||||
setMaximumSize(width(), height());
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::showMyFingerprint()
|
||||
{
|
||||
if (!QFile::exists(localFingerprintDb())) {
|
||||
if (!QFile::exists(Settings::tlsLocalDb())) {
|
||||
if (regenerateLocalFingerprints())
|
||||
showMyFingerprint();
|
||||
return;
|
||||
}
|
||||
|
||||
deskflow::FingerprintDatabase db;
|
||||
db.read(localFingerprintDb().toStdString());
|
||||
db.read(Settings::tlsLocalDb().toStdString());
|
||||
if (db.fingerprints().size() != kTlsDbSize) {
|
||||
if (regenerateLocalFingerprints())
|
||||
showMyFingerprint();
|
||||
@ -559,10 +541,10 @@ void MainWindow::coreModeToggled()
|
||||
const auto mode = serverMode ? QStringLiteral("server enabled") : QStringLiteral("client enabled");
|
||||
qDebug() << mode;
|
||||
|
||||
m_appConfig.setServerGroupChecked(serverMode);
|
||||
m_appConfig.setClientGroupChecked(!serverMode);
|
||||
m_configScopes.save();
|
||||
const auto coreMode = serverMode ? Settings::CoreMode::Server : Settings::CoreMode::Client;
|
||||
Settings::setValue(Settings::Core::CoreMode, coreMode);
|
||||
|
||||
Settings::save();
|
||||
updateModeControls(serverMode);
|
||||
}
|
||||
|
||||
@ -573,7 +555,7 @@ void MainWindow::updateModeControls(bool serverMode)
|
||||
ui->lblNoMode->setVisible(false);
|
||||
ui->btnToggleCore->setEnabled(true);
|
||||
m_actionStartCore->setEnabled(true);
|
||||
auto expectedCoreMode = serverMode ? CoreProcess::Mode::Server : CoreProcess::Mode::Client;
|
||||
auto expectedCoreMode = serverMode ? Settings::CoreMode::Server : Settings::CoreMode::Client;
|
||||
if (m_coreProcess.isStarted() && m_coreProcess.mode() != expectedCoreMode)
|
||||
m_coreProcess.stop();
|
||||
m_coreProcess.setMode(expectedCoreMode);
|
||||
@ -581,7 +563,8 @@ void MainWindow::updateModeControls(bool serverMode)
|
||||
// The server can run without any clients configured, and this is actually
|
||||
// what you'll want to do the first time since you'll be prompted when an
|
||||
// unrecognized client tries to connect.
|
||||
if (!m_appConfig.startedBefore() && !m_coreProcess.isStarted()) {
|
||||
const auto startedBefore = Settings::value(Settings::Core::StartedBefore).toBool();
|
||||
if (!startedBefore && !m_coreProcess.isStarted()) {
|
||||
qDebug() << "auto-starting core server for first time";
|
||||
m_coreProcess.start();
|
||||
messages::showFirstServerStartMessage(this);
|
||||
@ -595,7 +578,7 @@ void MainWindow::updateSecurityIcon(bool visible)
|
||||
if (!visible)
|
||||
return;
|
||||
|
||||
bool secureSocket = m_appConfig.tlsEnabled();
|
||||
bool secureSocket = Settings::value(Settings::Security::TlsEnabled).toBool();
|
||||
|
||||
const auto txt =
|
||||
secureSocket ? tr("%1 Encryption Enabled").arg(m_coreProcess.secureSocketVersion()) : tr("Encryption Disabled");
|
||||
@ -607,12 +590,12 @@ void MainWindow::updateSecurityIcon(bool visible)
|
||||
|
||||
void MainWindow::serverConnectionConfigureClient(const QString &clientName)
|
||||
{
|
||||
m_serverConfigDialogState.setVisible(true);
|
||||
ServerConfigDialog dialog(this, m_serverConfig, m_appConfig);
|
||||
Settings::setValue(Settings::Server::ConfigVisible, true);
|
||||
ServerConfigDialog dialog(this, m_serverConfig);
|
||||
if (dialog.addClient(clientName) && dialog.exec() == QDialog::Accepted) {
|
||||
m_coreProcess.restart();
|
||||
}
|
||||
m_serverConfigDialogState.setVisible(false);
|
||||
Settings::setValue(Settings::Server::ConfigVisible, false);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@ -621,13 +604,13 @@ void MainWindow::serverConnectionConfigureClient(const QString &clientName)
|
||||
|
||||
void MainWindow::open()
|
||||
{
|
||||
if (!m_appConfig.enableUpdateCheck().has_value()) {
|
||||
|
||||
if (!Settings::value(Settings::Gui::AutoUpdateCheck).isValid()) {
|
||||
showAndActivate();
|
||||
m_appConfig.setEnableUpdateCheck(messages::showUpdateCheckOption(this));
|
||||
m_configScopes.save();
|
||||
Settings::setValue(Settings::Gui::AutoUpdateCheck, messages::showUpdateCheckOption(this));
|
||||
}
|
||||
|
||||
if (m_appConfig.enableUpdateCheck().value()) {
|
||||
if (Settings::value(Settings::Gui::AutoUpdateCheck).toBool()) {
|
||||
m_versionChecker.checkLatest();
|
||||
} else {
|
||||
qDebug() << "update check disabled";
|
||||
@ -635,21 +618,17 @@ void MainWindow::open()
|
||||
|
||||
m_coreProcess.applyLogLevel();
|
||||
|
||||
if (m_appConfig.startedBefore()) {
|
||||
if (Settings::value(Settings::Core::StartedBefore).toBool()) {
|
||||
m_coreProcess.start();
|
||||
}
|
||||
|
||||
if (m_appConfig.autoHide()) {
|
||||
hide();
|
||||
} else {
|
||||
showAndActivate();
|
||||
}
|
||||
Settings::value(Settings::Gui::Autohide).toBool() ? hide() : showAndActivate();
|
||||
}
|
||||
|
||||
void MainWindow::coreProcessStarting()
|
||||
{
|
||||
if (deskflow::platform::isWayland()) {
|
||||
m_waylandWarnings.showOnce(this, m_coreProcess.mode());
|
||||
m_waylandWarnings.showOnce(this);
|
||||
}
|
||||
saveSettings();
|
||||
}
|
||||
@ -661,18 +640,16 @@ void MainWindow::setStatus(const QString &status)
|
||||
|
||||
void MainWindow::createMenuBar()
|
||||
{
|
||||
auto menuFile = new QMenu(tr("File"));
|
||||
auto menuFile = new QMenu(tr("File"), this);
|
||||
menuFile->addAction(m_actionStartCore);
|
||||
menuFile->addAction(m_actionStopCore);
|
||||
menuFile->addSeparator();
|
||||
menuFile->addAction(m_actionSave);
|
||||
menuFile->addSeparator();
|
||||
menuFile->addAction(m_actionQuit);
|
||||
|
||||
auto menuEdit = new QMenu(tr("Edit"));
|
||||
auto menuEdit = new QMenu(tr("Edit"), this);
|
||||
menuEdit->addAction(m_actionSettings);
|
||||
|
||||
auto menuHelp = new QMenu(tr("Help"));
|
||||
auto menuHelp = new QMenu(tr("Help"), this);
|
||||
menuHelp->addAction(m_actionAbout);
|
||||
menuHelp->addAction(m_actionReportBug);
|
||||
menuHelp->addSeparator();
|
||||
@ -683,14 +660,6 @@ void MainWindow::createMenuBar()
|
||||
menuBar->addMenu(menuEdit);
|
||||
menuBar->addMenu(menuHelp);
|
||||
|
||||
const auto enableTestMenu = strToTrue(qEnvironmentVariable("DESKFLOW_TEST_MENU"));
|
||||
if (enableTestMenu || kDebugBuild) {
|
||||
auto testMenu = new QMenu(tr("Test"));
|
||||
menuBar->addMenu(testMenu);
|
||||
testMenu->addAction(m_actionTestFatalError);
|
||||
testMenu->addAction(m_actionTestCriticalError);
|
||||
}
|
||||
|
||||
setMenuBar(menuBar);
|
||||
}
|
||||
|
||||
@ -708,22 +677,26 @@ void MainWindow::setupTrayIcon()
|
||||
|
||||
void MainWindow::applyConfig()
|
||||
{
|
||||
ui->lineHostname->setText(m_appConfig.serverHostname());
|
||||
ui->lineHostname->setText(Settings::value(Settings::Client::RemoteHost).toString());
|
||||
updateLocalFingerprint();
|
||||
setIcon();
|
||||
|
||||
if (!m_appConfig.serverGroupChecked() && !m_appConfig.clientGroupChecked())
|
||||
const auto coreMode = Settings::value(Settings::Core::CoreMode).value<Settings::CoreMode>();
|
||||
|
||||
if (coreMode == Settings::CoreMode::None)
|
||||
return;
|
||||
updateModeControls(m_appConfig.serverGroupChecked());
|
||||
updateModeControls(coreMode == Settings::CoreMode::Server);
|
||||
}
|
||||
|
||||
void MainWindow::saveSettings()
|
||||
{
|
||||
m_appConfig.setServerGroupChecked(ui->rbModeServer->isChecked());
|
||||
m_appConfig.setClientGroupChecked(ui->rbModeClient->isChecked());
|
||||
m_appConfig.setServerHostname(ui->lineHostname->text());
|
||||
|
||||
m_configScopes.save();
|
||||
if (ui->rbModeClient->isChecked()) {
|
||||
Settings::setValue(Settings::Core::CoreMode, Settings::CoreMode::Client);
|
||||
} else if (ui->rbModeServer->isChecked()) {
|
||||
Settings::setValue(Settings::Core::CoreMode, Settings::CoreMode::Server);
|
||||
}
|
||||
Settings::setValue(Settings::Client::RemoteHost, ui->lineHostname->text());
|
||||
Settings::save();
|
||||
}
|
||||
|
||||
void MainWindow::setIcon()
|
||||
@ -731,18 +704,19 @@ void MainWindow::setIcon()
|
||||
// Using a theme icon that is packed in exe renders an invisible icon
|
||||
// Instead use the resource path of the packed icon
|
||||
// TODO Report to Qt ref the bug here
|
||||
const bool symbolicIcon = Settings::value(Settings::Gui::SymbolicTrayIcon).toBool();
|
||||
#ifndef Q_OS_MAC
|
||||
QString iconString = QStringLiteral(":/icons/deskflow-%1/apps/64/deskflow").arg(iconMode());
|
||||
if (!appConfig().colorfulTrayIcon()) {
|
||||
if (symbolicIcon)
|
||||
iconString.append(QStringLiteral("-symbolic"));
|
||||
}
|
||||
m_trayIcon->setIcon(QIcon(iconString));
|
||||
#else
|
||||
if (m_appConfig.colorfulTrayIcon()) {
|
||||
m_trayIcon->setIcon(QIcon::fromTheme(QStringLiteral("deskflow")));
|
||||
if (symbolicIcon) {
|
||||
auto icon = QIcon::fromTheme(QStringLiteral("deskflow-symbolic"));
|
||||
icon.setIsMask(true);
|
||||
m_trayIcon->setIcon(icon);
|
||||
} else {
|
||||
m_trayIcon->setIcon(QIcon::fromTheme(QStringLiteral("deskflow-symbolic")));
|
||||
m_trayIcon->icon().setIsMask(true);
|
||||
m_trayIcon->setIcon(QIcon::fromTheme(QStringLiteral("deskflow")));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -758,7 +732,7 @@ void MainWindow::handleLogLine(const QString &line)
|
||||
|
||||
// only trim end instead of the whole line to prevent tab-indented debug
|
||||
// filenames from losing their indentation.
|
||||
ui->textLog->appendPlainText(trimEnd(line));
|
||||
ui->textLog->appendPlainText(line.trimmed());
|
||||
|
||||
if (scrollAtBottom) {
|
||||
verticalScroll->setValue(verticalScroll->maximum());
|
||||
@ -855,10 +829,10 @@ void MainWindow::showEvent(QShowEvent *event)
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
if (m_appConfig.closeToTray() && event->spontaneous()) {
|
||||
if (m_appConfig.showCloseReminder()) {
|
||||
if (Settings::value(Settings::Gui::CloseToTray).toBool() && event->spontaneous()) {
|
||||
if (Settings::value(Settings::Gui::CloseReminder).toBool()) {
|
||||
messages::showCloseReminder(this);
|
||||
m_appConfig.setShowCloseReminder(false);
|
||||
Settings::setValue(Settings::Gui::CloseReminder, false);
|
||||
}
|
||||
qDebug() << "hiding to tray";
|
||||
hide();
|
||||
@ -867,9 +841,7 @@ void MainWindow::closeEvent(QCloseEvent *event)
|
||||
}
|
||||
|
||||
if (m_saveOnExit) {
|
||||
m_appConfig.setMainWindowPosition(pos());
|
||||
m_appConfig.setMainWindowSize(size());
|
||||
m_configScopes.save();
|
||||
Settings::setValue(Settings::Gui::WindowGeometry, frameGeometry());
|
||||
}
|
||||
qDebug() << "quitting application";
|
||||
event->accept();
|
||||
@ -878,15 +850,16 @@ void MainWindow::closeEvent(QCloseEvent *event)
|
||||
|
||||
void MainWindow::showFirstConnectedMessage()
|
||||
{
|
||||
if (m_appConfig.startedBefore()) {
|
||||
if (Settings::value(Settings::Core::StartedBefore).toBool())
|
||||
return;
|
||||
}
|
||||
|
||||
m_appConfig.setStartedBefore(true);
|
||||
m_configScopes.save();
|
||||
Settings::setValue(Settings::Core::StartedBefore, true);
|
||||
|
||||
const auto isServer = m_coreProcess.mode() == CoreMode::Server;
|
||||
messages::showFirstConnectedMessage(this, m_appConfig.closeToTray(), m_appConfig.enableService(), isServer);
|
||||
const auto closeToTray = Settings::value(Settings::Gui::CloseToTray).toBool();
|
||||
|
||||
using ProcessMode = Settings::ProcessMode;
|
||||
const auto enableService = Settings::value(Settings::Core::ProcessMode).value<ProcessMode>() == ProcessMode::Service;
|
||||
messages::showFirstConnectedMessage(this, closeToTray, enableService, isServer);
|
||||
}
|
||||
|
||||
void MainWindow::updateStatus()
|
||||
@ -951,8 +924,7 @@ void MainWindow::coreProcessStateChanged(CoreProcessState state)
|
||||
|
||||
if (state == CoreProcessState::Started) {
|
||||
qDebug() << "recording that core has started";
|
||||
m_appConfig.setStartedBefore(true);
|
||||
m_configScopes.save();
|
||||
Settings::setValue(Settings::Core::StartedBefore, true);
|
||||
}
|
||||
|
||||
if (state == CoreProcessState::Started || state == CoreProcessState::Starting ||
|
||||
@ -1030,7 +1002,8 @@ QString MainWindow::getIPAddresses() const
|
||||
|
||||
void MainWindow::updateLocalFingerprint()
|
||||
{
|
||||
m_btnFingerprint->setVisible(m_appConfig.tlsEnabled() && QFile::exists(localFingerprintDb()));
|
||||
const bool tlsEnabled = Settings::value(Settings::Security::TlsEnabled).toBool();
|
||||
m_btnFingerprint->setVisible(tlsEnabled && QFile::exists(Settings::tlsLocalDb()));
|
||||
}
|
||||
|
||||
void MainWindow::autoAddScreen(const QString name)
|
||||
@ -1040,13 +1013,15 @@ void MainWindow::autoAddScreen(const QString name)
|
||||
if (r != kAutoAddScreenOk) {
|
||||
switch (r) {
|
||||
case kAutoAddScreenManualServer:
|
||||
showConfigureServer(tr("Please add the server (%1) to the grid.").arg(m_appConfig.screenName()));
|
||||
showConfigureServer(
|
||||
tr("Please add the server (%1) to the grid.").arg(Settings::value(Settings::Core::ScreenName).toString())
|
||||
);
|
||||
break;
|
||||
|
||||
case kAutoAddScreenManualClient:
|
||||
showConfigureServer(tr("Please drag the new client screen (%1) "
|
||||
"to the desired position on the grid.")
|
||||
.arg(name));
|
||||
showConfigureServer(
|
||||
tr("Please add the server (%1) to the grid.").arg(Settings::value(Settings::Core::ScreenName).toString())
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1065,7 +1040,7 @@ void MainWindow::hide()
|
||||
|
||||
void MainWindow::showConfigureServer(const QString &message)
|
||||
{
|
||||
ServerConfigDialog dialog(this, serverConfig(), m_appConfig);
|
||||
ServerConfigDialog dialog(this, serverConfig());
|
||||
dialog.message(message);
|
||||
if ((dialog.exec() == QDialog::Accepted) && m_coreProcess.isStarted()) {
|
||||
m_coreProcess.restart();
|
||||
@ -1080,8 +1055,9 @@ void MainWindow::secureSocket(bool secureSocket)
|
||||
|
||||
void MainWindow::updateScreenName()
|
||||
{
|
||||
ui->lblComputerName->setText(m_appConfig.screenName());
|
||||
ui->lineEditName->setText(m_appConfig.screenName());
|
||||
const auto screenName = Settings::value(Settings::Core::ScreenName).toString();
|
||||
ui->lblComputerName->setText(screenName);
|
||||
ui->lineEditName->setText(screenName);
|
||||
m_serverConfig.updateServerName();
|
||||
}
|
||||
|
||||
@ -1112,11 +1088,12 @@ void MainWindow::setHostName()
|
||||
ui->btnEditName->show();
|
||||
|
||||
QString text = ui->lineEditName->text();
|
||||
bool existingScreen = serverConfig().screenExists(text) && text != m_appConfig.screenName();
|
||||
const auto screenName = Settings::value(Settings::Core::ScreenName).toString();
|
||||
bool existingScreen = serverConfig().screenExists(text) && (text != screenName);
|
||||
|
||||
if (!ui->lineEditName->hasAcceptableInput() || text.isEmpty() || existingScreen) {
|
||||
blockSignals(true);
|
||||
ui->lineEditName->setText(m_appConfig.screenName());
|
||||
ui->lineEditName->setText(screenName);
|
||||
blockSignals(false);
|
||||
|
||||
const auto title = tr("Invalid Screen Name");
|
||||
@ -1124,47 +1101,37 @@ void MainWindow::setHostName()
|
||||
if (existingScreen) {
|
||||
body = tr("Screen name already exists");
|
||||
} else {
|
||||
body = tr("The name you have chosen is invalid.\n\n"
|
||||
"Valid names:\n"
|
||||
"• Use letters and numbers\n"
|
||||
"• May also use _ or -\n"
|
||||
"• Are between 1 and 255 characters");
|
||||
body =
|
||||
tr("The name you have chosen is invalid.\n\n"
|
||||
"Valid names:\n"
|
||||
"• Use letters and numbers\n"
|
||||
"• May also use _ or -\n"
|
||||
"• Are between 1 and 255 characters");
|
||||
}
|
||||
QMessageBox::information(this, title, body);
|
||||
return;
|
||||
}
|
||||
|
||||
ui->lblComputerName->setText(ui->lineEditName->text());
|
||||
m_appConfig.setScreenName(ui->lineEditName->text());
|
||||
Settings::setValue(Settings::Core::ScreenName, ui->lineEditName->text());
|
||||
applyConfig();
|
||||
}
|
||||
|
||||
QString MainWindow::getTlsPath()
|
||||
{
|
||||
CoreTool coreTool;
|
||||
return QStringLiteral("%1/%2").arg(coreTool.getProfileDir(), kSslDir);
|
||||
}
|
||||
|
||||
QString MainWindow::localFingerprintDb()
|
||||
{
|
||||
return QStringLiteral("%1/%2").arg(getTlsPath(), kFingerprintLocalFilename);
|
||||
}
|
||||
|
||||
QString MainWindow::trustedFingerprintDb()
|
||||
{
|
||||
const bool isClient = m_coreProcess.mode() == CoreMode::Client;
|
||||
const auto trustFile = isClient ? kFingerprintTrustedServersFilename : kFingerprintTrustedClientsFilename;
|
||||
return QStringLiteral("%1/%2").arg(getTlsPath(), trustFile);
|
||||
return isClient ? Settings::tlsTrustedServersDb() : Settings::tlsTrustedClientsDb();
|
||||
}
|
||||
|
||||
bool MainWindow::regenerateLocalFingerprints()
|
||||
{
|
||||
if (!QFile::exists(m_appConfig.tlsCertPath()) && !m_tlsUtility.generateCertificate()) {
|
||||
const auto certificate = Settings::value(Settings::Security::Certificate).toString();
|
||||
if (!QFile::exists(certificate) && !m_tlsUtility.generateCertificate()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TlsCertificate tls;
|
||||
if (!tls.generateFingerprint(m_appConfig.tlsCertPath())) {
|
||||
if (!tls.generateFingerprint(certificate)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -18,9 +18,6 @@
|
||||
|
||||
#include "ServerConfig.h"
|
||||
#include "VersionChecker.h"
|
||||
#include "gui/config/AppConfig.h"
|
||||
#include "gui/config/ConfigScopes.h"
|
||||
#include "gui/config/ServerConfigDialogState.h"
|
||||
#include "gui/core/ClientConnection.h"
|
||||
#include "gui/core/CoreProcess.h"
|
||||
#include "gui/core/ServerConnection.h"
|
||||
@ -59,7 +56,7 @@ class DaemonIpcClient;
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
using CoreMode = deskflow::gui::CoreProcess::Mode;
|
||||
using CoreMode = Settings::CoreMode;
|
||||
using CoreProcess = deskflow::gui::CoreProcess;
|
||||
|
||||
Q_OBJECT
|
||||
@ -75,7 +72,7 @@ public:
|
||||
};
|
||||
|
||||
public:
|
||||
explicit MainWindow(deskflow::gui::ConfigScopes &configScopes, AppConfig &appConfig);
|
||||
explicit MainWindow();
|
||||
~MainWindow() override;
|
||||
|
||||
CoreMode coreMode() const
|
||||
@ -100,8 +97,8 @@ private:
|
||||
|
||||
void firstShown();
|
||||
|
||||
void configScopesSaving();
|
||||
void appConfigTlsChanged();
|
||||
void settingsChanged(const QString &key = QString());
|
||||
void serverConfigSaving();
|
||||
void coreProcessStarting();
|
||||
void coreProcessError(CoreProcess::Error error);
|
||||
void coreConnectionStateChanged(CoreProcess::ConnectionState state);
|
||||
@ -117,9 +114,7 @@ private:
|
||||
void openSettings();
|
||||
void startCore();
|
||||
void stopCore();
|
||||
bool saveConfig();
|
||||
void testFatalError() const;
|
||||
void testCriticalError() const;
|
||||
bool saveServerConfig();
|
||||
void resetCore();
|
||||
|
||||
void showMyFingerprint();
|
||||
@ -131,14 +126,6 @@ private:
|
||||
std::unique_ptr<Ui::MainWindow> ui;
|
||||
|
||||
void updateSize();
|
||||
AppConfig &appConfig()
|
||||
{
|
||||
return m_appConfig;
|
||||
}
|
||||
AppConfig const &appConfig() const
|
||||
{
|
||||
return m_appConfig;
|
||||
}
|
||||
void createMenuBar();
|
||||
void setupTrayIcon();
|
||||
void applyConfig();
|
||||
@ -172,14 +159,6 @@ private:
|
||||
void showHostNameEditor();
|
||||
void setHostName();
|
||||
|
||||
QString getTlsPath();
|
||||
|
||||
/**
|
||||
* @brief localFingerprintDb
|
||||
* @return The path to the local fingerprint file
|
||||
*/
|
||||
QString localFingerprintDb();
|
||||
|
||||
/**
|
||||
* @brief trustedFingerprintDb get the fingerprintDb for the trusted clients or trusted servers.
|
||||
* @return The path to the trusted fingerprint file
|
||||
@ -195,11 +174,8 @@ private:
|
||||
|
||||
VersionChecker m_versionChecker;
|
||||
bool m_secureSocket = false;
|
||||
deskflow::gui::config::ServerConfigDialogState m_serverConfigDialogState;
|
||||
bool m_saveOnExit = true;
|
||||
deskflow::gui::core::WaylandWarnings m_waylandWarnings;
|
||||
deskflow::gui::ConfigScopes &m_configScopes;
|
||||
AppConfig &m_appConfig;
|
||||
ServerConfig m_serverConfig;
|
||||
deskflow::gui::CoreProcess m_coreProcess;
|
||||
deskflow::gui::ServerConnection m_serverConnection;
|
||||
@ -225,10 +201,7 @@ private:
|
||||
QAction *m_actionQuit = nullptr;
|
||||
QAction *m_actionTrayQuit = nullptr;
|
||||
QAction *m_actionRestore = nullptr;
|
||||
QAction *m_actionSave = nullptr;
|
||||
QAction *m_actionSettings = nullptr;
|
||||
QAction *m_actionStartCore = nullptr;
|
||||
QAction *m_actionStopCore = nullptr;
|
||||
QAction *m_actionTestCriticalError = nullptr;
|
||||
QAction *m_actionTestFatalError = nullptr;
|
||||
};
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>730</width>
|
||||
<height>520</height>
|
||||
<width>735</width>
|
||||
<height>515</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -233,6 +233,25 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnSaveServerConfig">
|
||||
<property name="toolTip">
|
||||
<string>Export server configuration</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="QIcon::ThemeIcon::DocumentSaveAs"/>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
@ -325,33 +344,6 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widgetModes" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<property name="spacing">
|
||||
<number>20</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frameLog">
|
||||
<property name="sizePolicy">
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2015 - 2016 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
enum qProcessorArch
|
||||
{
|
||||
kProcessorArchWin32,
|
||||
kProcessorArchWin64,
|
||||
kProcessorArchMac32,
|
||||
kProcessorArchMac64,
|
||||
kProcessorArchLinux32,
|
||||
kProcessorArchLinux64,
|
||||
kProcessorArchUnknown
|
||||
};
|
||||
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2013 - 2016 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "QUtility.h"
|
||||
|
||||
#include "ProcessorArch.h"
|
||||
|
||||
#if defined(Q_OS_LINUX)
|
||||
#include <QFile>
|
||||
#include <QProcess>
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
void setIndexFromItemData(QComboBox *comboBox, const QVariant &itemData)
|
||||
{
|
||||
for (int i = 0; i < comboBox->count(); ++i) {
|
||||
if (comboBox->itemData(i) == itemData) {
|
||||
comboBox->setCurrentIndex(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString hash(const QString &string)
|
||||
{
|
||||
QByteArray data = string.toUtf8();
|
||||
QByteArray hash = QCryptographicHash::hash(data, QCryptographicHash::Md5);
|
||||
return hash.toHex();
|
||||
}
|
||||
|
||||
qProcessorArch getProcessorArch()
|
||||
{
|
||||
#if defined(Q_OS_WIN)
|
||||
SYSTEM_INFO systemInfo;
|
||||
GetNativeSystemInfo(&systemInfo);
|
||||
|
||||
switch (systemInfo.wProcessorArchitecture) {
|
||||
case PROCESSOR_ARCHITECTURE_INTEL:
|
||||
return kProcessorArchWin32;
|
||||
case PROCESSOR_ARCHITECTURE_IA64:
|
||||
return kProcessorArchWin64;
|
||||
case PROCESSOR_ARCHITECTURE_AMD64:
|
||||
return kProcessorArchWin64;
|
||||
default:
|
||||
return kProcessorArchUnknown;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_LINUX)
|
||||
#ifdef __i386__
|
||||
return kProcessorArchLinux32;
|
||||
#else
|
||||
return kProcessorArchLinux64;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return kProcessorArchUnknown;
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2013 - 2016 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ProcessorArch.h"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QCryptographicHash>
|
||||
#include <QNetworkInterface>
|
||||
#include <QVariant>
|
||||
|
||||
void setIndexFromItemData(QComboBox *comboBox, const QVariant &itemData);
|
||||
QString hash(const QString &string);
|
||||
qProcessorArch getProcessorArch();
|
||||
@ -10,13 +10,13 @@
|
||||
|
||||
#include "Hotkey.h"
|
||||
#include "MainWindow.h"
|
||||
#include "common/Settings.h"
|
||||
#include "dialogs/AddClientDialog.h"
|
||||
|
||||
#include <QAbstractButton>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
|
||||
using namespace deskflow::gui::proxy;
|
||||
using enum ScreenConfig::Modifier;
|
||||
using enum ScreenConfig::SwitchCorner;
|
||||
using enum ScreenConfig::Fix;
|
||||
@ -36,9 +36,8 @@ static const struct
|
||||
|
||||
const int serverDefaultIndex = 7;
|
||||
|
||||
ServerConfig::ServerConfig(AppConfig &appConfig, MainWindow &mainWindow, int columns, int rows)
|
||||
: m_pAppConfig(&appConfig),
|
||||
m_pMainWindow(&mainWindow),
|
||||
ServerConfig::ServerConfig(MainWindow &mainWindow, int columns, int rows)
|
||||
: m_pMainWindow(&mainWindow),
|
||||
m_Screens(columns),
|
||||
m_Columns(columns),
|
||||
m_Rows(rows),
|
||||
@ -76,7 +75,6 @@ bool ServerConfig::operator==(const ServerConfig &sc) const
|
||||
m_SwitchCornerSize == sc.m_SwitchCornerSize && //
|
||||
m_SwitchCorners == sc.m_SwitchCorners && //
|
||||
m_Hotkeys == sc.m_Hotkeys && //
|
||||
m_pAppConfig == sc.m_pAppConfig && //
|
||||
m_EnableDragAndDrop == sc.m_EnableDragAndDrop && //
|
||||
m_DisableLockToScreen == sc.m_DisableLockToScreen && //
|
||||
m_ClipboardSharing == sc.m_ClipboardSharing && //
|
||||
@ -138,8 +136,9 @@ void ServerConfig::commit()
|
||||
settings().setArrayIndex(i);
|
||||
auto &screen = screens()[i];
|
||||
screen.saveSettings(settings());
|
||||
if (screen.isServer() && m_pAppConfig->screenName() != screen.name()) {
|
||||
m_pAppConfig->setScreenName(screen.name());
|
||||
auto screenName = Settings::value(Settings::Core::ScreenName).toString();
|
||||
if (screen.isServer() && screenName != screen.name()) {
|
||||
Settings::setValue(Settings::Core::ScreenName, screen.name());
|
||||
}
|
||||
}
|
||||
settings().endArray();
|
||||
@ -331,8 +330,8 @@ int ServerConfig::autoAddScreen(const QString name)
|
||||
{
|
||||
int serverIndex = -1;
|
||||
int targetIndex = -1;
|
||||
if (!findScreenName(m_pAppConfig->screenName(), serverIndex) &&
|
||||
!fixNoServer(m_pAppConfig->screenName(), serverIndex)) {
|
||||
const auto screenName = Settings::value(Settings::Core::ScreenName).toString();
|
||||
if (!findScreenName(screenName, serverIndex) && !fixNoServer(screenName, serverIndex)) {
|
||||
return kAutoAddScreenManualServer;
|
||||
}
|
||||
|
||||
@ -388,29 +387,29 @@ int ServerConfig::autoAddScreen(const QString name)
|
||||
return kAutoAddScreenOk;
|
||||
}
|
||||
|
||||
const QString &ServerConfig::getServerName() const
|
||||
const QString ServerConfig::getServerName() const
|
||||
{
|
||||
return m_pAppConfig->screenName();
|
||||
return Settings::value(Settings::Core::ScreenName).toString();
|
||||
}
|
||||
|
||||
void ServerConfig::updateServerName()
|
||||
{
|
||||
for (auto &screen : screens()) {
|
||||
if (screen.isServer()) {
|
||||
screen.setName(m_pAppConfig->screenName());
|
||||
screen.setName(Settings::value(Settings::Core::ScreenName).toString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const QString &ServerConfig::configFile() const
|
||||
const QString ServerConfig::configFile() const
|
||||
{
|
||||
return m_pAppConfig->configFile();
|
||||
return Settings::value(Settings::Server::ExternalConfigFile).toString();
|
||||
}
|
||||
|
||||
bool ServerConfig::useExternalConfig() const
|
||||
{
|
||||
return m_pAppConfig->useExternalConfig();
|
||||
return Settings::value(Settings::Server::ExternalConfig).toBool();
|
||||
}
|
||||
|
||||
bool ServerConfig::isFull() const
|
||||
@ -444,11 +443,12 @@ bool ServerConfig::screenExists(const QString &screenName) const
|
||||
void ServerConfig::addClient(const QString &clientName)
|
||||
{
|
||||
int serverIndex = -1;
|
||||
const auto screenName = Settings::value(Settings::Core::ScreenName).toString();
|
||||
|
||||
if (findScreenName(m_pAppConfig->screenName(), serverIndex)) {
|
||||
if (findScreenName(screenName, serverIndex)) {
|
||||
m_Screens[serverIndex].markAsServer();
|
||||
} else {
|
||||
fixNoServer(m_pAppConfig->screenName(), serverIndex);
|
||||
fixNoServer(screenName, serverIndex);
|
||||
}
|
||||
|
||||
m_Screens.addScreenByPriority(Screen(clientName));
|
||||
@ -456,12 +456,12 @@ void ServerConfig::addClient(const QString &clientName)
|
||||
|
||||
void ServerConfig::setConfigFile(const QString &configFile)
|
||||
{
|
||||
m_pAppConfig->setConfigFile(configFile);
|
||||
Settings::setValue(Settings::Server::ExternalConfigFile, configFile);
|
||||
}
|
||||
|
||||
void ServerConfig::setUseExternalConfig(bool useExternalConfig)
|
||||
{
|
||||
m_pAppConfig->setUseExternalConfig(useExternalConfig);
|
||||
Settings::setValue(Settings::Server::ExternalConfig, useExternalConfig);
|
||||
}
|
||||
|
||||
bool ServerConfig::findScreenName(const QString &name, int &index)
|
||||
@ -538,5 +538,5 @@ size_t ServerConfig::setClipboardSharingSize(size_t size)
|
||||
|
||||
QSettingsProxy &ServerConfig::settings()
|
||||
{
|
||||
return m_pAppConfig->scopes().activeSettings();
|
||||
return Settings::proxy();
|
||||
}
|
||||
|
||||
@ -23,7 +23,6 @@ class QString;
|
||||
class QFile;
|
||||
class ServerConfigDialog;
|
||||
class MainWindow;
|
||||
class AppConfig;
|
||||
|
||||
namespace synergy::gui {
|
||||
|
||||
@ -40,14 +39,13 @@ const auto kDefaultProtocol = ServerProtocol::kBarrier;
|
||||
|
||||
class ServerConfig : public ScreenConfig, public deskflow::gui::IServerConfig
|
||||
{
|
||||
using QSettingsProxy = deskflow::gui::proxy::QSettingsProxy;
|
||||
using ServerProtocol = synergy::gui::ServerProtocol;
|
||||
|
||||
friend class ServerConfigDialog;
|
||||
friend QTextStream &operator<<(QTextStream &outStream, const ServerConfig &config);
|
||||
|
||||
public:
|
||||
ServerConfig(AppConfig &appConfig, MainWindow &mainWindow, int columns = kDefaultColumns, int rows = kDefaultRows);
|
||||
ServerConfig(MainWindow &mainWindow, int columns = kDefaultColumns, int rows = kDefaultRows);
|
||||
~ServerConfig() override = default;
|
||||
|
||||
bool operator==(const ServerConfig &sc) const;
|
||||
@ -155,9 +153,9 @@ public:
|
||||
void commit();
|
||||
int numScreens() const;
|
||||
int autoAddScreen(const QString name);
|
||||
const QString &getServerName() const;
|
||||
const QString getServerName() const;
|
||||
void updateServerName();
|
||||
const QString &configFile() const;
|
||||
const QString configFile() const;
|
||||
bool useExternalConfig() const;
|
||||
void addClient(const QString &clientName);
|
||||
QString getClientAddress() const;
|
||||
@ -278,7 +276,6 @@ private:
|
||||
QList<bool> m_SwitchCorners;
|
||||
HotkeyList m_Hotkeys;
|
||||
|
||||
AppConfig *m_pAppConfig;
|
||||
MainWindow *m_pMainWindow;
|
||||
ScreenList m_Screens;
|
||||
int m_Columns;
|
||||
|
||||
@ -6,8 +6,7 @@
|
||||
|
||||
#include "VersionChecker.h"
|
||||
|
||||
#include "common/constants.h"
|
||||
#include "gui/env_vars.h"
|
||||
#include "common/Settings.h"
|
||||
|
||||
#include <QLocale>
|
||||
#include <QNetworkAccessManager>
|
||||
@ -17,18 +16,14 @@
|
||||
#include <QRegularExpression>
|
||||
#include <memory>
|
||||
|
||||
using namespace deskflow::gui;
|
||||
|
||||
VersionChecker::VersionChecker(std::shared_ptr<QNetworkAccessManagerProxy> network)
|
||||
: m_network(network ? network : std::make_shared<QNetworkAccessManagerProxy>())
|
||||
VersionChecker::VersionChecker(QObject *parent) : QObject(parent), m_network{new QNetworkAccessManager(this)}
|
||||
{
|
||||
m_network->init();
|
||||
connect(m_network.get(), &QNetworkAccessManagerProxy::finished, this, &VersionChecker::replyFinished);
|
||||
connect(m_network, &QNetworkAccessManager::finished, this, &VersionChecker::replyFinished, Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
void VersionChecker::checkLatest() const
|
||||
{
|
||||
const QString url = env_vars::versionUrl();
|
||||
const QString url = Settings::value(Settings::Core::UpdateUrl).toString();
|
||||
qDebug("checking for updates at: %s", qPrintable(url));
|
||||
auto request = QNetworkRequest(url);
|
||||
auto userAgent = QString("%1 %2 on %3").arg(kAppName, kVersion, QSysInfo::prettyProductName());
|
||||
@ -50,13 +45,20 @@ void VersionChecker::replyFinished(QNetworkReply *reply)
|
||||
qDebug("version check server success, http status: %d", httpStatus);
|
||||
|
||||
const auto newestVersion = QString(reply->readAll());
|
||||
reply->deleteLater();
|
||||
qDebug("version check response: %s", qPrintable(newestVersion));
|
||||
|
||||
if (!newestVersion.isEmpty() && compareVersions(kVersion, newestVersion) > 0) {
|
||||
qDebug("update found");
|
||||
if (newestVersion.isEmpty()) {
|
||||
qWarning() << "version check is response is empty";
|
||||
return;
|
||||
}
|
||||
|
||||
if (compareVersions(kVersion, newestVersion) > 0) {
|
||||
qWarning().noquote() //
|
||||
<< QStringLiteral("current version %1 out of date, update available: %2").arg(kVersion, newestVersion);
|
||||
Q_EMIT updateFound(newestVersion);
|
||||
} else {
|
||||
qDebug("no updates found");
|
||||
qDebug().noquote() << QStringLiteral("current version %1 is upto date").arg(kVersion);
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,8 +99,11 @@ int VersionChecker::compareVersions(const QString &left, const QString &right)
|
||||
QStringList leftParts = left.split("-");
|
||||
QStringList rightParts = right.split("-");
|
||||
|
||||
QStringList leftNumberParts = left.split(".");
|
||||
QStringList rightNumberParts = right.split(".");
|
||||
QString leftNumber = leftParts.at(0);
|
||||
QString rightNumber = rightParts.at(0);
|
||||
|
||||
QStringList leftNumberParts = leftNumber.split(".");
|
||||
QStringList rightNumberParts = rightNumber.split(".");
|
||||
|
||||
auto leftStagePart = leftParts.size() > 1 ? leftParts.at(1) : "";
|
||||
auto rightStagePart = rightParts.size() > 1 ? rightParts.at(1) : "";
|
||||
|
||||
@ -6,26 +6,18 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gui/proxy/QNetworkAccessManagerProxy.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <memory>
|
||||
|
||||
class QNetworkAccessManager;
|
||||
class QNetworkReply;
|
||||
class VersionCheckerTests;
|
||||
|
||||
class VersionChecker : public QObject
|
||||
{
|
||||
using QNetworkAccessManagerProxy = deskflow::gui::proxy::QNetworkAccessManagerProxy;
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
friend class VersionCheckerTests;
|
||||
|
||||
public:
|
||||
explicit VersionChecker(std::shared_ptr<QNetworkAccessManagerProxy> network = nullptr);
|
||||
explicit VersionChecker(QObject *parent = nullptr);
|
||||
void checkLatest() const;
|
||||
public slots:
|
||||
void replyFinished(QNetworkReply *reply);
|
||||
@ -42,6 +34,5 @@ private:
|
||||
* more recent the version
|
||||
*/
|
||||
static int getStageVersion(QString stage);
|
||||
|
||||
std::shared_ptr<QNetworkAccessManagerProxy> m_network;
|
||||
QNetworkAccessManager *m_network = nullptr;
|
||||
};
|
||||
|
||||
@ -9,8 +9,7 @@
|
||||
#include "AboutDialog.h"
|
||||
#include "ui_AboutDialog.h"
|
||||
|
||||
#include "common/constants.h"
|
||||
#include "gui/style_utils.h"
|
||||
#include "common/Constants.h"
|
||||
|
||||
#include <QClipboard>
|
||||
#include <QDateTime>
|
||||
@ -32,15 +31,7 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui{std::make_unique
|
||||
ui->btnCopyVersion->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::EditCopy));
|
||||
connect(ui->btnCopyVersion, &QPushButton::clicked, this, &AboutDialog::copyVersionText);
|
||||
|
||||
// Set up the displayed version number
|
||||
auto versionString = QString(kVersion);
|
||||
if (versionString.endsWith(QStringLiteral(".0"))) {
|
||||
versionString.chop(2);
|
||||
} else {
|
||||
versionString.append(QStringLiteral(" (%1)").arg(kVersionGitSha));
|
||||
}
|
||||
|
||||
ui->lblVersion->setText(versionString);
|
||||
ui->lblVersion->setText(kDisplayVersion);
|
||||
|
||||
ui->lblDescription->setText(kAppDescription);
|
||||
ui->lblCopyright->setText(kCopyright);
|
||||
|
||||
@ -149,7 +149,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Computers to recieve this event</string>
|
||||
<string>Computers to receive this event</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="_3">
|
||||
<item>
|
||||
|
||||
@ -45,8 +45,9 @@ FingerprintDialog::FingerprintDialog(
|
||||
connect(m_buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &QDialog::accept);
|
||||
} else {
|
||||
setWindowTitle(tr("Security Question"));
|
||||
auto body = tr("Compare the fingerprints in this dialog to those on the %1.\n"
|
||||
"Only connect if they match!");
|
||||
auto body =
|
||||
tr("Compare the fingerprints in this dialog to those on the %1.\n"
|
||||
"Only connect if they match!");
|
||||
|
||||
if (mode == FingerprintDialogMode::Server) {
|
||||
m_lblHeader->setText(tr("A new client is connecting.\n%1").arg(body.arg(tr("client"))));
|
||||
|
||||
@ -8,11 +8,11 @@
|
||||
#include "ScreenSettingsDialog.h"
|
||||
#include "ui_ScreenSettingsDialog.h"
|
||||
|
||||
#include "gui/Styles.h"
|
||||
#include "gui/config/Screen.h"
|
||||
#include "gui/styles.h"
|
||||
#include "gui/validators/AliasValidator.h"
|
||||
#include "gui/validators/ScreenNameValidator.h"
|
||||
#include "gui/validators/ValidationError.h"
|
||||
#include "validators/AliasValidator.h"
|
||||
#include "validators/ScreenNameValidator.h"
|
||||
#include "validators/ValidationError.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
#include "ServerConfigDialog.h"
|
||||
#include "ui_ServerConfigDialog.h"
|
||||
|
||||
#include "common/constants.h"
|
||||
#include "common/Constants.h"
|
||||
#include "dialogs/ActionDialog.h"
|
||||
#include "dialogs/HotkeyDialog.h"
|
||||
#include "dialogs/ScreenSettingsDialog.h"
|
||||
@ -22,7 +22,7 @@
|
||||
using enum ScreenConfig::SwitchCorner;
|
||||
using ServerProtocol = synergy::gui::ServerProtocol;
|
||||
|
||||
ServerConfigDialog::ServerConfigDialog(QWidget *parent, ServerConfig &config, AppConfig &appConfig)
|
||||
ServerConfigDialog::ServerConfigDialog(QWidget *parent, ServerConfig &config)
|
||||
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint),
|
||||
ui{std::make_unique<Ui::ServerConfigDialog>()},
|
||||
m_OriginalServerConfig(config),
|
||||
@ -30,8 +30,7 @@ ServerConfigDialog::ServerConfigDialog(QWidget *parent, ServerConfig &config, Ap
|
||||
m_OriginalServerConfigUsesExternalFile(config.configFile()),
|
||||
m_ServerConfig(config),
|
||||
m_ScreenSetupModel(serverConfig().screens(), serverConfig().numColumns(), serverConfig().numRows()),
|
||||
m_Message(""),
|
||||
m_appConfig(appConfig)
|
||||
m_Message("")
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
|
||||
@ -10,7 +10,6 @@
|
||||
|
||||
#include "ScreenSetupModel.h"
|
||||
#include "ServerConfig.h"
|
||||
#include "gui/config/AppConfig.h"
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
@ -25,7 +24,7 @@ class ServerConfigDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ServerConfigDialog(QWidget *parent, ServerConfig &config, AppConfig &appConfig);
|
||||
ServerConfigDialog(QWidget *parent, ServerConfig &config);
|
||||
~ServerConfigDialog();
|
||||
bool addClient(const QString &clientName);
|
||||
|
||||
@ -93,10 +92,6 @@ protected:
|
||||
{
|
||||
return m_ScreenSetupModel;
|
||||
}
|
||||
AppConfig &appConfig()
|
||||
{
|
||||
return m_appConfig;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui::ServerConfigDialog> ui;
|
||||
@ -106,7 +101,6 @@ private:
|
||||
QString m_OriginalServerConfigUsesExternalFile;
|
||||
ScreenSetupModel m_ScreenSetupModel;
|
||||
QString m_Message;
|
||||
AppConfig &m_appConfig;
|
||||
|
||||
private slots:
|
||||
void onChange();
|
||||
|
||||
@ -9,8 +9,9 @@
|
||||
#include "SettingsDialog.h"
|
||||
#include "ui_SettingsDialog.h"
|
||||
|
||||
#include "common/Settings.h"
|
||||
#include "gui/Messages.h"
|
||||
#include "gui/core/CoreProcess.h"
|
||||
#include "gui/messages.h"
|
||||
#include "gui/tls/TlsCertificate.h"
|
||||
#include "gui/tls/TlsUtility.h"
|
||||
|
||||
@ -20,15 +21,12 @@
|
||||
|
||||
using namespace deskflow::gui;
|
||||
|
||||
SettingsDialog::SettingsDialog(
|
||||
QWidget *parent, AppConfig &appConfig, const IServerConfig &serverConfig, const CoreProcess &coreProcess
|
||||
)
|
||||
SettingsDialog::SettingsDialog(QWidget *parent, const IServerConfig &serverConfig, const CoreProcess &coreProcess)
|
||||
: QDialog(parent),
|
||||
ui{std::make_unique<Ui::SettingsDialog>()},
|
||||
m_appConfig(appConfig),
|
||||
m_serverConfig(serverConfig),
|
||||
m_coreProcess(coreProcess),
|
||||
m_tlsUtility(appConfig)
|
||||
m_tlsUtility(this)
|
||||
{
|
||||
|
||||
ui->setupUi(this);
|
||||
@ -36,6 +34,7 @@ SettingsDialog::SettingsDialog(
|
||||
ui->comboTlsKeyLength->setItemIcon(0, QIcon::fromTheme(QIcon::ThemeIcon::SecurityLow));
|
||||
ui->comboTlsKeyLength->setItemIcon(1, QIcon::fromTheme(QStringLiteral("security-medium")));
|
||||
ui->comboTlsKeyLength->setItemIcon(2, QIcon::fromTheme(QIcon::ThemeIcon::SecurityHigh));
|
||||
ui->lblTlsCertInfo->setFixedSize(28, 28);
|
||||
|
||||
ui->rbIconMono->setIcon(QIcon::fromTheme(QStringLiteral("deskflow-symbolic")));
|
||||
ui->rbIconColorful->setIcon(QIcon::fromTheme(QStringLiteral("deskflow")));
|
||||
@ -45,7 +44,6 @@ SettingsDialog::SettingsDialog(
|
||||
ui->tabWidget->setCurrentIndex(0);
|
||||
|
||||
loadFromConfig();
|
||||
m_wasOriginallySystemScope = m_appConfig.isActiveScopeSystem();
|
||||
updateControls();
|
||||
|
||||
adjustSize();
|
||||
@ -59,25 +57,26 @@ SettingsDialog::SettingsDialog(
|
||||
void SettingsDialog::initConnections()
|
||||
{
|
||||
connect(this, &SettingsDialog::shown, this, &SettingsDialog::showReadOnlyMessage, Qt::QueuedConnection);
|
||||
connect(Settings::instance(), &Settings::writableChanged, this, &SettingsDialog::showReadOnlyMessage);
|
||||
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &SettingsDialog::accept);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &SettingsDialog::reject);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
connect(ui->groupSecurity, &QGroupBox::toggled, this, &SettingsDialog::updateTlsControlsEnabled);
|
||||
connect(ui->cbServiceEnabled, &QCheckBox::toggled, this, &SettingsDialog::updateControls);
|
||||
connect(ui->btnTlsRegenCert, &QPushButton::clicked, this, &SettingsDialog::regenCertificates);
|
||||
connect(ui->comboTlsKeyLength, &QComboBox::currentIndexChanged, this, &SettingsDialog::updateRequestedKeySize);
|
||||
connect(ui->btnTlsCertPath, &QPushButton::clicked, this, &SettingsDialog::browseCertificatePath);
|
||||
connect(ui->btnBrowseLog, &QPushButton::clicked, this, &SettingsDialog::browseLogPath);
|
||||
connect(ui->cbLogToFile, &QCheckBox::toggled, this, &SettingsDialog::setLogToFile);
|
||||
|
||||
// We only need to test the System scoped Radio as they are connected
|
||||
connect(ui->rbScopeSystem, &QRadioButton::toggled, this, &SettingsDialog::setSystemScope);
|
||||
}
|
||||
|
||||
void SettingsDialog::regenCertificates()
|
||||
{
|
||||
if (m_tlsUtility.generateCertificate()) {
|
||||
QMessageBox::information(this, tr("TLS Certificate Regenerated"), tr("TLS certificate regenerated successfully."));
|
||||
const auto certificate = Settings::value(Settings::Security::Certificate).toString();
|
||||
updateKeyLengthOnFile(certificate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,17 +113,6 @@ void SettingsDialog::setLogToFile(bool logToFile)
|
||||
ui->widgetLogFilename->setEnabled(logToFile);
|
||||
}
|
||||
|
||||
void SettingsDialog::setSystemScope(bool systemScope)
|
||||
{
|
||||
m_appConfig.setLoadFromSystemScope(systemScope);
|
||||
loadFromConfig();
|
||||
updateControls();
|
||||
|
||||
if (isVisible() && !m_appConfig.isActiveScopeWritable()) {
|
||||
showReadOnlyMessage();
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsDialog::showEvent(QShowEvent *event)
|
||||
{
|
||||
QDialog::showEvent(event);
|
||||
@ -133,79 +121,63 @@ void SettingsDialog::showEvent(QShowEvent *event)
|
||||
|
||||
void SettingsDialog::showReadOnlyMessage()
|
||||
{
|
||||
if (m_appConfig.isActiveScopeWritable())
|
||||
if (Settings::isWritable())
|
||||
return;
|
||||
const auto activeScopeFilename = m_appConfig.scopes().activeFilePath();
|
||||
messages::showReadOnlySettings(this, activeScopeFilename);
|
||||
messages::showReadOnlySettings(this, Settings::settingsFile());
|
||||
}
|
||||
|
||||
void SettingsDialog::accept()
|
||||
{
|
||||
m_appConfig.setLoadFromSystemScope(ui->rbScopeSystem->isChecked());
|
||||
m_appConfig.setPort(ui->sbPort->value());
|
||||
m_appConfig.setNetworkInterface(ui->lineInterface->text());
|
||||
m_appConfig.setLogLevel(ui->comboLogLevel->currentIndex());
|
||||
m_appConfig.setLogToFile(ui->cbLogToFile->isChecked());
|
||||
m_appConfig.setLogFilename(ui->lineLogFilename->text());
|
||||
m_appConfig.setElevateMode(static_cast<ElevateMode>(ui->comboElevate->currentIndex()));
|
||||
m_appConfig.setAutoHide(ui->cbAutoHide->isChecked());
|
||||
m_appConfig.setEnableUpdateCheck(ui->cbAutoUpdate->isChecked());
|
||||
m_appConfig.setPreventSleep(ui->cbPreventSleep->isChecked());
|
||||
m_appConfig.setTlsCertPath(ui->lineTlsCertPath->text());
|
||||
m_appConfig.setTlsKeyLength(ui->comboTlsKeyLength->currentText().toInt());
|
||||
m_appConfig.setTlsEnabled(ui->groupSecurity->isChecked());
|
||||
m_appConfig.setLanguageSync(ui->cbLanguageSync->isChecked());
|
||||
m_appConfig.setInvertScrollDirection(ui->cbScrollDirection->isChecked());
|
||||
m_appConfig.setEnableService(ui->cbServiceEnabled->isChecked());
|
||||
m_appConfig.setCloseToTray(ui->cbCloseToTray->isChecked());
|
||||
m_appConfig.setColorfulTrayIcon(ui->rbIconColorful->isChecked());
|
||||
m_appConfig.setRequireClientCerts(ui->cbRequireClientCert->isChecked());
|
||||
Settings::setValue(Settings::Core::Port, ui->sbPort->value());
|
||||
Settings::setValue(Settings::Core::Interface, ui->lineInterface->text());
|
||||
Settings::setValue(Settings::Log::Level, ui->comboLogLevel->currentIndex());
|
||||
Settings::setValue(Settings::Log::ToFile, ui->cbLogToFile->isChecked());
|
||||
Settings::setValue(Settings::Log::File, ui->lineLogFilename->text());
|
||||
Settings::setValue(Settings::Core::ElevateMode, ui->comboElevate->currentIndex());
|
||||
Settings::setValue(Settings::Gui::Autohide, ui->cbAutoHide->isChecked());
|
||||
Settings::setValue(Settings::Gui::AutoUpdateCheck, ui->cbAutoUpdate->isChecked());
|
||||
Settings::setValue(Settings::Core::PreventSleep, ui->cbPreventSleep->isChecked());
|
||||
Settings::setValue(Settings::Security::Certificate, ui->lineTlsCertPath->text());
|
||||
Settings::setValue(Settings::Security::KeySize, ui->comboTlsKeyLength->currentText().toInt());
|
||||
Settings::setValue(Settings::Security::TlsEnabled, ui->groupSecurity->isChecked());
|
||||
Settings::setValue(Settings::Client::LanguageSync, ui->cbLanguageSync->isChecked());
|
||||
Settings::setValue(Settings::Client::InvertScrollDirection, ui->cbScrollDirection->isChecked());
|
||||
Settings::setValue(Settings::Gui::CloseToTray, ui->cbCloseToTray->isChecked());
|
||||
Settings::setValue(Settings::Gui::SymbolicTrayIcon, ui->rbIconMono->isChecked());
|
||||
Settings::setValue(Settings::Security::CheckPeers, ui->cbRequireClientCert->isChecked());
|
||||
|
||||
Settings::ProcessMode mode;
|
||||
if (ui->cbServiceEnabled->isChecked())
|
||||
mode = Settings::ProcessMode::Service;
|
||||
else
|
||||
mode = Settings::ProcessMode::Desktop;
|
||||
Settings::setValue(Settings::Core::ProcessMode, mode);
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void SettingsDialog::reject()
|
||||
{
|
||||
// restore original system scope value on reject.
|
||||
if (m_appConfig.isActiveScopeSystem() != m_wasOriginallySystemScope) {
|
||||
m_appConfig.setLoadFromSystemScope(m_wasOriginallySystemScope);
|
||||
}
|
||||
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
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());
|
||||
ui->cbAutoHide->setChecked(Settings::value(Settings::Gui::Autohide).toBool());
|
||||
ui->cbPreventSleep->setChecked(Settings::value(Settings::Core::PreventSleep).toBool());
|
||||
ui->cbLanguageSync->setChecked(Settings::value(Settings::Client::LanguageSync).toBool());
|
||||
ui->cbScrollDirection->setChecked(Settings::value(Settings::Client::InvertScrollDirection).toBool());
|
||||
ui->cbCloseToTray->setChecked(Settings::value(Settings::Gui::CloseToTray).toBool());
|
||||
ui->comboElevate->setCurrentIndex(Settings::value(Settings::Core::ElevateMode).toInt());
|
||||
ui->cbAutoUpdate->setChecked(Settings::value(Settings::Gui::Autohide).toBool());
|
||||
|
||||
ui->sbPort->setValue(m_appConfig.port());
|
||||
ui->lineInterface->setText(m_appConfig.networkInterface());
|
||||
ui->comboLogLevel->setCurrentIndex(m_appConfig.logLevel());
|
||||
ui->cbLogToFile->setChecked(m_appConfig.logToFile());
|
||||
ui->lineLogFilename->setText(m_appConfig.logFilename());
|
||||
ui->cbAutoHide->setChecked(m_appConfig.autoHide());
|
||||
ui->cbPreventSleep->setChecked(m_appConfig.preventSleep());
|
||||
ui->cbLanguageSync->setChecked(m_appConfig.languageSync());
|
||||
ui->cbScrollDirection->setChecked(m_appConfig.invertScrollDirection());
|
||||
ui->cbServiceEnabled->setChecked(m_appConfig.enableService());
|
||||
ui->cbCloseToTray->setChecked(m_appConfig.closeToTray());
|
||||
ui->comboElevate->setCurrentIndex(static_cast<int>(m_appConfig.elevateMode()));
|
||||
const auto processMode = Settings::value(Settings::Core::ProcessMode).value<Settings::ProcessMode>();
|
||||
ui->cbServiceEnabled->setChecked(processMode == Settings::ProcessMode::Service);
|
||||
|
||||
if (m_appConfig.enableUpdateCheck().has_value()) {
|
||||
ui->cbAutoUpdate->setChecked(m_appConfig.enableUpdateCheck().value());
|
||||
} else {
|
||||
ui->cbAutoUpdate->setChecked(false);
|
||||
}
|
||||
|
||||
if (m_appConfig.isActiveScopeSystem()) {
|
||||
ui->rbScopeSystem->setChecked(true);
|
||||
} else {
|
||||
ui->rbScopeUser->setChecked(true);
|
||||
}
|
||||
|
||||
if (m_appConfig.colorfulTrayIcon())
|
||||
ui->rbIconColorful->setChecked(true);
|
||||
else
|
||||
if (Settings::value(Settings::Gui::SymbolicTrayIcon).toBool())
|
||||
ui->rbIconMono->setChecked(true);
|
||||
else
|
||||
ui->rbIconColorful->setChecked(true);
|
||||
|
||||
qDebug() << "load from config done";
|
||||
updateTlsControls();
|
||||
@ -213,20 +185,19 @@ void SettingsDialog::loadFromConfig()
|
||||
|
||||
void SettingsDialog::updateTlsControls()
|
||||
{
|
||||
|
||||
if (QFile(m_appConfig.tlsCertPath()).exists()) {
|
||||
updateKeyLengthOnFile(m_appConfig.tlsCertPath());
|
||||
} else {
|
||||
const auto keyLengthText = QString::number(m_appConfig.tlsKeyLength());
|
||||
ui->comboTlsKeyLength->setCurrentIndex(ui->comboTlsKeyLength->findText(keyLengthText));
|
||||
const auto certificate = Settings::value(Settings::Security::Certificate).toString();
|
||||
if (QFile(certificate).exists()) {
|
||||
updateKeyLengthOnFile(certificate);
|
||||
}
|
||||
|
||||
const auto tlsEnabled = m_tlsUtility.isEnabled();
|
||||
const auto writable = m_appConfig.isActiveScopeWritable();
|
||||
ui->comboTlsKeyLength->setCurrentText(Settings::value(Settings::Security::KeySize).toString());
|
||||
|
||||
const auto tlsEnabled = Settings::value(Settings::Security::TlsEnabled).toBool();
|
||||
const auto writable = Settings::isWritable();
|
||||
const auto enabled = writable && tlsEnabled;
|
||||
|
||||
ui->lineTlsCertPath->setText(m_appConfig.tlsCertPath());
|
||||
ui->cbRequireClientCert->setChecked(m_appConfig.requireClientCerts());
|
||||
ui->lineTlsCertPath->setText(certificate);
|
||||
ui->cbRequireClientCert->setChecked(Settings::value(Settings::Security::CheckPeers).toBool());
|
||||
ui->groupSecurity->setChecked(tlsEnabled);
|
||||
|
||||
ui->groupSecurity->setEnabled(writable);
|
||||
@ -239,8 +210,9 @@ void SettingsDialog::updateTlsControls()
|
||||
|
||||
void SettingsDialog::updateTlsControlsEnabled()
|
||||
{
|
||||
const auto writable = m_appConfig.isActiveScopeWritable();
|
||||
const auto clientMode = m_appConfig.clientGroupChecked();
|
||||
const auto writable = Settings::isWritable();
|
||||
const auto clientMode =
|
||||
Settings::value(Settings::Core::CoreMode).value<Settings::CoreMode>() == Settings::CoreMode::Client;
|
||||
const auto tlsChecked = ui->groupSecurity->isChecked();
|
||||
|
||||
auto enabled = writable && tlsChecked && !clientMode;
|
||||
@ -254,7 +226,7 @@ void SettingsDialog::updateTlsControlsEnabled()
|
||||
|
||||
bool SettingsDialog::isClientMode() const
|
||||
{
|
||||
return m_coreProcess.mode() == deskflow::gui::CoreProcess::Mode::Client;
|
||||
return m_coreProcess.mode() == Settings::CoreMode::Client;
|
||||
}
|
||||
|
||||
void SettingsDialog::updateKeyLengthOnFile(const QString &path)
|
||||
@ -265,9 +237,14 @@ void SettingsDialog::updateKeyLengthOnFile(const QString &path)
|
||||
}
|
||||
|
||||
auto length = ssl.getCertKeyLength(path);
|
||||
auto index = ui->comboTlsKeyLength->findText(QString::number(length));
|
||||
ui->comboTlsKeyLength->setCurrentIndex(index);
|
||||
m_appConfig.setTlsKeyLength(length);
|
||||
QPixmap labelIcon = QPixmap(QIcon::fromTheme(QIcon::ThemeIcon::SecurityLow).pixmap(24, 24));
|
||||
if (length == 2048)
|
||||
labelIcon = QPixmap(QIcon::fromTheme(QStringLiteral("security-medium")).pixmap(24, 24));
|
||||
if (length == 4096)
|
||||
labelIcon = QPixmap(QIcon::fromTheme(QIcon::ThemeIcon::SecurityHigh).pixmap(24, 24));
|
||||
|
||||
ui->lblTlsCertInfo->setPixmap(labelIcon);
|
||||
ui->lblTlsCertInfo->setToolTip(QStringLiteral("Key length: %1 bits").arg(QString::number(length)));
|
||||
}
|
||||
|
||||
void SettingsDialog::updateControls()
|
||||
@ -281,7 +258,7 @@ void SettingsDialog::updateControls()
|
||||
ui->groupService->setTitle("Service (Windows only)");
|
||||
#endif
|
||||
|
||||
const bool writable = m_appConfig.isActiveScopeWritable();
|
||||
const bool writable = Settings::isWritable();
|
||||
const bool serviceChecked = ui->cbServiceEnabled->isChecked();
|
||||
const bool logToFile = ui->cbLogToFile->isChecked();
|
||||
|
||||
@ -307,4 +284,11 @@ void SettingsDialog::updateControls()
|
||||
updateTlsControls();
|
||||
}
|
||||
|
||||
void SettingsDialog::updateRequestedKeySize()
|
||||
{
|
||||
if (ui->comboTlsKeyLength->currentText() == Settings::value(Settings::Security::KeySize).toString())
|
||||
return;
|
||||
Settings::setValue(Settings::Security::KeySize, ui->comboTlsKeyLength->currentText());
|
||||
}
|
||||
|
||||
SettingsDialog::~SettingsDialog() = default;
|
||||
|
||||
@ -9,11 +9,10 @@
|
||||
#pragma once
|
||||
#include <QDialog>
|
||||
|
||||
#include "gui/config/AppConfig.h"
|
||||
#include "gui/config/IServerConfig.h"
|
||||
#include "gui/core/CoreProcess.h"
|
||||
#include "gui/tls/TlsUtility.h"
|
||||
#include "gui/validators/ValidationError.h"
|
||||
#include "validators/ValidationError.h"
|
||||
|
||||
namespace Ui {
|
||||
class SettingsDialog;
|
||||
@ -28,9 +27,7 @@ class SettingsDialog : public QDialog
|
||||
|
||||
public:
|
||||
void extracted();
|
||||
SettingsDialog(
|
||||
QWidget *parent, AppConfig &appConfig, const IServerConfig &serverConfig, const CoreProcess &coreProcess
|
||||
);
|
||||
SettingsDialog(QWidget *parent, const IServerConfig &serverConfig, const CoreProcess &coreProcess);
|
||||
~SettingsDialog() override;
|
||||
|
||||
signals:
|
||||
@ -42,9 +39,7 @@ private:
|
||||
void browseCertificatePath();
|
||||
void browseLogPath();
|
||||
void setLogToFile(bool logToFile);
|
||||
void setSystemScope(bool systemScope);
|
||||
void accept() override;
|
||||
void reject() override;
|
||||
void showEvent(QShowEvent *event) override;
|
||||
bool isClientMode() const;
|
||||
void updateTlsControls();
|
||||
@ -54,22 +49,16 @@ private:
|
||||
/// @brief Load all settings.
|
||||
void loadFromConfig();
|
||||
|
||||
/// @brief Enables or disables the TLS regenerate button.
|
||||
void updateTlsRegenerateButton();
|
||||
|
||||
/// @brief Updates the key length value based on the loaded file.
|
||||
void updateKeyLengthOnFile(const QString &path);
|
||||
|
||||
/// @brief Enables controls when they should be.
|
||||
void updateControls();
|
||||
|
||||
/// @brief Stores settings scope at start of settings dialog
|
||||
/// This is necessary to restore state if user changes
|
||||
/// the scope and doesn't save changes
|
||||
bool m_wasOriginallySystemScope = false;
|
||||
/// @brief updates the setting vaule for key size.
|
||||
void updateRequestedKeySize();
|
||||
|
||||
std::unique_ptr<Ui::SettingsDialog> ui;
|
||||
AppConfig &m_appConfig;
|
||||
const IServerConfig &m_serverConfig;
|
||||
const CoreProcess &m_coreProcess;
|
||||
deskflow::gui::TlsUtility m_tlsUtility;
|
||||
|
||||
@ -163,6 +163,13 @@
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblTlsCertInfo">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblTlsCert">
|
||||
<property name="sizePolicy">
|
||||
@ -176,22 +183,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Policy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineTlsCertPath">
|
||||
<property name="minimumSize">
|
||||
@ -656,38 +647,6 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupScope">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Use settings profile from</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="_5">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbScopeUser">
|
||||
<property name="text">
|
||||
<string>Current user</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbScopeSystem">
|
||||
<property name="text">
|
||||
<string>All users</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
@ -728,8 +687,6 @@
|
||||
<tabstop>btnBrowseLog</tabstop>
|
||||
<tabstop>cbServiceEnabled</tabstop>
|
||||
<tabstop>comboElevate</tabstop>
|
||||
<tabstop>rbScopeUser</tabstop>
|
||||
<tabstop>rbScopeSystem</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
||||
@ -6,17 +6,15 @@
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "Diagnostic.h"
|
||||
#include "MainWindow.h"
|
||||
#include "common/constants.h"
|
||||
#include "StyleUtils.h"
|
||||
|
||||
#include "common/Constants.h"
|
||||
#include "common/UrlConstants.h"
|
||||
#include "gui/DotEnv.h"
|
||||
#include "gui/Logger.h"
|
||||
#include "gui/config/AppConfig.h"
|
||||
#include "gui/config/ConfigScopes.h"
|
||||
#include "gui/constants.h"
|
||||
#include "gui/diagnostic.h"
|
||||
#include "gui/dotenv.h"
|
||||
#include "gui/messages.h"
|
||||
#include "gui/string_utils.h"
|
||||
#include "gui/style_utils.h"
|
||||
#include "gui/Messages.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
@ -120,8 +118,10 @@ int main(int argc, char *argv[])
|
||||
#if defined(Q_OS_MAC)
|
||||
|
||||
if (app.applicationDirPath().startsWith("/Volumes/")) {
|
||||
QString msgBody = QStringLiteral("Please drag %1 to the Applications folder, "
|
||||
"and open it from there.");
|
||||
QString msgBody = QStringLiteral(
|
||||
"Please drag %1 to the Applications folder, "
|
||||
"and open it from there."
|
||||
);
|
||||
QMessageBox::information(NULL, kAppName, msgBody.arg(kAppName));
|
||||
return 1;
|
||||
}
|
||||
@ -131,23 +131,15 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
#endif
|
||||
|
||||
ConfigScopes configScopes;
|
||||
|
||||
// --no-reset
|
||||
QStringList arguments = QCoreApplication::arguments();
|
||||
const auto noReset = hasArg("--no-reset", arguments);
|
||||
const auto resetEnvVar = strToTrue(qEnvironmentVariable("DESKFLOW_RESET_ALL"));
|
||||
const auto resetEnvVar = QVariant(qEnvironmentVariable("DESKFLOW_RESET_ALL")).toBool();
|
||||
if (resetEnvVar && !noReset) {
|
||||
diagnostic::clearSettings(configScopes, false);
|
||||
diagnostic::clearSettings(false);
|
||||
}
|
||||
|
||||
AppConfig appConfig(configScopes);
|
||||
|
||||
QObject::connect(
|
||||
&configScopes, &ConfigScopes::saving, &appConfig, [&appConfig]() { appConfig.commit(); }, Qt::DirectConnection
|
||||
);
|
||||
|
||||
MainWindow mainWindow(configScopes, appConfig);
|
||||
MainWindow mainWindow;
|
||||
mainWindow.open();
|
||||
|
||||
return QApplication::exec();
|
||||
@ -181,9 +173,11 @@ bool checkMacAssistiveDevices()
|
||||
// now deprecated in mavericks.
|
||||
bool result = AXAPIEnabled();
|
||||
if (!result) {
|
||||
QString msgBody = QString("Please enable access to assistive devices "
|
||||
"System Preferences -> Security & Privacy -> "
|
||||
"Privacy -> Accessibility, then re-open %1.");
|
||||
QString msgBody = QString(
|
||||
"Please enable access to assistive devices "
|
||||
"System Preferences -> Security & Privacy -> "
|
||||
"Privacy -> Accessibility, then re-open %1."
|
||||
);
|
||||
QMessageBox::information(NULL, kAppName, msgBody.arg(kAppName));
|
||||
}
|
||||
return result;
|
||||
|
||||
@ -4,11 +4,11 @@
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "gui/validators/ComputerNameValidator.h"
|
||||
#include "gui/validators/SpacesValidator.h"
|
||||
|
||||
#include "AliasValidator.h"
|
||||
|
||||
#include "ComputerNameValidator.h"
|
||||
#include "SpacesValidator.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
|
||||
namespace validators {
|
||||
@ -7,7 +7,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "LineEditValidator.h"
|
||||
#include "gui/validators/ValidationError.h"
|
||||
#include "ValidationError.h"
|
||||
|
||||
namespace validators {
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
#include "LineEditValidator.h"
|
||||
|
||||
#include "gui/styles.h"
|
||||
#include "gui/Styles.h"
|
||||
|
||||
#include <QValidator>
|
||||
|
||||
@ -6,11 +6,11 @@
|
||||
|
||||
#include "ScreenNameValidator.h"
|
||||
|
||||
#include "gui/validators/ComputerNameValidator.h"
|
||||
#include "gui/validators/EmptyStringValidator.h"
|
||||
#include "gui/validators/ScreenDuplicationsValidator.h"
|
||||
#include "gui/validators/SpacesValidator.h"
|
||||
#include "gui/validators/ValidationError.h"
|
||||
#include "ComputerNameValidator.h"
|
||||
#include "EmptyStringValidator.h"
|
||||
#include "ScreenDuplicationsValidator.h"
|
||||
#include "SpacesValidator.h"
|
||||
#include "ValidationError.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
#include <memory>
|
||||
@ -23,9 +23,11 @@ ScreenNameValidator::ScreenNameValidator(QLineEdit *lineEdit, ValidationError *e
|
||||
addValidator(std::make_unique<EmptyStringValidator>("Computer name cannot be empty"));
|
||||
addValidator(std::make_unique<SpacesValidator>("Computer name cannot contain spaces"));
|
||||
addValidator(std::make_unique<ComputerNameValidator>("Contains invalid characters or is too long"));
|
||||
addValidator(std::make_unique<ScreenDuplicationsValidator>(
|
||||
"A computer with this name already exists", lineEdit ? lineEdit->text() : "", pScreens
|
||||
));
|
||||
addValidator(
|
||||
std::make_unique<ScreenDuplicationsValidator>(
|
||||
"A computer with this name already exists", lineEdit ? lineEdit->text() : "", pScreens
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace validators
|
||||
@ -7,8 +7,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "LineEditValidator.h"
|
||||
#include "ValidationError.h"
|
||||
|
||||
#include "gui/config/ScreenList.h"
|
||||
#include "gui/validators/ValidationError.h"
|
||||
|
||||
namespace validators {
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
#include "ValidationError.h"
|
||||
|
||||
#include "gui/styles.h"
|
||||
#include "gui/Styles.h"
|
||||
|
||||
using namespace deskflow::gui;
|
||||
|
||||
@ -18,6 +18,8 @@
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
#if SYSAPI_WIN32
|
||||
ArchMiscWindows::guardRuntimeVersion();
|
||||
|
||||
// record window instance for tray icon, etc
|
||||
ArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL));
|
||||
#endif
|
||||
|
||||
@ -10,27 +10,12 @@
|
||||
/* Define if the <X11/extensions/dpms.h> header file declares function prototypes. */
|
||||
#cmakedefine HAVE_DPMS_PROTOTYPES @HAVE_DPMS_PROTOTYPES@
|
||||
|
||||
/* Define if you have a working `getpwuid_r` function. */
|
||||
#cmakedefine HAVE_GETPWUID_R @HAVE_GETPWUID_R@
|
||||
|
||||
/* Define to 1 if you have the `gmtime_r` function. */
|
||||
#cmakedefine HAVE_GMTIME_R @HAVE_GMTIME_R@
|
||||
|
||||
/* Define if you have the `inet_aton` function. */
|
||||
#cmakedefine HAVE_INET_ATON @HAVE_INET_ATON@
|
||||
|
||||
/* Define to 1 if you have the <istream> header file. */
|
||||
#cmakedefine HAVE_ISTREAM @HAVE_ISTREAM@
|
||||
|
||||
/* Define to 1 if you have the <locale.h> header file. */
|
||||
#cmakedefine HAVE_LOCALE_H @HAVE_LOCALE_H@
|
||||
|
||||
/* Define if you have the `nanosleep` function. */
|
||||
#cmakedefine HAVE_NANOSLEEP @HAVE_NANOSLEEP@
|
||||
|
||||
/* Define to 1 if you have the <ostream> header file. */
|
||||
#cmakedefine HAVE_OSTREAM @HAVE_OSTREAM@
|
||||
|
||||
/* Define if you have a POSIX `sigwait` function. */
|
||||
#cmakedefine HAVE_POSIX_SIGWAIT @HAVE_POSIX_SIGWAIT@
|
||||
|
||||
@ -43,9 +28,6 @@
|
||||
/* Define if your compiler defines socklen_t. */
|
||||
#cmakedefine HAVE_SOCKLEN_T @HAVE_SOCKLEN_T@
|
||||
|
||||
/* Define to 1 if you have the <sstream> header file. */
|
||||
#cmakedefine HAVE_SSTREAM @HAVE_SSTREAM@
|
||||
|
||||
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||
#cmakedefine HAVE_SYS_SELECT_H @HAVE_SYS_SELECT_H@
|
||||
|
||||
@ -58,15 +40,9 @@
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#cmakedefine HAVE_SYS_TYPES_H @HAVE_SYS_TYPES_H@
|
||||
|
||||
/* Define to 1 if you have the <sys/utsname.h> header file. */
|
||||
#cmakedefine HAVE_SYS_UTSNAME_H @HAVE_SYS_UTSNAME_H@
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#cmakedefine HAVE_UNISTD_H @HAVE_UNISTD_H@
|
||||
|
||||
/* Define to 1 if you have the <wchar.h> header file. */
|
||||
#cmakedefine HAVE_WCHAR_H @HAVE_WCHAR_H@
|
||||
|
||||
/* Define to 1 if you have the <X11/extensions/Xrandr.h> header file. */
|
||||
#cmakedefine HAVE_X11_EXTENSIONS_XRANDR_H @HAVE_X11_EXTENSIONS_XRANDR_H@
|
||||
|
||||
@ -30,9 +30,6 @@ Arch::Arch(Arch *arch)
|
||||
|
||||
Arch::~Arch()
|
||||
{
|
||||
#if SYSAPI_WIN32
|
||||
ArchMiscWindows::cleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Arch::init()
|
||||
|
||||
@ -24,31 +24,27 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/common.h"
|
||||
#include "common/Common.h"
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
|
||||
#include "arch/win32/ArchConsoleWindows.h"
|
||||
#include "arch/win32/ArchDaemonWindows.h"
|
||||
#include "arch/win32/ArchFileWindows.h"
|
||||
#include "arch/win32/ArchLogWindows.h"
|
||||
#include "arch/win32/ArchMultithreadWindows.h"
|
||||
#include "arch/win32/ArchNetworkWinsock.h"
|
||||
#include "arch/win32/ArchSleepWindows.h"
|
||||
#include "arch/win32/ArchStringWindows.h"
|
||||
#include "arch/win32/ArchSystemWindows.h"
|
||||
#include "arch/win32/ArchTimeWindows.h"
|
||||
|
||||
#elif SYSAPI_UNIX
|
||||
|
||||
#include "arch/unix/ArchConsoleUnix.h"
|
||||
#include "arch/unix/ArchDaemonUnix.h"
|
||||
#include "arch/unix/ArchFileUnix.h"
|
||||
#include "arch/unix/ArchLogUnix.h"
|
||||
#include "arch/unix/ArchNetworkBSD.h"
|
||||
#include "arch/unix/ArchSleepUnix.h"
|
||||
#include "arch/unix/ArchStringUnix.h"
|
||||
#include "arch/unix/ArchSystemUnix.h"
|
||||
#include "arch/unix/ArchTimeUnix.h"
|
||||
|
||||
#if HAVE_PTHREAD
|
||||
@ -75,13 +71,11 @@ typically at the beginning of \c main().
|
||||
*/
|
||||
class Arch : public ARCH_CONSOLE,
|
||||
public ARCH_DAEMON,
|
||||
public ARCH_FILE,
|
||||
public ARCH_LOG,
|
||||
public ARCH_MULTITHREAD,
|
||||
public ARCH_NETWORK,
|
||||
public ARCH_SLEEP,
|
||||
public ARCH_STRING,
|
||||
public ARCH_SYSTEM,
|
||||
public ARCH_TIME
|
||||
{
|
||||
public:
|
||||
|
||||
@ -10,8 +10,6 @@ if(WIN32)
|
||||
win32/ArchConsoleWindows.h
|
||||
win32/ArchDaemonWindows.cpp
|
||||
win32/ArchDaemonWindows.h
|
||||
win32/ArchFileWindows.cpp
|
||||
win32/ArchFileWindows.h
|
||||
win32/ArchLogWindows.cpp
|
||||
win32/ArchLogWindows.h
|
||||
win32/ArchMiscWindows.cpp
|
||||
@ -24,8 +22,6 @@ if(WIN32)
|
||||
win32/ArchSleepWindows.h
|
||||
win32/ArchStringWindows.cpp
|
||||
win32/ArchStringWindows.h
|
||||
win32/ArchSystemWindows.cpp
|
||||
win32/ArchSystemWindows.h
|
||||
win32/ArchTimeWindows.cpp
|
||||
win32/ArchTimeWindows.h
|
||||
win32/XArchWindows.cpp
|
||||
@ -38,8 +34,6 @@ elseif(UNIX)
|
||||
unix/ArchConsoleUnix.h
|
||||
unix/ArchDaemonUnix.cpp
|
||||
unix/ArchDaemonUnix.h
|
||||
unix/ArchFileUnix.cpp
|
||||
unix/ArchFileUnix.h
|
||||
unix/ArchLogUnix.cpp
|
||||
unix/ArchLogUnix.h
|
||||
unix/ArchMultithreadPosix.cpp
|
||||
@ -50,8 +44,6 @@ elseif(UNIX)
|
||||
unix/ArchSleepUnix.h
|
||||
unix/ArchStringUnix.cpp
|
||||
unix/ArchStringUnix.h
|
||||
unix/ArchSystemUnix.cpp
|
||||
unix/ArchSystemUnix.h
|
||||
unix/ArchTimeUnix.cpp
|
||||
unix/ArchTimeUnix.h
|
||||
unix/XArchUnix.cpp
|
||||
@ -68,23 +60,16 @@ add_library(arch STATIC ${PLATFORM_CODE}
|
||||
ArchDaemonNone.h
|
||||
IArchConsole.h
|
||||
IArchDaemon.h
|
||||
IArchFile.h
|
||||
IArchLog.h
|
||||
IArchMultithread.h
|
||||
IArchNetwork.h
|
||||
IArchSleep.h
|
||||
IArchString.cpp
|
||||
IArchString.h
|
||||
IArchSystem.h
|
||||
IArchTime.h
|
||||
multibyte.h
|
||||
XArch.h
|
||||
)
|
||||
|
||||
if(UNIX)
|
||||
target_link_libraries(arch ${CMAKE_DL_LIBS} ${libs})
|
||||
if(NOT APPLE)
|
||||
find_package(Qt6 ${REQUIRED_QT_VERSION} REQUIRED COMPONENTS DBus)
|
||||
target_link_libraries(arch Qt6::DBus)
|
||||
endif()
|
||||
target_link_libraries(arch ${libs})
|
||||
endif()
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/IInterface.h"
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
//! Interface for architecture dependent daemonizing
|
||||
@ -19,7 +21,7 @@ implement this interface.
|
||||
class IArchDaemon : public IInterface
|
||||
{
|
||||
public:
|
||||
typedef int (*DaemonFunc)(int argc, const char **argv);
|
||||
using DaemonFunc = std::function<int(int, const char **)>;
|
||||
|
||||
//! @name manipulators
|
||||
//@{
|
||||
|
||||
@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/IInterface.h"
|
||||
#include <string>
|
||||
|
||||
//! Interface for architecture dependent file system operations
|
||||
/*!
|
||||
This interface defines the file system operations required by
|
||||
deskflow. Each architecture must implement this interface.
|
||||
*/
|
||||
class IArchFile : public IInterface
|
||||
{
|
||||
public:
|
||||
//! @name manipulators
|
||||
//@{
|
||||
|
||||
//! Extract base name
|
||||
/*!
|
||||
Find the base name in the given \c pathname.
|
||||
*/
|
||||
virtual const char *getBasename(const char *pathname) = 0;
|
||||
|
||||
//! Get user's home directory
|
||||
/*!
|
||||
Returns the user's home directory. Returns the empty string if
|
||||
this cannot be determined.
|
||||
*/
|
||||
virtual std::string getUserDirectory() = 0;
|
||||
|
||||
//! Get system directory
|
||||
/*!
|
||||
Returns the ussystem configuration file directory.
|
||||
*/
|
||||
virtual std::string getSystemDirectory() = 0;
|
||||
|
||||
//! Get installed directory
|
||||
/*!
|
||||
Returns the directory in which Deskflow is installed.
|
||||
*/
|
||||
virtual std::string getInstalledDirectory() = 0;
|
||||
|
||||
//! Get log directory
|
||||
/*!
|
||||
Returns the log file directory.
|
||||
*/
|
||||
virtual std::string getLogDirectory() = 0;
|
||||
|
||||
//! Get plugins directory
|
||||
/*!
|
||||
Returns the plugin files directory. If no plugin directory is set,
|
||||
this will return the plugin folder within the user's profile.
|
||||
*/
|
||||
virtual std::string getPluginDirectory() = 0;
|
||||
|
||||
//! Get user's profile directory
|
||||
/*!
|
||||
Returns the user's profile directory. If no profile directory is set,
|
||||
this will return the user's profile according to the operating system,
|
||||
which will depend on which user launched the program.
|
||||
*/
|
||||
virtual std::string getProfileDirectory() = 0;
|
||||
|
||||
//! Concatenate path components
|
||||
/*!
|
||||
Concatenate pathname components with a directory separator
|
||||
between them. This should not check if the resulting path
|
||||
is longer than allowed by the system; we'll rely on the
|
||||
system calls to tell us that.
|
||||
*/
|
||||
virtual std::string concatPath(const std::string &prefix, const std::string &suffix) = 0;
|
||||
|
||||
//@}
|
||||
//! Set the user's profile directory
|
||||
/*
|
||||
Returns the user's profile directory.
|
||||
*/
|
||||
virtual void setProfileDirectory(const std::string &s) = 0;
|
||||
|
||||
//@}
|
||||
//! Set the user's plugin directory
|
||||
/*
|
||||
Returns the user's plugin directory.
|
||||
*/
|
||||
virtual void setPluginDirectory(const std::string &s) = 0;
|
||||
};
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
#include "arch/IArchString.h"
|
||||
#include "arch/Arch.h"
|
||||
#include "common/common.h"
|
||||
#include "common/Common.h"
|
||||
|
||||
#include <climits>
|
||||
#include <cstdlib>
|
||||
|
||||
@ -8,8 +8,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/Common.h"
|
||||
#include "common/IInterface.h"
|
||||
#include "common/common.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2004 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/IInterface.h"
|
||||
#include <string>
|
||||
|
||||
//! Interface for architecture dependent system queries
|
||||
/*!
|
||||
This interface defines operations for querying system info.
|
||||
*/
|
||||
class IArchSystem : public IInterface
|
||||
{
|
||||
public:
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Identify the OS
|
||||
/*!
|
||||
Returns a string identifying the operating system.
|
||||
*/
|
||||
virtual std::string getOSName() const = 0;
|
||||
|
||||
//! Identify the platform
|
||||
/*!
|
||||
Returns a string identifying the platform this OS is running on.
|
||||
*/
|
||||
virtual std::string getPlatformName() const = 0;
|
||||
//@}
|
||||
|
||||
//! Get a Deskflow setting
|
||||
/*!
|
||||
Reads a Deskflow setting from the system.
|
||||
*/
|
||||
virtual std::string setting(const std::string &valueName) const = 0;
|
||||
//@}
|
||||
|
||||
//! Set a Deskflow setting
|
||||
/*!
|
||||
Writes a Deskflow setting from the system.
|
||||
*/
|
||||
virtual void setting(const std::string &valueName, const std::string &valueString) const = 0;
|
||||
//@}
|
||||
|
||||
//! Delete settings
|
||||
/*!
|
||||
Deletes all Core settings from the system.
|
||||
*/
|
||||
virtual void clearSettings() const = 0;
|
||||
//@}
|
||||
};
|
||||
@ -7,8 +7,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/common.h"
|
||||
#include "common/stdexcept.h"
|
||||
#include "common/Common.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
//! Generic thread exception
|
||||
@ -57,7 +58,7 @@ public:
|
||||
XArchEval()
|
||||
{
|
||||
}
|
||||
virtual ~XArchEval() _NOEXCEPT
|
||||
virtual ~XArchEval() throw()
|
||||
{
|
||||
}
|
||||
|
||||
@ -75,7 +76,7 @@ public:
|
||||
XArch(const std::string &msg) : std::runtime_error(msg)
|
||||
{
|
||||
}
|
||||
virtual ~XArch() _NOEXCEPT
|
||||
virtual ~XArch() throw()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "arch/Arch.h"
|
||||
#include "common/common.h"
|
||||
|
||||
#include <climits>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#if HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
#if HAVE_WCHAR_H || defined(_MSC_VER)
|
||||
#include <wchar.h>
|
||||
#elif __APPLE__
|
||||
// wtf? Darwin puts mbtowc() et al. in stdlib
|
||||
#include <cstdlib>
|
||||
#else
|
||||
// platform apparently has no wchar_t support. provide dummy
|
||||
// implementations. hopefully at least the C++ compiler has
|
||||
// a built-in wchar_t type.
|
||||
|
||||
static inline int mbtowc(wchar_t *dst, const char *src, int n)
|
||||
{
|
||||
*dst = static_cast<wchar_t>(*src);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int wctomb(char *dst, wchar_t src)
|
||||
{
|
||||
*dst = static_cast<char>(src);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,146 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "arch/unix/ArchFileUnix.h"
|
||||
|
||||
#include "common/constants.h"
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
//
|
||||
// ArchFileUnix
|
||||
//
|
||||
|
||||
ArchFileUnix::ArchFileUnix()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
ArchFileUnix::~ArchFileUnix()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
const char *ArchFileUnix::getBasename(const char *pathname)
|
||||
{
|
||||
if (pathname == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *basename = strrchr(pathname, '/');
|
||||
if (basename != NULL) {
|
||||
return basename + 1;
|
||||
} else {
|
||||
return pathname;
|
||||
}
|
||||
}
|
||||
|
||||
std::string ArchFileUnix::getUserDirectory()
|
||||
{
|
||||
char *buffer = NULL;
|
||||
std::string dir;
|
||||
#if HAVE_GETPWUID_R
|
||||
struct passwd pwent;
|
||||
struct passwd *pwentp{};
|
||||
#if defined(_SC_GETPW_R_SIZE_MAX)
|
||||
long size = sysconf(_SC_GETPW_R_SIZE_MAX);
|
||||
if (size == -1) {
|
||||
size = BUFSIZ;
|
||||
}
|
||||
#else
|
||||
long size = BUFSIZ;
|
||||
#endif
|
||||
buffer = new char[size];
|
||||
getpwuid_r(getuid(), &pwent, buffer, size, &pwentp);
|
||||
#else
|
||||
struct passwd *pwentp = getpwuid(getuid());
|
||||
#endif
|
||||
if (pwentp != NULL && pwentp->pw_dir != NULL) {
|
||||
dir = pwentp->pw_dir;
|
||||
}
|
||||
delete[] buffer;
|
||||
return dir;
|
||||
}
|
||||
|
||||
std::string ArchFileUnix::getSystemDirectory()
|
||||
{
|
||||
return "/etc";
|
||||
}
|
||||
|
||||
std::string ArchFileUnix::getInstalledDirectory()
|
||||
{
|
||||
#if WINAPI_XWINDOWS
|
||||
return "/usr/bin";
|
||||
#else
|
||||
std::string rtn = "/Applications/";
|
||||
rtn.append(kAppName).append(".app/Contents/MacOS");
|
||||
return rtn;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string ArchFileUnix::getLogDirectory()
|
||||
{
|
||||
return "/var/log";
|
||||
}
|
||||
|
||||
std::string ArchFileUnix::getPluginDirectory()
|
||||
{
|
||||
if (!m_pluginDirectory.empty()) {
|
||||
return m_pluginDirectory;
|
||||
}
|
||||
|
||||
#if WINAPI_XWINDOWS
|
||||
return getProfileDirectory().append("/plugins");
|
||||
#else
|
||||
return getProfileDirectory().append("/Plugins");
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string ArchFileUnix::getProfileDirectory()
|
||||
{
|
||||
if (!m_profileDirectory.empty()) {
|
||||
return m_profileDirectory;
|
||||
} else {
|
||||
const std::filesystem::path homeDir = getUserDirectory();
|
||||
#if WINAPI_XWINDOWS
|
||||
const auto xdgDir = std::getenv("XDG_CONFIG_HOME");
|
||||
if (xdgDir != nullptr) {
|
||||
return std::filesystem::path(xdgDir) / kAppName;
|
||||
} else {
|
||||
return homeDir / ".config" / kAppName;
|
||||
}
|
||||
#else
|
||||
return homeDir / "Library" / kAppName;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
std::string ArchFileUnix::concatPath(const std::string &prefix, const std::string &suffix)
|
||||
{
|
||||
std::string path;
|
||||
path.reserve(prefix.size() + 1 + suffix.size());
|
||||
path += prefix;
|
||||
if (path.size() == 0 || path[path.size() - 1] != '/') {
|
||||
path += '/';
|
||||
}
|
||||
path += suffix;
|
||||
return path;
|
||||
}
|
||||
|
||||
void ArchFileUnix::setProfileDirectory(const std::string &s)
|
||||
{
|
||||
m_profileDirectory = s;
|
||||
}
|
||||
|
||||
void ArchFileUnix::setPluginDirectory(const std::string &s)
|
||||
{
|
||||
m_pluginDirectory = s;
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "arch/IArchFile.h"
|
||||
|
||||
#define ARCH_FILE ArchFileUnix
|
||||
|
||||
//! Unix implementation of IArchFile
|
||||
class ArchFileUnix : public IArchFile
|
||||
{
|
||||
public:
|
||||
ArchFileUnix();
|
||||
virtual ~ArchFileUnix();
|
||||
|
||||
// IArchFile overrides
|
||||
virtual const char *getBasename(const char *pathname);
|
||||
virtual std::string getUserDirectory();
|
||||
virtual std::string getSystemDirectory();
|
||||
virtual std::string getInstalledDirectory();
|
||||
virtual std::string getLogDirectory();
|
||||
virtual std::string getPluginDirectory();
|
||||
virtual std::string getProfileDirectory();
|
||||
virtual std::string concatPath(const std::string &prefix, const std::string &suffix);
|
||||
virtual void setProfileDirectory(const std::string &s);
|
||||
virtual void setPluginDirectory(const std::string &s);
|
||||
|
||||
private:
|
||||
std::string m_profileDirectory;
|
||||
std::string m_pluginDirectory;
|
||||
};
|
||||
@ -8,8 +8,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "arch/IArchMultithread.h"
|
||||
#include "common/stdlist.h"
|
||||
|
||||
#include <list>
|
||||
#include <pthread.h>
|
||||
|
||||
#define ARCH_MULTITHREAD ArchMultithreadPosix
|
||||
|
||||
@ -13,8 +13,6 @@
|
||||
// ArchStringUnix
|
||||
//
|
||||
|
||||
#include "arch/multibyte.h"
|
||||
|
||||
ArchStringUnix::ArchStringUnix()
|
||||
{
|
||||
}
|
||||
|
||||
@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "arch/unix/ArchSystemUnix.h"
|
||||
#include <array>
|
||||
|
||||
#include <common/constants.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#ifndef __APPLE__
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusError>
|
||||
#include <QDBusInterface>
|
||||
#include <QDBusReply>
|
||||
#endif
|
||||
|
||||
//
|
||||
// ArchSystemUnix
|
||||
//
|
||||
|
||||
ArchSystemUnix::ArchSystemUnix()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
ArchSystemUnix::~ArchSystemUnix()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
std::string ArchSystemUnix::getOSName() const
|
||||
{
|
||||
#if defined(HAVE_SYS_UTSNAME_H)
|
||||
struct utsname info;
|
||||
if (uname(&info) == 0) {
|
||||
std::string msg;
|
||||
msg += info.sysname;
|
||||
msg += " ";
|
||||
msg += info.release;
|
||||
return msg;
|
||||
}
|
||||
#endif
|
||||
return "Unix";
|
||||
}
|
||||
|
||||
std::string ArchSystemUnix::getPlatformName() const
|
||||
{
|
||||
#if defined(HAVE_SYS_UTSNAME_H)
|
||||
struct utsname info;
|
||||
if (uname(&info) == 0) {
|
||||
return std::string(info.machine);
|
||||
}
|
||||
#endif
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
std::string ArchSystemUnix::setting(const std::string &) const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
void ArchSystemUnix::setting(const std::string &, const std::string &) const
|
||||
{
|
||||
}
|
||||
|
||||
void ArchSystemUnix::clearSettings() const
|
||||
{
|
||||
// Not implemented
|
||||
}
|
||||
|
||||
std::string ArchSystemUnix::getLibsUsed(void) const
|
||||
{
|
||||
return "not implemented.\nuse lsof on shell";
|
||||
}
|
||||
|
||||
#ifndef __APPLE__
|
||||
bool ArchSystemUnix::DBusInhibitScreenCall(InhibitScreenServices serviceID, bool state, std::string &error)
|
||||
{
|
||||
error = "";
|
||||
static const std::array<QString, 2> services = {"org.freedesktop.ScreenSaver", "org.gnome.SessionManager"};
|
||||
static const std::array<QString, 2> paths = {"/org/freedesktop/ScreenSaver", "/org/gnome/SessionManager"};
|
||||
static std::array<uint, 2> cookies;
|
||||
|
||||
auto serviceNum = static_cast<uint8_t>(serviceID);
|
||||
|
||||
QDBusConnection bus = QDBusConnection::sessionBus();
|
||||
if (!bus.isConnected()) {
|
||||
error = "bus failed to connect";
|
||||
return false;
|
||||
}
|
||||
|
||||
QDBusInterface screenSaverInterface(services[serviceNum], paths[serviceNum], services[serviceNum], bus);
|
||||
|
||||
if (!screenSaverInterface.isValid()) {
|
||||
error = "screen saver interface failed to initialize";
|
||||
return false;
|
||||
}
|
||||
|
||||
QDBusReply<uint> reply;
|
||||
if (state) {
|
||||
if (cookies[serviceNum]) {
|
||||
error = "coockies are not empty";
|
||||
return false;
|
||||
}
|
||||
|
||||
QString msg = "Sleep is manually prevented by the %1 preferences";
|
||||
reply = screenSaverInterface.call("Inhibit", kAppName, msg.arg(kAppName));
|
||||
if (reply.isValid())
|
||||
cookies[serviceNum] = reply.value();
|
||||
} else {
|
||||
if (!cookies[serviceNum]) {
|
||||
error = "coockies are empty";
|
||||
return false;
|
||||
}
|
||||
reply = screenSaverInterface.call("UnInhibit", cookies[serviceNum]);
|
||||
cookies[serviceNum] = 0;
|
||||
}
|
||||
|
||||
if (!reply.isValid()) {
|
||||
QDBusError qerror = reply.error();
|
||||
error = qerror.name().toStdString() + " : " + qerror.message().toStdString();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "arch/IArchSystem.h"
|
||||
|
||||
#define ARCH_SYSTEM ArchSystemUnix
|
||||
|
||||
//! Unix implementation of IArchString
|
||||
class ArchSystemUnix : public IArchSystem
|
||||
{
|
||||
public:
|
||||
ArchSystemUnix();
|
||||
virtual ~ArchSystemUnix();
|
||||
|
||||
// IArchSystem overrides
|
||||
virtual std::string getOSName() const;
|
||||
virtual std::string getPlatformName() const;
|
||||
virtual std::string setting(const std::string &) const;
|
||||
virtual void setting(const std::string &, const std::string &) const;
|
||||
virtual std::string getLibsUsed(void) const;
|
||||
virtual void clearSettings() const;
|
||||
|
||||
#ifndef __APPLE__
|
||||
enum class InhibitScreenServices
|
||||
{
|
||||
kScreenSaver,
|
||||
kSessionManager
|
||||
};
|
||||
static bool DBusInhibitScreenCall(InhibitScreenServices serviceID, bool state, std::string &error);
|
||||
#endif
|
||||
};
|
||||
@ -16,7 +16,7 @@ public:
|
||||
XArchEvalUnix(int error) : m_error(error)
|
||||
{
|
||||
}
|
||||
virtual ~XArchEvalUnix() _NOEXCEPT
|
||||
virtual ~XArchEvalUnix() throw()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@ -350,6 +350,8 @@ void ArchDaemonWindows::setStatus(DWORD state, DWORD step, DWORD waitHint)
|
||||
{
|
||||
assert(s_daemon != NULL);
|
||||
|
||||
LOG_DEBUG("setting service status: state=%d, step=%d, waitHint=%d", state, step, waitHint);
|
||||
|
||||
SERVICE_STATUS status;
|
||||
status.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;
|
||||
status.dwCurrentState = state;
|
||||
|
||||
@ -9,20 +9,22 @@
|
||||
|
||||
#include "arch/IArchDaemon.h"
|
||||
#include "arch/IArchMultithread.h"
|
||||
#include "common/constants.h"
|
||||
#include <string>
|
||||
#include "common/Constants.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#define ARCH_DAEMON ArchDaemonWindows
|
||||
|
||||
//! Win32 implementation of IArchDaemon
|
||||
class ArchDaemonWindows : public IArchDaemon
|
||||
{
|
||||
public:
|
||||
typedef int (*RunFunc)(void);
|
||||
using RunFunc = std::function<int()>;
|
||||
|
||||
ArchDaemonWindows();
|
||||
virtual ~ArchDaemonWindows();
|
||||
@ -135,7 +137,7 @@ private:
|
||||
};
|
||||
|
||||
#define DEFAULT_DAEMON_NAME _T(kAppName)
|
||||
#define DEFAULT_DAEMON_INFO _T("Manages the Deskflow foreground processes.")
|
||||
#define DEFAULT_DAEMON_INFO _T("Runs the Core process on secure desktops (UAC prompts, login screen, etc).")
|
||||
|
||||
#define LEGACY_SERVER_DAEMON_NAME _T("Deskflow Server")
|
||||
#define LEGACY_CLIENT_DAEMON_NAME _T("Deskflow Client")
|
||||
|
||||
@ -1,173 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "arch/win32/ArchFileWindows.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <shlobj.h>
|
||||
#include <string.h>
|
||||
#include <tchar.h>
|
||||
|
||||
//
|
||||
// ArchFileWindows
|
||||
//
|
||||
|
||||
ArchFileWindows::ArchFileWindows()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
ArchFileWindows::~ArchFileWindows()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
const char *ArchFileWindows::getBasename(const char *pathname)
|
||||
{
|
||||
if (pathname == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// check for last slash
|
||||
const char *basename = strrchr(pathname, '/');
|
||||
if (basename != NULL) {
|
||||
++basename;
|
||||
} else {
|
||||
basename = pathname;
|
||||
}
|
||||
|
||||
// check for last backslash
|
||||
const char *basename2 = strrchr(pathname, '\\');
|
||||
if (basename2 != NULL && basename2 > basename) {
|
||||
basename = basename2 + 1;
|
||||
}
|
||||
|
||||
return basename;
|
||||
}
|
||||
|
||||
std::string ArchFileWindows::getUserDirectory()
|
||||
{
|
||||
// try %HOMEPATH%
|
||||
TCHAR dir[MAX_PATH];
|
||||
DWORD size = sizeof(dir) / sizeof(TCHAR);
|
||||
DWORD result = GetEnvironmentVariable(_T("HOMEPATH"), dir, size);
|
||||
if (result != 0 && result <= size) {
|
||||
// sanity check -- if dir doesn't appear to start with a
|
||||
// drive letter and isn't a UNC name then don't use it
|
||||
// FIXME -- allow UNC names
|
||||
if (dir[0] != '\0' && (dir[1] == ':' || ((dir[0] == '\\' || dir[0] == '/') && (dir[1] == '\\' || dir[1] == '/')))) {
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
|
||||
// get the location of the personal files. that's as close to
|
||||
// a home directory as we're likely to find.
|
||||
ITEMIDLIST *idl;
|
||||
if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_PERSONAL, &idl))) {
|
||||
TCHAR *path = NULL;
|
||||
if (SHGetPathFromIDList(idl, dir)) {
|
||||
DWORD attr = GetFileAttributes(dir);
|
||||
if (attr != 0xffffffff && (attr & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
||||
path = dir;
|
||||
}
|
||||
|
||||
IMalloc *shalloc;
|
||||
if (SUCCEEDED(SHGetMalloc(&shalloc))) {
|
||||
shalloc->Free(idl);
|
||||
shalloc->Release();
|
||||
}
|
||||
|
||||
if (path != NULL) {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
// use root of C drive as a default
|
||||
return "C:";
|
||||
}
|
||||
|
||||
std::string ArchFileWindows::getSystemDirectory()
|
||||
{
|
||||
// get windows directory
|
||||
char dir[MAX_PATH];
|
||||
if (GetWindowsDirectory(dir, sizeof(dir)) != 0) {
|
||||
return dir;
|
||||
} else {
|
||||
// can't get it. use C:\ as a default.
|
||||
return "C:";
|
||||
}
|
||||
}
|
||||
|
||||
std::string ArchFileWindows::getInstalledDirectory()
|
||||
{
|
||||
char fileNameBuffer[MAX_PATH];
|
||||
GetModuleFileName(NULL, fileNameBuffer, MAX_PATH);
|
||||
std::string fileName(fileNameBuffer);
|
||||
size_t lastSlash = fileName.find_last_of("\\");
|
||||
fileName = fileName.substr(0, lastSlash);
|
||||
|
||||
return fileName;
|
||||
}
|
||||
|
||||
std::string ArchFileWindows::getLogDirectory()
|
||||
{
|
||||
return getInstalledDirectory();
|
||||
}
|
||||
|
||||
std::string ArchFileWindows::getPluginDirectory()
|
||||
{
|
||||
if (!m_pluginDirectory.empty()) {
|
||||
return m_pluginDirectory;
|
||||
}
|
||||
|
||||
std::string dir = getProfileDirectory();
|
||||
dir.append("\\Plugins");
|
||||
return dir;
|
||||
}
|
||||
|
||||
std::string ArchFileWindows::getProfileDirectory()
|
||||
{
|
||||
std::string dir;
|
||||
if (!m_profileDirectory.empty()) {
|
||||
dir = m_profileDirectory;
|
||||
} else {
|
||||
TCHAR result[MAX_PATH];
|
||||
if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, result))) {
|
||||
dir = result;
|
||||
} else {
|
||||
dir = getUserDirectory();
|
||||
}
|
||||
}
|
||||
|
||||
// HACK: append program name, this seems wrong.
|
||||
dir.append("\\Deskflow");
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
std::string ArchFileWindows::concatPath(const std::string &prefix, const std::string &suffix)
|
||||
{
|
||||
std::string path;
|
||||
path.reserve(prefix.size() + 1 + suffix.size());
|
||||
path += prefix;
|
||||
if (path.size() == 0 || (path[path.size() - 1] != '\\' && path[path.size() - 1] != '/')) {
|
||||
path += '\\';
|
||||
}
|
||||
path += suffix;
|
||||
return path;
|
||||
}
|
||||
|
||||
void ArchFileWindows::setProfileDirectory(const std::string &s)
|
||||
{
|
||||
m_profileDirectory = s;
|
||||
}
|
||||
|
||||
void ArchFileWindows::setPluginDirectory(const std::string &s)
|
||||
{
|
||||
m_pluginDirectory = s;
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "arch/IArchFile.h"
|
||||
|
||||
#define ARCH_FILE ArchFileWindows
|
||||
|
||||
//! Win32 implementation of IArchFile
|
||||
class ArchFileWindows : public IArchFile
|
||||
{
|
||||
public:
|
||||
ArchFileWindows();
|
||||
virtual ~ArchFileWindows();
|
||||
|
||||
// IArchFile overrides
|
||||
virtual const char *getBasename(const char *pathname);
|
||||
virtual std::string getUserDirectory();
|
||||
virtual std::string getSystemDirectory();
|
||||
virtual std::string getInstalledDirectory();
|
||||
virtual std::string getLogDirectory();
|
||||
virtual std::string getPluginDirectory();
|
||||
virtual std::string getProfileDirectory();
|
||||
virtual std::string concatPath(const std::string &prefix, const std::string &suffix);
|
||||
virtual void setProfileDirectory(const std::string &s);
|
||||
virtual void setPluginDirectory(const std::string &s);
|
||||
|
||||
private:
|
||||
std::string m_profileDirectory;
|
||||
std::string m_pluginDirectory;
|
||||
};
|
||||
@ -1,69 +1,66 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016, 2024 - 2025 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "arch/win32/ArchMiscWindows.h"
|
||||
|
||||
#include "arch/win32/ArchDaemonWindows.h"
|
||||
#include "arch/win32/XArchWindows.h"
|
||||
#include "base/Log.h"
|
||||
#include "common/constants.h"
|
||||
#include "base/String.h"
|
||||
|
||||
#include <Wtsapi32.h>
|
||||
#pragma warning(disable : 4099)
|
||||
#include <Userenv.h>
|
||||
#pragma warning(default : 4099)
|
||||
#include <Psapi.h>
|
||||
|
||||
// parent process name for services in Vista
|
||||
#define SERVICE_LAUNCHER "services.exe"
|
||||
#include <array>
|
||||
#include <filesystem>
|
||||
|
||||
#ifndef ES_SYSTEM_REQUIRED
|
||||
#define ES_SYSTEM_REQUIRED ((DWORD)0x00000001)
|
||||
#endif
|
||||
#ifndef ES_DISPLAY_REQUIRED
|
||||
#define ES_DISPLAY_REQUIRED ((DWORD)0x00000002)
|
||||
#endif
|
||||
#ifndef ES_CONTINUOUS
|
||||
#define ES_CONTINUOUS ((DWORD)0x80000000)
|
||||
#endif
|
||||
using EXECUTION_STATE = DWORD;
|
||||
// Useful for debugging Windows specific bootstrapping code before the logging system is initialized.
|
||||
// This output can be viewed by attaching a Microsoft debugger or by using the DebugView program.
|
||||
#define MS_LOG_DEBUG(message, ...) \
|
||||
OutputDebugStringA((deskflow::string::sprintf((s_binaryName + ": " + message + "\n").c_str(), __VA_ARGS__)).c_str())
|
||||
|
||||
//
|
||||
// Free functions
|
||||
//
|
||||
|
||||
void errorMessageBox(const char *message, const char *title = "Fatal Error");
|
||||
|
||||
std::string getBinaryName()
|
||||
{
|
||||
std::array<char, MAX_PATH> buffer;
|
||||
if (!GetModuleFileNameA(NULL, buffer.data(), MAX_PATH)) {
|
||||
errorMessageBox("Failed to get binary name.");
|
||||
abort();
|
||||
}
|
||||
|
||||
return std::filesystem::path(buffer.data()).filename().string();
|
||||
}
|
||||
|
||||
void errorMessageBox(const char *message, const char *title)
|
||||
{
|
||||
MessageBoxA(nullptr, message, title, MB_ICONERROR | MB_OK);
|
||||
}
|
||||
|
||||
// Used by bootstrap logging to differentiate between daemon and client/server messages.
|
||||
const std::string s_binaryName = getBinaryName();
|
||||
|
||||
//
|
||||
// ArchMiscWindows
|
||||
//
|
||||
|
||||
ArchMiscWindows::Dialogs *ArchMiscWindows::s_dialogs = NULL;
|
||||
DWORD ArchMiscWindows::s_busyState = 0;
|
||||
ArchMiscWindows::STES_t ArchMiscWindows::s_stes = NULL;
|
||||
HICON ArchMiscWindows::s_largeIcon = NULL;
|
||||
HICON ArchMiscWindows::s_smallIcon = NULL;
|
||||
HINSTANCE ArchMiscWindows::s_instanceWin32 = NULL;
|
||||
|
||||
void ArchMiscWindows::cleanup()
|
||||
{
|
||||
delete s_dialogs;
|
||||
}
|
||||
|
||||
void ArchMiscWindows::init()
|
||||
{
|
||||
// stop windows system error dialogs from showing.
|
||||
SetErrorMode(SEM_FAILCRITICALERRORS);
|
||||
|
||||
s_dialogs = new Dialogs;
|
||||
}
|
||||
|
||||
void ArchMiscWindows::setIcons(HICON largeIcon, HICON smallIcon)
|
||||
{
|
||||
s_largeIcon = largeIcon;
|
||||
s_smallIcon = smallIcon;
|
||||
}
|
||||
|
||||
void ArchMiscWindows::getIcons(HICON &largeIcon, HICON &smallIcon)
|
||||
{
|
||||
largeIcon = s_largeIcon;
|
||||
smallIcon = s_smallIcon;
|
||||
}
|
||||
|
||||
int ArchMiscWindows::runDaemon(RunFunc runFunc)
|
||||
@ -156,31 +153,6 @@ void ArchMiscWindows::deleteKey(HKEY key, const TCHAR *name)
|
||||
RegDeleteKey(key, name);
|
||||
}
|
||||
|
||||
void ArchMiscWindows::deleteValue(HKEY key, const TCHAR *name)
|
||||
{
|
||||
assert(key != NULL);
|
||||
assert(name != NULL);
|
||||
if (key == NULL || name == NULL)
|
||||
return;
|
||||
RegDeleteValue(key, name);
|
||||
}
|
||||
|
||||
void ArchMiscWindows::deleteKeyTree(HKEY key, const TCHAR *name)
|
||||
{
|
||||
assert(key != NULL);
|
||||
assert(name != NULL);
|
||||
if (key == NULL || name == NULL)
|
||||
return;
|
||||
RegDeleteTree(key, name);
|
||||
}
|
||||
|
||||
bool ArchMiscWindows::hasValue(HKEY key, const TCHAR *name)
|
||||
{
|
||||
DWORD type;
|
||||
LONG result = RegQueryValueEx(key, name, 0, &type, NULL, NULL);
|
||||
return (result == ERROR_SUCCESS && (type == REG_DWORD || type == REG_SZ));
|
||||
}
|
||||
|
||||
ArchMiscWindows::EValueType ArchMiscWindows::typeOfValue(HKEY key, const TCHAR *name)
|
||||
{
|
||||
DWORD type;
|
||||
@ -223,17 +195,6 @@ void ArchMiscWindows::setValue(HKEY key, const TCHAR *name, DWORD value)
|
||||
RegSetValueEx(key, name, 0, REG_DWORD, reinterpret_cast<CONST BYTE *>(&value), sizeof(DWORD));
|
||||
}
|
||||
|
||||
void ArchMiscWindows::setValueBinary(HKEY key, const TCHAR *name, const std::string &value)
|
||||
{
|
||||
assert(key != NULL);
|
||||
assert(name != NULL);
|
||||
if (key == NULL || name == NULL) {
|
||||
// TODO: throw exception
|
||||
return;
|
||||
}
|
||||
RegSetValueEx(key, name, 0, REG_BINARY, reinterpret_cast<const BYTE *>(value.data()), (DWORD)value.size());
|
||||
}
|
||||
|
||||
std::string ArchMiscWindows::readBinaryOrString(HKEY key, const TCHAR *name, DWORD type)
|
||||
{
|
||||
// get the size of the string
|
||||
@ -274,11 +235,6 @@ std::string ArchMiscWindows::readValueString(HKEY key, const TCHAR *name)
|
||||
return readBinaryOrString(key, name, REG_SZ);
|
||||
}
|
||||
|
||||
std::string ArchMiscWindows::readValueBinary(HKEY key, const TCHAR *name)
|
||||
{
|
||||
return readBinaryOrString(key, name, REG_BINARY);
|
||||
}
|
||||
|
||||
DWORD
|
||||
ArchMiscWindows::readValueInt(HKEY key, const TCHAR *name)
|
||||
{
|
||||
@ -292,26 +248,6 @@ ArchMiscWindows::readValueInt(HKEY key, const TCHAR *name)
|
||||
return value;
|
||||
}
|
||||
|
||||
void ArchMiscWindows::addDialog(HWND hwnd)
|
||||
{
|
||||
s_dialogs->insert(hwnd);
|
||||
}
|
||||
|
||||
void ArchMiscWindows::removeDialog(HWND hwnd)
|
||||
{
|
||||
s_dialogs->erase(hwnd);
|
||||
}
|
||||
|
||||
bool ArchMiscWindows::processDialog(MSG *msg)
|
||||
{
|
||||
for (Dialogs::const_iterator index = s_dialogs->begin(); index != s_dialogs->end(); ++index) {
|
||||
if (IsDialogMessage(*index, msg)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ArchMiscWindows::addBusyState(DWORD busyModes)
|
||||
{
|
||||
s_busyState |= busyModes;
|
||||
@ -338,7 +274,7 @@ void ArchMiscWindows::setThreadExecutionState(DWORD busyModes)
|
||||
}
|
||||
|
||||
// convert to STES form
|
||||
EXECUTION_STATE state = 0;
|
||||
DWORD state = 0;
|
||||
if ((busyModes & kSYSTEM) != 0) {
|
||||
state |= ES_SYSTEM_REQUIRED;
|
||||
}
|
||||
@ -389,7 +325,7 @@ bool ArchMiscWindows::wasLaunchedAsService()
|
||||
return false;
|
||||
}
|
||||
|
||||
return (name == SERVICE_LAUNCHER);
|
||||
return (name == "services.exe");
|
||||
}
|
||||
|
||||
bool ArchMiscWindows::getParentProcessName(std::string &name)
|
||||
@ -483,3 +419,133 @@ std::string ArchMiscWindows::getActiveDesktopName()
|
||||
CloseDesktop(desk);
|
||||
return name;
|
||||
}
|
||||
|
||||
HMODULE ArchMiscWindows::findLoadedModule(std::array<const char *, 2> moduleNames)
|
||||
{
|
||||
std::array<HMODULE, 1024> hModules;
|
||||
DWORD cbNeeded;
|
||||
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
if (!EnumProcessModules(hProcess, hModules.data(), sizeof(hModules), &cbNeeded)) {
|
||||
errorMessageBox("Failed to enumerate process modules.");
|
||||
abort();
|
||||
}
|
||||
|
||||
std::string loadedModuleName;
|
||||
for (size_t i = 0; i < (cbNeeded / sizeof(HMODULE)); ++i) {
|
||||
if (!GetModuleBaseNameA(hProcess, hModules[i], loadedModuleName.data(), sizeof(loadedModuleName))) {
|
||||
LOG_WARN("could not get base name of loaded module %d", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const auto &moduleName : moduleNames) {
|
||||
if (_stricmp(loadedModuleName.data(), moduleName) == 0) {
|
||||
return hModules[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Enforcing minimum MSVC runtime version is quite strict, but we have a good reason.
|
||||
//
|
||||
// Microsoft lets you run a program with an older version of the runtime DLL than the one it was
|
||||
// compiled with. This is because the runtime DLLs are supposedly ABI-compatible when the major
|
||||
// version is the same, so hypothetically MSVC runtime 14.0 is compatible with 14.42.
|
||||
// However, we have found subtle edge cases such as mutex lock causes access violation.
|
||||
//
|
||||
// Example of how Microsoft breaks ABI compatibility between minor runtime versions:
|
||||
// https://stackoverflow.com/questions/69990339/why-is-stdmutex-so-much-worse-than-stdshared-mutex-in-visual-c
|
||||
//
|
||||
// Our CI is set up to build with the latest compiler, so in this case we should insist on at least
|
||||
// the runtime DLL that was released at the same time as the compiler.
|
||||
//
|
||||
// As a developer convenience, we also allow builds on older compilers such as the minimum
|
||||
// requirements for the current Qt version we support.
|
||||
void ArchMiscWindows::guardRuntimeVersion() // NOSONAR - `noreturn` is not available
|
||||
{
|
||||
auto hModule = findLoadedModule({"vcruntime140.dll", "vcruntime140d.dll"});
|
||||
if (hModule == nullptr) {
|
||||
errorMessageBox("Failed to find MSVC runtime DLL.");
|
||||
abort();
|
||||
}
|
||||
|
||||
MS_LOG_DEBUG("found msvc runtime dll, handle: %p", hModule);
|
||||
|
||||
std::array<char, MAX_PATH> pathBuffer;
|
||||
const auto path = pathBuffer.data();
|
||||
if (!GetModuleFileNameA(hModule, path, MAX_PATH)) {
|
||||
errorMessageBox("Failed to get path of MSVC runtime.");
|
||||
abort();
|
||||
}
|
||||
|
||||
MS_LOG_DEBUG("msvc runtime dll path: %s", path);
|
||||
|
||||
DWORD handle;
|
||||
DWORD size = GetFileVersionInfoSizeA(path, &handle);
|
||||
if (size <= 0) {
|
||||
errorMessageBox("Failed to get version info size for MSVC runtime.");
|
||||
abort();
|
||||
}
|
||||
|
||||
MS_LOG_DEBUG("msvc runtime dll version info size: %d", size);
|
||||
|
||||
std::vector<BYTE> versionInfo(size);
|
||||
if (!GetFileVersionInfoA(path, handle, size, versionInfo.data())) {
|
||||
errorMessageBox("Failed to get file version info for MSVC runtime.");
|
||||
abort();
|
||||
}
|
||||
|
||||
MS_LOG_DEBUG("msvc runtime dll version info ok, querying values");
|
||||
|
||||
VS_FIXEDFILEINFO *fileInfo = nullptr;
|
||||
const auto lplpFileInfo = reinterpret_cast<void **>(&fileInfo); // NOSONAR - Idiomatic Win32
|
||||
if (UINT len = 0; !VerQueryValueA(versionInfo.data(), "\\", lplpFileInfo, &len)) {
|
||||
errorMessageBox("Failed to query file version info for MSVC runtime.");
|
||||
abort();
|
||||
}
|
||||
|
||||
const auto currentMajor = HIWORD(fileInfo->dwFileVersionMS);
|
||||
const auto currentMinor = LOWORD(fileInfo->dwFileVersionMS);
|
||||
const auto currentBuild = HIWORD(fileInfo->dwFileVersionLS);
|
||||
|
||||
MS_LOG_DEBUG("msvc runtime dll version: %d.%d.%d", currentMajor, currentMinor, currentBuild);
|
||||
|
||||
if (currentMajor < kWindowsRuntimeMajor || currentMinor < kWindowsRuntimeMinor) {
|
||||
const auto message = deskflow::string::sprintf(
|
||||
"Installed Microsoft Visual C++ Runtime v%d.%d.%d is outdated.\n\n"
|
||||
"Minimum required version: v%d.%d\n\n"
|
||||
"Please update to the latest Microsoft Visual C++ Redistributable.",
|
||||
currentMajor, currentMinor, currentBuild, kWindowsRuntimeMajor, kWindowsRuntimeMinor
|
||||
);
|
||||
MessageBoxA(nullptr, message.c_str(), "Dependency Error", MB_ICONERROR | MB_OK);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
bool ArchMiscWindows::isProcessElevated()
|
||||
{
|
||||
LOG_DEBUG("checking if process is elevated");
|
||||
|
||||
HANDLE hToken = nullptr;
|
||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
|
||||
throw XArch(new XArchEvalWindows());
|
||||
}
|
||||
|
||||
TOKEN_ELEVATION elevation;
|
||||
|
||||
try {
|
||||
DWORD dwSize = sizeof(TOKEN_ELEVATION);
|
||||
if (!GetTokenInformation(hToken, TokenElevation, &elevation, sizeof(elevation), &dwSize)) {
|
||||
throw XArch(new XArchEvalWindows());
|
||||
}
|
||||
} catch (...) {
|
||||
CloseHandle(hToken);
|
||||
throw;
|
||||
}
|
||||
|
||||
const auto isElevated = elevation.TokenIsElevated;
|
||||
LOG_DEBUG("process is %s", isElevated ? "elevated" : "not elevated");
|
||||
return isElevated;
|
||||
}
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/stdset.h"
|
||||
#include <string>
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
@ -15,6 +14,8 @@
|
||||
|
||||
#include <Tlhelp32.h>
|
||||
|
||||
#include <functional>
|
||||
|
||||
//! Miscellaneous win32 functions.
|
||||
class ArchMiscWindows
|
||||
{
|
||||
@ -34,26 +35,11 @@ public:
|
||||
kDISPLAY = 0x0002
|
||||
};
|
||||
|
||||
typedef int (*RunFunc)(void);
|
||||
using RunFunc = std::function<int(void)>;
|
||||
|
||||
//! Initialize
|
||||
static void init();
|
||||
|
||||
//! Delete memory
|
||||
static void cleanup();
|
||||
|
||||
//! Set the application icons
|
||||
/*!
|
||||
Set the application icons.
|
||||
*/
|
||||
static void setIcons(HICON largeIcon, HICON smallIcon);
|
||||
|
||||
//! Get the application icons
|
||||
/*!
|
||||
Get the application icons.
|
||||
*/
|
||||
static void getIcons(HICON &largeIcon, HICON &smallIcon);
|
||||
|
||||
//! Run the daemon
|
||||
/*!
|
||||
Delegates to ArchDaemonWindows.
|
||||
@ -96,15 +82,6 @@ public:
|
||||
//! Delete a key (which should have no subkeys)
|
||||
static void deleteKey(HKEY parent, const TCHAR *name);
|
||||
|
||||
//! Delete a value
|
||||
static void deleteValue(HKEY parent, const TCHAR *name);
|
||||
|
||||
//! Delete a tree of keys from the registry
|
||||
static void deleteKeyTree(HKEY parent, const TCHAR *name);
|
||||
|
||||
//! Test if a value exists
|
||||
static bool hasValue(HKEY key, const TCHAR *name);
|
||||
|
||||
//! Get type of value
|
||||
static EValueType typeOfValue(HKEY key, const TCHAR *name);
|
||||
|
||||
@ -114,34 +91,12 @@ public:
|
||||
//! Set a DWORD value in the registry
|
||||
static void setValue(HKEY key, const TCHAR *name, DWORD value);
|
||||
|
||||
//! Set a BINARY value in the registry
|
||||
/*!
|
||||
Sets the \p name value of \p key to \p value.data().
|
||||
*/
|
||||
static void setValueBinary(HKEY key, const TCHAR *name, const std::string &value);
|
||||
|
||||
//! Read a string value from the registry
|
||||
static std::string readValueString(HKEY, const TCHAR *name);
|
||||
|
||||
//! Read a DWORD value from the registry
|
||||
static DWORD readValueInt(HKEY, const TCHAR *name);
|
||||
|
||||
//! Read a BINARY value from the registry
|
||||
static std::string readValueBinary(HKEY, const TCHAR *name);
|
||||
|
||||
//! Add a dialog
|
||||
static void addDialog(HWND);
|
||||
|
||||
//! Remove a dialog
|
||||
static void removeDialog(HWND);
|
||||
|
||||
//! Process dialog message
|
||||
/*!
|
||||
Checks if the message is destined for a dialog. If so the message
|
||||
is passed to the dialog and returns true, otherwise returns false.
|
||||
*/
|
||||
static bool processDialog(MSG *);
|
||||
|
||||
//! Disable power saving
|
||||
static void addBusyState(DWORD busyModes);
|
||||
|
||||
@ -157,13 +112,24 @@ public:
|
||||
//! Returns true if we got the parent process name.
|
||||
static bool getParentProcessName(std::string &name);
|
||||
|
||||
//! Prevent hard to troubleshoot errors, e.g. access violations.
|
||||
static void guardRuntimeVersion();
|
||||
|
||||
//! Gets the window instance saved at program start.
|
||||
/*!
|
||||
e.g. Used by `GetModuleFileName` which is used when installing the daemon.
|
||||
*/
|
||||
static HINSTANCE instanceWin32();
|
||||
|
||||
//! Saves the window instance for later use.
|
||||
static void setInstanceWin32(HINSTANCE instance);
|
||||
static BOOL WINAPI getProcessEntry(PROCESSENTRY32 &entry, DWORD processID);
|
||||
static BOOL WINAPI getSelfProcessEntry(PROCESSENTRY32 &entry);
|
||||
static BOOL WINAPI getParentProcessEntry(PROCESSENTRY32 &entry);
|
||||
|
||||
//! Get the name of the active input desktop.
|
||||
static std::string getActiveDesktopName();
|
||||
|
||||
//! Returns true if the process is running with elevated privileges (i.e. as admin).
|
||||
static bool isProcessElevated();
|
||||
|
||||
private:
|
||||
//! Open and return a registry key, closing the parent key
|
||||
static HKEY openKey(HKEY parent, const TCHAR *child, bool create);
|
||||
@ -177,15 +143,29 @@ private:
|
||||
//! Set thread busy state
|
||||
static void setThreadExecutionState(DWORD);
|
||||
|
||||
//! Dummy function for thread execution state
|
||||
static DWORD WINAPI dummySetThreadExecutionState(DWORD);
|
||||
|
||||
//! Iterates over the process snapshot to find a process entry
|
||||
static BOOL WINAPI getProcessEntry(PROCESSENTRY32 &entry, DWORD processID);
|
||||
|
||||
//! Calls `getProcessEntry` with the current process ID
|
||||
static BOOL WINAPI getSelfProcessEntry(PROCESSENTRY32 &entry);
|
||||
|
||||
//! Calls `getProcessEntry` with the parent process ID
|
||||
static BOOL WINAPI getParentProcessEntry(PROCESSENTRY32 &entry);
|
||||
|
||||
//! Searches the loaded modules and returns the matching module handle
|
||||
/**
|
||||
* @param moduleNames Provide two module names to search for both release and debug versions.
|
||||
*/
|
||||
static HMODULE findLoadedModule(std::array<const char *, 2> moduleNames);
|
||||
|
||||
private:
|
||||
using Dialogs = std::set<HWND>;
|
||||
typedef DWORD(WINAPI *STES_t)(DWORD);
|
||||
|
||||
static Dialogs *s_dialogs;
|
||||
static DWORD s_busyState;
|
||||
static STES_t s_stes;
|
||||
static STES_t s_stes; // STES: Set thread execution state
|
||||
static HICON s_largeIcon;
|
||||
static HICON s_smallIcon;
|
||||
static HINSTANCE s_instanceWin32;
|
||||
|
||||
@ -8,7 +8,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "arch/IArchMultithread.h"
|
||||
#include "common/stdlist.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
|
||||
@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2004 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "arch/win32/ArchSystemWindows.h"
|
||||
#include "arch/win32/ArchMiscWindows.h"
|
||||
|
||||
#include "arch/XArch.h"
|
||||
#include "base/Log.h"
|
||||
#include "common/constants.h"
|
||||
|
||||
#include "tchar.h"
|
||||
#include <string>
|
||||
|
||||
#include <psapi.h>
|
||||
#include <windows.h>
|
||||
|
||||
static const TCHAR *s_settingsKeyNames[] = {_T("SOFTWARE"), _T(kAppName), NULL};
|
||||
|
||||
//
|
||||
// ArchSystemWindows
|
||||
//
|
||||
|
||||
ArchSystemWindows::ArchSystemWindows()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
ArchSystemWindows::~ArchSystemWindows()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
std::string ArchSystemWindows::getOSName() const
|
||||
{
|
||||
std::string osName("Microsoft Windows <unknown>");
|
||||
static const TCHAR *const windowsVersionKeyNames[] = {
|
||||
_T("SOFTWARE"), _T("Microsoft"), _T("Windows NT"), _T("CurrentVersion"), NULL
|
||||
};
|
||||
|
||||
HKEY key = ArchMiscWindows::openKey(HKEY_LOCAL_MACHINE, windowsVersionKeyNames);
|
||||
if (key == NULL) {
|
||||
return osName;
|
||||
}
|
||||
|
||||
std::string productName = ArchMiscWindows::readValueString(key, "ProductName");
|
||||
if (osName.empty()) {
|
||||
return osName;
|
||||
}
|
||||
|
||||
return "Microsoft " + productName;
|
||||
}
|
||||
|
||||
std::string ArchSystemWindows::getPlatformName() const
|
||||
{
|
||||
#ifdef _X86_
|
||||
if (isWOW64())
|
||||
return "x86 (WOW64)";
|
||||
else
|
||||
return "x86";
|
||||
#else
|
||||
#ifdef _AMD64_
|
||||
return "x64";
|
||||
#else
|
||||
return "Unknown";
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string ArchSystemWindows::setting(const std::string &valueName) const
|
||||
{
|
||||
HKEY key = ArchMiscWindows::openKey(HKEY_LOCAL_MACHINE, s_settingsKeyNames);
|
||||
if (key == NULL)
|
||||
return "";
|
||||
|
||||
return ArchMiscWindows::readValueString(key, valueName.c_str());
|
||||
}
|
||||
|
||||
void ArchSystemWindows::setting(const std::string &valueName, const std::string &valueString) const
|
||||
{
|
||||
HKEY key = ArchMiscWindows::addKey(HKEY_LOCAL_MACHINE, s_settingsKeyNames);
|
||||
if (key == NULL)
|
||||
throw XArch(std::string("could not access registry key: ") + valueName);
|
||||
ArchMiscWindows::setValue(key, valueName.c_str(), valueString.c_str());
|
||||
}
|
||||
|
||||
void ArchSystemWindows::clearSettings() const
|
||||
{
|
||||
ArchMiscWindows::deleteKeyTree(HKEY_LOCAL_MACHINE, kWindowsRegistryKey);
|
||||
}
|
||||
|
||||
bool ArchSystemWindows::isWOW64() const
|
||||
{
|
||||
#if WINVER >= _WIN32_WINNT_WINXP
|
||||
typedef BOOL(WINAPI * LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);
|
||||
HMODULE hModule = GetModuleHandle(TEXT("kernel32"));
|
||||
if (!hModule)
|
||||
return FALSE;
|
||||
|
||||
LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(hModule, "IsWow64Process");
|
||||
|
||||
BOOL bIsWow64 = FALSE;
|
||||
if (NULL != fnIsWow64Process && fnIsWow64Process(GetCurrentProcess(), &bIsWow64) && bIsWow64) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2004 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "arch/IArchSystem.h"
|
||||
|
||||
#define ARCH_SYSTEM ArchSystemWindows
|
||||
|
||||
//! Win32 implementation of IArchString
|
||||
class ArchSystemWindows : public IArchSystem
|
||||
{
|
||||
public:
|
||||
ArchSystemWindows();
|
||||
virtual ~ArchSystemWindows();
|
||||
|
||||
// IArchSystem overrides
|
||||
virtual std::string getOSName() const;
|
||||
virtual std::string getPlatformName() const;
|
||||
virtual std::string setting(const std::string &valueName) const;
|
||||
virtual void setting(const std::string &valueName, const std::string &valueString) const;
|
||||
virtual void clearSettings() const;
|
||||
|
||||
bool isWOW64() const;
|
||||
};
|
||||
@ -41,92 +41,166 @@ std::string XArchEvalWinsock::eval() const throw()
|
||||
{
|
||||
int m_code;
|
||||
const char *m_msg;
|
||||
} s_netErrorCodes[] = {
|
||||
/* 10004 */ {WSAEINTR, "The (blocking) call was canceled via WSACancelBlockingCall"},
|
||||
/* 10009 */ {WSAEBADF, "Bad file handle"},
|
||||
/* 10013 */
|
||||
{WSAEACCES, "The requested address is a broadcast address, but the "
|
||||
"appropriate flag was not set"},
|
||||
/* 10014 */ {WSAEFAULT, "WSAEFAULT"},
|
||||
/* 10022 */ {WSAEINVAL, "WSAEINVAL"},
|
||||
/* 10024 */ {WSAEMFILE, "No more file descriptors available"},
|
||||
/* 10035 */
|
||||
{WSAEWOULDBLOCK, "Socket is marked as non-blocking and no connections "
|
||||
"are present or the receive operation would block"},
|
||||
/* 10036 */
|
||||
}
|
||||
|
||||
s_netErrorCodes[] = {
|
||||
|
||||
// 10004
|
||||
{WSAEINTR, "The (blocking) call was canceled via WSACancelBlockingCall"},
|
||||
|
||||
// 10009
|
||||
{WSAEBADF, "Bad file handle"},
|
||||
|
||||
// 10013
|
||||
{WSAEACCES, "The requested address is a broadcast address, but the appropriate flag was not set"},
|
||||
|
||||
// 10014
|
||||
{WSAEFAULT, "WSAEFAULT"},
|
||||
|
||||
// 10022
|
||||
{WSAEINVAL, "WSAEINVAL"},
|
||||
|
||||
// 10024
|
||||
{WSAEMFILE, "No more file descriptors available"},
|
||||
|
||||
// 10035
|
||||
{WSAEWOULDBLOCK,
|
||||
"Socket is marked as non-blocking and no connections are present or the receive operation would block"},
|
||||
|
||||
// 10036
|
||||
{WSAEINPROGRESS, "A blocking Windows Sockets operation is in progress"},
|
||||
/* 10037 */
|
||||
|
||||
// 10037
|
||||
{WSAEALREADY, "The asynchronous routine being canceled has already completed"},
|
||||
/* 10038 */ {WSAENOTSOCK, "At least on descriptor is not a socket"},
|
||||
/* 10039 */ {WSAEDESTADDRREQ, "A destination address is required"},
|
||||
/* 10040 */
|
||||
{WSAEMSGSIZE, "The datagram was too large to fit into the specified "
|
||||
"buffer and was truncated"},
|
||||
/* 10041 */
|
||||
|
||||
// 10038
|
||||
{WSAENOTSOCK, "At least on descriptor is not a socket"},
|
||||
|
||||
// 10039
|
||||
{WSAEDESTADDRREQ, "A destination address is required"},
|
||||
|
||||
// 10040
|
||||
{WSAEMSGSIZE, "The datagram was too large to fit into the specified buffer and was truncated"},
|
||||
|
||||
// 10041
|
||||
{WSAEPROTOTYPE, "The specified protocol is the wrong type for this socket"},
|
||||
/* 10042 */ {WSAENOPROTOOPT, "The option is unknown or unsupported"},
|
||||
/* 10043 */
|
||||
|
||||
// 10042
|
||||
{WSAENOPROTOOPT, "The option is unknown or unsupported"},
|
||||
|
||||
// 10043
|
||||
{WSAEPROTONOSUPPORT, "The specified protocol is not supported"},
|
||||
/* 10044 */
|
||||
|
||||
// 10044
|
||||
{WSAESOCKTNOSUPPORT, "The specified socket type is not supported by this address family"},
|
||||
/* 10045 */
|
||||
|
||||
// 10045
|
||||
{WSAEOPNOTSUPP, "The referenced socket is not a type that supports that operation"},
|
||||
/* 10046 */ {WSAEPFNOSUPPORT, "BSD: Protocol family not supported"},
|
||||
/* 10047 */
|
||||
|
||||
// 10046
|
||||
{WSAEPFNOSUPPORT, "BSD: Protocol family not supported"},
|
||||
|
||||
// 10047
|
||||
{WSAEAFNOSUPPORT, "The specified address family is not supported"},
|
||||
/* 10048 */ {WSAEADDRINUSE, "The specified address is already in use"},
|
||||
/* 10049 */
|
||||
|
||||
// 10048
|
||||
{WSAEADDRINUSE, "The specified address is already in use"},
|
||||
|
||||
// 10049
|
||||
{WSAEADDRNOTAVAIL, "The specified address is not available from the local machine"},
|
||||
/* 10050 */
|
||||
{WSAENETDOWN, "The Windows Sockets implementation has detected that the "
|
||||
"network subsystem has failed"},
|
||||
/* 10051 */
|
||||
|
||||
// 10050
|
||||
{WSAENETDOWN, "The Windows Sockets implementation has detected that the network subsystem has failed"},
|
||||
|
||||
// 10051
|
||||
{WSAENETUNREACH, "The network can't be reached from this host at this time"},
|
||||
/* 10052 */
|
||||
{WSAENETRESET, "The connection must be reset because the Windows Sockets "
|
||||
"implementation dropped it"},
|
||||
/* 10053 */
|
||||
|
||||
// 10052
|
||||
{WSAENETRESET, "The connection must be reset because the Windows Sockets implementation dropped it"},
|
||||
|
||||
// 10053
|
||||
{WSAECONNABORTED, "The virtual circuit was aborted due to timeout or other failure"},
|
||||
/* 10054 */
|
||||
|
||||
// 10054
|
||||
{WSAECONNRESET, "The virtual circuit was reset by the remote side"},
|
||||
/* 10055 */
|
||||
{WSAENOBUFS, "No buffer space is available or a buffer deadlock has "
|
||||
"occured. The socket cannot be created"},
|
||||
/* 10056 */ {WSAEISCONN, "The socket is already connected"},
|
||||
/* 10057 */ {WSAENOTCONN, "The socket is not connected"},
|
||||
/* 10058 */ {WSAESHUTDOWN, "The socket has been shutdown"},
|
||||
/* 10059 */ {WSAETOOMANYREFS, "BSD: Too many references"},
|
||||
/* 10060 */
|
||||
|
||||
// 10055
|
||||
{WSAENOBUFS, "No buffer space is available or a buffer deadlock has occurred. The socket cannot be created"},
|
||||
|
||||
// 10056
|
||||
{WSAEISCONN, "The socket is already connected"},
|
||||
|
||||
// 10057
|
||||
{WSAENOTCONN, "The socket is not connected"},
|
||||
|
||||
// 10058
|
||||
{WSAESHUTDOWN, "The socket has been shutdown"},
|
||||
|
||||
// 10059
|
||||
{WSAETOOMANYREFS, "BSD: Too many references"},
|
||||
|
||||
// 10060
|
||||
{WSAETIMEDOUT, "Attempt to connect timed out without establishing a connection"},
|
||||
/* 10061 */ {WSAECONNREFUSED, "Connection was refused"},
|
||||
/* 10062 */ {WSAELOOP, "Undocumented WinSock error code used in BSD"},
|
||||
/* 10063 */
|
||||
|
||||
// 10061
|
||||
{WSAECONNREFUSED, "Connection was refused"},
|
||||
|
||||
// 10062
|
||||
{WSAELOOP, "Undocumented WinSock error code used in BSD"},
|
||||
|
||||
// 10063
|
||||
{WSAENAMETOOLONG, "Undocumented WinSock error code used in BSD"},
|
||||
/* 10064 */ {WSAEHOSTDOWN, "Undocumented WinSock error code used in BSD"},
|
||||
/* 10065 */ {WSAEHOSTUNREACH, "No route to host"},
|
||||
/* 10066 */ {WSAENOTEMPTY, "Undocumented WinSock error code"},
|
||||
/* 10067 */ {WSAEPROCLIM, "Undocumented WinSock error code"},
|
||||
/* 10068 */ {WSAEUSERS, "Undocumented WinSock error code"},
|
||||
/* 10069 */ {WSAEDQUOT, "Undocumented WinSock error code"},
|
||||
/* 10070 */ {WSAESTALE, "Undocumented WinSock error code"},
|
||||
/* 10071 */ {WSAEREMOTE, "Undocumented WinSock error code"},
|
||||
/* 10091 */
|
||||
|
||||
// 10064
|
||||
{WSAEHOSTDOWN, "Undocumented WinSock error code used in BSD"},
|
||||
|
||||
// 10065
|
||||
{WSAEHOSTUNREACH, "No route to host"},
|
||||
|
||||
// 10066
|
||||
{WSAENOTEMPTY, "Undocumented WinSock error code"},
|
||||
|
||||
// 10067
|
||||
{WSAEPROCLIM, "Undocumented WinSock error code"},
|
||||
|
||||
// 10068
|
||||
{WSAEUSERS, "Undocumented WinSock error code"},
|
||||
|
||||
// 10069
|
||||
{WSAEDQUOT, "Undocumented WinSock error code"},
|
||||
|
||||
// 10070
|
||||
{WSAESTALE, "Undocumented WinSock error code"},
|
||||
|
||||
// 10071
|
||||
{WSAEREMOTE, "Undocumented WinSock error code"},
|
||||
|
||||
// 10091
|
||||
{WSASYSNOTREADY, "Underlying network subsytem is not ready for network communication"},
|
||||
/* 10092 */
|
||||
{WSAVERNOTSUPPORTED, "The version of WinSock API support requested is "
|
||||
"not provided in this implementation"},
|
||||
/* 10093 */
|
||||
|
||||
// 10092
|
||||
{WSAVERNOTSUPPORTED, "The version of WinSock API support requested is not provided in this implementation"},
|
||||
|
||||
// 10093
|
||||
{WSANOTINITIALISED, "WinSock subsystem not properly initialized"},
|
||||
/* 10101 */
|
||||
|
||||
// 10101
|
||||
{WSAEDISCON, "Virtual circuit has gracefully terminated connection"},
|
||||
/* 11001 */ {WSAHOST_NOT_FOUND, "The specified host is unknown"},
|
||||
/* 11002 */
|
||||
|
||||
// 11001
|
||||
{WSAHOST_NOT_FOUND, "The specified host is unknown"},
|
||||
|
||||
// 11002
|
||||
{WSATRY_AGAIN, "A temporary error occurred on an authoritative name server"},
|
||||
/* 11003 */
|
||||
|
||||
// 11003
|
||||
{WSANO_RECOVERY, "A non-recoverable name server error occurred"},
|
||||
/* 11004 */
|
||||
|
||||
// 11004
|
||||
{WSANO_DATA, "The requested name is valid but does not have an IP address"},
|
||||
/* end */ {0, NULL}
|
||||
|
||||
// end
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
for (unsigned int i = 0; s_netErrorCodes[i].m_code != 0; ++i) {
|
||||
|
||||
@ -11,7 +11,7 @@ add_library(base STATIC
|
||||
EventQueue.h
|
||||
EventTypes.cpp
|
||||
EventTypes.h
|
||||
finally.h
|
||||
FinalAction.h
|
||||
FunctionEventJob.cpp
|
||||
FunctionEventJob.h
|
||||
FunctionJob.cpp
|
||||
@ -21,8 +21,8 @@ add_library(base STATIC
|
||||
IEventQueueBuffer.h
|
||||
IJob.h
|
||||
ILogOutputter.h
|
||||
log_outputters.cpp
|
||||
log_outputters.h
|
||||
LogOutputters.cpp
|
||||
LogOutputters.h
|
||||
Log.cpp
|
||||
Log.h
|
||||
Path.cpp
|
||||
|
||||
@ -7,8 +7,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/common.h"
|
||||
#include "common/stdmap.h"
|
||||
#include "common/Common.h"
|
||||
|
||||
class EventData
|
||||
{
|
||||
|
||||
@ -11,7 +11,6 @@
|
||||
#include "base/IEventJob.h"
|
||||
#include "base/Log.h"
|
||||
#include "base/SimpleEventQueueBuffer.h"
|
||||
#include "base/Stopwatch.h"
|
||||
#include "mt/Lock.h"
|
||||
#include "mt/Mutex.h"
|
||||
|
||||
|
||||
@ -7,17 +7,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "arch/IArchMultithread.h"
|
||||
#include "base/Event.h"
|
||||
#include "base/EventTypes.h"
|
||||
#include "base/IEventQueue.h"
|
||||
#include "base/PriorityQueue.h"
|
||||
#include "base/Stopwatch.h"
|
||||
#include "common/stdmap.h"
|
||||
#include "common/stdset.h"
|
||||
#include "mt/CondVar.h"
|
||||
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
|
||||
class Mutex;
|
||||
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
#include "base/IEventQueue.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
|
||||
EventTypes::EventTypes() : m_events(NULL)
|
||||
{
|
||||
@ -160,7 +159,7 @@ REGISTER_EVENT(Clipboard, clipboardSending)
|
||||
//
|
||||
|
||||
REGISTER_EVENT(File, fileChunkSending)
|
||||
REGISTER_EVENT(File, fileRecieveCompleted)
|
||||
REGISTER_EVENT(File, fileReceiveCompleted)
|
||||
REGISTER_EVENT(File, keepAlive)
|
||||
|
||||
//
|
||||
|
||||
@ -673,7 +673,7 @@ class FileEvents : public EventTypes
|
||||
public:
|
||||
FileEvents()
|
||||
: m_fileChunkSending(Event::kUnknown),
|
||||
m_fileRecieveCompleted(Event::kUnknown),
|
||||
m_fileReceiveCompleted(Event::kUnknown),
|
||||
m_keepAlive(Event::kUnknown)
|
||||
{
|
||||
}
|
||||
@ -685,7 +685,7 @@ public:
|
||||
Event::Type fileChunkSending();
|
||||
|
||||
//! Completed receiving a file
|
||||
Event::Type fileRecieveCompleted();
|
||||
Event::Type fileReceiveCompleted();
|
||||
|
||||
//! Send a keep alive
|
||||
Event::Type keepAlive();
|
||||
@ -694,7 +694,7 @@ public:
|
||||
|
||||
private:
|
||||
Event::Type m_fileChunkSending;
|
||||
Event::Type m_fileRecieveCompleted;
|
||||
Event::Type m_fileReceiveCompleted;
|
||||
Event::Type m_keepAlive;
|
||||
};
|
||||
|
||||
|
||||
@ -7,8 +7,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace deskflow {
|
||||
|
||||
/**
|
||||
@ -7,8 +7,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/Common.h"
|
||||
#include "common/IInterface.h"
|
||||
#include "common/common.h"
|
||||
|
||||
class Event;
|
||||
class EventQueueTimer;
|
||||
|
||||
@ -7,8 +7,8 @@
|
||||
|
||||
#include "base/Log.h"
|
||||
#include "arch/Arch.h"
|
||||
#include "base/log_outputters.h"
|
||||
#include "common/constants.h"
|
||||
#include "base/LogOutputters.h"
|
||||
#include "common/Constants.h"
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdint>
|
||||
|
||||
@ -9,10 +9,7 @@
|
||||
|
||||
#include "arch/Arch.h"
|
||||
#include "arch/IArchMultithread.h"
|
||||
#include "common/common.h"
|
||||
#include "common/stdlist.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "common/Common.h"
|
||||
|
||||
#define CLOG (Log::getInstance())
|
||||
#define BYE "\nTry `%s --help' for more information."
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user