193 Commits

Author SHA1 Message Date
3ef5793beb Release 1.20.0
Some checks are pending
Continuous Integration / pr-comment-flags (push) Blocked by required conditions
Continuous Integration / ci-passed (push) Blocked by required conditions
Continuous Integration / test-results (push) Blocked by required conditions
Continuous Integration / reuse-lint (push) Waiting to run
Continuous Integration / lint-check (push) Blocked by required conditions
Continuous Integration / analyse-valgrind (push) Blocked by required conditions
Continuous Integration / analyse-sonarcloud (push) Blocked by required conditions
Continuous Integration / macos-14-arm64 (push) Blocked by required conditions
Continuous Integration / macos-13-x64 (push) Blocked by required conditions
Continuous Integration / archlinux-x86_84 (push) Blocked by required conditions
Continuous Integration / debian-13-arm64 (push) Blocked by required conditions
Continuous Integration / debian-13-x86_64 (push) Blocked by required conditions
Continuous Integration / fedora-40-arm64 (push) Blocked by required conditions
Continuous Integration / fedora-40-x86_84 (push) Blocked by required conditions
Continuous Integration / fedora-41-arm64 (push) Blocked by required conditions
Continuous Integration / fedora-41-x86_64 (push) Blocked by required conditions
Continuous Integration / opensuse-arm64 (push) Blocked by required conditions
Continuous Integration / opensuse-x86_84 (push) Blocked by required conditions
Continuous Integration / ubuntu-25.04-arm64 (push) Blocked by required conditions
Continuous Integration / ubuntu-25.04-x86_64 (push) Blocked by required conditions
Continuous Integration / windows-2022-x64 (push) Blocked by required conditions
Continuous Integration / unix-freebsd (push) Blocked by required conditions
Continuous Integration / flatpak-aarch64 (push) Blocked by required conditions
Continuous Integration / flatpak-x86_64 (push) Blocked by required conditions
Continuous Integration / release (push) Blocked by required conditions
Continuous Integration / winget-publish (push) Blocked by required conditions
2025-03-03 16:37:24 -05:00
b64942e3a3 fix: Delete HKEY_LOCAL_MACHINE\SOFTWARE\Deskflow when clearing settings 2025-03-03 15:05:09 -05:00
9de268d293 chore: Reduce noisy log lines related to fingerprints not required by GUI 2025-03-03 13:31:18 -05:00
1f08cafffe fix: Use string data instead of path data for fingerprint logging 2025-03-03 13:31:18 -05:00
9eeda33293 fix: do not reset screenCorners on startup
fixes #8276
2025-03-03 17:26:48 +00:00
17bedb1072 fix: Correct parsing of screen corners
fixes #8231
2025-03-03 17:26:48 +00:00
8cca8440b7 fixes #7695 adjust the serverconfig clipboard max size label 2025-03-03 17:16:24 +00:00
b2dadba6fa refactor: serverdialog, use maximum for spinbox horizontal sizepolicy 2025-03-03 17:16:24 +00:00
4f057d706f refactor: serverconfigdialog, use suffix for spinboxes 2025-03-03 17:16:24 +00:00
5e69657176 chore: update windows rc descriptions fixes #8270 2025-03-03 16:32:08 +00:00
2638cce0c0 fix: Do stop the client on fingerprint dialog
fixes #8267
2025-03-03 16:16:57 +00:00
5eac984757 chore: Add mutex for process state management in MSWindowsWatchdog 2025-03-03 14:33:46 +00:00
1bd3f5060e refactor: Add Doxygen comments for MSWindowsWatchdog member functions 2025-03-03 14:33:46 +00:00
55b4cffd3f chore: Remove unused setStartupInfo member function from MSWindowsWatchdog 2025-03-03 14:33:46 +00:00
51ec36f23d chore: Set default values for m_foreground and m_activeDesktop MSWindowsWatchdog 2025-03-03 14:33:46 +00:00
58cb2b76de chore: Remove unused include in MSWindowsWatchdog.h 2025-03-03 14:33:46 +00:00
8d4a715b1c chore: Make MSWindowsWatchdog constructor explicit 2025-03-03 14:33:46 +00:00
997d4a9473 chore: Move free functions to top of Windows watchdog source 2025-03-03 14:33:46 +00:00
0f11b61576 chore: Reduce complexity of outputLoop in Windows watchdog 2025-03-03 14:33:46 +00:00
98aba612c0 chore: Improve loop stop log line in Windows watchdog 2025-03-03 14:33:46 +00:00
b0547f6713 chore: Use ref to const for openProcessForKill arg in Windows watchdog 2025-03-03 14:33:46 +00:00
40fefb9369 chore: Use string_view for MSWindowsWatchdog::setProcessConfig 2025-03-03 14:33:46 +00:00
48e1c43a01 chore: Add cspell words for Windows watchdog 2025-03-03 14:33:46 +00:00
d8d022e9fe chore: Scope constants in Windows watchdog 2025-03-03 14:33:46 +00:00
84194cf5ef chore: Use default init instead of ctor init Windows watchdog 2025-03-03 14:33:46 +00:00
cd5ba1382d chore: Clean up shutdownExistingProcesses (unused var and use if-init) in Windows watchdog 2025-03-03 14:33:46 +00:00
c84b4e3f00 refactor: Reduce complexity of mainLoop in Windows watchdog 2025-03-03 14:33:46 +00:00
be8029deb6 chore: Remove unused g_activeDesktop from Windows watchdog 2025-03-03 14:33:46 +00:00
dbb9b3bf5a chore: Remove unused trimDesktopName from Windows watchdog 2025-03-03 14:33:46 +00:00
32bf9aa02a chore: Use const auto instead of enum for kOutputBufferSize in Windows watchdog 2025-03-03 14:33:46 +00:00
0891afdd63 chore: Use nullptr instead of NULL in Windows watchdog 2025-03-03 14:33:46 +00:00
f7ab6aba58 chore: Remove unused includes from Windows watchdog 2025-03-03 14:33:46 +00:00
74e8a63dcd chore: Remove unused getCommand from Windows watchdog 2025-03-03 14:33:46 +00:00
475172597a chore: Remove unused m_ready from Windows watchdog 2025-03-03 14:33:46 +00:00
8c30ed7a59 chore: Remove unused m_autoDetectCommand and ctor arg from Windows watchdog 2025-03-03 14:33:46 +00:00
44f72a29e9 refactor: Use state machine for Windows daemon watchdog 2025-03-03 14:33:46 +00:00
4db77ba2f7 chore: Improve function name for setting daemon process config 2025-03-03 14:33:46 +00:00
5e29fa93ac chore: Quieten noisy daemon IPC server read log messages 2025-03-03 14:33:46 +00:00
ce8c262a9c build: mac os rpath for client, server and core 2025-02-28 23:04:33 +00:00
3b30065ec3 chore: Prevent static analysis from complaining about new (idiomatic Qt) 2025-02-28 17:58:16 +00:00
54483f26ba refactor: Use member instead of passing param in daemon main loop 2025-02-28 17:58:16 +00:00
13ed447a93 chore: Move daemon constants to constants file 2025-02-28 17:58:16 +00:00
74812fbf75 chore: Remove dead code, function isServerCommandLine from daemon 2025-02-28 17:58:16 +00:00
bdf5a0f352 chore: Clearer naming for static daemon loop functions 2025-02-28 17:58:16 +00:00
b425b43801 fix: Use desktop process mode for core process tests rather than random value 2025-02-28 17:58:16 +00:00
f0c60f5ca9 chore: Improve logging for pipe readers in Windows watchdog 2025-02-28 17:58:16 +00:00
b2ca9bc17b chore: Remove dead code from --debug-service-wait arg 2025-02-28 17:58:16 +00:00
f46474c9f2 refactor: Use WaitForSingleObject instead of sleep for Windows process shutdown 2025-02-28 17:58:16 +00:00
a99d408be1 chore: Improve logging related to Windows daemon start/stop/install/uninstall 2025-02-28 17:58:16 +00:00
19c41e2ac5 fix: Improve Windows daemon stop speed by using non-blocking pipes and shorter sleep times 2025-02-28 17:58:16 +00:00
890fd61e6e refactor: Move ownership of Windows daemon file log outputter to Log 2025-02-28 17:58:16 +00:00
1c42552b3b refactor: Begin logging to file as soon as Windows daemon starts 2025-02-28 17:58:16 +00:00
a6956b9516 refactor: Improve Daemon uninstall exception flow 2025-02-28 17:58:16 +00:00
5a7f6bd1c0 refactor: Remove old Windows TCP IPC implementation (replaced by Qt equivalent) 2025-02-28 17:58:16 +00:00
a3b0ec28fc refactor: Improve logging message for process backoff and reset failure count when no command is set 2025-02-28 17:58:16 +00:00
fa1ab27ee9 refactor: Clear watchdog command setting to prevent persistence on daemon restart 2025-02-28 17:58:16 +00:00
e07a2efbcc refactor: Implement Windows event loop in AppUtilWindows for graceful shutdown handling 2025-02-28 17:58:16 +00:00
e967944c1e fix: Strip line endings for Windows daemon file logging
Windows file logger and `OutputDebugString` already add new lines, so remove the ones added by the Core.
2025-02-28 17:58:16 +00:00
389028ccf9 refactor: Connect socket events in ctor for daemon IPC client 2025-02-28 17:58:16 +00:00
dc6383d593 refactor: Properly disconnect and clean up previous daemon file tail on connection 2025-02-28 17:58:16 +00:00
1c7adf5add refactor: Allocate daemon app and it's thread on stack to reduce memory leak risk 2025-02-28 17:58:16 +00:00
5743db3040 feat: Apply log level on IPC connection 2025-02-28 17:58:16 +00:00
5733541b2a feat: Tail daemon log file instead of using IPC log outputter 2025-02-28 17:58:16 +00:00
5980fb741b refactor: Move daemon process stop command to new Qt IPC 2025-02-28 17:58:16 +00:00
7c672b06d8 refactor: Update IPC server to handle log level and elevate mode changes 2025-02-28 17:58:16 +00:00
53038760de refactor: Use core mode for daemon install on Windows 2025-02-28 17:58:16 +00:00
d6228416a1 refactor: Send log level to daemon over IPC instead of when sending command 2025-02-28 17:58:16 +00:00
80cc323f5a refactor: Improve logging and error handling for SendSAS function in Windows watchdog 2025-02-28 17:58:16 +00:00
90e63e2e9e refactor: Exclude current process when killing existing process from Windows daemon 2025-02-28 17:58:16 +00:00
24c57e46e2 refactor: Run legacy daemon loop in thread 2025-02-28 17:58:16 +00:00
e72faf1446 feat: Connect to daemon IPC on start request 2025-02-28 17:58:16 +00:00
c1d7474700 feat: Restart process from daemon through new Qt IPC impl 2025-02-28 17:58:16 +00:00
0d2d9f385d feat: Implement basic IPC connection between Daemon and GUI 2025-02-28 17:58:16 +00:00
c0094554b1 feat: Convert daemon to Qt app and introduce Qt local server 2025-02-28 17:58:16 +00:00
95603c82ec refactor: Improve logging and args for Windows daemon install/uninstall 2025-02-28 17:58:16 +00:00
8debc1ea7f chore: SettingsDialog remove set defaults from ui file 2025-02-28 16:51:33 +00:00
b4f703562d chore: Settings Dialog do not open with the checkbox for peer certificates having active focus 2025-02-28 16:51:33 +00:00
34b61cc8cd fix: #8259 track a client and server list
fixes 8259
2025-02-28 13:17:26 +00:00
551e0211ac ci: don't send temp screenshots to flathub, fix lint failure for not doing so 2025-02-28 13:06:32 +00:00
0fc5368253 fix: Prevent access violation by moving events, arch, and log objects to top of stack in Windows daemon
This is how we do it in the server/client apps, so it makes sense to mirror the same pattern.
2025-02-28 12:57:15 +00:00
383b39636e chore: Remove dead code; unused outputter param on runInner functions 2025-02-28 12:57:15 +00:00
f56a3ba305 refactor: Rename param for Log::insert to make adoption clearer 2025-02-28 12:57:15 +00:00
0bca094fce chore: Explain use of new for all log outputters 2025-02-28 12:57:15 +00:00
220711c2d7 fix: Only use MS debug outputter when the process is daemonized 2025-02-28 12:57:15 +00:00
66acf9038b fix: Solve double-free by letting Log adopt FileLogOutputter in Windows daemon 2025-02-28 12:57:15 +00:00
aa5a704131 chore: settings dialog remove unused includes 2025-02-27 15:17:13 +00:00
bae494476b refactor: Settings Dialog, update security layout 2025-02-27 15:17:13 +00:00
3ae2de52f4 refactor: SettingsDialog set icons in ui where possible 2025-02-27 15:17:13 +00:00
088d69fec8 refactor: SettingsDialog, use standard object names 2025-02-27 15:17:13 +00:00
63744ddbd6 refactor: settingsdialog, remove autoconnect slots 2025-02-27 15:17:13 +00:00
2d04e0be4d refactor: SettingDialog do not connect from inside the ui file 2025-02-27 15:17:13 +00:00
4f2ef7174a refactor: do not stop sever on new client fingerprint, track the last print we checked and if we are chekcing it do not show a new box 2025-02-27 15:07:50 +00:00
1003de21b5 refactor: do not show error if the fingerprint database is not created yet 2025-02-27 15:07:50 +00:00
b3866b69b2 chore: Fix order of MainWindow ctor init list to match header 2025-02-27 15:07:50 +00:00
9bd7fce45c refactor: MainWindow: Update name change 2025-02-27 13:41:55 +00:00
f0d33ce9de chore: aboutDialog remove unused static strings 2025-02-27 13:32:24 +00:00
07bf6de093 chore: add icon credit to about box 2025-02-27 13:32:24 +00:00
9c463a557a docs: Expand version field on bug_report.yml 2025-02-27 05:12:43 -08:00
566d716feb chore: Remove unused config lines from sonar-project.properties 2025-02-27 04:55:13 -08:00
e7e518d76e refactor: don't quote debug line 2025-02-26 11:52:03 +00:00
08be9fa33f chore: use a style for the flat buttons 2025-02-26 11:52:03 +00:00
72d27c70e0 refactor: gui::styles use QStringLiteral 2025-02-26 11:52:03 +00:00
6de1920d88 chore: remove bufferedLogView 2025-02-25 06:53:57 -08:00
2d3f64f662 chore: cleanup additional item missed in when removing the legacy tray icon 2025-02-25 06:53:57 -08:00
193c28af53 fix: settings dialog can have tls options enabled when they should not be leading to a case where tls gen fails as it not enabled fixes 7883 2025-02-25 06:34:47 -08:00
5b54849fd6 refactor: mainwindow simplify the mode selection UI 2025-02-25 14:18:32 +00:00
b7eb5c467b feat: Remove Inverse Connections Option 2025-02-25 14:18:32 +00:00
f9b6bcc950 refactor: mv net/InverseSockets/SslLogger => net/SslLogger 2025-02-25 14:18:32 +00:00
5d5e32a676 refactor: remove setupwizard 2025-02-25 13:21:39 +00:00
d52939a3fc fix: raise mainwindow on update check dialog
fixes #8234
2025-02-25 13:11:35 +00:00
173e521004 ci: Set timeout for windows job to 30 minutes 2025-02-25 04:07:10 -08:00
038c8af949 ci: use pkg list for vcpkg on ci builds 2025-02-25 04:07:10 -08:00
9f68514577 ci: use Qt install action for windows 2025-02-25 04:07:10 -08:00
d5624ba65e ci: use Qt 6.8.2 for Qt action installs
update vcpkg manifest to newest vcpkg release
2025-02-25 04:07:10 -08:00
d5ee57f349 build: vcpkg rm nolonger used openssl tools 2025-02-25 04:07:10 -08:00
6a08305338 fix: log expanded on start up and windows no resizeable 2025-02-20 22:26:21 +00:00
05ed47be2e fix: server resets to listing state with no clients connected 2025-02-20 21:16:48 +00:00
29d04ea8e0 chore: update lib/gui/constants to use QStringLiterals 2025-02-20 21:16:48 +00:00
ab118a3aa3 chore: remove unused style items 2025-02-20 21:16:48 +00:00
10e5a305bb refactor: remove redundant client / server staus labels, the status label provides this info already 2025-02-20 21:16:48 +00:00
e9c8965066 refactor: mainwindow move tls version to securty tooltip 2025-02-20 21:16:48 +00:00
53d2b3bd2e refactor: MainWindow move update info to status tray 2025-02-20 21:16:48 +00:00
d4cc66a9f9 refactor: move Tls Label to status bar 2025-02-20 21:16:48 +00:00
18cc8565f9 refactor: mainwindow use status bar for status items 2025-02-20 21:16:48 +00:00
caee2b149a chore: move version check log to debug, fixes #8224 2025-02-20 11:15:58 +00:00
e808eed413 refactor: Improve Windows daemon failure backoff for faster client restarts on first fail 2025-02-19 18:23:10 +00:00
16c57d7960 refactor: Improve log message related to desk switch on Windows 2025-02-19 18:23:10 +00:00
200d32db80 chore: Improve log message for leave screen warning on Windows 2025-02-19 18:23:10 +00:00
2322f312a9 refactor: Improve logging for errors when setting/getting cursor pos on Windows 2025-02-19 18:23:10 +00:00
09c157f9e1 fix: Remove --exit-pause to stop "press any key to exit..." showing when Windows daemon kills server/client 2025-02-19 18:23:10 +00:00
c9a360a144 fix: Restore active desktop name check in Windows daemon
- Use `PIPE_NOWAIT` to skip empty stderr output on process output reading from Windows daemon watchdog
- Use `CreateProcess` result to determine when to call `CloseHandle` in Windows daemon watchdog
- Trim output from active desktop process in Windows daemon watchdog
- Improve error logging in Windows daemon watchdog
2025-02-19 18:23:10 +00:00
3de2c1bcf0 fix: missing reuse info for SECURITY.md file 2025-02-18 08:04:26 -05:00
73292f05c8 docs: Create GitHub recommended security policy file 2025-02-18 07:57:08 -05:00
48407d7f8f refactor: simplify MainWindow::checkFingerprints 2025-02-18 12:12:41 +00:00
83c190c385 refactor: use better name to describe for the tlsEnabled var in messages , and correct the name in virtual method 2025-02-18 12:12:41 +00:00
ad79ba907d refactor: Mainwindow localFingerPrintDb => localFingerprintDb 2025-02-18 12:12:41 +00:00
9294f2a026 refactor: use a function to get the trustedFingerprintDb 2025-02-18 12:12:41 +00:00
bfb64f0653 fix: Generate TLS certificate before generating TLS fingerprint 2025-02-17 11:55:28 -05:00
6f66fe767f fix: inabliity to resize when first opening if log open on startup 2025-02-17 11:55:28 -05:00
63846292ff refactor: update tooltips for security icon
add check when appTls State Changes
2025-02-17 11:55:28 -05:00
2f8b78e2a6 refactor: new private MainWindow method localhostFingerprintDb 2025-02-17 11:55:28 -05:00
8d0491f1ad refactor: narrow use of stdString in mainwindow 2025-02-17 11:55:28 -05:00
79dc858446 chore: modify client trying to connect dialog to inform user the new client needs to be put in the layout when both tls is enabled and peer key checking is enabled , otherwise show the old dialog asking to allow the client to connect 2025-02-17 16:26:29 +00:00
0667f5de73 refactor: allow the fingerprint dialog to show local keys and remote if needed 2025-02-17 16:26:29 +00:00
e51956e2c7 feat: Client ID verification
based on barrier: 229abab
  Fixes: CVE-2021-42072, CVE-2021-42073
2025-02-17 16:26:29 +00:00
60c7e512f2 refactor: use enum for secure sockets
based on barrier: 57769cf
2025-02-17 16:26:29 +00:00
e996471e37 refactor: use enum for connections security level
based on barrier: 5c7d719
2025-02-17 16:26:29 +00:00
638349b48a feat: add config for client cert required
based on barrier: 8bc280e0
2025-02-17 16:26:29 +00:00
3e7b14cbd4 fix: Attempt to load SSL certs when connecting
based on barrier: c0ce8937, 4d73ed9f
2025-02-17 16:26:29 +00:00
3abf38aff9 ci: Improve flatpak builder to include arm flatpaks, linting and validation check 2025-02-17 15:38:19 +00:00
12a56f4df0 chore: add updated screenshots from deskflow.org 2025-02-17 15:38:19 +00:00
9bd5fe9afb chore: Replace deprecated developer_name tag with developer block 2025-02-17 15:38:19 +00:00
6ff5d2d5d3 fix: Update local fingerprint label after fingerprint regeneration 2025-02-14 09:42:47 -05:00
c04610c561 chore: use fancy-checkout v1 tag 2025-02-14 13:46:44 +00:00
67e2f56724 chore: update daemon description and icon 2025-02-14 12:44:29 +00:00
5288546231 refactor: use const for tlsDb expected size 2025-02-14 12:44:29 +00:00
d8e311fe59 fix: only regenerate the tls certificate if tls is enabled and we do not already have a certificate 2025-02-14 12:44:29 +00:00
500067a778 fix: generate cert if tls is on and its not found
fixes #8191
  fixes #8192
2025-02-14 12:44:29 +00:00
3c12915fd3 fix: Security icons showing with fresh install
fixes #8170
2025-02-14 12:20:48 +00:00
eb19547b45 refactor: mainwindow force regen of local prints if tls is enabled with a sha256 key 2025-02-12 13:41:45 +00:00
65eed64f04 refactor: new fingerprintdialog 2025-02-12 13:41:45 +00:00
fbaa0a8433 feat: use sha256
based-on: a428b61c7d
 based-on: b7757fbd68
 based-on: a238b27879
2025-02-12 13:41:45 +00:00
743c3feef3 refactor: use FingerprintData for fingerprints
based-on: 7cced74119
2025-02-12 13:41:45 +00:00
d0d5182425 refactor: use new Fingerprint database
based-on: 50534ecb43
   based-on: be8ba0d132
2025-02-12 13:41:45 +00:00
298b1047c4 refactor: add ssl consts into common/constansts 2025-02-12 13:41:45 +00:00
e257501072 chore: add Fingerprint Db Tests 2025-02-12 13:41:45 +00:00
aaa64e986e feat!: Add support for FingerPrintDatabase 2025-02-12 13:41:45 +00:00
7d79a4d729 chore: TlsCertificate, remove unused items 2025-02-12 13:41:45 +00:00
2058519e57 refactor: generate Certs using secureUtils method 2025-02-12 13:41:45 +00:00
5a71d63923 refactor: secureutils add pemFileCertFingerprint 2025-02-12 13:41:45 +00:00
fb32f141cc refactor: secureUtils fingerprint method
Signed-off-by: sithlord48 <sithlord48@gmail.com>
2025-02-12 13:41:45 +00:00
39da277ead refactor: use vector<uint8_t> for keys 2025-02-12 13:41:45 +00:00
a98f2d745e refactor: move SecureSocket::formatFingerprint -> SecureUtils std::string formatSSLFingerprint
based on 0e406d4918
         9d8e1faf59
         b793675ef8
2025-02-12 13:41:45 +00:00
524c3b0e7b refactor: Change log level for active desktop query to debug 2025-02-11 13:06:51 +00:00
e420b9b986 chore: small cmake cleanup
lib/platform: use the REQUIRED_QT_VERSION when looking for Qt Dbus module
  lib/deskflow: rm extra space in cmake file
2025-02-11 13:06:51 +00:00
cb14d158cc refactor: Cleanup core binary help text 2025-02-11 13:06:51 +00:00
ac6809d40f refactor: Rename core process start/stop function names 2025-02-11 13:06:51 +00:00
92603df93d fix: Out of order m_trayIcon in ctor init,
chore: remove unused m_btnCancel
2025-02-11 13:06:51 +00:00
a5f28616f4 chore: df-gui mainwindow directly connect more methods without intermediarty methods 2025-02-11 13:06:51 +00:00
cad1243d75 chore: windows, set icon for deskflow-core 2025-02-11 13:06:51 +00:00
610786ad2e chore: clean up extra empty lines 2025-02-11 13:06:51 +00:00
d093894743 fix: [test]fix #8174, create empty config file under HOME dir
The server always create an empty config file in user's home dir, set tmp config file path for the unittest in order to fix this issue.

Log: Fix unittest create empty config file.
2025-02-11 07:13:31 -05:00
942070950d refactor: MainWindow do not use onNames 2025-02-04 18:11:41 +00:00
ddc24ffb22 refactor: MainWindow don't use lambda where direct connect can happen 2025-02-04 18:11:41 +00:00
b14de6f9e2 refactor: MainWindow conform to naming standards 2025-02-04 18:11:41 +00:00
10c50c9740 docs: Link to the known wayland issues in the readme 2025-02-03 12:45:22 +00:00
60577f00dc chore: add Icons for list-add , list-remove and document-edit 2025-02-03 12:36:18 +00:00
fedd9d33c9 refactor: serverConfig finish renaming, improve logic 2025-02-03 12:36:18 +00:00
ae30237f90 refactor: ServerConfigDialog/tabAdvanced no autoconnections, use naming std 2025-02-03 12:36:18 +00:00
169422a0eb refactor: ServerConfigDialog hotkeyTab, no auto connections use naming std 2025-02-03 12:36:18 +00:00
76fd40a3ec refactor: ServerConfigDialog/tabComputers, no autoconnect slots, use new names 2025-02-03 12:36:18 +00:00
816d66b703 refactor: Don't use autoconnect slots for the button box 2025-02-03 12:36:18 +00:00
774f1fded9 fix: Add client dialog not showing for new clients 2025-02-03 12:36:18 +00:00
236 changed files with 6028 additions and 8890 deletions

View File

@ -22,12 +22,16 @@ body:
validations:
required: true
- type: input
- type: textarea
id: version
attributes:
label: Deskflow version number
description: You can find the Deskflow version number on the about screen.
placeholder: 1.2.3.4
label: Deskflow version info
description: You can find the Deskflow version number on the About screen.
placeholder: |
Deskflow: 1.2.3.4 (deadc0de)
Qt: 3.2.1
System: Hannah Montana Linux (Workstation Edition)
Session: Unity (Compiz)
validations:
required: true
@ -51,7 +55,7 @@ body:
id: os
attributes:
label: Operating systems (OS)
description: Which operating systems (OS) are you using?
description: Operating systems (OS) in use for all servers and clients
options:
- label: Windows
- label: macOS
@ -110,8 +114,7 @@ body:
label: Deskflow configuration
description: |
Please provide a very brief description of your configuration.
Let us know the OS of the server/host/primary and the OS of the client/guest/secondary.
This will help us understand how you're using Deskflow.
Let us know what OS your server and client are running.
placeholder: |
- Windows 11 server, macOS 15 client
- Each computer has a single monitor
@ -122,9 +125,8 @@ body:
attributes:
label: What steps will reproduce the problem?
description: |
Please list the steps to reproduce the issue.
Please list the _numbered steps_ to reproduce the issue.
If you're not sure, please provide as much detail as possible.
This will help us understand the problem.
placeholder: |
1. Start Deskflow
2. Click 'Configure Server'

View File

@ -9,8 +9,12 @@ inputs:
description: "Used only on linux distro type: debian, fedora, suse, arch"
required: false
mac-qt-version:
description: "The verison of Qt to install on mac os"
qt-version:
description: "The version of Qt to install (Windows & macOS)"
required: false
qt-install-dir:
description: "The path to install Qt into (Windows & macOS)"
required: false
outputs:
@ -67,13 +71,13 @@ runs:
shell: bash
- name: Install Qt
if: ${{runner.os == 'macOS' }}
if: ${{runner.os != 'Linux' }}
uses: jurplel/install-qt-action@v4
with:
dir: "/Users/runner"
version: ${{inputs.mac-qt-version}}
dir: ${{inputs.qt-install-dir}}
version: ${{inputs.qt-version}}
cache: true
cache-key-prefix: ${{matrix.target.os}}-${{env.qt-version}}
cache-key-prefix: ${{matrix.target.os}}-${{inputs.qt-version}}
# Install Ninja with an action instead of using Chocolatey, as it's more
# reliable and faster. The Ninja install action is pretty good as it
@ -87,7 +91,8 @@ runs:
id: vcpkg
uses: johnwason/vcpkg-action@v6
with:
manifest-dir: ${{ github.workspace }}
pkgs: wintoast gtest pkgconf openssl
extra-args: --classic
triplet: x64-windows-release
token: ${{ github.token }}
github-binarycache: true

View File

@ -44,7 +44,7 @@ jobs:
apt install -qqq git > /dev/null
- name: Fancy Checkout
uses: sithlord48/fancy-checkout@v1.0.0
uses: sithlord48/fancy-checkout@v1
- name: Install dependencies
uses: ./.github/actions/install-dependencies

View File

@ -131,19 +131,22 @@ jobs:
target:
- name: "windows-2022-x64"
runs-on: "windows-2022"
timeout: 120 #Windows can take while if it has to build vcpkg cache
timeout: 30
config-args: "-G Ninja"
qt-install-dir: "C:"
- name: "macos-14-arm64"
runs-on: "macos-14"
timeout: 10
arch: arm64
config-args: "-DCMAKE_OSX_ARCHITECTURES=\"arm64\""
qt-install-dir: "/Users/runner"
- name: "macos-13-x64"
runs-on: macos-13
timeout: 20
config-args: "-DCMAKE_OSX_ARCHITECTURES=\"x86_64\""
qt-install-dir: "/Users/runner"
- name: "debian-13-x86_64"
runs-on: ubuntu-latest
@ -243,7 +246,7 @@ jobs:
# Fancy checkout gets all the tags
# it also makes sure we can use git --describe correctly
- name: Fancy Checkout
uses: sithlord48/fancy-checkout@v1.0.0
uses: sithlord48/fancy-checkout@v1
# This effectively runs `vcvarsall.bat`, etc. It's not actually installing
# VC++ as that's already pre-installed on the Windows runner.
@ -255,7 +258,8 @@ jobs:
id: get-deps
uses: ./.github/actions/install-dependencies
with:
mac-qt-version: 6.7.3
qt-version: 6.8.2
qt-install-dir: ${{matrix.target.qt-install-dir}}
like: ${{ matrix.target.like }}
- name: Get version
@ -311,7 +315,7 @@ jobs:
# Fancy checkout gets all the tags
# it also makes sure we can use git --describe correctly
- name: Fancy Checkout
uses: sithlord48/fancy-checkout@v1.0.0
uses: sithlord48/fancy-checkout@v1
- name: Build on FreeBSD
if: ${{ matrix.distro.name == 'freebsd' }}
@ -331,36 +335,45 @@ jobs:
needs: lint-check
name: flatpak-${{matrix.flatpak.arch}}
runs-on: ${{matrix.flatpak.runs-on}}
timeout-minutes: 60
container:
image: ghcr.io/flathub-infra/flatpak-github-actions:kde-6.8
options: --privileged
strategy:
fail-fast: false
matrix:
flatpak:
- runs-on: ubuntu-latest
arch: x86_64
# TODO: Action does not yet provide arm image; re-enable when available
# - runs-on: ubuntu-24.04-arm
# arch: aarch64
container:
image: bilelmoussaoui/flatpak-github-actions:kde-6.7
options: --privileged
- runs-on: ubuntu-24.04-arm
arch: aarch64
steps:
- name: Check out repository
uses: sithlord48/fancy-checkout@v1.0.0
uses: sithlord48/fancy-checkout@v1
- run: git config --global protocol.file.allow always
- name: Get version
uses: ./.github/actions/get-version
- uses: flatpak/flatpak-github-actions/flatpak-builder@master
name: "Build"
- name: Lint appsteam
run: flatpak-builder-lint appstream deploy/linux/org.deskflow.deskflow.metainfo.xml
- name: Lint manifest
run: flatpak-builder-lint manifest deploy/linux/flatpak/org.deskflow.deskflow.yml
- name: Build
uses: flathub-infra/flatpak-github-actions/flatpak-builder@53987ffa5f687586936d85fdce3f440848bea04d
with:
bundle: deskflow-${{env.DESKFLOW_PACKAGE_VERSION}}-linux-${{matrix.flatpak.arch}}.flatpak
manifest-path: deploy/linux/flatpak/org.deskflow.deskflow.yml
cache-key: flatpak-builder-${{matrix.flatpak.arch}}-1.0
cache-key: flatpak-builder-${{matrix.flatpak.arch}}-2.0
arch: ${{matrix.flatpak.arch}}
upload-artifact: false
- name: Validate build
run: flatpak-builder-lint --exceptions --user-exceptions deploy/linux/flatpak/ci-build-lint-exceptions.json repo repo
- name: Upload
uses: actions/upload-artifact@v4
with:
@ -374,7 +387,7 @@ jobs:
steps:
- name: Fancy Checkout
uses: sithlord48/fancy-checkout@v1.0.0
uses: sithlord48/fancy-checkout@v1
- name: Get version
uses: ./.github/actions/get-version
@ -419,7 +432,7 @@ jobs:
runs-on: windows-latest
steps:
- name: Fancy Checkout
uses: sithlord48/fancy-checkout@v1.0.0
uses: sithlord48/fancy-checkout@v1
- name: Get version
uses: ./.github/actions/get-version

View File

@ -28,7 +28,7 @@ jobs:
apt install -qqq git curl unzip gcovr > /dev/null
- name: Fancy Checkout
uses: sithlord48/fancy-checkout@v1.0.0
uses: sithlord48/fancy-checkout@v1
- name: Install project dependencies
uses: ./.github/actions/install-dependencies

View File

@ -17,7 +17,7 @@ jobs:
apt install -qqq git valgrind > /dev/null
- name: Fancy Checkout
uses: sithlord48/fancy-checkout@v1.0.0
uses: sithlord48/fancy-checkout@v1
- name: Install dependencies
uses: ./.github/actions/install-dependencies

View File

@ -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 19)
set(DESKFLOW_VERSION_MINOR 20)
set(DESKFLOW_VERSION_PATCH 0)
set(DESKFLOW_VERSION_TWEAK 0)

View File

@ -167,6 +167,8 @@ who is the author of `libei`, a major contributor to `libportal`, and the author
implementation in Deskflow. Others such as Olivier Fourdan and Povilas Kanapickas helped with the
Wayland implementation.
Some features _may_ be unavailable or broken on Wayland. Please see the [known Wayland issues](https://github.com/deskflow/deskflow/discussions/7499).
### Where did it all start?
Deskflow was first created as Synergy in 2001 by Chris Schoeneman.

View File

@ -48,6 +48,12 @@ precedence = "override"
SPDX-FileCopyrightText = "Deskflow Developers"
SPDX-License-Identifier = "MIT"
[[annotations]]
path = "SECURITY.md"
precedence = "override"
SPDX-FileCopyrightText = "Deskflow Developers"
SPDX-License-Identifier = "MIT"
[[annotations]]
path = "sonar-project.properties"
precedence = "override"
@ -91,7 +97,7 @@ SPDX-FileCopyrightText = "Deskflow Developers"
SPDX-License-Identifier = "GPL-2.0-only"
[[annotations]]
path = "deploy/linux/flatpak/org.deskflow.deskflow.yml"
path = "deploy/linux/flatpak/**"
precedence = "override"
SPDX-FileCopyrightText = "Deskflow Developers"
SPDX-License-Identifier = "MIT"

11
SECURITY.md Normal file
View File

@ -0,0 +1,11 @@
# Security Policy
## Supported Versions
The latest minor release is supported and receives security updates:
https://github.com/deskflow/deskflow/releases
## Reporting a Vulnerability
Please report vulnerabilities on our issue tracker as bugs:
https://github.com/deskflow/deskflow/issues

View File

@ -45,20 +45,6 @@ macro(configure_libs)
endif()
find_package(OpenSSL ${REQUIRED_OPENSSL_VERSION} REQUIRED COMPONENTS SSL Crypto)
if(WIN32) #Used for dev in TLS and WIX
cmake_path(SET OPENSSL_ROOT_DIR NORMALIZE "${OPENSSL_INCLUDE_DIR}/..")
message(VERBOSE "Set OPENSSL_ROOT_DIR: ${OPENSSL_ROOT_DIR}")
set(OPENSSL_EXE_DIR "${OPENSSL_ROOT_DIR}/tools/openssl")
add_definitions(-DOPENSSL_EXE_DIR="${OPENSSL_EXE_DIR}")
# HACK Install a copy of openssl on windows
install(
FILES
${OPENSSL_EXE_DIR}/openssl.exe
${OPENSSL_EXE_DIR}/openssl.cnf
DESTINATION .
)
endif()
option(ENABLE_COVERAGE "Enable test coverage" OFF)
if(ENABLE_COVERAGE)

View File

@ -11,9 +11,10 @@
"codesigning",
"Compat",
"contribs",
"daemonized",
"Daun",
"Devs",
"Deskflow",
"Devs",
"distro",
"distros",
"dmgbuild",
@ -24,6 +25,7 @@
"gdrive",
"Hadzhylov",
"Hetu",
"HINSTANCE",
"hotspots",
"Hutterer",
"ifdef",
@ -39,6 +41,7 @@
"Libera",
"libportal",
"LLDB",
"logonui",
"Lysytsia",
"macdeployqt",
"msvc",
@ -48,6 +51,8 @@
"Oleksandr",
"Olena",
"outputdir",
"outputter",
"outputters",
"pacman",
"Petroules",
"Pixmap",
@ -57,6 +62,7 @@
"Priddy",
"psutil",
"pyproject",
"qobject",
"qputenv",
"readf",
"Regen",
@ -67,9 +73,11 @@
"Schoeneman",
"Serhii",
"shemp",
"SNAPPROCESS",
"Sorin",
"subproject",
"subprojects",
"Toolhelp",
"trackpad",
"Trixie",
"unittests",

View File

@ -0,0 +1,6 @@
{
"org.deskflow.deskflow": [
"appstream-external-screenshot-url",
"appstream-screenshots-not-mirrored-in-ostree"
]
}

View File

@ -4,7 +4,9 @@
<metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-2.0+</project_license>
<name>Deskflow</name>
<developer_name>Deskflow Developers</developer_name>
<developer id="org.deskflow">
<name>Deskflow Developers</name>
</developer>
<summary>Software Keyboard and mouse sharing</summary>
<description>
<p>
@ -16,7 +18,12 @@
<url type="bugtracker">https://github.com/deskflow/deskflow/issues</url>
<screenshots>
<screenshot type="default">
<image>https://github.com/user-attachments/assets/883660dc-f3f5-4b69-8821-a079a58d3882</image>
<image>https://deskflow.org/screenshots/deskflow.png</image>
<caption>Deskflow's mainwindow on KDE</caption>
</screenshot>
<screenshot>
<image>https://deskflow.org/screenshots/deskflow-dark.png</image>
<caption>Deskflow's mainwindow on KDE (dark mode)</caption>
</screenshot>
</screenshots>
<provides> <id>org.deskflow.deskflow.desktop</id> </provides>
@ -35,9 +42,25 @@
</branding>
<content_rating type="oars-1.0" />
<releases>
<release version="1.20.0" date="2025-3-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>
<li>Feature: Peer Id Checking - Fixes CVE-2021-42072 and CVE-2021-42073</li>
<li>Feature: Use Sha256 fingerprints</li>
<li>Feature: Gui cleanup and improvements</li>
<li>Remove: Inverse connection option</li>
<li>Fix: Screen Corner option</li>
<li>Fix: Show new client dialog</li>
<li>Win32: Daemon Improvements</li>
<li>Win32: Fix clear settings</li>
</ul>
</description>
<url>https://github.com/deskflow/deskflow/releases/tag/v1.20.0</url>
</release>
<release version="1.19.0" date="2025-1-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>
<p>This stable release fixes several bugs and adds a few new features. For the full changelog see the release page.</p>
<ul>
<li>Feature: New Fallback icon theme</li>
<li>Feature: Allow only one gui instance</li>
@ -57,7 +80,7 @@
</release>
<release version="1.18.0" date="2024-12-26" 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>
<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>
<li>Fix CVE-2021-42075: Close connection on app-level handshake failure</li>
<li>Fix CVE-2021-42074: Handle SSL race conditions and segmentation fault</li>
@ -130,7 +153,7 @@
</release>
<release version="1.17.1" date="2024-11-7" urgency="high">
<description>
<p>This stable Release Has a very long chagelog some notable ones are.</p>
<p>This stable release has a very long changelog some notable ones are.</p>
<ul>
<li>Remove word 'beta' from Wayland message</li>
<li>docs: Update `README.md` with Matrix link</li>
@ -247,7 +270,7 @@
</release>
<release version="1.17.0" date="2024-10-02" urgency="low">
<description>
<p>This is the first Deskflow Release.</p>
<p>This is the first Deskflow release.</p>
<ul>
<li>Use Deskflow Name</li>
<li>fix: windows build typos</li>

View File

@ -6,7 +6,10 @@ sonar.exclusions=subprojects/**,build/**
sonar.coverage.exclusions=subprojects/**,src/test/**,src/apps/deskflow-gui/**,src/apps/res/**
sonar.cpd.exclusions=**/*Test*.cpp
sonar.host.url=https://sonarcloud.io
sonar.coverageReportPaths=${{ steps.coverage-paths.outputs.csv }}
sonar.cfamily.compile-commands=build/compile_commands.json
sonar.cfamily.threads=${{ env.CPU_CORE_COUNT }}
sonar.python.version=3.10
# Allow use of `new` which is idiomatic for Qt code.
sonar.issue.ignore.multicriteria=e1
sonar.issue.ignore.multicriteria.e1.ruleKey=cpp:S5025
sonar.issue.ignore.multicriteria.e1.resourceKey=**

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2024 Chris Rizzitello <sithlord48@gmail.com>
# SPDX-FileCopyrightText: 2024 - 2025 Chris Rizzitello <sithlord48@gmail.com>
# SPDX-FileCopyrightText: 2012 - 2024 Symless Ltd
# SPDX-FileCopyrightText: 2009 - 2012 Nick Bolton
# SPDX-License-Identifier: MIT
@ -7,7 +7,7 @@ set(target ${CMAKE_PROJECT_NAME}-client)
if(WIN32)
# Generate rc file
set(EXE_DESCRIPTION "${CMAKE_PROJECT_DESCRIPTION}\\n CLI client application")
set(EXE_DESCRIPTION "${CMAKE_PROJECT_PROPER_NAME} client application")
set(EXE_ICON "
IDI_DESKFLOW ICON DISCARDABLE \"${CMAKE_SOURCE_DIR}/src/apps/res/deskflow.ico\"
@ -32,14 +32,17 @@ target_link_libraries(
io
mt
net
ipc
platform
server
app
${libs})
if(APPLE)
set_target_properties(${target} PROPERTIES RUNTIME_OUTPUT_DIRECTORY $<TARGET_BUNDLE_CONTENT_DIR:${CMAKE_PROJECT_PROPER_NAME}>/MacOS)
set_target_properties(${target} PROPERTIES
BUILD_WITH_INSTALL_RPATH TRUE
INSTALL_RPATH "@loader_path/../Libraries;@loader_path/../Frameworks"
RUNTIME_OUTPUT_DIRECTORY $<TARGET_BUNDLE_CONTENT_DIR:${CMAKE_PROJECT_PROPER_NAME}>/MacOS
)
elseif(UNIX)
install(TARGETS ${target} DESTINATION bin)
elseif(WIN32)

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2024 Chris Rizzitello <sithlord48@gmail.com>
# SPDX-FileCopyrightText: 2024 - 2025 Chris Rizzitello <sithlord48@gmail.com>
# SPDX-FileCopyrightText: 2012 - 2024 Symless Ltd
# SPDX-FileCopyrightText: 2009 - 2012 Nick Bolton
# SPDX-License-Identifier: MIT
@ -8,11 +8,13 @@ set(target ${CMAKE_PROJECT_NAME}-core)
add_executable(${target} "${target}.cpp")
if(WIN32)
# Generate rc file
set(EXE_DESCRIPTION "${CMAKE_PROJECT_DESCRIPTION}\\n CLI combined server and client")
set(EXE_DESCRIPTION "${CMAKE_PROJECT_PROPER_NAME} combined server and client application")
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)
target_sources(${target} PRIVATE
"${target}.exe.manifest"
${target}.exe.manifest
${CMAKE_SOURCE_DIR}/src/apps/res/deskflow.ico
${CMAKE_CURRENT_BINARY_DIR}/${target}.rc
)
endif()
@ -25,14 +27,17 @@ target_link_libraries(
io
mt
net
ipc
platform
server
app
${libs})
if(APPLE)
set_target_properties(${target} PROPERTIES RUNTIME_OUTPUT_DIRECTORY $<TARGET_BUNDLE_CONTENT_DIR:${CMAKE_PROJECT_PROPER_NAME}>/MacOS)
set_target_properties(${target} PROPERTIES
BUILD_WITH_INSTALL_RPATH TRUE
INSTALL_RPATH "@loader_path/../Libraries;@loader_path/../Frameworks"
RUNTIME_OUTPUT_DIRECTORY $<TARGET_BUNDLE_CONTENT_DIR:${CMAKE_PROJECT_PROPER_NAME}>/MacOS
)
elseif(UNIX)
install(TARGETS ${target} DESTINATION bin)
elseif(WIN32)

View File

@ -11,17 +11,18 @@
#include "base/Log.h"
#include "deskflow/ClientApp.h"
#include "deskflow/ServerApp.h"
#include <iostream>
#if SYSAPI_WIN32
#include "arch/win32/ArchMiscWindows.h"
#endif
#include <iostream>
void showHelp()
{
std::cout << "Usage: " CORE_BINARY_NAME " <server | client> [...options]" << std::endl;
std::cout << "server - start as a server ( deskflow-server)" << std::endl;
std::cout << "client - start as a client ( deslflow-client)" << std::endl;
std::cout << "Usage: deskflow-core <server | client> [...options]" << std::endl;
std::cout << "server - start as a server (deskflow-server)" << std::endl;
std::cout << "client - start as a client (deskflow-client)" << std::endl;
std::cout << "use deskflow-core <server|client> --help for more information." << std::endl;
}

View File

@ -8,22 +8,25 @@ if(WIN32)
set(target ${CMAKE_PROJECT_NAME}-daemon)
# Generate rc file
set(EXE_DESCRIPTION "This service runs in the background to help ${CMAKE_PROJECT_NAME} deal with UAC prompts")
set(EXE_DESCRIPTION "Windows service to run ${CMAKE_PROJECT_NAME} in 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
base
io
ipc
mt
net
platform
app
${libs})
${libs}
Qt6::Core)
install(
TARGETS ${target}

View File

@ -1,31 +1,143 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
* SPDX-FileCopyrightText: (C) 2012 - 2016, 2025 Symless Ltd.
* SPDX-FileCopyrightText: (C) 2012 Nick Bolton
* 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 <iostream>
#include "arch/Arch.h"
#include "base/EventQueue.h"
#include "base/Log.h"
#ifdef SYSAPI_UNIX
#if SYSAPI_WIN32
int main(int argc, char **argv)
{
DaemonApp app;
return app.run(argc, argv);
}
#elif SYSAPI_WIN32
#include "arch/win32/ArchMiscWindows.h"
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#endif
#include <QCoreApplication>
#include <QThread>
using namespace deskflow::core;
void handleError(const char *message);
int main(int argc, char **argv)
{
#if SYSAPI_WIN32
// Save window instance for later use, e.g. `GetModuleFileName` which is used when installing the daemon.
ArchMiscWindows::setInstanceWin32(GetModuleHandle(nullptr));
#endif
Arch arch;
arch.init();
Log log;
EventQueue events;
LOG((CLOG_PRINT "%s daemon (v%s)", kAppName, kVersion));
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;
}
switch (initResult) {
using enum DaemonApp::InitResult;
case StartDaemon: {
LOG_INFO("starting daemon");
QCoreApplication app(argc, argv);
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);
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:
return kExitFailed;
default:
return kExitSuccess;
}
}
#if SYSAPI_WIN32
// Win32 subsystem entry point (simply forwards to main).
// We need this because using regular main under the Win32 subsystem results in empty args.
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
DaemonApp app;
return app.run(__argc, __argv);
return main(__argc, __argv);
}
#endif
void handleError(const char *message)
{
// Always print error to stdout in case run as CLI program.
LOG_ERR("%s", message);
#if SYSAPI_WIN32
// Show a message box for when run from MSI in Win32 subsystem.
MessageBoxA(nullptr, message, "Deskflow daemon error", MB_OK | MB_ICONERROR);
#endif
}

View File

@ -15,7 +15,7 @@ set(CMAKE_AUTOUIC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
if(WIN32)
set(EXE_DESCRIPTION "${CMAKE_PROJECT_DESCRIPTION}\\n Control and configure deskflow")
set(EXE_DESCRIPTION "${CMAKE_PROJECT_PROPER_NAME} GUI configuration tool")
set(EXE_ICON "IDI_ICON1 ICON DISCARDABLE \"${CMAKE_SOURCE_DIR}/src/apps/res/deskflow.ico\" ")
configure_file(${CMAKE_SOURCE_DIR}/src/apps/res/windows.rc.in deskflow.rc)
set(platform_extra deskflow.rc)
@ -67,8 +67,6 @@ add_executable(${target} WIN32 MACOSX_BUNDLE
ScreenSetupModel.h
ServerConfig.cpp
ServerConfig.h
SetupWizard.cpp
SetupWizard.h
VersionChecker.cpp
VersionChecker.h
dialogs/AboutDialog.cpp
@ -80,6 +78,8 @@ add_executable(${target} WIN32 MACOSX_BUNDLE
dialogs/AddClientDialog.cpp
dialogs/AddClientDialog.h
dialogs/AddClientDialog.ui
dialogs/FingerprintDialog.h
dialogs/FingerprintDialog.cpp
dialogs/HotkeyDialog.cpp
dialogs/HotkeyDialog.h
dialogs/HotkeyDialog.ui
@ -92,16 +92,14 @@ add_executable(${target} WIN32 MACOSX_BUNDLE
dialogs/SettingsDialog.cpp
dialogs/SettingsDialog.h
dialogs/SettingsDialog.ui
widgets/ClientStateLabel.cpp
widgets/ClientStateLabel.h
widgets/FingerprintPreview.h
widgets/FingerprintPreview.cpp
widgets/KeySequenceWidget.cpp
widgets/KeySequenceWidget.h
widgets/NewScreenWidget.h
widgets/NewScreenWidget.cpp
widgets/ScreenSetupView.cpp
widgets/ScreenSetupView.h
widgets/ServerStateLabel.cpp
widgets/ServerStateLabel.h
widgets/TrashScreenWidget.cpp
widgets/TrashScreenWidget.h
)

File diff suppressed because it is too large Load Diff

View File

@ -11,13 +11,13 @@
#include <QMainWindow>
#include <QMutex>
#include <QProcess>
#include <QRegularExpression>
#include <QSettings>
#include <QSystemTrayIcon>
#include <QThread>
#include "ServerConfig.h"
#include "VersionChecker.h"
#include "common/ipc.h"
#include "gui/config/AppConfig.h"
#include "gui/config/ConfigScopes.h"
#include "gui/config/ServerConfigDialogState.h"
@ -33,12 +33,14 @@
class QAction;
class QMenu;
class QLabel;
class QLineEdit;
class QGroupBox;
class QPushButton;
class QTextEdit;
class QComboBox;
class QTabWidget;
class QToolButton;
class QCheckBox;
class QRadioButton;
class QMessageBox;
@ -46,12 +48,15 @@ class QAbstractButton;
class QLocalServer;
class DeskflowApplication;
class SetupWizard;
namespace Ui {
class MainWindow;
}
namespace deskflow::gui::ipc {
class DaemonIpcClient;
}
class MainWindow : public QMainWindow
{
using CoreMode = deskflow::gui::CoreProcess::Mode;
@ -60,7 +65,6 @@ class MainWindow : public QMainWindow
Q_OBJECT
friend class DeskflowApplication;
friend class SetupWizard;
friend class SettingsDialog;
public:
@ -76,13 +80,13 @@ public:
CoreMode coreMode() const
{
return m_CoreProcess.mode();
return m_coreProcess.mode();
}
QString address() const;
void open();
ServerConfig &serverConfig()
{
return m_ServerConfig;
return m_serverConfig;
}
void autoAddScreen(const QString name);
@ -91,28 +95,25 @@ public:
signals:
void shown();
private slots:
private:
void toggleLogVisible(bool visible);
//
// Manual slots
//
void onShown();
void onConfigScopesSaving();
void onAppConfigTlsChanged();
void onAppConfigScreenNameChanged();
void onAppConfigInvertConnection();
void onCoreProcessStarting();
void onCoreProcessError(CoreProcess::Error error);
void onCoreConnectionStateChanged(CoreProcess::ConnectionState state);
void onCoreProcessStateChanged(CoreProcess::ProcessState state);
void onCoreProcessSecureSocket(bool enabled);
void onVersionCheckerUpdateFound(const QString &version);
void onTrayIconActivated(QSystemTrayIcon::ActivationReason reason);
void onServerConnectionConfigureClient(const QString &clientName);
void firstShown();
void configScopesSaving();
void appConfigTlsChanged();
void coreProcessStarting();
void coreProcessError(CoreProcess::Error error);
void coreConnectionStateChanged(CoreProcess::ConnectionState state);
void coreProcessStateChanged(CoreProcess::ProcessState state);
void versionCheckerUpdateFound(const QString &version);
void trayIconActivated(QSystemTrayIcon::ActivationReason reason);
void serverConnectionConfigureClient(const QString &clientName);
void clearSettings();
void openAboutDialog();
void openHelpUrl() const;
void openGetNewVersionUrl() const;
void openSettings();
void startCore();
void stopCore();
@ -122,20 +123,21 @@ private slots:
void resetCore();
void showMyFingerprint();
void setModeServer();
void setModeClient();
void updateSecurityIcon(bool visible);
void coreModeToggled();
void updateModeControls(bool serverMode);
private:
std::unique_ptr<Ui::MainWindow> ui;
void updateSize();
AppConfig &appConfig()
{
return m_AppConfig;
return m_appConfig;
}
AppConfig const &appConfig() const
{
return m_AppConfig;
return m_appConfig;
}
void createMenuBar();
void setupTrayIcon();
@ -143,7 +145,6 @@ private:
void setIcon();
bool checkForApp(int which, QString &app);
void setStatus(const QString &status);
void sendIpcMessage(IpcMessageType type, const char *buffer, bool showErrors);
void updateFromLogLine(const QString &line);
QString getIPAddresses() const;
void enableServer(bool enable);
@ -168,26 +169,53 @@ private:
void showFirstConnectedMessage();
void updateStatus();
void showAndActivate();
void showHostNameEditor();
void setHostName();
VersionChecker m_VersionChecker;
QSystemTrayIcon *m_trayIcon = nullptr;
QAbstractButton *m_pCancelButton = nullptr;
bool m_SecureSocket = false;
deskflow::gui::config::ServerConfigDialogState m_ServerConfigDialogState;
bool m_SaveOnExit = true;
deskflow::gui::core::WaylandWarnings m_WaylandWarnings;
QString getTlsPath();
deskflow::gui::ConfigScopes &m_ConfigScopes;
AppConfig &m_AppConfig;
ServerConfig m_ServerConfig;
deskflow::gui::CoreProcess m_CoreProcess;
deskflow::gui::ServerConnection m_ServerConnection;
deskflow::gui::ClientConnection m_ClientConnection;
deskflow::gui::TlsUtility m_TlsUtility;
QSize m_expandedSize = QSize();
/**
* @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
*/
QString trustedFingerprintDb();
// Generate prints if they are missing
// Returns true if successful
bool regenerateLocalFingerprints();
QLocalServer *m_guiDupeChecker = nullptr;
inline static const auto m_guiSocketName = QStringLiteral("deskflow-gui");
inline static const auto m_nameRegEx = QRegularExpression(QStringLiteral("^[\\w\\-_\\.]{0,255}$"));
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;
deskflow::gui::ClientConnection m_clientConnection;
deskflow::gui::TlsUtility m_tlsUtility;
QSize m_expandedSize = QSize();
QStringList m_checkedClients;
QStringList m_checkedServers;
QSystemTrayIcon *m_trayIcon = nullptr;
QLocalServer *m_guiDupeChecker = nullptr;
deskflow::gui::ipc::DaemonIpcClient *m_daemonIpcClient = nullptr;
QLabel *m_lblSecurityStatus = nullptr;
QLabel *m_lblStatus = nullptr;
QToolButton *m_btnFingerprint = nullptr;
QPushButton *m_btnUpdate = nullptr;
// Window Actions
QAction *m_actionAbout = nullptr;

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>883</width>
<height>690</height>
<width>730</width>
<height>520</height>
</rect>
</property>
<property name="sizePolicy">
@ -19,62 +19,129 @@
<property name="windowTitle">
<string>Deskflow</string>
</property>
<widget class="QWidget" name="m_pWidgetTopLevel">
<layout class="QVBoxLayout" name="verticalLayout_7">
<widget class="QWidget" name="topLevelWidget">
<layout class="QVBoxLayout" name="_2">
<property name="spacing">
<number>10</number>
</property>
<item>
<layout class="QHBoxLayout" name="m_layoutName">
<property name="sizeConstraint">
<enum>QLayout::SizeConstraint::SetMinAndMaxSize</enum>
<widget class="QWidget" name="widget" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>28</height>
</size>
</property>
<item>
<widget class="QLabel" name="lblComputerName">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">This computer's name:</string>
</property>
</widget>
</item>
<item>
<spacer name="m_pSpacerUpdate">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="m_pLabelUpdate">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">m_pLabelUpdate</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>28</height>
</size>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<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>
<item>
<widget class="QLabel" name="labelComputerName">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">This computer's name:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblComputerName">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>lblName</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEditName">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Name can't have have spaces or special characters&lt;/p&gt;&lt;p&gt;Use Enter to save the name change.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="maxLength">
<number>255</number>
</property>
<property name="frame">
<bool>false</bool>
</property>
<property name="clearButtonEnabled">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnEditName">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Edit Computer Name</string>
</property>
<property name="icon">
<iconset theme="document-edit"/>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="m_pLabelIpAddresses">
<widget class="QLabel" name="lblIpAddresses">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
@ -90,23 +157,176 @@
</widget>
</item>
<item>
<widget class="QLabel" name="lblMyFingerprint">
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;TLS enabled (&lt;a href=&quot;#&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#4285f4;&quot;&gt;fingerprint&lt;/span&gt;&lt;/a&gt;)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::TextFormat::RichText</enum>
<property name="title">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QWidget" name="widgetModeSelection" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QRadioButton" name="rbModeServer">
<property name="text">
<string>Use this computer's keyboard and mouse
(make this computer the server)</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="rbModeClient">
<property name="text">
<string>Use another computers mouse and keyboard
(make this computer the client)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetModeOptions" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QWidget" name="serverOptions" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<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>
<item>
<widget class="QPushButton" name="btnConfigureServer">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&amp;Configure Server</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="lblNoMode">
<property name="text">
<string>You must select a mode</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="clientOptions" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<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>
<item>
<widget class="QLabel" name="m_pLabelServerName">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Server IP address or hostname:</string>
</property>
<property name="indent">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineHostname">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Hostname or IP address of the server computer.</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnConnect">
<property name="text">
<string>Connect</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="m_pWidgetModes" native="true">
<widget class="QWidget" name="widgetModes" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
@ -129,308 +349,6 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="m_pGroupServer">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>15</number>
</property>
<item alignment="Qt::AlignmentFlag::AlignTop">
<widget class="QWidget" name="m_pWidgetServerRadio" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>0</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>
<item>
<widget class="QRadioButton" name="rbModeServer">
<property name="text">
<string>Use this computer's keyboard and mouse</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>(make this computer the server)</string>
</property>
<property name="indent">
<number>20</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item alignment="Qt::AlignmentFlag::AlignTop">
<widget class="QWidget" name="m_pWidgetServer" native="true">
<layout class="QVBoxLayout" name="m_pLayoutServer">
<property name="spacing">
<number>15</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>
<item>
<widget class="QWidget" name="m_pWidgetServerInput" native="true">
<layout class="QVBoxLayout" name="m_pLayoutServerInverse">
<property name="spacing">
<number>15</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>
<item>
<widget class="QLabel" name="m_pLabelClientIp">
<property name="text">
<string>Client IP address or hostname:</string>
</property>
<property name="indent">
<number>20</number>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>20</number>
</property>
<item>
<widget class="QLineEdit" name="lineClientIp"/>
</item>
<item>
<widget class="QPushButton" name="btnConnectToClient">
<property name="text">
<string>Connect</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="deskflow::gui::widgets::ServerStateLabel" name="m_pLabelServerState">
<property name="text">
<string>No clients connected</string>
</property>
<property name="indent">
<number>20</number>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<spacer name="spacer_2">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btnConfigureServer">
<property name="text">
<string>&amp;Configure</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="m_pGroupClient">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="spacing">
<number>15</number>
</property>
<item alignment="Qt::AlignmentFlag::AlignTop">
<widget class="QWidget" name="m_pWidgetClientRadio" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<property name="spacing">
<number>0</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>
<item>
<widget class="QRadioButton" name="rbModeClient">
<property name="text">
<string>Use another computers mouse and keyboard</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>(make this computer the client)</string>
</property>
<property name="indent">
<number>20</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item alignment="Qt::AlignmentFlag::AlignTop">
<widget class="QWidget" name="m_pWidgetClientInput" native="true">
<layout class="QVBoxLayout" name="m_pLayoutClient">
<property name="spacing">
<number>15</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>
<item>
<widget class="QLabel" name="m_pLabelServerName">
<property name="text">
<string>Server IP address or hostname:</string>
</property>
<property name="indent">
<number>20</number>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>20</number>
</property>
<item>
<widget class="QLineEdit" name="lineHostname">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Hostname or IP address of the server computer.</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnConnect">
<property name="text">
<string>Connect</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="deskflow::gui::widgets::ClientStateLabel" name="m_pLabelClientState">
<property name="text">
<string>Connected to server</string>
</property>
<property name="indent">
<number>20</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
@ -443,22 +361,19 @@
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::Shape::StyledPanel</enum>
<enum>QFrame::Shape::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
<enum>QFrame::Shadow::Plain</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<layout class="QVBoxLayout" name="_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<layout class="QHBoxLayout" name="_4">
<property name="sizeConstraint">
<enum>QLayout::SizeConstraint::SetMinAndMaxSize</enum>
</property>
<item>
<widget class="QToolButton" name="btnToggleLog">
<property name="text">
<string>...</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
@ -480,6 +395,39 @@
</property>
</widget>
</item>
<item>
<spacer name="spacer">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btnApplySettings">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Apply</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnToggleCore">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Start</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
@ -496,9 +444,6 @@
<kerning>true</kerning>
</font>
</property>
<property name="undoRedoEnabled">
<bool>false</bool>
</property>
<property name="lineWrapMode">
<enum>QPlainTextEdit::LineWrapMode::NoWrap</enum>
</property>
@ -513,140 +458,13 @@
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="m_pLayoutActions">
<property name="spacing">
<number>6</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SizeConstraint::SetDefaultConstraint</enum>
</property>
<item>
<widget class="QLabel" name="lblConnectionSecurityStatus">
<property name="enabled">
<bool>true</bool>
</property>
<property name="minimumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_pStatusLabel">
<property name="text">
<string>Ready</string>
</property>
</widget>
</item>
<item>
<spacer name="spacer">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="m_pLabelNotice">
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="text">
<string notr="true">m_pLabelNotice</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
</property>
<property name="margin">
<number>0</number>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btnApplySettings">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Apply</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnToggleCore">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Start</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<customwidgets>
<customwidget>
<class>deskflow::gui::widgets::ServerStateLabel</class>
<extends>QLabel</extends>
<header>widgets/ServerStateLabel.h</header>
</customwidget>
<customwidget>
<class>deskflow::gui::widgets::ClientStateLabel</class>
<extends>QLabel</extends>
<header>widgets/ClientStateLabel.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>rbModeServer</tabstop>
<tabstop>lineClientIp</tabstop>
<tabstop>btnConnectToClient</tabstop>
<tabstop>btnConfigureServer</tabstop>
<tabstop>rbModeClient</tabstop>
<tabstop>lineHostname</tabstop>
<tabstop>btnConnect</tabstop>
<tabstop>btnToggleLog</tabstop>
<tabstop>textLog</tabstop>
<tabstop>btnApplySettings</tabstop>
<tabstop>btnToggleCore</tabstop>
</tabstops>
<resources/>
<connections/>

View File

@ -1,5 +1,6 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello <sithlord48@gmail.com>
* SPDX-FileCopyrightText: (C) 2012 Symless Ltd.
* SPDX-FileCopyrightText: (C) 2008 Volker Lanz <vl@fidra.de>
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
@ -130,10 +131,6 @@ void ServerConfig::commit()
settings().setValue("clipboardSharing", clipboardSharing());
settings().setValue("clipboardSharingSize", QVariant::fromValue(clipboardSharingSize()));
if (!getClientAddress().isEmpty()) {
settings().setValue("clientAddress", getClientAddress());
}
writeSettings(settings(), switchCorners(), "switchCorner");
settings().beginWriteArray("screens");
@ -186,9 +183,8 @@ void ServerConfig::recall()
settings().value("clipboardSharingSize", (int)ServerConfig::defaultClipboardSharingSize()).toULongLong()
);
setClipboardSharing(settings().value("clipboardSharing", true).toBool());
setClientAddress(settings().value("clientAddress", "").toString());
readSettings(settings(), switchCorners(), "switchCorner", 0, static_cast<int>(NumSwitchCorners));
readSettings(settings(), switchCorners(), "switchCorner", false, static_cast<int>(NumSwitchCorners));
int numScreens = settings().beginReadArray("screens");
Q_ASSERT(numScreens <= screens().size());
@ -293,11 +289,6 @@ QTextStream &operator<<(QTextStream &outStream, const ServerConfig &config)
outStream << "\t"
<< "clipboardSharingSize = " << config.clipboardSharingSize() << Qt::endl;
if (!config.getClientAddress().isEmpty()) {
outStream << "\t"
<< "clientAddress = " << config.getClientAddress() << Qt::endl;
}
if (config.hasSwitchDelay())
outStream << "\t"
<< "switchDelay = " << config.switchDelay() << Qt::endl;
@ -545,24 +536,6 @@ size_t ServerConfig::setClipboardSharingSize(size_t size)
return size;
}
void ServerConfig::setClientAddress(const QString &address)
{
if (m_pAppConfig->invertConnection()) {
m_ClientAddress = address;
}
}
QString ServerConfig::getClientAddress() const
{
QString clientAddress;
if (m_pAppConfig->invertConnection()) {
clientAddress = m_ClientAddress.trimmed();
}
return clientAddress;
}
QSettingsProxy &ServerConfig::settings()
{
return m_pAppConfig->scopes().activeSettings();

View File

@ -1,89 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2024 Chris Rizzitello <sithlord48@gmail.com>
* SPDX-FileCopyrightText: (C) 2012 Symless Ltd.
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#include "SetupWizard.h"
#include <QApplication>
#include <QFormLayout>
#include <QPushButton>
#include "common/constants.h"
#include "gui/config/AppConfig.h"
#include "gui/styles.h"
#include "gui/validators/ScreenNameValidator.h"
#include "gui/validators/ValidationError.h"
SetupWizard::SetupWizard(AppConfig &appConfig)
: m_appConfig{appConfig},
m_lblError{new QLabel(this)},
m_lineName{new QLineEdit(this)},
m_btnApply{new QPushButton(tr("Continue"), this)}
{
setWindowTitle(tr("Setup %1").arg(kAppName));
setFixedSize(740, 550);
auto headerFont = QFont(QStringLiteral("Cantarell"), 18, 600);
auto labelTitle = new QLabel(this);
labelTitle->setFont(headerFont);
labelTitle->setText(tr("Name your computer"));
labelTitle->setAlignment(Qt::AlignHCenter | Qt::AlignHCenter);
auto labelName = new QLabel(this);
labelName->setText(tr("Computer Name"));
auto formLayout = new QFormLayout();
formLayout->addRow(labelName, m_lineName);
formLayout->addWidget(m_lblError);
formLayout->addWidget(new QLabel(tr("Call your computer something short and meaningful, but it must have:"), this));
formLayout->addWidget(new QLabel(tr("\t⬤ No spaces"), this));
formLayout->addWidget(new QLabel(tr("\t⬤ Only these special characters: _ - ."), this));
formLayout->addWidget(new QLabel(tr("\t⬤ Only English characters and numbers"), this));
formLayout->addWidget(new QLabel(tr("\t⬤ A different name from other computers"), this));
auto labelImage = new QLabel(this);
labelImage->setPixmap(QPixmap(QStringLiteral(":/image/welcome.png")));
auto mainLayout = new QVBoxLayout();
mainLayout->setContentsMargins(9, 30, 9, 9);
mainLayout->addWidget(labelImage, 0, Qt::AlignHCenter);
mainLayout->addWidget(labelTitle);
mainLayout->addLayout(formLayout);
mainLayout->addSpacerItem(new QSpacerItem(0, 25, QSizePolicy::Fixed, QSizePolicy::Fixed));
mainLayout->addWidget(m_btnApply);
setLayout(mainLayout);
m_lblError->setStyleSheet(deskflow::gui::kStyleErrorActiveLabel);
m_lineName->setText(appConfig.screenName());
m_lineName->setValidator(
new validators::ScreenNameValidator(m_lineName, new validators::ValidationError(this, m_lblError))
);
connect(m_btnApply, &QPushButton::clicked, this, &SetupWizard::accept);
connect(m_lineName, &QLineEdit::textChanged, this, &SetupWizard::nameChanged);
}
void SetupWizard::accept()
{
m_appConfig.setWizardHasRun();
m_appConfig.setScreenName(m_lineName->text());
QDialog::accept();
}
void SetupWizard::nameChanged(const QString &error)
{
m_btnApply->setEnabled(m_lineName->hasAcceptableInput());
}
void SetupWizard::reject()
{
QDialog::reject();
QApplication::exit();
}

View File

@ -1,35 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2024 Chris Rizzitello <sithlord48@gmail.com>
* SPDX-FileCopyrightText: (C) 2012 Symless Ltd.
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#pragma once
#include <QDialog>
class AppConfig;
class QLabel;
class QLineEdit;
class SetupWizard : public QDialog
{
Q_OBJECT
public:
explicit SetupWizard(AppConfig &appConfig);
~SetupWizard() = default;
protected:
void accept() override;
void reject() override;
private:
void nameChanged(const QString &error);
AppConfig &m_appConfig;
QLabel *m_lblError = nullptr;
QLineEdit *m_lineName = nullptr;
QPushButton *m_btnApply = nullptr;
};

View File

@ -47,7 +47,7 @@ void VersionChecker::replyFinished(QNetworkReply *reply)
return;
}
qInfo("version check server success, http status: %d", httpStatus);
qDebug("version check server success, http status: %d", httpStatus);
const auto newestVersion = QString(reply->readAll());
qDebug("version check response: %s", qPrintable(newestVersion));

View File

@ -49,8 +49,8 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui{std::make_unique
ui->btnOk->setDefault(true);
connect(ui->btnOk, &QPushButton::clicked, this, [this] { close(); });
setFixedWidth(600);
adjustSize();
resize(QSize(parent->width() * 0.65, height()));
setMinimumSize(size());
}

View File

@ -25,8 +25,6 @@ private:
std::unique_ptr<Ui::AboutDialog> ui;
void copyVersionText();
inline static const auto s_lightCopy = QStringLiteral(":/icons/64x64/copy-light.png");
inline static const auto s_darkCopy = QStringLiteral(":/icons/64x64/copy-dark.png");
inline static const auto s_awesomeDevs = QStringList{
// Chris is the ultimate creator, and the one who started it all in 2001.
QStringLiteral("Chris Schoeneman"),

View File

@ -3,13 +3,13 @@
<class>AboutDialog</class>
<widget class="QDialog" name="AboutDialog">
<property name="windowModality">
<enum>Qt::WindowModality::ApplicationModal</enum>
<enum>Qt::ApplicationModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>493</width>
<width>600</width>
<height>475</height>
</rect>
</property>
@ -67,7 +67,7 @@ p, li { white-space: pre-wrap; }
<item row="6" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@ -80,7 +80,7 @@ p, li { white-space: pre-wrap; }
<item row="0" column="1">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@ -105,7 +105,7 @@ p, li { white-space: pre-wrap; }
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignBottom|Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft</set>
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
<property name="indent">
<number>0</number>
@ -158,7 +158,7 @@ p, li { white-space: pre-wrap; }
<string>Version: </string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="indent">
<number>0</number>
@ -182,7 +182,7 @@ p, li { white-space: pre-wrap; }
<string>lbl_version</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="smaller_text" stdset="0">
<bool>true</bool>
@ -207,7 +207,7 @@ p, li { white-space: pre-wrap; }
<string>Copy version info</string>
</property>
<property name="icon">
<iconset resource="../../res/deskflow.qrc">
<iconset>
<normaloff>:/icons/64x64/copy-dark.png</normaloff>:/icons/64x64/copy-dark.png</iconset>
</property>
<property name="flat">
@ -224,7 +224,7 @@ p, li { white-space: pre-wrap; }
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@ -272,7 +272,7 @@ p, li { white-space: pre-wrap; }
<string>lblDescription</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
@ -292,10 +292,10 @@ p, li { white-space: pre-wrap; }
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Fixed</enum>
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@ -306,49 +306,105 @@ p, li { white-space: pre-wrap; }
</spacer>
</item>
<item>
<widget class="QGroupBox" name="groupBox_17">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<widget class="QScrollArea" name="scrollArea">
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustIgnored</enum>
</property>
<property name="title">
<string>Important developers</string>
<property name="widgetResizable">
<bool>true</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8" stretch="0">
<property name="spacing">
<number>6</number>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>574</width>
<height>191</height>
</rect>
</property>
<property name="leftMargin">
<number>6</number>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item>
<widget class="QLabel" name="lblImportantDevs">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>lblImportantDevs</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Icons from &lt;a href=&quot;https://develop.kde.org/frameworks/breeze-icons/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#007af4;&quot;&gt;KDE Breeze&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Important Developers</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QLabel" name="lblImportantDevs">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>lblImportantDevs</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
@ -375,8 +431,6 @@ p, li { white-space: pre-wrap; }
</item>
</layout>
</widget>
<resources>
<include location="../../res/deskflow.qrc"/>
</resources>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,77 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2025 Deskflow Developers
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#include "FingerprintDialog.h"
#include "widgets/FingerprintPreview.h"
#include <QFont>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
FingerprintDialog::FingerprintDialog(
QWidget *parent, const QList<deskflow::FingerprintData> &fingerprints, FingerprintDialogMode mode
)
: QDialog(parent),
m_lblHeader{new QLabel(this)},
m_lblFooter{new QLabel(this)},
m_fingerprintPreview{new FingerprintPreview(this, fingerprints)},
m_buttonBox{new QDialogButtonBox(this)}
{
setWindowIcon(QIcon::fromTheme("fingerprint"));
setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
m_lblHeader->setWordWrap(true);
m_lblFooter->setWordWrap(true);
m_lblFooter->setAlignment(Qt::AlignHCenter);
auto layout = new QVBoxLayout();
layout->addWidget(m_lblHeader);
layout->addSpacerItem(new QSpacerItem(0, 10, QSizePolicy::Fixed, QSizePolicy::Fixed));
layout->addWidget(m_fingerprintPreview, 0, Qt::AlignTop | Qt::AlignHCenter);
layout->addWidget(m_lblFooter);
layout->addWidget(m_buttonBox);
setLayout(layout);
if (mode == Local) {
setWindowTitle(tr("Local Fingerprints"));
m_lblHeader->setText(tr("Local computer's fingerprints"));
m_lblFooter->setVisible(false);
m_buttonBox->setStandardButtons(QDialogButtonBox::Ok);
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!");
if (mode == FingerprintDialogMode::Server) {
m_lblHeader->setText(tr("A new client is connecting.\n%1").arg(body.arg(tr("client"))));
m_lblFooter->setText(tr("\nDo you want connect to and trust the client?\n"));
} else {
m_lblHeader->setText(tr("You are connecting to a new server.\n%1").arg(body.arg(tr("server"))));
m_lblFooter->setText(tr("\nDo you want connect to the server?\n"));
}
m_buttonBox->setStandardButtons(QDialogButtonBox::Help | QDialogButtonBox::Yes | QDialogButtonBox::No);
// Use help to request a dialog with the host prints
// Help is used because its always to the furthest from the other buttons.
m_buttonBox->button(QDialogButtonBox::Help)->setText(tr("View local fingerprints"));
m_buttonBox->button(QDialogButtonBox::Help)->setIcon(QIcon::fromTheme("fingerprint"));
m_buttonBox->button(QDialogButtonBox::Help)->setToolTip(tr("Show the local machines fingerprints"));
connect(
m_buttonBox->button(QDialogButtonBox::Help), &QPushButton::clicked, this,
&FingerprintDialog::requestLocalPrintsDialog
);
m_buttonBox->button(QDialogButtonBox::No)->setFocus();
connect(m_buttonBox->button(QDialogButtonBox::No), &QPushButton::clicked, this, &QDialog::reject);
connect(m_buttonBox->button(QDialogButtonBox::Yes), &QPushButton::clicked, this, &QDialog::accept);
}
adjustSize();
setFixedSize(size());
}

View File

@ -0,0 +1,43 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2025 Deskflow Developers
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#pragma once
#include "net/FingerprintData.h"
#include <QDialog>
#include <QDialogButtonBox>
enum FingerprintDialogMode
{
Local,
Client,
Server
};
class QLabel;
class FingerprintPreview;
class FingerprintDialog : public QDialog
{
Q_OBJECT
public:
explicit FingerprintDialog(
QWidget *parent = nullptr, const QList<deskflow::FingerprintData> &fingerprints = {},
FingerprintDialogMode mode = FingerprintDialogMode::Local
);
~FingerprintDialog() = default;
signals:
void requestLocalPrintsDialog();
private:
QLabel *m_lblHeader = nullptr;
QLabel *m_lblFooter = nullptr;
FingerprintPreview *m_fingerprintPreview = nullptr;
QDialogButtonBox *m_buttonBox = nullptr;
};

View File

@ -1,5 +1,6 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello <sithlord48@gmail.com>
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
* SPDX-FileCopyrightText: (C) 2008 Volker Lanz <vl@fidra.de>
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
@ -34,47 +35,115 @@ ServerConfigDialog::ServerConfigDialog(QWidget *parent, ServerConfig &config, Ap
{
ui->setupUi(this);
ui->m_pButtonBrowseConfigFile->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::DocumentOpen));
ui->m_pTrashScreenWidget->setPixmap(QIcon::fromTheme("user-trash").pixmap(QSize(64, 64)));
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &ServerConfigDialog::accept);
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &ServerConfigDialog::reject);
ui->lblRemoveScreen->setPixmap(QIcon::fromTheme("user-trash").pixmap(QSize(64, 64)));
connect(ui->lblRemoveScreen, &TrashScreenWidget::screenRemoved, this, &ServerConfigDialog::onScreenRemoved);
ui->lblNewScreen->setEnabled(!model().isFull());
ui->lblNewScreen->setPixmap(QIcon::fromTheme("video-display").pixmap(QSize(64, 64)));
ui->lblNewScreen->setToolTip(tr("Drag to the grid to add a new computer."));
connect(ui->btnNewHotkey, &QPushButton::clicked, this, &ServerConfigDialog::addHotkey);
connect(ui->btnEditHotkey, &QPushButton::clicked, this, &ServerConfigDialog::editHotkey);
connect(ui->btnRemoveHotkey, &QPushButton::clicked, this, &ServerConfigDialog::removeHotkey);
connect(ui->listHotkeys, &QListView::doubleClicked, this, &ServerConfigDialog::editHotkey);
connect(
ui->listHotkeys->selectionModel(), &QItemSelectionModel::selectionChanged, this,
&ServerConfigDialog::listHotkeysSelectionChanged
);
connect(ui->btnNewAction, &QPushButton::clicked, this, &ServerConfigDialog::addAction);
connect(ui->btnEditAction, &QPushButton::clicked, this, &ServerConfigDialog::editAction);
connect(ui->btnRemoveAction, &QPushButton::clicked, this, &ServerConfigDialog::removeAction);
connect(ui->listActions, &QListView::doubleClicked, this, &ServerConfigDialog::editAction);
connect(
ui->listActions->selectionModel(), &QItemSelectionModel::selectionChanged, this,
&ServerConfigDialog::listActionsSelectionChanged
);
// force the first tab, since qt creator sets the active tab as the last one
// the developer was looking at, and it's easy to accidentally save that.
ui->m_pTabWidget->setCurrentIndex(0);
ui->tabWidget->setCurrentIndex(0);
ui->m_pEditConfigFile->setText(serverConfig().configFile());
ui->m_pCheckBoxUseExternalConfig->setChecked(serverConfig().useExternalConfig());
ui->m_pCheckBoxHeartbeat->setChecked(serverConfig().hasHeartbeat());
ui->m_pRadioProtocolSynergy->setChecked(serverConfig().protocol() == ServerProtocol::kSynergy);
ui->m_pRadioProtocolBarrier->setChecked(serverConfig().protocol() == ServerProtocol::kBarrier);
ui->m_pSpinBoxHeartbeat->setValue(serverConfig().heartbeat());
ui->btnBrowseConfigFile->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::DocumentOpen));
ui->lineConfigFile->setText(serverConfig().configFile());
ui->m_pCheckBoxRelativeMouseMoves->setChecked(serverConfig().relativeMouseMoves());
ui->m_pCheckBoxWin32KeepForeground->setChecked(serverConfig().win32KeepForeground());
ui->groupExternalConfig->setChecked(serverConfig().useExternalConfig());
ui->m_pCheckBoxSwitchDelay->setChecked(serverConfig().hasSwitchDelay());
ui->m_pSpinBoxSwitchDelay->setValue(serverConfig().switchDelay());
ui->rbProtocolSynergy->setChecked(serverConfig().protocol() == ServerProtocol::kSynergy);
ui->rbProtocolBarrier->setChecked(serverConfig().protocol() == ServerProtocol::kBarrier);
connect(ui->rbProtocolBarrier, &QRadioButton::toggled, this, &ServerConfigDialog::toggleProtocol);
ui->m_pCheckBoxSwitchDoubleTap->setChecked(serverConfig().hasSwitchDoubleTap());
ui->m_pSpinBoxSwitchDoubleTap->setValue(serverConfig().switchDoubleTap());
ui->cbHeartbeat->setChecked(serverConfig().hasHeartbeat());
connect(ui->cbHeartbeat, &QCheckBox::toggled, this, &ServerConfigDialog::toggleHeartbeat);
ui->m_pCheckBoxCornerTopLeft->setChecked(serverConfig().switchCorner(static_cast<int>(TopLeft)));
ui->m_pCheckBoxCornerTopRight->setChecked(serverConfig().switchCorner(static_cast<int>(TopRight)));
ui->m_pCheckBoxCornerBottomLeft->setChecked(serverConfig().switchCorner(static_cast<int>(BottomLeft)));
ui->m_pCheckBoxCornerBottomRight->setChecked(serverConfig().switchCorner(static_cast<int>(BottomRight)));
ui->m_pSpinBoxSwitchCornerSize->setValue(serverConfig().switchCornerSize());
ui->m_pCheckBoxDisableLockToScreen->setChecked(serverConfig().disableLockToScreen());
ui->sbHeartbeat->setValue(serverConfig().heartbeat());
connect(ui->sbHeartbeat, QOverload<int>::of(&QSpinBox::valueChanged), this, &ServerConfigDialog::setHeartbeat);
ui->m_pCheckBoxEnableClipboard->setChecked(serverConfig().clipboardSharing());
ui->cbRelativeMouseMoves->setChecked(serverConfig().relativeMouseMoves());
#ifndef Q_OS_WIN
ui->cbWin32KeepForeground->setVisible(false);
#endif
ui->cbWin32KeepForeground->setChecked(serverConfig().win32KeepForeground());
connect(ui->cbWin32KeepForeground, &QCheckBox::toggled, this, &ServerConfigDialog::toggleWin32Foreground);
ui->cbSwitchDelay->setChecked(serverConfig().hasSwitchDelay());
connect(ui->cbSwitchDelay, &QCheckBox::toggled, this, &ServerConfigDialog::toggleSwitchDelay);
ui->sbSwitchDelay->setValue(serverConfig().switchDelay());
connect(ui->sbSwitchDelay, QOverload<int>::of(&QSpinBox::valueChanged), this, &ServerConfigDialog::setSwitchDelay);
ui->cbSwitchDoubleTap->setChecked(serverConfig().hasSwitchDoubleTap());
connect(ui->cbSwitchDoubleTap, &QCheckBox::toggled, this, &ServerConfigDialog::toggleSwitchDoubleTap);
ui->sbSwitchDoubleTap->setValue(serverConfig().switchDoubleTap());
connect(
ui->sbSwitchDoubleTap, QOverload<int>::of(&QSpinBox::valueChanged), this, &ServerConfigDialog::setSwitchDoubleTap
);
connect(ui->cbRelativeMouseMoves, &QCheckBox::toggled, this, &ServerConfigDialog::toggleRelativeMouseMoves);
connect(ui->cbEnableClipboard, &QCheckBox::toggled, this, &ServerConfigDialog::toggleClipboard);
connect(ui->groupExternalConfig, &QGroupBox::toggled, this, &ServerConfigDialog::toggleExternalConfig);
connect(ui->btnBrowseConfigFile, &QPushButton::clicked, this, &ServerConfigDialog::browseConfigFile);
connect(
ui->sbSwitchCornerSize, QOverload<int>::of(&QSpinBox::valueChanged), this,
&ServerConfigDialog::setSwitchCornerSize
);
connect(
ui->sbClipboardSizeLimit, QOverload<int>::of(&QSpinBox::valueChanged), this,
&ServerConfigDialog::setClipboardLimit
);
ui->cbCornerTopLeft->setChecked(serverConfig().switchCorner(static_cast<int>(TopLeft)));
connect(ui->cbCornerTopLeft, &QCheckBox::toggled, this, &ServerConfigDialog::toggleCornerTopLeft);
ui->cbCornerTopRight->setChecked(serverConfig().switchCorner(static_cast<int>(TopRight)));
connect(ui->cbCornerTopRight, &QCheckBox::toggled, this, &ServerConfigDialog::toggleCornerTopRight);
ui->cbCornerBottomLeft->setChecked(serverConfig().switchCorner(static_cast<int>(BottomLeft)));
connect(ui->cbCornerBottomLeft, &QCheckBox::toggled, this, &ServerConfigDialog::toggleCornerBottomLeft);
ui->cbCornerBottomRight->setChecked(serverConfig().switchCorner(static_cast<int>(BottomRight)));
connect(ui->cbCornerBottomRight, &QCheckBox::toggled, this, &ServerConfigDialog::toggleCornerBottomRight);
ui->sbSwitchCornerSize->setValue(serverConfig().switchCornerSize());
ui->cbDisableLockToScreen->setChecked(serverConfig().disableLockToScreen());
connect(ui->cbDisableLockToScreen, &QCheckBox::toggled, this, &ServerConfigDialog::toggleLockToScreen);
ui->cbEnableClipboard->setChecked(serverConfig().clipboardSharing());
int clipboardSharingSizeM = static_cast<int>(serverConfig().clipboardSharingSize() / 1024);
ui->m_pSpinBoxClipboardSizeLimit->setValue(clipboardSharingSizeM);
ui->m_pSpinBoxClipboardSizeLimit->setEnabled(serverConfig().clipboardSharing());
ui->sbClipboardSizeLimit->setValue(clipboardSharingSizeM);
ui->sbClipboardSizeLimit->setEnabled(serverConfig().clipboardSharing());
for (const Hotkey &hotkey : std::as_const(serverConfig().hotkeys()))
ui->m_pListHotkeys->addItem(hotkey.text());
ui->listHotkeys->addItem(hotkey.text());
ui->m_pScreenSetupView->setModel(&m_ScreenSetupModel);
ui->screenSetupView->setModel(&m_ScreenSetupModel);
auto &screens = serverConfig().screens();
auto server = std::find_if(screens.begin(), screens.end(), [this](const Screen &screen) {
@ -89,170 +158,10 @@ ServerConfigDialog::ServerConfigDialog(QWidget *parent, ServerConfig &config, Ap
server->markAsServer();
}
ui->lblNewScreen->setEnabled(!model().isFull());
connect(ui->m_pTrashScreenWidget, &TrashScreenWidget::screenRemoved, this, &ServerConfigDialog::onScreenRemoved);
onChange();
// computers
connect(&m_ScreenSetupModel, &ScreenSetupModel::screensChanged, this, &ServerConfigDialog::onChange);
// Above Qt 6.7 the checkbox signal signature has changed from int to Qt::CheckState
#if QT_VERSION <= QT_VERSION_CHECK(6, 7, 0)
// advanced
connect(ui->m_pCheckBoxSwitchDelay, &QCheckBox::stateChanged, this, [this](const int &v) {
serverConfig().haveSwitchDelay(v);
onChange();
});
connect(ui->m_pCheckBoxSwitchDoubleTap, &QCheckBox::stateChanged, this, [this](const int &v) {
serverConfig().haveSwitchDoubleTap(v);
onChange();
});
connect(ui->m_pCheckBoxEnableClipboard, &QCheckBox::stateChanged, this, [this](const int &v) {
serverConfig().setClipboardSharing(v);
onChange();
});
connect(ui->m_pCheckBoxHeartbeat, &QCheckBox::stateChanged, this, [this](const int &v) {
serverConfig().haveHeartbeat(v);
onChange();
});
connect(ui->m_pCheckBoxRelativeMouseMoves, &QCheckBox::stateChanged, this, [this](const int &v) {
serverConfig().setRelativeMouseMoves(v);
onChange();
});
connect(ui->m_pCheckBoxWin32KeepForeground, &QCheckBox::stateChanged, this, [this](const int &v) {
serverConfig().setWin32KeepForeground(v);
onChange();
});
connect(ui->m_pCheckBoxDisableLockToScreen, &QCheckBox::stateChanged, this, [this](const int &v) {
serverConfig().setDisableLockToScreen(v);
onChange();
});
connect(ui->m_pCheckBoxCornerTopLeft, &QCheckBox::stateChanged, this, [this](const int &v) {
serverConfig().setSwitchCorner(static_cast<int>(TopLeft), v);
onChange();
});
connect(ui->m_pCheckBoxCornerTopRight, &QCheckBox::stateChanged, this, [this](const int &v) {
serverConfig().setSwitchCorner(static_cast<int>(TopRight), v);
onChange();
});
connect(ui->m_pCheckBoxCornerBottomLeft, &QCheckBox::stateChanged, this, [this](const int &v) {
serverConfig().setSwitchCorner(static_cast<int>(BottomLeft), v);
onChange();
});
connect(ui->m_pCheckBoxCornerBottomRight, &QCheckBox::stateChanged, this, [this](const int &v) {
serverConfig().setSwitchCorner(static_cast<int>(BottomRight), v);
onChange();
});
// config
connect(ui->m_pCheckBoxUseExternalConfig, &QCheckBox::stateChanged, this, [this](const int &v) {
serverConfig().setUseExternalConfig(v);
onChange();
});
#else
connect(ui->m_pCheckBoxSwitchDelay, &QCheckBox::checkStateChanged, this, [this](const Qt::CheckState &v) {
serverConfig().haveSwitchDelay(v == Qt::Checked);
onChange();
});
connect(ui->m_pCheckBoxSwitchDoubleTap, &QCheckBox::checkStateChanged, this, [this](const Qt::CheckState &v) {
serverConfig().haveSwitchDoubleTap(v == Qt::Checked);
onChange();
});
connect(ui->m_pCheckBoxEnableClipboard, &QCheckBox::checkStateChanged, this, [this](const Qt::CheckState &v) {
serverConfig().setClipboardSharing(v == Qt::Checked);
onChange();
});
connect(ui->m_pCheckBoxHeartbeat, &QCheckBox::checkStateChanged, this, [this](const Qt::CheckState &v) {
serverConfig().haveHeartbeat(v == Qt::Checked);
onChange();
});
connect(ui->m_pCheckBoxRelativeMouseMoves, &QCheckBox::checkStateChanged, this, [this](const Qt::CheckState &v) {
serverConfig().setRelativeMouseMoves(v == Qt::Checked);
onChange();
});
connect(ui->m_pCheckBoxWin32KeepForeground, &QCheckBox::checkStateChanged, this, [this](const Qt::CheckState &v) {
serverConfig().setWin32KeepForeground(v == Qt::Checked);
onChange();
});
connect(ui->m_pCheckBoxDisableLockToScreen, &QCheckBox::checkStateChanged, this, [this](const Qt::CheckState &v) {
serverConfig().setDisableLockToScreen(v == Qt::Checked);
onChange();
});
connect(ui->m_pCheckBoxCornerTopLeft, &QCheckBox::checkStateChanged, this, [this](const Qt::CheckState &v) {
serverConfig().setSwitchCorner(static_cast<int>(TopLeft), v == Qt::Checked);
onChange();
});
connect(ui->m_pCheckBoxCornerTopRight, &QCheckBox::checkStateChanged, this, [this](const Qt::CheckState &v) {
serverConfig().setSwitchCorner(static_cast<int>(TopRight), v == Qt::Checked);
onChange();
});
connect(ui->m_pCheckBoxCornerBottomLeft, &QCheckBox::checkStateChanged, this, [this](const Qt::CheckState &v) {
serverConfig().setSwitchCorner(static_cast<int>(BottomLeft), v == Qt::Checked);
onChange();
});
connect(ui->m_pCheckBoxCornerBottomRight, &QCheckBox::checkStateChanged, this, [this](const Qt::CheckState &v) {
serverConfig().setSwitchCorner(static_cast<int>(BottomRight), v == Qt::Checked);
onChange();
});
// config
connect(ui->m_pCheckBoxUseExternalConfig, &QCheckBox::checkStateChanged, this, [this](const Qt::CheckState &v) {
serverConfig().setUseExternalConfig(v == Qt::Checked);
onChange();
});
#endif
connect(
ui->m_pSpinBoxSwitchDelay, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this,
[this](const int &v) {
serverConfig().setSwitchDelay(v);
onChange();
}
);
connect(
ui->m_pSpinBoxSwitchDoubleTap, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this,
[this](const int &v) {
serverConfig().setSwitchDoubleTap(v);
onChange();
}
);
connect(
ui->m_pSpinBoxClipboardSizeLimit, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this,
[this](const int &v) {
serverConfig().setClipboardSharingSize(v * 1024);
onChange();
}
);
connect(
ui->m_pSpinBoxHeartbeat, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this,
[this](const int &v) {
serverConfig().setHeartbeat(v);
onChange();
}
);
connect(
ui->m_pSpinBoxSwitchCornerSize, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this,
[this](const int &v) {
serverConfig().setSwitchCornerSize(v);
onChange();
}
);
connect(ui->m_pRadioProtocolSynergy, &QRadioButton::toggled, this, [this](const bool &v) {
if (v) {
serverConfig().setProtocol(ServerProtocol::kSynergy);
onChange();
}
});
connect(ui->m_pRadioProtocolBarrier, &QRadioButton::toggled, this, [this](const bool &v) {
if (v) {
serverConfig().setProtocol(ServerProtocol::kBarrier);
onChange();
}
});
connect(ui->m_pEditConfigFile, &QLineEdit::textChanged, this, [this]() {
serverConfig().setConfigFile(ui->m_pEditConfigFile->text());
onChange();
});
}
ServerConfigDialog::~ServerConfigDialog() = default;
@ -264,13 +173,13 @@ bool ServerConfigDialog::addClient(const QString &clientName)
void ServerConfigDialog::accept()
{
if (ui->m_pCheckBoxUseExternalConfig->isChecked() && !QFile::exists(ui->m_pEditConfigFile->text())) {
if (ui->groupExternalConfig->isChecked() && !QFile::exists(ui->lineConfigFile->text())) {
auto selectedButton = QMessageBox::warning(
this, "Filename invalid", "Please select a valid configuration file.", QMessageBox::Ok | QMessageBox::Ignore
);
if (selectedButton != QMessageBox::Ok || !on_m_pButtonBrowseConfigFile_clicked()) {
if (selectedButton != QMessageBox::Ok || !browseConfigFile()) {
return;
}
}
@ -290,130 +199,242 @@ void ServerConfigDialog::reject()
QDialog::reject();
}
void ServerConfigDialog::on_m_pButtonNewHotkey_clicked()
void ServerConfigDialog::addHotkey()
{
Hotkey hotkey;
HotkeyDialog dlg(this, hotkey);
if (dlg.exec() == QDialog::Accepted) {
serverConfig().hotkeys().append(hotkey);
ui->m_pListHotkeys->addItem(hotkey.text());
ui->listHotkeys->addItem(hotkey.text());
onChange();
}
}
void ServerConfigDialog::on_m_pButtonEditHotkey_clicked()
void ServerConfigDialog::editHotkey()
{
int idx = ui->m_pListHotkeys->currentRow();
Q_ASSERT(idx >= 0 && idx < serverConfig().hotkeys().size());
Hotkey &hotkey = serverConfig().hotkeys()[idx];
int row = ui->listHotkeys->currentRow();
if (row < 0 || row >= serverConfig().hotkeys().size()) {
qDebug() << "Attempt to editing out of bounds hotkey row: " << row;
return;
}
Hotkey &hotkey = serverConfig().hotkeys()[row];
HotkeyDialog dlg(this, hotkey);
if (dlg.exec() == QDialog::Accepted) {
ui->m_pListHotkeys->currentItem()->setText(hotkey.text());
ui->listHotkeys->currentItem()->setText(hotkey.text());
onChange();
}
}
void ServerConfigDialog::on_m_pButtonRemoveHotkey_clicked()
void ServerConfigDialog::removeHotkey()
{
int idx = ui->m_pListHotkeys->currentRow();
Q_ASSERT(idx >= 0 && idx < serverConfig().hotkeys().size());
serverConfig().hotkeys().removeAt(idx);
ui->m_pListActions->clear();
delete ui->m_pListHotkeys->item(idx);
int row = ui->listHotkeys->currentRow();
if (row < 0 || row >= serverConfig().hotkeys().size()) {
qDebug() << "Attempt to remove out of bounds hotkey row: " << row;
return;
}
serverConfig().hotkeys().removeAt(row);
ui->listActions->clear();
delete ui->listHotkeys->item(row);
onChange();
}
void ServerConfigDialog::on_m_pListHotkeys_itemSelectionChanged()
void ServerConfigDialog::listHotkeysSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
bool itemsSelected = !ui->m_pListHotkeys->selectedItems().isEmpty();
ui->m_pButtonEditHotkey->setEnabled(itemsSelected);
ui->m_pButtonRemoveHotkey->setEnabled(itemsSelected);
ui->m_pButtonNewAction->setEnabled(itemsSelected);
bool itemsSelected = !selected.isEmpty();
ui->btnEditHotkey->setEnabled(itemsSelected);
ui->btnRemoveHotkey->setEnabled(itemsSelected);
ui->btnNewAction->setEnabled(itemsSelected);
if (itemsSelected && serverConfig().hotkeys().size() > 0) {
ui->m_pListActions->clear();
int idx = ui->m_pListHotkeys->row(ui->m_pListHotkeys->selectedItems()[0]);
// There's a bug somewhere around here: We get idx == 1 right after we
// deleted the next to last item, so idx can only possibly be 0. GDB shows
// we got called indirectly from the delete line in
// on_m_pButtonRemoveHotkey_clicked() above, but the delete is of course
// necessary and seems correct. The while() is a generalized workaround for
// all that and shouldn't be required.
while (idx >= 0 && idx >= serverConfig().hotkeys().size())
idx--;
Q_ASSERT(idx >= 0 && idx < serverConfig().hotkeys().size());
const Hotkey &hotkey = serverConfig().hotkeys()[idx];
if (itemsSelected && !serverConfig().hotkeys().isEmpty()) {
ui->listActions->clear();
const Hotkey &hotkey = serverConfig().hotkeys().at(selected.indexes().first().row());
for (const Action &action : hotkey.actions())
ui->m_pListActions->addItem(action.text());
ui->listActions->addItem(action.text());
}
}
void ServerConfigDialog::on_m_pButtonNewAction_clicked()
void ServerConfigDialog::addAction()
{
int idx = ui->m_pListHotkeys->currentRow();
Q_ASSERT(idx >= 0 && idx < serverConfig().hotkeys().size());
Hotkey &hotkey = serverConfig().hotkeys()[idx];
int row = ui->listHotkeys->currentRow();
if (row < 0 || row >= serverConfig().hotkeys().size()) {
qDebug() << "Attempt to add action to out of bounds hotkey row: " << row;
return;
}
Hotkey &hotkey = serverConfig().hotkeys()[row];
Action action;
ActionDialog dlg(this, serverConfig(), hotkey, action);
if (dlg.exec() == QDialog::Accepted) {
hotkey.actions().append(action);
ui->m_pListActions->addItem(action.text());
ui->listActions->addItem(action.text());
onChange();
}
}
void ServerConfigDialog::on_m_pButtonEditAction_clicked()
void ServerConfigDialog::editAction()
{
int idxHotkey = ui->m_pListHotkeys->currentRow();
Q_ASSERT(idxHotkey >= 0 && idxHotkey < serverConfig().hotkeys().size());
Hotkey &hotkey = serverConfig().hotkeys()[idxHotkey];
int hotkeyRow = ui->listHotkeys->currentRow();
if (hotkeyRow < 0 || hotkeyRow >= serverConfig().hotkeys().size()) {
qDebug() << "Attempt to edit action from out of bounds hotkey row: " << hotkeyRow;
return;
}
Hotkey &hotkey = serverConfig().hotkeys()[hotkeyRow];
int idxAction = ui->m_pListActions->currentRow();
Q_ASSERT(idxAction >= 0 && idxAction < hotkey.actions().size());
Action &action = hotkey.actions()[idxAction];
int actionRow = ui->listActions->currentRow();
if (actionRow < 0 || actionRow >= hotkey.actions().size()) {
qDebug() << "Attempt to remove out of bounds action row: " << actionRow;
return;
}
Action &action = hotkey.actions()[actionRow];
ActionDialog dlg(this, serverConfig(), hotkey, action);
if (dlg.exec() == QDialog::Accepted) {
ui->m_pListActions->currentItem()->setText(action.text());
ui->listActions->currentItem()->setText(action.text());
onChange();
}
}
void ServerConfigDialog::on_m_pButtonRemoveAction_clicked()
void ServerConfigDialog::removeAction()
{
int idxHotkey = ui->m_pListHotkeys->currentRow();
Q_ASSERT(idxHotkey >= 0 && idxHotkey < serverConfig().hotkeys().size());
Hotkey &hotkey = serverConfig().hotkeys()[idxHotkey];
int hotkeyRow = ui->listHotkeys->currentRow();
if (hotkeyRow < 0 || hotkeyRow >= serverConfig().hotkeys().size()) {
qDebug() << "Attempt to remove action from out of bounds hotkey row: " << hotkeyRow;
return;
}
Hotkey &hotkey = serverConfig().hotkeys()[hotkeyRow];
int idxAction = ui->m_pListActions->currentRow();
Q_ASSERT(idxAction >= 0 && idxAction < hotkey.actions().size());
int actionRow = ui->listActions->currentRow();
if (actionRow < 0 || actionRow >= hotkey.actions().size()) {
qDebug() << "Attempt to remove out of bounds action row: " << actionRow;
return;
}
hotkey.actions().removeAt(idxAction);
delete ui->m_pListActions->currentItem();
hotkey.actions().removeAt(actionRow);
delete ui->listActions->currentItem();
onChange();
}
void ServerConfigDialog::on_m_pCheckBoxEnableClipboard_stateChanged(int const state)
void ServerConfigDialog::toggleClipboard(bool enabled)
{
ui->m_pSpinBoxClipboardSizeLimit->setEnabled(state == Qt::Checked);
if ((state == Qt::Checked) && (!ui->m_pSpinBoxClipboardSizeLimit->value())) {
ui->sbClipboardSizeLimit->setEnabled(enabled);
if (enabled && !ui->sbClipboardSizeLimit->value()) {
int size = static_cast<int>((serverConfig().defaultClipboardSharingSize() + 512) / 1024);
ui->m_pSpinBoxClipboardSizeLimit->setValue(size ? size : 1);
ui->sbClipboardSizeLimit->setValue(size ? size : 1);
}
serverConfig().setClipboardSharing(enabled);
onChange();
}
void ServerConfigDialog::on_m_pListActions_itemSelectionChanged()
void ServerConfigDialog::setClipboardLimit(int limit)
{
ui->m_pButtonEditAction->setEnabled(!ui->m_pListActions->selectedItems().isEmpty());
ui->m_pButtonRemoveAction->setEnabled(!ui->m_pListActions->selectedItems().isEmpty());
serverConfig().setClipboardSharingSize(limit * 1024);
onChange();
}
void ServerConfigDialog::on_m_pButtonAddComputer_clicked()
void ServerConfigDialog::toggleHeartbeat(bool enabled)
{
ui->sbHeartbeat->setEnabled(enabled);
serverConfig().haveHeartbeat(enabled);
onChange();
}
void ServerConfigDialog::setHeartbeat(int rate)
{
serverConfig().setHeartbeat(rate);
onChange();
}
void ServerConfigDialog::toggleRelativeMouseMoves(bool enabled)
{
serverConfig().setRelativeMouseMoves(enabled);
onChange();
}
void ServerConfigDialog::toggleProtocol()
{
ServerProtocol proto = ui->rbProtocolBarrier->isChecked() ? ServerProtocol::kBarrier : ServerProtocol::kSynergy;
serverConfig().setProtocol(proto);
onChange();
}
void ServerConfigDialog::setSwitchCornerSize(int size)
{
serverConfig().setSwitchCornerSize(size);
onChange();
}
void ServerConfigDialog::toggleCornerBottomLeft(bool enable)
{
serverConfig().setSwitchCorner(static_cast<int>(BottomLeft), enable);
onChange();
}
void ServerConfigDialog::toggleCornerTopLeft(bool enable)
{
serverConfig().setSwitchCorner(static_cast<int>(TopLeft), enable);
onChange();
}
void ServerConfigDialog::toggleCornerBottomRight(bool enable)
{
serverConfig().setSwitchCorner(static_cast<int>(BottomRight), enable);
onChange();
}
void ServerConfigDialog::toggleCornerTopRight(bool enable)
{
serverConfig().setSwitchCorner(static_cast<int>(TopRight), enable);
onChange();
}
void ServerConfigDialog::listActionsSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
bool enabled = !selected.isEmpty();
ui->btnEditAction->setEnabled(enabled);
ui->btnRemoveAction->setEnabled(enabled);
}
void ServerConfigDialog::toggleSwitchDoubleTap(bool enable)
{
ui->sbSwitchDoubleTap->setEnabled(enable);
serverConfig().haveSwitchDoubleTap(enable);
onChange();
}
void ServerConfigDialog::setSwitchDoubleTap(int within)
{
serverConfig().setSwitchDoubleTap(within);
onChange();
}
void ServerConfigDialog::toggleSwitchDelay(bool enable)
{
ui->sbSwitchDelay->setEnabled(enable);
serverConfig().haveSwitchDelay(enable);
onChange();
}
void ServerConfigDialog::setSwitchDelay(int delay)
{
serverConfig().setSwitchDelay(delay);
onChange();
}
void ServerConfigDialog::toggleLockToScreen(bool disabled)
{
serverConfig().setDisableLockToScreen(disabled);
onChange();
}
void ServerConfigDialog::toggleWin32Foreground(bool enabled)
{
serverConfig().setWin32KeepForeground(enabled);
onChange();
}
void ServerConfigDialog::addClient()
{
addComputer("", false);
}
@ -424,18 +445,21 @@ void ServerConfigDialog::onScreenRemoved()
onChange();
}
void ServerConfigDialog::on_m_pCheckBoxUseExternalConfig_toggled(bool checked)
void ServerConfigDialog::toggleExternalConfig(bool checked)
{
ui->m_pLabelConfigFile->setEnabled(checked);
ui->m_pEditConfigFile->setEnabled(checked);
ui->m_pButtonBrowseConfigFile->setEnabled(checked);
ui->labelConfigFile->setEnabled(checked);
ui->lineConfigFile->setEnabled(checked);
ui->btnBrowseConfigFile->setEnabled(checked);
ui->m_pTabWidget->setTabEnabled(0, !checked);
ui->m_pTabWidget->setTabEnabled(1, !checked);
ui->m_pTabWidget->setTabEnabled(2, !checked);
ui->tabWidget->setTabEnabled(0, !checked);
ui->tabWidget->setTabEnabled(1, !checked);
ui->tabWidget->setTabEnabled(2, !checked);
serverConfig().setUseExternalConfig(checked);
onChange();
}
bool ServerConfigDialog::on_m_pButtonBrowseConfigFile_clicked()
bool ServerConfigDialog::browseConfigFile()
{
#if defined(Q_OS_WIN)
static const auto configExt = QStringLiteral("sgc");
@ -448,7 +472,9 @@ bool ServerConfigDialog::on_m_pButtonBrowseConfigFile_clicked()
QFileDialog::getOpenFileName(this, "Browse for a config file", "", deskflowConfigFilter.arg(kAppName, configExt));
if (!fileName.isEmpty()) {
ui->m_pEditConfigFile->setText(fileName);
ui->lineConfigFile->setText(fileName);
serverConfig().setConfigFile(ui->lineConfigFile->text());
onChange();
return true;
}
@ -474,6 +500,6 @@ void ServerConfigDialog::onChange()
{
bool isAppConfigDataEqual = m_OriginalServerConfigIsExternal == serverConfig().useExternalConfig() &&
m_OriginalServerConfigUsesExternalFile == serverConfig().configFile();
ui->m_pButtonBox->button(QDialogButtonBox::Ok)
ui->buttonBox->button(QDialogButtonBox::Ok)
->setEnabled(!isAppConfigDataEqual || !(m_OriginalServerConfig == m_ServerConfig));
}

View File

@ -1,5 +1,6 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello <sithlord48@gmail.com>
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
* SPDX-FileCopyrightText: (C) 2008 Volker Lanz <vl@fidra.de>
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
@ -13,6 +14,8 @@
#include <QDialog>
class QItemSelection;
namespace Ui {
class ServerConfigDialog;
}
@ -35,23 +38,49 @@ public slots:
}
protected slots:
void on_m_pButtonNewHotkey_clicked();
void on_m_pListHotkeys_itemSelectionChanged();
void on_m_pButtonEditHotkey_clicked();
void on_m_pButtonRemoveHotkey_clicked();
void on_m_pButtonNewAction_clicked();
void on_m_pListActions_itemSelectionChanged();
void on_m_pButtonEditAction_clicked();
void on_m_pButtonRemoveAction_clicked();
void on_m_pCheckBoxEnableClipboard_stateChanged(int state);
void on_m_pButtonAddComputer_clicked();
void onScreenRemoved();
void on_m_pCheckBoxUseExternalConfig_toggled(bool checked = false);
bool on_m_pButtonBrowseConfigFile_clicked();
protected:
void addClient();
bool addComputer(const QString &clientName, bool doSilent);
void addHotkey();
void editHotkey();
void removeHotkey();
void listHotkeysSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
void addAction();
void editAction();
void removeAction();
void listActionsSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
void toggleSwitchDoubleTap(bool enable);
void setSwitchDoubleTap(int within);
void toggleSwitchDelay(bool enable);
void setSwitchDelay(int delay);
void toggleLockToScreen(bool disabled);
void toggleWin32Foreground(bool enabled);
void toggleClipboard(bool enabled);
void setClipboardLimit(int limit);
void toggleHeartbeat(bool enabled);
void setHeartbeat(int rate);
void toggleRelativeMouseMoves(bool enabled);
void toggleProtocol();
void setSwitchCornerSize(int size);
void toggleCornerBottomLeft(bool enable);
void toggleCornerTopLeft(bool enable);
void toggleCornerBottomRight(bool enable);
void toggleCornerTopRight(bool enable);
void toggleExternalConfig(bool enable = false);
bool browseConfigFile();
ServerConfig &serverConfig()
{
return m_ServerConfig;

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2025 Deskflow Developers
* SPDX-FileCopyrightText: (C) 2012 Symless Ltd.
* SPDX-FileCopyrightText: (C) 2008 Volker Lanz <vl@fidra.de>
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
@ -10,11 +11,8 @@
#include "gui/core/CoreProcess.h"
#include "gui/messages.h"
#include "gui/style_utils.h"
#include "gui/tls/TlsCertificate.h"
#include "gui/tls/TlsUtility.h"
#include "gui/validators/ScreenNameValidator.h"
#include "gui/validators/ValidationError.h"
#include <QDir>
#include <QFileDialog>
@ -35,99 +33,63 @@ SettingsDialog::SettingsDialog(
ui->setupUi(this);
ui->m_pComboBoxTlsKeyLength->setItemIcon(0, QIcon::fromTheme(QIcon::ThemeIcon::SecurityLow));
ui->m_pComboBoxTlsKeyLength->setItemIcon(1, QIcon::fromTheme(QStringLiteral("security-medium")));
ui->m_pComboBoxTlsKeyLength->setItemIcon(2, QIcon::fromTheme(QIcon::ThemeIcon::SecurityHigh));
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->m_pPushButtonTlsRegenCert->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::ViewRefresh));
ui->m_pPushButtonTlsCertPath->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::DocumentOpen));
ui->m_pButtonBrowseLog->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::DocumentOpen));
ui->rb_icon_mono->setIcon(QIcon::fromTheme(QStringLiteral("deskflow-symbolic")));
ui->rb_icon_colorful->setIcon(QIcon::fromTheme(QStringLiteral("deskflow")));
ui->rbIconMono->setIcon(QIcon::fromTheme(QStringLiteral("deskflow-symbolic")));
ui->rbIconColorful->setIcon(QIcon::fromTheme(QStringLiteral("deskflow")));
// force the first tab, since qt creator sets the active tab as the last one
// the developer was looking at, and it's easy to accidentally save that.
ui->m_pTabWidget->setCurrentIndex(0);
ui->tabWidget->setCurrentIndex(0);
loadFromConfig();
m_wasOriginallySystemScope = m_appConfig.isActiveScopeSystem();
updateControls();
m_pScreenNameError = new validators::ValidationError(this);
ui->m_pLineEditScreenName->setValidator(
new validators::ScreenNameValidator(ui->m_pLineEditScreenName, m_pScreenNameError, &serverConfig.screens())
);
connect(ui->m_pCheckBoxEnableTls, &QCheckBox::toggled, this, &SettingsDialog::updateTlsControlsEnabled);
connect(
this, &SettingsDialog::shown, this,
[this] {
if (!m_appConfig.isActiveScopeWritable()) {
showReadOnlyMessage();
}
},
Qt::QueuedConnection
);
adjustSize();
QApplication::processEvents();
setFixedHeight(height());
setWindowFlags((windowFlags() | Qt::CustomizeWindowHint) & ~Qt::WindowMinMaxButtonsHint);
initConnections();
}
//
// Auto-connect slots
//
void SettingsDialog::on_m_pCheckBoxLogToFile_stateChanged(int i)
void SettingsDialog::initConnections()
{
bool checked = i == 2;
connect(this, &SettingsDialog::shown, this, &SettingsDialog::showReadOnlyMessage, Qt::QueuedConnection);
ui->m_pLabelLogPath->setEnabled(checked);
ui->m_pLineEditLogFilename->setEnabled(checked);
ui->m_pButtonBrowseLog->setEnabled(checked);
}
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &SettingsDialog::accept);
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &SettingsDialog::reject);
void SettingsDialog::on_m_pButtonBrowseLog_clicked()
{
QString fileName = QFileDialog::getSaveFileName(
this, tr("Save log file to..."), ui->m_pLineEditLogFilename->text(), "Logs (*.log *.txt)"
);
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->btnTlsCertPath, &QPushButton::clicked, this, &SettingsDialog::browseCertificatePath);
connect(ui->btnBrowseLog, &QPushButton::clicked, this, &SettingsDialog::browseLogPath);
connect(ui->cbLogToFile, &QCheckBox::toggled, this, &SettingsDialog::setLogToFile);
if (!fileName.isEmpty()) {
ui->m_pLineEditLogFilename->setText(fileName);
}
}
void SettingsDialog::on_m_pCheckBoxEnableTls_clicked(bool)
{
updateTlsControlsEnabled();
}
void SettingsDialog::on_m_pRadioSystemScope_toggled(bool checked)
{
// We only need to test the System scoped Radio as they are connected
m_appConfig.setLoadFromSystemScope(checked);
loadFromConfig();
updateControls();
connect(ui->rbScopeSystem, &QRadioButton::toggled, this, &SettingsDialog::setSystemScope);
}
if (isVisible() && !m_appConfig.isActiveScopeWritable()) {
showReadOnlyMessage();
void SettingsDialog::regenCertificates()
{
if (m_tlsUtility.generateCertificate()) {
QMessageBox::information(this, tr("TLS Certificate Regenerated"), tr("TLS certificate regenerated successfully."));
}
}
void SettingsDialog::on_m_pPushButtonTlsCertPath_clicked()
void SettingsDialog::browseCertificatePath()
{
QString fileName = QFileDialog::getSaveFileName(
this, tr("Select a TLS certificate to use..."), ui->m_pLineEditTlsCertPath->text(), "Cert (*.pem)", nullptr,
this, tr("Select a TLS certificate to use..."), ui->lineTlsCertPath->text(), "Cert (*.pem)", nullptr,
QFileDialog::DontConfirmOverwrite
);
if (!fileName.isEmpty()) {
ui->m_pLineEditTlsCertPath->setText(fileName);
ui->lineTlsCertPath->setText(fileName);
if (QFile(fileName).exists()) {
updateKeyLengthOnFile(fileName);
@ -137,21 +99,31 @@ void SettingsDialog::on_m_pPushButtonTlsCertPath_clicked()
}
}
void SettingsDialog::on_m_pPushButtonTlsRegenCert_clicked()
void SettingsDialog::browseLogPath()
{
if (m_tlsUtility.generateCertificate()) {
QMessageBox::information(this, tr("TLS Certificate Regenerated"), tr("TLS certificate regenerated successfully."));
QString fileName =
QFileDialog::getSaveFileName(this, tr("Save log file to..."), ui->lineLogFilename->text(), "Logs (*.log *.txt)");
if (!fileName.isEmpty()) {
ui->lineLogFilename->setText(fileName);
}
}
void SettingsDialog::on_m_pCheckBoxServiceEnabled_toggled(bool)
void SettingsDialog::setLogToFile(bool logToFile)
{
updateControls();
ui->widgetLogFilename->setEnabled(logToFile);
}
//
// End of auto-connect slots
//
void SettingsDialog::setSystemScope(bool systemScope)
{
m_appConfig.setLoadFromSystemScope(systemScope);
loadFromConfig();
updateControls();
if (isVisible() && !m_appConfig.isActiveScopeWritable()) {
showReadOnlyMessage();
}
}
void SettingsDialog::showEvent(QShowEvent *event)
{
@ -161,37 +133,33 @@ void SettingsDialog::showEvent(QShowEvent *event)
void SettingsDialog::showReadOnlyMessage()
{
if (m_appConfig.isActiveScopeWritable())
return;
const auto activeScopeFilename = m_appConfig.scopes().activeFilePath();
messages::showReadOnlySettings(this, activeScopeFilename);
}
void SettingsDialog::accept()
{
if (!ui->m_pLineEditScreenName->hasAcceptableInput()) {
QMessageBox::warning(this, tr("Invalid screen name"), m_pScreenNameError->message());
return;
}
m_appConfig.setLoadFromSystemScope(ui->m_pRadioSystemScope->isChecked());
m_appConfig.setScreenName(ui->m_pLineEditScreenName->text());
m_appConfig.setPort(ui->m_pSpinBoxPort->value());
m_appConfig.setNetworkInterface(ui->m_pLineEditInterface->text());
m_appConfig.setLogLevel(ui->m_pComboLogLevel->currentIndex());
m_appConfig.setLogToFile(ui->m_pCheckBoxLogToFile->isChecked());
m_appConfig.setLogFilename(ui->m_pLineEditLogFilename->text());
m_appConfig.setElevateMode(static_cast<ElevateMode>(ui->m_pComboElevate->currentIndex()));
m_appConfig.setAutoHide(ui->m_pCheckBoxAutoHide->isChecked());
m_appConfig.setEnableUpdateCheck(ui->m_pCheckBoxAutoUpdate->isChecked());
m_appConfig.setPreventSleep(ui->m_pCheckBoxPreventSleep->isChecked());
m_appConfig.setTlsCertPath(ui->m_pLineEditTlsCertPath->text());
m_appConfig.setTlsKeyLength(ui->m_pComboBoxTlsKeyLength->currentText().toInt());
m_appConfig.setTlsEnabled(ui->m_pCheckBoxEnableTls->isChecked());
m_appConfig.setLanguageSync(ui->m_pCheckBoxLanguageSync->isChecked());
m_appConfig.setInvertScrollDirection(ui->m_pCheckBoxScrollDirection->isChecked());
m_appConfig.setEnableService(ui->m_pCheckBoxServiceEnabled->isChecked());
m_appConfig.setCloseToTray(ui->m_pCheckBoxCloseToTray->isChecked());
m_appConfig.setInvertConnection(ui->m_pInvertConnection->isChecked());
m_appConfig.setColorfulTrayIcon(ui->rb_icon_colorful->isChecked());
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());
QDialog::accept();
}
@ -209,39 +177,37 @@ void SettingsDialog::reject()
void SettingsDialog::loadFromConfig()
{
ui->m_pLineEditScreenName->setText(m_appConfig.screenName());
ui->m_pSpinBoxPort->setValue(m_appConfig.port());
ui->m_pLineEditInterface->setText(m_appConfig.networkInterface());
ui->m_pComboLogLevel->setCurrentIndex(m_appConfig.logLevel());
ui->m_pCheckBoxLogToFile->setChecked(m_appConfig.logToFile());
ui->m_pLineEditLogFilename->setText(m_appConfig.logFilename());
ui->m_pCheckBoxAutoHide->setChecked(m_appConfig.autoHide());
ui->m_pCheckBoxPreventSleep->setChecked(m_appConfig.preventSleep());
ui->m_pCheckBoxLanguageSync->setChecked(m_appConfig.languageSync());
ui->m_pCheckBoxScrollDirection->setChecked(m_appConfig.invertScrollDirection());
ui->m_pCheckBoxServiceEnabled->setChecked(m_appConfig.enableService());
ui->m_pCheckBoxCloseToTray->setChecked(m_appConfig.closeToTray());
ui->m_pComboElevate->setCurrentIndex(static_cast<int>(m_appConfig.elevateMode()));
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()));
if (m_appConfig.enableUpdateCheck().has_value()) {
ui->m_pCheckBoxAutoUpdate->setChecked(m_appConfig.enableUpdateCheck().value());
ui->cbAutoUpdate->setChecked(m_appConfig.enableUpdateCheck().value());
} else {
ui->m_pCheckBoxAutoUpdate->setChecked(false);
ui->cbAutoUpdate->setChecked(false);
}
if (m_appConfig.isActiveScopeSystem()) {
ui->m_pRadioSystemScope->setChecked(true);
ui->rbScopeSystem->setChecked(true);
} else {
ui->m_pRadioUserScope->setChecked(true);
ui->rbScopeUser->setChecked(true);
}
ui->m_pInvertConnection->setChecked(m_appConfig.invertConnection());
if (m_appConfig.colorfulTrayIcon())
ui->rb_icon_colorful->setChecked(true);
ui->rbIconColorful->setChecked(true);
else
ui->rb_icon_mono->setChecked(true);
ui->rbIconMono->setChecked(true);
qDebug() << "load from config done";
updateTlsControls();
}
@ -252,30 +218,38 @@ void SettingsDialog::updateTlsControls()
updateKeyLengthOnFile(m_appConfig.tlsCertPath());
} else {
const auto keyLengthText = QString::number(m_appConfig.tlsKeyLength());
ui->m_pComboBoxTlsKeyLength->setCurrentIndex(ui->m_pComboBoxTlsKeyLength->findText(keyLengthText));
ui->comboTlsKeyLength->setCurrentIndex(ui->comboTlsKeyLength->findText(keyLengthText));
}
const auto tlsEnabled = m_tlsUtility.isEnabled();
const auto writable = m_appConfig.isActiveScopeWritable();
const auto enabled = writable && tlsEnabled;
ui->m_pCheckBoxEnableTls->setEnabled(writable);
ui->m_pCheckBoxEnableTls->setChecked(writable && tlsEnabled);
ui->m_pLineEditTlsCertPath->setText(m_appConfig.tlsCertPath());
ui->lineTlsCertPath->setText(m_appConfig.tlsCertPath());
ui->cbRequireClientCert->setChecked(m_appConfig.requireClientCerts());
ui->groupSecurity->setChecked(tlsEnabled);
ui->groupSecurity->setEnabled(writable);
ui->comboTlsKeyLength->setEnabled(enabled);
ui->widgetTlsCert->setEnabled(enabled);
ui->lblTlsKeyLength->setEnabled(enabled);
ui->btnTlsRegenCert->setEnabled(enabled);
ui->cbRequireClientCert->setEnabled(enabled);
}
void SettingsDialog::updateTlsControlsEnabled()
{
const auto writable = m_appConfig.isActiveScopeWritable();
const auto clientMode = m_appConfig.clientGroupChecked();
const auto tlsChecked = ui->m_pCheckBoxEnableTls->isChecked();
const auto tlsChecked = ui->groupSecurity->isChecked();
auto enabled = writable && tlsChecked && !clientMode;
ui->m_pLabelTlsKeyLength->setEnabled(enabled);
ui->m_pComboBoxTlsKeyLength->setEnabled(enabled);
ui->m_pLabelTlsCert->setEnabled(enabled);
ui->m_pLineEditTlsCertPath->setEnabled(enabled);
ui->m_pPushButtonTlsCertPath->setEnabled(enabled);
ui->m_pPushButtonTlsRegenCert->setEnabled(enabled);
ui->lblTlsKeyLength->setEnabled(enabled);
ui->comboTlsKeyLength->setEnabled(enabled);
ui->lblTlsCert->setEnabled(enabled);
ui->widgetTlsCert->setEnabled(enabled);
ui->btnTlsRegenCert->setEnabled(enabled);
ui->cbRequireClientCert->setEnabled(enabled);
}
bool SettingsDialog::isClientMode() const
@ -291,8 +265,8 @@ void SettingsDialog::updateKeyLengthOnFile(const QString &path)
}
auto length = ssl.getCertKeyLength(path);
auto index = ui->m_pComboBoxTlsKeyLength->findText(QString::number(length));
ui->m_pComboBoxTlsKeyLength->setCurrentIndex(index);
auto index = ui->comboTlsKeyLength->findText(QString::number(length));
ui->comboTlsKeyLength->setCurrentIndex(index);
m_appConfig.setTlsKeyLength(length);
}
@ -304,35 +278,31 @@ void SettingsDialog::updateControls()
#else
// service not supported on unix yet, so always disable.
const auto serviceAvailable = false;
ui->m_pGroupService->setTitle("Service (Windows only)");
ui->groupService->setTitle("Service (Windows only)");
#endif
const bool writable = m_appConfig.isActiveScopeWritable();
const bool serviceChecked = ui->m_pCheckBoxServiceEnabled->isChecked();
const bool logToFile = ui->m_pCheckBoxLogToFile->isChecked();
const bool serviceChecked = ui->cbServiceEnabled->isChecked();
const bool logToFile = ui->cbLogToFile->isChecked();
ui->m_pLineEditScreenName->setEnabled(writable);
ui->m_pSpinBoxPort->setEnabled(writable);
ui->m_pLineEditInterface->setEnabled(writable);
ui->m_pComboLogLevel->setEnabled(writable);
ui->m_pCheckBoxLogToFile->setEnabled(writable);
ui->m_pCheckBoxAutoHide->setEnabled(writable);
ui->m_pCheckBoxAutoUpdate->setEnabled(writable);
ui->m_pCheckBoxPreventSleep->setEnabled(writable);
ui->m_pLineEditTlsCertPath->setEnabled(writable);
ui->m_pComboBoxTlsKeyLength->setEnabled(writable);
ui->m_pCheckBoxCloseToTray->setEnabled(writable);
ui->sbPort->setEnabled(writable);
ui->lineInterface->setEnabled(writable);
ui->comboLogLevel->setEnabled(writable);
ui->cbLogToFile->setEnabled(writable);
ui->cbAutoHide->setEnabled(writable);
ui->cbAutoUpdate->setEnabled(writable);
ui->cbPreventSleep->setEnabled(writable);
ui->lineTlsCertPath->setEnabled(writable);
ui->comboTlsKeyLength->setEnabled(writable);
ui->cbCloseToTray->setEnabled(writable);
ui->m_pCheckBoxServiceEnabled->setEnabled(writable && serviceAvailable);
ui->m_pLabelElevate->setEnabled(writable && serviceChecked && serviceAvailable);
ui->m_pComboElevate->setEnabled(writable && serviceChecked && serviceAvailable);
ui->cbServiceEnabled->setEnabled(writable && serviceAvailable);
ui->widgetElevate->setEnabled(writable && serviceChecked && serviceAvailable);
ui->m_pCheckBoxLanguageSync->setEnabled(writable && isClientMode());
ui->m_pCheckBoxScrollDirection->setEnabled(writable && isClientMode());
ui->cbLanguageSync->setEnabled(writable && isClientMode());
ui->cbScrollDirection->setEnabled(writable && isClientMode());
ui->m_pLabelLogPath->setEnabled(writable && logToFile);
ui->m_pLineEditLogFilename->setEnabled(writable && logToFile);
ui->m_pButtonBrowseLog->setEnabled(writable && logToFile);
ui->widgetLogFilename->setEnabled(writable && logToFile);
updateTlsControls();
}

View File

@ -1,5 +1,6 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2025 Deskflow Developers
* SPDX-FileCopyrightText: (C) 2012 Symless Ltd.
* SPDX-FileCopyrightText: (C) 2008 Volker Lanz <vl@fidra.de>
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
@ -35,16 +36,13 @@ public:
signals:
void shown();
private slots:
void on_m_pCheckBoxEnableTls_clicked(bool checked);
void on_m_pCheckBoxLogToFile_stateChanged(int);
void on_m_pButtonBrowseLog_clicked();
void on_m_pRadioSystemScope_toggled(bool checked);
void on_m_pPushButtonTlsCertPath_clicked();
void on_m_pPushButtonTlsRegenCert_clicked();
void on_m_pCheckBoxServiceEnabled_toggled(bool checked);
private:
void initConnections();
void regenCertificates();
void browseCertificatePath();
void browseLogPath();
void setLogToFile(bool logToFile);
void setSystemScope(bool systemScope);
void accept() override;
void reject() override;
void showEvent(QShowEvent *event) override;
@ -65,8 +63,6 @@ private:
/// @brief Enables controls when they should be.
void updateControls();
validators::ValidationError *m_pScreenNameError;
/// @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

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,6 @@
*/
#include "MainWindow.h"
#include "SetupWizard.h"
#include "common/constants.h"
#include "gui/Logger.h"
#include "gui/config/AppConfig.h"
@ -148,17 +147,6 @@ int main(int argc, char *argv[])
&configScopes, &ConfigScopes::saving, &appConfig, [&appConfig]() { appConfig.commit(); }, Qt::DirectConnection
);
if (appConfig.wizardShouldRun()) {
SetupWizard wizard(appConfig);
auto result = wizard.exec();
if (result != QDialog::Accepted) {
qInfo("wizard cancelled, exiting");
return 0;
}
configScopes.save();
}
MainWindow mainWindow(configScopes, appConfig);
mainWindow.open();

View File

@ -1,25 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2021 Symless Ltd.
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#include "ClientStateLabel.h"
namespace deskflow::gui::widgets {
ClientStateLabel::ClientStateLabel(QWidget *parent) : QLabel(parent)
{
hide();
}
void ClientStateLabel::updateClientState(const QString &line)
{
if (line.contains("connected to server")) {
show();
} else if (line.contains("disconnected from server") || line.contains("process exited")) {
hide();
}
}
} // namespace deskflow::gui::widgets

View File

@ -1,20 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2021 Symless Ltd.
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#pragma once
#include <QLabel>
namespace deskflow::gui::widgets {
class ClientStateLabel : public QLabel
{
public:
explicit ClientStateLabel(QWidget *parent = nullptr);
void updateClientState(const QString &line);
};
} // namespace deskflow::gui::widgets

View File

@ -0,0 +1,101 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2025 Deskflow Developers
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#include "FingerprintPreview.h"
#include <QFont>
#include <QHBoxLayout>
#include <QLabel>
#include <net/SecureUtils.h>
FingerprintPreview::FingerprintPreview(QWidget *parent, const QList<deskflow::FingerprintData> &fingerprints)
: QFrame(parent)
{
setFrameShape(QFrame::StyledPanel);
setFrameStyle(QFrame::Sunken);
setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
QString sha1String;
QString sha256String;
QString sha256Art;
for (const auto &fingerprint : fingerprints) {
if (fingerprint.algorithm == "sha1") {
sha1String = QString::fromStdString(deskflow::formatSSLFingerprint(fingerprint.data));
}
if (fingerprint.algorithm == "sha256") {
sha256String = QString::fromStdString(deskflow::formatSSLFingerprintColumns(fingerprint.data));
sha256Art = QString::fromStdString(deskflow::generateFingerprintArt(fingerprint.data));
}
}
auto labelSha1 = new QLabel(QStringLiteral("SHA1:"), this);
labelSha1->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
auto lblSha1 = new QLabel(sha1String, this);
lblSha1->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
lblSha1->setTextInteractionFlags(Qt::TextSelectableByMouse);
auto sha1Layout = new QHBoxLayout();
sha1Layout->addWidget(labelSha1);
sha1Layout->addWidget(lblSha1);
auto frameSha1 = new QFrame(this);
frameSha1->setFrameShape(QFrame::StyledPanel);
frameSha1->setFrameStyle(QFrame::Sunken);
frameSha1->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
frameSha1->setLayout(sha1Layout);
auto labelSha256 = new QLabel(QStringLiteral("SHA256:"), this);
labelSha256->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
auto lblSha256String = new QLabel(sha256String, this);
lblSha256String->setAlignment(Qt::AlignTop | Qt::AlignHCenter);
lblSha256String->setTextInteractionFlags(Qt::TextSelectableByMouse);
auto lblSha256Art = new QLabel(sha256Art, this);
lblSha256Art->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
lblSha256Art->setTextInteractionFlags(Qt::TextSelectableByMouse);
QFont f = font();
f.setFamilies({"Hack", "Liberation Mono", "Monospace", "Andale Mono"});
f.setStyleHint(QFont::Monospace);
lblSha256Art->setFont(f);
auto innersha256Layout = new QHBoxLayout();
innersha256Layout->setContentsMargins(0, 0, 0, 0);
innersha256Layout->addWidget(lblSha256String);
innersha256Layout->addWidget(lblSha256Art);
auto sha256Layout = new QVBoxLayout();
sha256Layout->addWidget(labelSha256);
sha256Layout->addLayout(innersha256Layout);
auto frameSha256 = new QFrame(this);
frameSha256->setFrameShape(QFrame::StyledPanel);
frameSha256->setFrameStyle(QFrame::Sunken);
frameSha256->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
frameSha256->setLayout(sha256Layout);
auto layout = new QVBoxLayout();
layout->addWidget(frameSha1);
layout->addWidget(frameSha256);
setLayout(layout);
if (sha1String.isEmpty()) {
frameSha1->setVisible(false);
}
if (sha256String.isEmpty()) {
frameSha256->setVisible(false);
}
adjustSize();
setFixedSize(size());
}

View File

@ -0,0 +1,18 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2025 Deskflow Developers
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#pragma once
#include <QFrame>
#include <net/FingerprintData.h>
class FingerprintPreview : public QFrame
{
Q_OBJECT
public:
explicit FingerprintPreview(QWidget *parent, const QList<deskflow::FingerprintData> &fingerprints = {});
~FingerprintPreview() = default;
};

View File

@ -1,45 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2021 Symless Ltd.
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#include "ServerStateLabel.h"
#include "gui/core/ServerMessage.h"
using namespace deskflow::gui;
namespace deskflow::gui::widgets {
ServerStateLabel::ServerStateLabel(QWidget *parent) : QLabel(parent)
{
}
void ServerStateLabel::updateServerState(const QString &line)
{
ServerMessage message(line);
if (message.isExitMessage()) {
m_clients.clear();
} else if (message.isConnectedMessage()) {
m_clients.append(message.getClientName());
} else if (message.isDisconnectedMessage()) {
m_clients.removeAll(message.getClientName());
}
if (m_clients.isEmpty()) {
setText(tr("No clients connected"));
} else {
// unfortunately, we can't rely on the clients list because we don't always
// catch the connect/disconnect messages. so clients tend to get stuck in
// the list even though they're offline.
// in order to properly show a list of clients, we would need the core to
// print a list of connected clients on every connect/disconnect event,
// which could be a bit noisy in the logs (perhaps an ipc message would be
// needed).
setText(tr("Client(s) are connected"));
}
}
} // namespace deskflow::gui::widgets

View File

@ -1,26 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2021 Symless Ltd.
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#pragma once
#include <QLabel>
#include <QStringList>
namespace deskflow::gui::widgets {
class ServerStateLabel : public QLabel
{
public:
explicit ServerStateLabel(QWidget *parent = nullptr);
void updateServerState(const QString &line);
private:
QStringList m_clients;
void updateState();
};
} // namespace deskflow::gui::widgets

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2024 Chris Rizzitello <sithlord48@gmail.com>
# SPDX-FileCopyrightText: 2024 - 2025 Chris Rizzitello <sithlord48@gmail.com>
# SPDX-FileCopyrightText: 2012 - 2024 Symless Ltd
# SPDX-FileCopyrightText: 2009 - 2012 Nick Bolton
# SPDX-License-Identifier: MIT
@ -7,7 +7,7 @@ set(target ${CMAKE_PROJECT_NAME}-server)
if(WIN32)
# Generate rc file
set(EXE_DESCRIPTION "${CMAKE_PROJECT_DESCRIPTION}\\n CLI server application")
set(EXE_DESCRIPTION "${CMAKE_PROJECT_PROPER_NAME} server application")
set(EXE_ICON "
IDI_DESKFLOW ICON DISCARDABLE \"${CMAKE_SOURCE_DIR}/src/apps/res/deskflow.ico\"
@ -32,14 +32,17 @@ target_link_libraries(
io
mt
net
ipc
platform
server
app
${libs})
if(APPLE)
set_target_properties(${target} PROPERTIES RUNTIME_OUTPUT_DIRECTORY $<TARGET_BUNDLE_CONTENT_DIR:${CMAKE_PROJECT_PROPER_NAME}>/MacOS)
set_target_properties(${target} PROPERTIES
BUILD_WITH_INSTALL_RPATH TRUE
INSTALL_RPATH "@loader_path/../Libraries;@loader_path/../Frameworks"
RUNTIME_OUTPUT_DIRECTORY $<TARGET_BUNDLE_CONTENT_DIR:${CMAKE_PROJECT_PROPER_NAME}>/MacOS
)
elseif(UNIX)
install(TARGETS ${target} DESTINATION bin)
elseif(WIN32)

View File

@ -28,6 +28,30 @@ int main(int argc, char **argv)
Log log;
EventQueue events;
// HACK: the `--active-desktop` arg actually belongs in the `deskflow-core` binary,
// but we are placing it here in the server binary temporarily until we are ready to
// ship the `deskflow-core` binary. we are deliberately not integrating `--active-desktop`
// into the existing `ServerApp` arg parsing code as that would be a waste of time.
#if SYSAPI_WIN32
for (int i = 1; i < argc; ++i) {
std::string arg(argv[i]);
// This is called by the daemon (running in session 0) when it needs to know the name of the
// interactive desktop.
// It is necessary to run a utility process because the daemon runs in session 0, which does not
// have access to the active desktop, and so cannot query it's name.
if (arg == "--active-desktop") {
const auto name = ArchMiscWindows::getActiveDesktopName();
if (name.empty()) {
LOG((CLOG_CRIT "failed to get active desktop name"));
return kExitFailed;
}
LOG((CLOG_PRINT "%s", name.c_str()));
return kExitSuccess;
}
}
#endif
ServerApp app(&events);
return app.run(argc, argv);
}

View File

@ -2,6 +2,7 @@
<qresource prefix="/">
<file>icons/deskflow-dark/actions/16/configure.svg</file>
<file>icons/deskflow-dark/actions/16/edit-copy.svg</file>
<file>icons/deskflow-dark/actions/16/document-edit.svg</file>
<file>icons/deskflow-dark/actions/16/document-open.svg</file>
<file>icons/deskflow-dark/actions/16/document-save-as.svg</file>
<file>icons/deskflow-dark/actions/16/help-about.svg</file>
@ -11,8 +12,10 @@
<file>icons/deskflow-dark/actions/16/view-refresh.svg</file>
<file>icons/deskflow-dark/actions/22/configure.svg</file>
<file>icons/deskflow-dark/actions/22/edit-copy.svg</file>
<file>icons/deskflow-dark/actions/22/document-edit.svg</file>
<file>icons/deskflow-dark/actions/22/document-open.svg</file>
<file>icons/deskflow-dark/actions/22/document-save-as.svg</file>
<file>icons/deskflow-dark/actions/22/fingerprint.svg</file>
<file>icons/deskflow-dark/actions/22/help-about.svg</file>
<file>icons/deskflow-dark/actions/22/process-stop.svg</file>
<file>icons/deskflow-dark/actions/22/system-run.svg</file>
@ -20,9 +23,11 @@
<file>icons/deskflow-dark/actions/22/view-refresh.svg</file>
<file>icons/deskflow-dark/actions/24/configure.svg</file>
<file>icons/deskflow-dark/actions/24/edit-copy.svg</file>
<file>icons/deskflow-dark/actions/24/document-edit.svg</file>
<file>icons/deskflow-dark/actions/24/document-open.svg</file>
<file>icons/deskflow-dark/actions/24/document-save-as.svg</file>
<file>icons/deskflow-dark/actions/24/edit-clear-all.svg</file>
<file>icons/deskflow-dark/actions/24/fingerprint.svg</file>
<file>icons/deskflow-dark/actions/24/help-about.svg</file>
<file>icons/deskflow-dark/actions/24/process-stop.svg</file>
<file>icons/deskflow-dark/actions/24/system-run.svg</file>
@ -41,6 +46,7 @@
<file>icons/deskflow-dark/apps/64/deskflow-symbolic.svg</file>
<file>icons/deskflow-dark/devices/64/video-display.svg</file>
<file>icons/deskflow-dark/places/64/user-trash.svg</file>
<file>icons/deskflow-dark/status/32/software-updates-release.svg</file>
<file>icons/deskflow-dark/status/64/dialog-error.svg</file>
<file>icons/deskflow-dark/status/64/dialog-information.svg</file>
<file>icons/deskflow-dark/status/64/dialog-positive.svg</file>
@ -53,6 +59,7 @@
<file>icons/deskflow-light/actions/16/configure.svg</file>
<file>icons/deskflow-light/actions/16/edit-clear-all.svg</file>
<file>icons/deskflow-light/actions/16/edit-copy.svg</file>
<file>icons/deskflow-light/actions/16/document-edit.svg</file>
<file>icons/deskflow-light/actions/16/document-open.svg</file>
<file>icons/deskflow-light/actions/16/document-save-as.svg</file>
<file>icons/deskflow-light/actions/16/help-about.svg</file>
@ -63,8 +70,10 @@
<file>icons/deskflow-light/actions/22/configure.svg</file>
<file>icons/deskflow-light/actions/22/edit-clear-all.svg</file>
<file>icons/deskflow-light/actions/22/edit-copy.svg</file>
<file>icons/deskflow-light/actions/22/document-edit.svg</file>
<file>icons/deskflow-light/actions/22/document-open.svg</file>
<file>icons/deskflow-light/actions/22/document-save-as.svg</file>
<file>icons/deskflow-light/actions/22/fingerprint.svg</file>
<file>icons/deskflow-light/actions/22/help-about.svg</file>
<file>icons/deskflow-light/actions/22/process-stop.svg</file>
<file>icons/deskflow-light/actions/22/system-run.svg</file>
@ -73,6 +82,8 @@
<file>icons/deskflow-light/actions/24/configure.svg</file>
<file>icons/deskflow-light/actions/24/edit-clear-all.svg</file>
<file>icons/deskflow-light/actions/24/edit-copy.svg</file>
<file>icons/deskflow-light/actions/24/fingerprint.svg</file>
<file>icons/deskflow-light/actions/24/document-edit.svg</file>
<file>icons/deskflow-light/actions/24/document-open.svg</file>
<file>icons/deskflow-light/actions/24/document-save-as.svg</file>
<file>icons/deskflow-light/actions/24/help-about.svg</file>
@ -92,6 +103,7 @@
<file>icons/deskflow-light/apps/64/deskflow.svg</file>
<file>icons/deskflow-light/apps/64/deskflow-symbolic.svg</file>
<file>icons/deskflow-light/devices/64/video-display.svg</file>
<file>icons/deskflow-light/status/32/software-updates-release.svg</file>
<file>icons/deskflow-light/status/64/dialog-error.svg</file>
<file>icons/deskflow-light/status/64/dialog-information.svg</file>
<file>icons/deskflow-light/status/64/dialog-positive.svg</file>
@ -101,6 +113,5 @@
<file>icons/deskflow-light/status/64/security-low.svg</file>
<file>icons/deskflow-light/status/64/security-medium.svg</file>
<file>icons/deskflow-light/index.theme</file>
<file>image/welcome.png</file>
</qresource>
</RCC>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">.ColorScheme-Text { color: #fcfcfc; } </style>
</defs>
<path style="fill:currentColor;fill-opacity:1;stroke:none" d="M 10.398438 2 L 5.2871094 7.1113281 L 2 10.398438 L 2 14 L 5.6015625 14 L 14 5.6015625 L 10.398438 2 z M 8.3496094 5.4902344 L 10.509766 7.6503906 L 7.3359375 10.826172 L 7.3359375 10.150391 L 6.3222656 10.171875 L 5.2871094 10.171875 L 5.2871094 9.1367188 L 5.2871094 8.5507812 L 6.7285156 7.1113281 L 8.3496094 5.4902344 z M 4.2734375 9.5644531 L 4.2734375 11.185547 L 5.3085938 11.185547 L 6.3007812 11.185547 L 6.3222656 11.837891 L 5.2421875 12.919922 L 3.8007812 12.919922 L 3.0800781 12.199219 L 3.0800781 10.757812 L 4.2734375 9.5644531 z " class="ColorScheme-Text"/>
</svg>

After

Width:  |  Height:  |  Size: 879 B

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">.ColorScheme-Text { color: #fcfcfc; } </style>
</defs>
<path style="fill:currentColor;fill-opacity:1;stroke:none" d="M 7 3.0058594 L 7 8 L 2 8 L 2 8.9980469 L 7 8.9980469 L 7 14.007812 L 8 14.007812 L 8 8.9980469 L 13 8.9980469 L 13 8 L 8 8 L 8 3.0058594 L 7 3.0058594 z " class="ColorScheme-Text"/>
</svg>

After

Width:  |  Height:  |  Size: 486 B

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<style type="text/css" id="current-color-scheme">.ColorScheme-NegativeText { color: #da4453; } </style>
<path class="ColorScheme-NegativeText" d="M 2.6992188,2 2,2.6992188 7.3007812,8 2,13.300781 C 2,13.300781 2.7082187,13.995 2.6992188,14 L 8,8.6992188 13.300781,14 C 13.291781,13.995 14,13.300781 14,13.300781 L 8.6992188,8 14,2.6992188 13.300781,2 8,7.3007812 Z" fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 517 B

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">.ColorScheme-Text { color: #fcfcfc; } </style>
</defs>
<path style="fill:currentColor;fill-opacity:1;stroke:none" d="m14.996094 3l-11.992188 11.992188h-.003906v4.00781h1 2 1.00781v-.003906l11.992188-11.992188-.001953-.001953.001953-.001953-4-4-.001953.001953-.001953-.001953m-1.998047 3.412109l2.589844 2.589844-7.587891 7.587891v-1.589844h-1-1v-1-.589844l6.998047-6.998047m-7.998047 7.998047v1.589844h1 1v1 .589844l-.410156.410156h-1.589844l-1-1v-1.589844l1-1" class="ColorScheme-Text"/>
</svg>

After

Width:  |  Height:  |  Size: 675 B

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="svg2" height="22" style="" viewBox="0 0 22 22" width="22" xmlns="http://www.w3.org/2000/svg" sodipodi:docname="fingerprint.svg" inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">.ColorScheme-Text { color: #fcfcfc; } </style>
</defs>
<path id="path1" d="m 10.964844 2.9980469 c -1.5845236 -.0072353 -2.9422744 .2857394 -4.1777346 .9042969 c -.4112899 .2059109 -.4758434 .2776955 -.4492188 .5 c .0543735 .4537067 .2885593 .498883 .9824219 .1875 c 1.2899294 -.578856 1.9178453 -.7033109 3.5449215 -.7050782 c 1.867366 -.00153 2.554482 .1581718 4.085938 .9511719 c .263122 .1360571 1.097292 .7789323 1.408203 .4335937 c .307924 -.3078945 .144513 -.5609142 -.648437 -1.0117187 c -1.563801 -.8890431 -2.930512 -1.2511653 -4.746094 -1.2597656 z m -.046875 1.8320312 c -2.0906577 -.0015904 -4.1807664 .8256559 -5.7128909 2.4804688 c -.5926987 .640169 -1.2832031 1.689795 -1.2832031 1.9492187 c 0 .3024858 .1234451 .46875 .3496094 .46875 c .1772788 0 .3578489 -.190821 .7871094 -.8359375 c .9600458 -1.4427908 2.2051389 -2.4006204 3.8085937 -2.9296875 c 1.2435415 -.4058614 2.7001995 -.3588754 4.0996095 0 c 1.806888 .5938948 3.355915 1.916279 4.205078 3.5898438 c .184782 .3641515 .295572 .4765626 .476563 .4765626 c .311704 0 .495303 -.23344 .410156 -.5214845 c -.137293 -.4645988 -.869271 -1.5904919 -1.423828 -2.1894531 c -1.534258 -1.657146 -3.626141 -2.4866996 -5.716797 -2.4882813 z m .097656 1.8222657 c -.445604 -.00775 -.897825 .0344876 -1.3496094 .1289062 c -2.146845 .4487425 -3.9412221 2.1872289 -4.515625 4.375 c -.3048255 1.160984 -.1650506 3.057421 .3378906 4.574219 c .1503076 .453288 .223992 .547173 .4394532 .572265 c .4953707 .05757 .5425194 -.177958 .2460937 -1.203125 c -.8481973 -2.933423 -.117367 -5.4282751 1.9863281 -6.7890621 c 2.0798818 -1.3453843 4.9406298 -.948559 6.5683598 .9121093 c 1.020005 1.1659848 1.579872 3.1393058 1.134765 3.9999998 c -.294034 .568598 -1.009591 .909304 -1.597656 .761719 c -.429745 -.107851 -.940652 -.635832 -1.005859 -1.041016 c -.230123 -1.429844 -.554761 -1.988299 -1.376954 -2.371093 c -.701353 -.32655 -1.284385 -.317345 -1.9726558 .03125 c -.6413124 .324823 -1.1329202 .979024 -1.2324218 1.642578 c -.035906 .239115 -.0206307 .757671 .0351562 1.15039 c .3469606 2.446271 2.0965544 4.381247 4.5000004 4.976563 c .302262 .07484 .797346 .127554 1.099609 .117187 l .548828 -.017578 c .310632 -.157676 .327632 -.52228 0 -.701172 l -.777344 -.117187 c -.978866 -.149158 -1.383803 -.279437 -2.05664 -.658203 c -1.46318 -.823674 -2.511719 -2.609239 -2.511719 -4.277344 c 0 -.735113 .2787884 -1.164663 .927734 -1.433594 c .468905 -.194333 .474455 -.194333 .94336 0 c .593428 .24593 .879612 .658428 .953125 1.371094 c .134996 1.307917 1.042601 2.167969 2.287109 2.167969 c .998776 0 1.840549 -.647171 2.138672 -1.646485 c .291784 -.977992 -.101062 -2.621655 -.923828 -3.8710934 c -1.090395 -1.6558477 -2.895221 -2.6207549 -4.826172 -2.6542968 z m -.064453 1.8945312 c -.621891 .0078591 -1.2610341 .1220648 -1.7851564 .3261719 c -.8081421 .3957774 -1.5782434 1.1864461 -1.9765625 2.0273441 c -.3030937 .639832 -.3205007 .739905 -.3203125 1.826171 c .0002242 1.336431 .1608293 2.045939 .7363282 3.246094 c .4958946 1.034132 1.1835844 1.936783 1.9472656 2.554688 c .6619406 .535587 .7322516 .560867 1.0078126 .359375 c .282107 -.20626 .124685 -.56108 -.445313 -.998047 c -.6180212 -.473788 -1.2857839 -1.329765 -1.7363278 -2.228516 c -.7400486 -1.476217 -.9257648 -3.301198 -.4433593 -4.345703 c .3501094 -.758061 .8837753 -1.3239492 1.5644531 -1.658203 c .817809 -.4015966 2.012269 -.4015966 2.830078 0 c .976109 .479324 1.599333 1.353519 1.820313 2.550781 c .1319 .714664 .332068 .952234 .636718 .75586 c .141164 -.09099 .171337 -.242829 .158203 -.78711 c -.031914 -1.323089 -.957834 -2.6511972 -2.3125 -3.316406 c -.454743 -.2212609 -1.059749 -.3203662 -1.68164 -.3125 z m -.003906 3.615234 c -.072134 -.001465 -.153033 .023509 -.244141 .072266 c -.191281 .102402 -.208829 .174075 -.162109 .726563 c .147755 1.748088 1.464452 3.25256 3.171875 3.625 c .757301 .165124 .960616 .162423 1.142578 -.019532 c .363429 -.363416 .119519 -.652706 -.634766 -.755859 c -1.541693 -.21083 -2.687806 -1.387877 -2.871094 -2.947266 c -.054671 -.465046 -.185943 -.696776 -.402343 -.701172 z" class="ColorScheme-Text" fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">.ColorScheme-Text { color: #fcfcfc; } </style>
</defs>
<path style="fill:currentColor;fill-opacity:1;stroke:none" d="M 10 4 L 10 11 L 3 11 L 3 12 L 10 12 L 10 19 L 11 19 L 11 12 L 18 12 L 18 11 L 11 11 L 11 4 L 10 4 z " class="ColorScheme-Text"/>
</svg>

After

Width:  |  Height:  |  Size: 435 B

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" viewBox="0 0 22 22" xmlns="http://www.w3.org/2000/svg">
<style type="text/css" id="current-color-scheme">.ColorScheme-NegativeText { color: #da4453; } </style>
<path class="ColorScheme-NegativeText" d="M 3.6992188 3 L 3 3.6992188 L 10.300781 11 L 3 18.300781 C 3 18.300781 3.7112147 18.993333 3.6992188 19 L 11 11.699219 L 18.300781 19 C 18.288781 18.9933 19 18.300781 19 18.300781 L 11.699219 11.001953 L 19 3.6992188 L 18.300781 3 L 11 10.300781 L 3.6992188 3 z " fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 561 B

View File

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">.ColorScheme-Text { color: #fcfcfc; } </style>
</defs>
<g transform="translate(1,1)">
<path style="fill:currentColor;fill-opacity:1;stroke:none" d="m14.996094 3l-11.992188 11.992188h-.003906v4.00781h1 2 1.00781v-.003906l11.992188-11.992188-.001953-.001953.001953-.001953-4-4-.001953.001953-.001953-.001953m-1.998047 3.412109l2.589844 2.589844-7.587891 7.587891v-1.589844h-1-1v-1-.589844l6.998047-6.998047m-7.998047 7.998047v1.589844h1 1v1 .589844l-.410156.410156h-1.589844l-1-1v-1.589844l1-1" class="ColorScheme-Text"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 702 B

View File

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg" id="svg2" height="24" style="" viewBox="0 0 24 24" width="24" sodipodi:docname="fingerprint.svg" inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">.ColorScheme-Text { color: #fcfcfc; } </style>
</defs>
<g transform="translate(1,1)">
<path id="path1" d="m 10.964844 2.9980469 c -1.5845236 -.0072353 -2.9422744 .2857394 -4.1777346 .9042969 c -.4112899 .2059109 -.4758434 .2776955 -.4492188 .5 c .0543735 .4537067 .2885593 .498883 .9824219 .1875 c 1.2899294 -.578856 1.9178453 -.7033109 3.5449215 -.7050782 c 1.867366 -.00153 2.554482 .1581718 4.085938 .9511719 c .263122 .1360571 1.097292 .7789323 1.408203 .4335937 c .307924 -.3078945 .144513 -.5609142 -.648437 -1.0117187 c -1.563801 -.8890431 -2.930512 -1.2511653 -4.746094 -1.2597656 z m -.046875 1.8320312 c -2.0906577 -.0015904 -4.1807664 .8256559 -5.7128909 2.4804688 c -.5926987 .640169 -1.2832031 1.689795 -1.2832031 1.9492187 c 0 .3024858 .1234451 .46875 .3496094 .46875 c .1772788 0 .3578489 -.190821 .7871094 -.8359375 c .9600458 -1.4427908 2.2051389 -2.4006204 3.8085937 -2.9296875 c 1.2435415 -.4058614 2.7001995 -.3588754 4.0996095 0 c 1.806888 .5938948 3.355915 1.916279 4.205078 3.5898438 c .184782 .3641515 .295572 .4765626 .476563 .4765626 c .311704 0 .495303 -.23344 .410156 -.5214845 c -.137293 -.4645988 -.869271 -1.5904919 -1.423828 -2.1894531 c -1.534258 -1.657146 -3.626141 -2.4866996 -5.716797 -2.4882813 z m .097656 1.8222657 c -.445604 -.00775 -.897825 .0344876 -1.3496094 .1289062 c -2.146845 .4487425 -3.9412221 2.1872289 -4.515625 4.375 c -.3048255 1.160984 -.1650506 3.057421 .3378906 4.574219 c .1503076 .453288 .223992 .547173 .4394532 .572265 c .4953707 .05757 .5425194 -.177958 .2460937 -1.203125 c -.8481973 -2.933423 -.117367 -5.4282751 1.9863281 -6.7890621 c 2.0798818 -1.3453843 4.9406298 -.948559 6.5683598 .9121093 c 1.020005 1.1659848 1.579872 3.1393058 1.134765 3.9999998 c -.294034 .568598 -1.009591 .909304 -1.597656 .761719 c -.429745 -.107851 -.940652 -.635832 -1.005859 -1.041016 c -.230123 -1.429844 -.554761 -1.988299 -1.376954 -2.371093 c -.701353 -.32655 -1.284385 -.317345 -1.9726558 .03125 c -.6413124 .324823 -1.1329202 .979024 -1.2324218 1.642578 c -.035906 .239115 -.0206307 .757671 .0351562 1.15039 c .3469606 2.446271 2.0965544 4.381247 4.5000004 4.976563 c .302262 .07484 .797346 .127554 1.099609 .117187 l .548828 -.017578 c .310632 -.157676 .327632 -.52228 0 -.701172 l -.777344 -.117187 c -.978866 -.149158 -1.383803 -.279437 -2.05664 -.658203 c -1.46318 -.823674 -2.511719 -2.609239 -2.511719 -4.277344 c 0 -.735113 .2787884 -1.164663 .927734 -1.433594 c .468905 -.194333 .474455 -.194333 .94336 0 c .593428 .24593 .879612 .658428 .953125 1.371094 c .134996 1.307917 1.042601 2.167969 2.287109 2.167969 c .998776 0 1.840549 -.647171 2.138672 -1.646485 c .291784 -.977992 -.101062 -2.621655 -.923828 -3.8710934 c -1.090395 -1.6558477 -2.895221 -2.6207549 -4.826172 -2.6542968 z m -.064453 1.8945312 c -.621891 .0078591 -1.2610341 .1220648 -1.7851564 .3261719 c -.8081421 .3957774 -1.5782434 1.1864461 -1.9765625 2.0273441 c -.3030937 .639832 -.3205007 .739905 -.3203125 1.826171 c .0002242 1.336431 .1608293 2.045939 .7363282 3.246094 c .4958946 1.034132 1.1835844 1.936783 1.9472656 2.554688 c .6619406 .535587 .7322516 .560867 1.0078126 .359375 c .282107 -.20626 .124685 -.56108 -.445313 -.998047 c -.6180212 -.473788 -1.2857839 -1.329765 -1.7363278 -2.228516 c -.7400486 -1.476217 -.9257648 -3.301198 -.4433593 -4.345703 c .3501094 -.758061 .8837753 -1.3239492 1.5644531 -1.658203 c .817809 -.4015966 2.012269 -.4015966 2.830078 0 c .976109 .479324 1.599333 1.353519 1.820313 2.550781 c .1319 .714664 .332068 .952234 .636718 .75586 c .141164 -.09099 .171337 -.242829 .158203 -.78711 c -.031914 -1.323089 -.957834 -2.6511972 -2.3125 -3.316406 c -.454743 -.2212609 -1.059749 -.3203662 -1.68164 -.3125 z m -.003906 3.615234 c -.072134 -.001465 -.153033 .023509 -.244141 .072266 c -.191281 .102402 -.208829 .174075 -.162109 .726563 c .147755 1.748088 1.464452 3.25256 3.171875 3.625 c .757301 .165124 .960616 .162423 1.142578 -.019532 c .363429 -.363416 .119519 -.652706 -.634766 -.755859 c -1.541693 -.21083 -2.687806 -1.387877 -2.871094 -2.947266 c -.054671 -.465046 -.185943 -.696776 -.402343 -.701172 z" class="ColorScheme-Text" fill="currentColor"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">.ColorScheme-Text { color: #fcfcfc; } </style>
</defs>
<g transform="translate(1,1)">
<path style="fill:currentColor;fill-opacity:1;stroke:none" d="M 10 4 L 10 11 L 3 11 L 3 12 L 10 12 L 10 19 L 11 19 L 11 12 L 18 12 L 18 11 L 11 11 L 11 4 L 10 4 z " class="ColorScheme-Text"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 460 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 24 24" width="24" height="24">
<style type="text/css" id="current-color-scheme">.ColorScheme-NegativeText { color: #da4453; } </style>
<g transform="translate(1,1)">
<path class="ColorScheme-NegativeText" d="M 3.6992188 3 L 3 3.6992188 L 10.300781 11 L 3 18.300781 C 3 18.300781 3.7112147 18.993333 3.6992188 19 L 11 11.699219 L 18.300781 19 C 18.288781 18.9933 19 18.300781 19 18.300781 L 11.699219 11.001953 L 19 3.6992188 L 18.300781 3 L 11 10.300781 L 3.6992188 3 z " fill="currentColor"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 583 B

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">.ColorScheme-Text { color: #fcfcfc; } </style>
</defs>
<path style="fill:currentColor;fill-opacity:1;stroke:none" d="m22.27 4l-18.27 18.27v5.73h5.73c0 0 18.269-18.269 18.27-18.27zm-2.865 4.299l4.297 4.297-11.701 11.703v-2.299h-4v-2.299zm-12.404 12.402v2.299h4v2.299l-1.701 1.701h-2l-2.297-2.297v-2z" class="ColorScheme-Text"/>
</svg>

After

Width:  |  Height:  |  Size: 513 B

View File

@ -29,7 +29,7 @@ KDE-Extensions=.svg
########## Directories
########## ordered by category and alphabetically
Directories=actions/16,actions/22,actions/24,actions/32,apps/64,devices/64,places/64,status/16,status/22,status,24,status/64
Directories=actions/16,actions/22,actions/24,actions/32,apps/64,devices/64,places/64,status/16,status/22,status,24,status/32,status/64
ScaledDirectories=actions/16@2x,actions/16@3x,actions/22@2x,actions/22@3x,actions/24@2x,actions/24@3x,actions/32@2x,actions/32@3x
[apps/64]
@ -156,6 +156,14 @@ Context=Places
MinSize=48
MaxSize=256
#32x32 - Fixed size - For dialog icons >!!!ONLY!!!< - DO_NOT_USE_ANYWHERE_ELSE - Color
[status/32]
Size=32
Context=Status
Type=Scalable
MinSize=22
MaxSize=256
#64x64 - Fixed size - For dialog icons >!!!ONLY!!!< - DO_NOT_USE_ANYWHERE_ELSE - Color
[status/64]
Size=64

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" width="22" height="22">
<style type="text/css" id="current-color-scheme">.ColorScheme-Accent { color: #3daee9; } .ColorScheme-Background { color: #2a2e32; } .ColorScheme-ButtonText { color: #31363b; } .ColorScheme-Text { color: #fcfcfc; } </style>
<g id="software-updates-release" transform="translate(0,22) translate(0,-22)">
<path style="fill:#2ecc71;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M 7,7 4,10 4,19 9.0996094,19 13,19 l 5.099609,0 0,-9 -3,-3 L 13,7 9.0996094,7 Z m 0.3,1 3.7,0 3.7,0 2,2 -11.4,0 z m 1.7,3 4,0 0,5 -1,-1 -1,1 -1,-1 -1,1 z" id="path4164" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccccccccccccccccccccccc"/>
<path style="opacity:1;fill:#2ecc71;fill-opacity:1;stroke:none" d="M 16,3 A 3,3 0 0 0 13,6 3,3 0 0 0 16,9 3,3 0 0 0 19,6 3,3 0 0 0 16,3 Z" id="path4166" inkscape:connector-curvature="0"/>
<path style="opacity:1;fill:currentColor;fill-opacity:1;stroke:none" d="m 16,4 2,2 -1,0 0,2 -2,0 0,-2 -1,0 1,-1 1,-1 z" id="path4168" inkscape:connector-curvature="0" class="ColorScheme-Background"/>
<rect y="-2.6645353e-15" x="0" height="22" width="22" id="rect4170" style="opacity:1;fill:none;fill-opacity:0.59905659;stroke:none"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#232629;
}
</style>
</defs>
<path style="fill:currentColor;fill-opacity:1;stroke:none"
d="M 10.398438 2 L 5.2871094 7.1113281 L 2 10.398438 L 2 14 L 5.6015625 14 L 14 5.6015625 L 10.398438 2 z M 8.3496094 5.4902344 L 10.509766 7.6503906 L 7.3359375 10.826172 L 7.3359375 10.150391 L 6.3222656 10.171875 L 5.2871094 10.171875 L 5.2871094 9.1367188 L 5.2871094 8.5507812 L 6.7285156 7.1113281 L 8.3496094 5.4902344 z M 4.2734375 9.5644531 L 4.2734375 11.185547 L 5.3085938 11.185547 L 6.3007812 11.185547 L 6.3222656 11.837891 L 5.2421875 12.919922 L 3.8007812 12.919922 L 3.0800781 12.199219 L 3.0800781 10.757812 L 4.2734375 9.5644531 z "
class="ColorScheme-Text"
/>
</svg>

After

Width:  |  Height:  |  Size: 883 B

View File

@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#232629;
}
</style>
</defs>
<path style="fill:currentColor;fill-opacity:1;stroke:none"
d="M 7 3.0058594 L 7 8 L 2 8 L 2 8.9980469 L 7 8.9980469 L 7 14.007812 L 8 14.007812 L 8 8.9980469 L 13 8.9980469 L 13 8 L 8 8 L 8 3.0058594 L 7 3.0058594 z "
class="ColorScheme-Text"
/>
</svg>

After

Width:  |  Height:  |  Size: 490 B

View File

@ -0,0 +1,10 @@
<svg version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<style
type="text/css"
id="current-color-scheme">
.ColorScheme-NegativeText {
color:#da4453;
}
</style>
<path class="ColorScheme-NegativeText" d="M 2.6992188,2 2,2.6992188 7.3007812,8 2,13.300781 C 2,13.300781 2.7082187,13.995 2.6992188,14 L 8,8.6992188 13.300781,14 C 13.291781,13.995 14,13.300781 14,13.300781 L 8.6992188,8 14,2.6992188 13.300781,2 8,7.3007812 Z" fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 526 B

View File

@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#232629;
}
</style>
</defs>
<path
style="fill:currentColor;fill-opacity:1;stroke:none"
d="m14.996094 3l-11.992188 11.992188h-.003906v4.00781h1 2 1.00781v-.003906l11.992188-11.992188-.001953-.001953.001953-.001953-4-4-.001953.001953-.001953-.001953m-1.998047 3.412109l2.589844 2.589844-7.587891 7.587891v-1.589844h-1-1v-1-.589844l6.998047-6.998047m-7.998047 7.998047v1.589844h1 1v1 .589844l-.410156.410156h-1.589844l-1-1v-1.589844l1-1"
class="ColorScheme-Text"
/>
</svg>

After

Width:  |  Height:  |  Size: 681 B

View File

@ -0,0 +1,10 @@
<svg id="svg2" height="22" style="" viewBox="0 0 22 22" width="22" xmlns="http://www.w3.org/2000/svg" sodipodi:docname="fingerprint.svg" inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#232629;
}
</style>
</defs>
<path id="path1" d="m 10.964844 2.9980469 c -1.5845236 -.0072353 -2.9422744 .2857394 -4.1777346 .9042969 c -.4112899 .2059109 -.4758434 .2776955 -.4492188 .5 c .0543735 .4537067 .2885593 .498883 .9824219 .1875 c 1.2899294 -.578856 1.9178453 -.7033109 3.5449215 -.7050782 c 1.867366 -.00153 2.554482 .1581718 4.085938 .9511719 c .263122 .1360571 1.097292 .7789323 1.408203 .4335937 c .307924 -.3078945 .144513 -.5609142 -.648437 -1.0117187 c -1.563801 -.8890431 -2.930512 -1.2511653 -4.746094 -1.2597656 z m -.046875 1.8320312 c -2.0906577 -.0015904 -4.1807664 .8256559 -5.7128909 2.4804688 c -.5926987 .640169 -1.2832031 1.689795 -1.2832031 1.9492187 c 0 .3024858 .1234451 .46875 .3496094 .46875 c .1772788 0 .3578489 -.190821 .7871094 -.8359375 c .9600458 -1.4427908 2.2051389 -2.4006204 3.8085937 -2.9296875 c 1.2435415 -.4058614 2.7001995 -.3588754 4.0996095 0 c 1.806888 .5938948 3.355915 1.916279 4.205078 3.5898438 c .184782 .3641515 .295572 .4765626 .476563 .4765626 c .311704 0 .495303 -.23344 .410156 -.5214845 c -.137293 -.4645988 -.869271 -1.5904919 -1.423828 -2.1894531 c -1.534258 -1.657146 -3.626141 -2.4866996 -5.716797 -2.4882813 z m .097656 1.8222657 c -.445604 -.00775 -.897825 .0344876 -1.3496094 .1289062 c -2.146845 .4487425 -3.9412221 2.1872289 -4.515625 4.375 c -.3048255 1.160984 -.1650506 3.057421 .3378906 4.574219 c .1503076 .453288 .223992 .547173 .4394532 .572265 c .4953707 .05757 .5425194 -.177958 .2460937 -1.203125 c -.8481973 -2.933423 -.117367 -5.4282751 1.9863281 -6.7890621 c 2.0798818 -1.3453843 4.9406298 -.948559 6.5683598 .9121093 c 1.020005 1.1659848 1.579872 3.1393058 1.134765 3.9999998 c -.294034 .568598 -1.009591 .909304 -1.597656 .761719 c -.429745 -.107851 -.940652 -.635832 -1.005859 -1.041016 c -.230123 -1.429844 -.554761 -1.988299 -1.376954 -2.371093 c -.701353 -.32655 -1.284385 -.317345 -1.9726558 .03125 c -.6413124 .324823 -1.1329202 .979024 -1.2324218 1.642578 c -.035906 .239115 -.0206307 .757671 .0351562 1.15039 c .3469606 2.446271 2.0965544 4.381247 4.5000004 4.976563 c .302262 .07484 .797346 .127554 1.099609 .117187 l .548828 -.017578 c .310632 -.157676 .327632 -.52228 0 -.701172 l -.777344 -.117187 c -.978866 -.149158 -1.383803 -.279437 -2.05664 -.658203 c -1.46318 -.823674 -2.511719 -2.609239 -2.511719 -4.277344 c 0 -.735113 .2787884 -1.164663 .927734 -1.433594 c .468905 -.194333 .474455 -.194333 .94336 0 c .593428 .24593 .879612 .658428 .953125 1.371094 c .134996 1.307917 1.042601 2.167969 2.287109 2.167969 c .998776 0 1.840549 -.647171 2.138672 -1.646485 c .291784 -.977992 -.101062 -2.621655 -.923828 -3.8710934 c -1.090395 -1.6558477 -2.895221 -2.6207549 -4.826172 -2.6542968 z m -.064453 1.8945312 c -.621891 .0078591 -1.2610341 .1220648 -1.7851564 .3261719 c -.8081421 .3957774 -1.5782434 1.1864461 -1.9765625 2.0273441 c -.3030937 .639832 -.3205007 .739905 -.3203125 1.826171 c .0002242 1.336431 .1608293 2.045939 .7363282 3.246094 c .4958946 1.034132 1.1835844 1.936783 1.9472656 2.554688 c .6619406 .535587 .7322516 .560867 1.0078126 .359375 c .282107 -.20626 .124685 -.56108 -.445313 -.998047 c -.6180212 -.473788 -1.2857839 -1.329765 -1.7363278 -2.228516 c -.7400486 -1.476217 -.9257648 -3.301198 -.4433593 -4.345703 c .3501094 -.758061 .8837753 -1.3239492 1.5644531 -1.658203 c .817809 -.4015966 2.012269 -.4015966 2.830078 0 c .976109 .479324 1.599333 1.353519 1.820313 2.550781 c .1319 .714664 .332068 .952234 .636718 .75586 c .141164 -.09099 .171337 -.242829 .158203 -.78711 c -.031914 -1.323089 -.957834 -2.6511972 -2.3125 -3.316406 c -.454743 -.2212609 -1.059749 -.3203662 -1.68164 -.3125 z m -.003906 3.615234 c -.072134 -.001465 -.153033 .023509 -.244141 .072266 c -.191281 .102402 -.208829 .174075 -.162109 .726563 c .147755 1.748088 1.464452 3.25256 3.171875 3.625 c .757301 .165124 .960616 .162423 1.142578 -.019532 c .363429 -.363416 .119519 -.652706 -.634766 -.755859 c -1.541693 -.21083 -2.687806 -1.387877 -2.871094 -2.947266 c -.054671 -.465046 -.185943 -.696776 -.402343 -.701172 z" class="ColorScheme-Text" fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#232629;
}
</style>
</defs>
<path
style="fill:currentColor;fill-opacity:1;stroke:none"
d="M 10 4 L 10 11 L 3 11 L 3 12 L 10 12 L 10 19 L 11 19 L 11 12 L 18 12 L 18 11 L 11 11 L 11 4 L 10 4 z "
class="ColorScheme-Text"
/>
</svg>

After

Width:  |  Height:  |  Size: 441 B

View File

@ -0,0 +1,10 @@
<svg version="1.1" viewBox="0 0 22 22" xmlns="http://www.w3.org/2000/svg">
<style
type="text/css"
id="current-color-scheme">
.ColorScheme-NegativeText {
color:#da4453;
}
</style>
<path class="ColorScheme-NegativeText" d="M 3.6992188 3 L 3 3.6992188 L 10.300781 11 L 3 18.300781 C 3 18.300781 3.7112147 18.993333 3.6992188 19 L 11 11.699219 L 18.300781 19 C 18.288781 18.9933 19 18.300781 19 18.300781 L 11.699219 11.001953 L 19 3.6992188 L 18.300781 3 L 11 10.300781 L 3.6992188 3 z " fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 570 B

View File

@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#232629;
}
</style>
</defs>
<g transform="translate(1,1)">
<path style="fill:currentColor;fill-opacity:1;stroke:none" d="m14.996094 3l-11.992188 11.992188h-.003906v4.00781h1 2 1.00781v-.003906l11.992188-11.992188-.001953-.001953.001953-.001953-4-4-.001953.001953-.001953-.001953m-1.998047 3.412109l2.589844 2.589844-7.587891 7.587891v-1.589844h-1-1v-1-.589844l6.998047-6.998047m-7.998047 7.998047v1.589844h1 1v1 .589844l-.410156.410156h-1.589844l-1-1v-1.589844l1-1" class="ColorScheme-Text"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 728 B

View File

@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg" id="svg2" height="24" style="" viewBox="0 0 24 24" width="24" sodipodi:docname="fingerprint.svg" inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#232629;
}
</style>
</defs>
<g transform="translate(1,1)">
<path id="path1" d="m 10.964844 2.9980469 c -1.5845236 -.0072353 -2.9422744 .2857394 -4.1777346 .9042969 c -.4112899 .2059109 -.4758434 .2776955 -.4492188 .5 c .0543735 .4537067 .2885593 .498883 .9824219 .1875 c 1.2899294 -.578856 1.9178453 -.7033109 3.5449215 -.7050782 c 1.867366 -.00153 2.554482 .1581718 4.085938 .9511719 c .263122 .1360571 1.097292 .7789323 1.408203 .4335937 c .307924 -.3078945 .144513 -.5609142 -.648437 -1.0117187 c -1.563801 -.8890431 -2.930512 -1.2511653 -4.746094 -1.2597656 z m -.046875 1.8320312 c -2.0906577 -.0015904 -4.1807664 .8256559 -5.7128909 2.4804688 c -.5926987 .640169 -1.2832031 1.689795 -1.2832031 1.9492187 c 0 .3024858 .1234451 .46875 .3496094 .46875 c .1772788 0 .3578489 -.190821 .7871094 -.8359375 c .9600458 -1.4427908 2.2051389 -2.4006204 3.8085937 -2.9296875 c 1.2435415 -.4058614 2.7001995 -.3588754 4.0996095 0 c 1.806888 .5938948 3.355915 1.916279 4.205078 3.5898438 c .184782 .3641515 .295572 .4765626 .476563 .4765626 c .311704 0 .495303 -.23344 .410156 -.5214845 c -.137293 -.4645988 -.869271 -1.5904919 -1.423828 -2.1894531 c -1.534258 -1.657146 -3.626141 -2.4866996 -5.716797 -2.4882813 z m .097656 1.8222657 c -.445604 -.00775 -.897825 .0344876 -1.3496094 .1289062 c -2.146845 .4487425 -3.9412221 2.1872289 -4.515625 4.375 c -.3048255 1.160984 -.1650506 3.057421 .3378906 4.574219 c .1503076 .453288 .223992 .547173 .4394532 .572265 c .4953707 .05757 .5425194 -.177958 .2460937 -1.203125 c -.8481973 -2.933423 -.117367 -5.4282751 1.9863281 -6.7890621 c 2.0798818 -1.3453843 4.9406298 -.948559 6.5683598 .9121093 c 1.020005 1.1659848 1.579872 3.1393058 1.134765 3.9999998 c -.294034 .568598 -1.009591 .909304 -1.597656 .761719 c -.429745 -.107851 -.940652 -.635832 -1.005859 -1.041016 c -.230123 -1.429844 -.554761 -1.988299 -1.376954 -2.371093 c -.701353 -.32655 -1.284385 -.317345 -1.9726558 .03125 c -.6413124 .324823 -1.1329202 .979024 -1.2324218 1.642578 c -.035906 .239115 -.0206307 .757671 .0351562 1.15039 c .3469606 2.446271 2.0965544 4.381247 4.5000004 4.976563 c .302262 .07484 .797346 .127554 1.099609 .117187 l .548828 -.017578 c .310632 -.157676 .327632 -.52228 0 -.701172 l -.777344 -.117187 c -.978866 -.149158 -1.383803 -.279437 -2.05664 -.658203 c -1.46318 -.823674 -2.511719 -2.609239 -2.511719 -4.277344 c 0 -.735113 .2787884 -1.164663 .927734 -1.433594 c .468905 -.194333 .474455 -.194333 .94336 0 c .593428 .24593 .879612 .658428 .953125 1.371094 c .134996 1.307917 1.042601 2.167969 2.287109 2.167969 c .998776 0 1.840549 -.647171 2.138672 -1.646485 c .291784 -.977992 -.101062 -2.621655 -.923828 -3.8710934 c -1.090395 -1.6558477 -2.895221 -2.6207549 -4.826172 -2.6542968 z m -.064453 1.8945312 c -.621891 .0078591 -1.2610341 .1220648 -1.7851564 .3261719 c -.8081421 .3957774 -1.5782434 1.1864461 -1.9765625 2.0273441 c -.3030937 .639832 -.3205007 .739905 -.3203125 1.826171 c .0002242 1.336431 .1608293 2.045939 .7363282 3.246094 c .4958946 1.034132 1.1835844 1.936783 1.9472656 2.554688 c .6619406 .535587 .7322516 .560867 1.0078126 .359375 c .282107 -.20626 .124685 -.56108 -.445313 -.998047 c -.6180212 -.473788 -1.2857839 -1.329765 -1.7363278 -2.228516 c -.7400486 -1.476217 -.9257648 -3.301198 -.4433593 -4.345703 c .3501094 -.758061 .8837753 -1.3239492 1.5644531 -1.658203 c .817809 -.4015966 2.012269 -.4015966 2.830078 0 c .976109 .479324 1.599333 1.353519 1.820313 2.550781 c .1319 .714664 .332068 .952234 .636718 .75586 c .141164 -.09099 .171337 -.242829 .158203 -.78711 c -.031914 -1.323089 -.957834 -2.6511972 -2.3125 -3.316406 c -.454743 -.2212609 -1.059749 -.3203662 -1.68164 -.3125 z m -.003906 3.615234 c -.072134 -.001465 -.153033 .023509 -.244141 .072266 c -.191281 .102402 -.208829 .174075 -.162109 .726563 c .147755 1.748088 1.464452 3.25256 3.171875 3.625 c .757301 .165124 .960616 .162423 1.142578 -.019532 c .363429 -.363416 .119519 -.652706 -.634766 -.755859 c -1.541693 -.21083 -2.687806 -1.387877 -2.871094 -2.947266 c -.054671 -.465046 -.185943 -.696776 -.402343 -.701172 z" class="ColorScheme-Text" fill="currentColor"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#232629;
}
</style>
</defs>
<g transform="translate(1,1)">
<path style="fill:currentColor;fill-opacity:1;stroke:none" d="M 10 4 L 10 11 L 3 11 L 3 12 L 10 12 L 10 19 L 11 19 L 11 12 L 18 12 L 18 11 L 11 11 L 11 4 L 10 4 z " class="ColorScheme-Text"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 486 B

View File

@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 24 24" width="24" height="24">
<style type="text/css" id="current-color-scheme">
.ColorScheme-NegativeText {
color:#da4453;
}
</style>
<g transform="translate(1,1)">
<path class="ColorScheme-NegativeText" d="M 3.6992188 3 L 3 3.6992188 L 10.300781 11 L 3 18.300781 C 3 18.300781 3.7112147 18.993333 3.6992188 19 L 11 11.699219 L 18.300781 19 C 18.288781 18.9933 19 18.300781 19 18.300781 L 11.699219 11.001953 L 19 3.6992188 L 18.300781 3 L 11 10.300781 L 3.6992188 3 z " fill="currentColor"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 615 B

View File

@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#232629;
}
</style>
</defs>
<path
style="fill:currentColor;fill-opacity:1;stroke:none"
d="m22.27 4l-18.27 18.27v5.73h5.73c0 0 18.269-18.269 18.27-18.27zm-2.865 4.299l4.297 4.297-11.701 11.703v-2.299h-4v-2.299zm-12.404 12.402v2.299h4v2.299l-1.701 1.701h-2l-2.297-2.297v-2z"
class="ColorScheme-Text"
/>
</svg>

After

Width:  |  Height:  |  Size: 523 B

View File

@ -29,7 +29,7 @@ KDE-Extensions=.svg
########## Directories
########## ordered by category and alphabetically
Directories=actions/16,actions/22,actions/24,actions/32,apps/64,devices/64,places/64,status/16,status/22,status,24,status/64
Directories=actions/16,actions/22,actions/24,actions/32,apps/64,devices/64,places/64,status/16,status/22,status,24,status/32,status/64
ScaledDirectories=actions/16@2x,actions/16@3x,actions/22@2x,actions/22@3x,actions/24@2x,actions/24@3x,actions/32@2x,actions/32@3x
[apps/64]
@ -157,6 +157,14 @@ Context=Places
MinSize=48
MaxSize=256
#32x32 - Fixed size - For dialog icons >!!!ONLY!!!< - DO_NOT_USE_ANYWHERE_ELSE - Color
[status/32]
Size=32
Context=Status
Type=Scalable
MinSize=22
MaxSize=256
#64x64 - Fixed size - For dialog icons >!!!ONLY!!!< - DO_NOT_USE_ANYWHERE_ELSE - Color
[status/64]
Size=64

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" width="22" height="22">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#31363b;
}
.ColorScheme-Background {
color:#eff0f1;
}
.ColorScheme-Accent {
color:#3daee9;
}
.ColorScheme-ButtonText {
color:#31363b;
}
</style>
<g id="software-updates-release" transform="translate(0,22) translate(0,-22)">
<path style="fill:#2ecc71;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M 7,7 4,10 4,19 9.0996094,19 13,19 l 5.099609,0 0,-9 -3,-3 L 13,7 9.0996094,7 Z m 0.3,1 3.7,0 3.7,0 2,2 -11.4,0 z m 1.7,3 4,0 0,5 -1,-1 -1,1 -1,-1 -1,1 z" id="path4164" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccccccccccccccccccccccc"/>
<path style="opacity:1;fill:#2ecc71;fill-opacity:1;stroke:none" d="M 16,3 A 3,3 0 0 0 13,6 3,3 0 0 0 16,9 3,3 0 0 0 19,6 3,3 0 0 0 16,3 Z" id="path4166" inkscape:connector-curvature="0"/>
<path style="opacity:1;fill:currentColor;fill-opacity:1;stroke:none" d="m 16,4 2,2 -1,0 0,2 -2,0 0,-2 -1,0 1,-1 1,-1 z" id="path4168" inkscape:connector-curvature="0" class="ColorScheme-Background"/>
<rect y="-2.6645353e-15" x="0" height="22" width="22" id="rect4170" style="opacity:1;fill:none;fill-opacity:0.59905659;stroke:none"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View File

@ -9,7 +9,6 @@ add_subdirectory(client)
add_subdirectory(common)
add_subdirectory(deskflow)
add_subdirectory(io)
add_subdirectory(ipc)
add_subdirectory(mt)
add_subdirectory(net)
add_subdirectory(platform)

View File

@ -46,4 +46,11 @@ public:
*/
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;
//@}
};

View File

@ -67,6 +67,11 @@ 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";

View File

@ -24,6 +24,7 @@ public:
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

View File

@ -6,12 +6,11 @@
*/
#include "arch/win32/ArchDaemonWindows.h"
#include "arch/Arch.h"
#include "arch/win32/ArchMiscWindows.h"
#include "arch/win32/XArchWindows.h"
#include "common/stdvector.h"
#include <sstream>
#include "base/Log.h"
//
// ArchDaemonWindows
@ -61,6 +60,8 @@ void ArchDaemonWindows::installDaemon(
const char *name, const char *description, const char *pathname, const char *commandLine, const char *dependencies
)
{
LOG_DEBUG("installing windows service: %s", name);
// open service manager
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE);
if (mgr == NULL) {
@ -127,6 +128,8 @@ void ArchDaemonWindows::installDaemon(
void ArchDaemonWindows::uninstallDaemon(const char *name)
{
LOG_DEBUG("uninstalling windows service: %s", name);
// remove parameters for this service. ignore failures.
HKEY key = openNTServicesKey();
key = ArchMiscWindows::openKey(key, name);
@ -165,9 +168,10 @@ void ArchDaemonWindows::uninstallDaemon(const char *name)
CloseServiceHandle(service);
CloseServiceHandle(mgr);
// give windows a chance to remove the service before
// we check if it still exists.
ARCH->sleep(1);
// give windows a chance to remove the service before we check if it still exists.
// 100ms should be plenty of time.
LOG_DEBUG("waiting for service to be removed");
ARCH->sleep(0.1);
// handle failure. ignore error if service isn't installed anymore.
if (!okay && isDaemonInstalled(name)) {
@ -603,16 +607,13 @@ void ArchDaemonWindows::installDaemon()
{
// install default daemon if not already installed.
if (!isDaemonInstalled(DEFAULT_DAEMON_NAME)) {
char path[MAX_PATH];
GetModuleFileName(ArchMiscWindows::instanceWin32(), path, MAX_PATH);
char binPath[MAX_PATH];
GetModuleFileName(ArchMiscWindows::instanceWin32(), binPath, MAX_PATH);
// wrap in quotes so a malicious user can't start \Program.exe as admin.
std::stringstream ss;
ss << '"';
ss << path;
ss << '"';
const auto command = "\"" + std::string(binPath) + "\"";
installDaemon(DEFAULT_DAEMON_NAME, DEFAULT_DAEMON_INFO, ss.str().c_str(), "", "");
installDaemon(DEFAULT_DAEMON_NAME, DEFAULT_DAEMON_INFO, command.c_str(), "", "");
}
start(DEFAULT_DAEMON_NAME);

View File

@ -7,6 +7,7 @@
#include "arch/win32/ArchMiscWindows.h"
#include "arch/win32/ArchDaemonWindows.h"
#include "arch/win32/XArchWindows.h"
#include "base/Log.h"
#include "common/constants.h"
@ -164,6 +165,15 @@ void ArchMiscWindows::deleteValue(HKEY key, const TCHAR *name)
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;
@ -457,3 +467,19 @@ void ArchMiscWindows::setInstanceWin32(HINSTANCE instance)
assert(instance != NULL);
s_instanceWin32 = instance;
}
std::string ArchMiscWindows::getActiveDesktopName()
{
HDESK desk = OpenInputDesktop(0, TRUE, GENERIC_READ);
if (desk == nullptr) {
LOG((CLOG_ERR "could not open input desktop"));
throw XArch(new XArchEvalWindows());
}
DWORD size;
GetUserObjectInformation(desk, UOI_NAME, nullptr, 0, &size);
auto *name = (TCHAR *)alloca(size + sizeof(TCHAR));
GetUserObjectInformation(desk, UOI_NAME, name, size, &size);
CloseDesktop(desk);
return name;
}

View File

@ -99,6 +99,9 @@ public:
//! 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);
@ -155,12 +158,11 @@ public:
static bool getParentProcessName(std::string &name);
static HINSTANCE instanceWin32();
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);
static std::string getActiveDesktopName();
private:
//! Open and return a registry key, closing the parent key

View File

@ -9,6 +9,7 @@
#include "arch/win32/ArchMiscWindows.h"
#include "arch/XArch.h"
#include "base/Log.h"
#include "common/constants.h"
#include "tchar.h"
@ -17,7 +18,7 @@
#include <psapi.h>
#include <windows.h>
static const char *s_settingsKeyNames[] = {_T("SOFTWARE"), _T(kAppName), NULL};
static const TCHAR *s_settingsKeyNames[] = {_T("SOFTWARE"), _T(kAppName), NULL};
//
// ArchSystemWindows
@ -86,6 +87,11 @@ void ArchSystemWindows::setting(const std::string &valueName, const std::string
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

View File

@ -23,6 +23,7 @@ public:
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;
};

View File

@ -11,6 +11,7 @@ add_library(base STATIC
EventQueue.h
EventTypes.cpp
EventTypes.h
finally.h
FunctionEventJob.cpp
FunctionEventJob.h
FunctionJob.cpp

View File

@ -6,7 +6,6 @@
*/
#include "base/Event.h"
#include "base/EventQueue.h"
//
// Event

View File

@ -8,21 +8,17 @@
#include "base/EventQueue.h"
#include "arch/Arch.h"
#include "base/EventTypes.h"
#include "base/IEventJob.h"
#include "base/Log.h"
#include "base/SimpleEventQueueBuffer.h"
#include "base/Stopwatch.h"
#include "base/XBase.h"
#include "mt/Lock.h"
#include "mt/Mutex.h"
#include <stdexcept>
EVENT_TYPE_ACCESSOR(Client)
EVENT_TYPE_ACCESSOR(IStream)
EVENT_TYPE_ACCESSOR(IpcClient)
EVENT_TYPE_ACCESSOR(IpcClientProxy)
EVENT_TYPE_ACCESSOR(IpcServer)
EVENT_TYPE_ACCESSOR(IpcServerProxy)
EVENT_TYPE_ACCESSOR(IDataSocket)
EVENT_TYPE_ACCESSOR(IListenSocket)
EVENT_TYPE_ACCESSOR(ISocket)
@ -55,10 +51,6 @@ EventQueue::EventQueue()
m_nextType(Event::kLast),
m_typesForClient(NULL),
m_typesForIStream(NULL),
m_typesForIpcClient(NULL),
m_typesForIpcClientProxy(NULL),
m_typesForIpcServer(NULL),
m_typesForIpcServerProxy(NULL),
m_typesForIDataSocket(NULL),
m_typesForIListenSocket(NULL),
m_typesForISocket(NULL),

View File

@ -130,10 +130,6 @@ public:
//
ClientEvents &forClient();
IStreamEvents &forIStream();
IpcClientEvents &forIpcClient();
IpcClientProxyEvents &forIpcClientProxy();
IpcServerEvents &forIpcServer();
IpcServerProxyEvents &forIpcServerProxy();
IDataSocketEvents &forIDataSocket();
IListenSocketEvents &forIListenSocket();
ISocketEvents &forISocket();
@ -153,10 +149,6 @@ public:
private:
ClientEvents *m_typesForClient;
IStreamEvents *m_typesForIStream;
IpcClientEvents *m_typesForIpcClient;
IpcClientProxyEvents *m_typesForIpcClientProxy;
IpcServerEvents *m_typesForIpcServer;
IpcServerProxyEvents *m_typesForIpcServerProxy;
IDataSocketEvents *m_typesForIDataSocket;
IListenSocketEvents *m_typesForIListenSocket;
ISocketEvents *m_typesForISocket;

View File

@ -45,26 +45,6 @@ REGISTER_EVENT(IStream, inputShutdown)
REGISTER_EVENT(IStream, outputShutdown)
REGISTER_EVENT(IStream, inputFormatError)
//
// IpcClient
//
REGISTER_EVENT(IpcClient, connected)
REGISTER_EVENT(IpcClient, messageReceived)
//
// IpcClientProxy
//
REGISTER_EVENT(IpcClientProxy, messageReceived)
REGISTER_EVENT(IpcClientProxy, disconnected)
//
// IpcServerProxy
//
REGISTER_EVENT(IpcServerProxy, messageReceived)
//
// IDataSocket
//
@ -167,13 +147,6 @@ REGISTER_EVENT(IScreen, shapeChanged)
REGISTER_EVENT(IScreen, suspend)
REGISTER_EVENT(IScreen, resume)
//
// IpcServer
//
REGISTER_EVENT(IpcServer, clientConnected)
REGISTER_EVENT(IpcServer, messageReceived)
//
// Clipboard
//

View File

@ -145,94 +145,6 @@ private:
Event::Type m_inputFormatError;
};
class IpcClientEvents : public EventTypes
{
public:
IpcClientEvents() : m_connected(Event::kUnknown), m_messageReceived(Event::kUnknown)
{
}
//! @name accessors
//@{
//! Raised when the socket is connected.
Event::Type connected();
//! Raised when a message is received.
Event::Type messageReceived();
//@}
private:
Event::Type m_connected;
Event::Type m_messageReceived;
};
class IpcClientProxyEvents : public EventTypes
{
public:
IpcClientProxyEvents() : m_messageReceived(Event::kUnknown), m_disconnected(Event::kUnknown)
{
}
//! @name accessors
//@{
//! Raised when the server receives a message from a client.
Event::Type messageReceived();
//! Raised when the client disconnects from the server.
Event::Type disconnected();
//@}
private:
Event::Type m_messageReceived;
Event::Type m_disconnected;
};
class IpcServerEvents : public EventTypes
{
public:
IpcServerEvents() : m_clientConnected(Event::kUnknown), m_messageReceived(Event::kUnknown)
{
}
//! @name accessors
//@{
//! Raised when we have created the client proxy.
Event::Type clientConnected();
//! Raised when a message is received through a client proxy.
Event::Type messageReceived();
//@}
private:
Event::Type m_clientConnected;
Event::Type m_messageReceived;
};
class IpcServerProxyEvents : public EventTypes
{
public:
IpcServerProxyEvents() : m_messageReceived(Event::kUnknown)
{
}
//! @name accessors
//@{
//! Raised when the client receives a message from the server.
Event::Type messageReceived();
//@}
private:
Event::Type m_messageReceived;
};
class IDataSocketEvents : public EventTypes
{
public:

View File

@ -21,10 +21,6 @@ class EventQueueTimer;
// Event type registration classes.
class ClientEvents;
class IStreamEvents;
class IpcClientEvents;
class IpcClientProxyEvents;
class IpcServerEvents;
class IpcServerProxyEvents;
class IDataSocketEvents;
class IListenSocketEvents;
class ISocketEvents;
@ -216,10 +212,6 @@ public:
virtual ClientEvents &forClient() = 0;
virtual IStreamEvents &forIStream() = 0;
virtual IpcClientEvents &forIpcClient() = 0;
virtual IpcClientProxyEvents &forIpcClientProxy() = 0;
virtual IpcServerEvents &forIpcServer() = 0;
virtual IpcServerProxyEvents &forIpcServerProxy() = 0;
virtual IDataSocketEvents &forIDataSocket() = 0;
virtual IListenSocketEvents &forIListenSocket() = 0;
virtual ISocketEvents &forISocket() = 0;

View File

@ -128,7 +128,7 @@ Log::Log(bool singleton)
// other initalization
m_maxPriority = g_defaultMaxPriority;
insert(new ConsoleLogOutputter);
insert(new ConsoleLogOutputter); // NOSONAR - Adopted by `Log`
if (singleton) {
s_log = this;
@ -208,27 +208,18 @@ void Log::print(const char *file, int line, const char *fmt, ...)
}
}
void Log::insert(ILogOutputter *outputter, bool alwaysAtHead)
void Log::insert(ILogOutputter *adoptedOutputter, bool alwaysAtHead)
{
assert(outputter != NULL);
assert(adoptedOutputter != NULL);
ArchMutexLock lock(m_mutex);
if (alwaysAtHead) {
m_alwaysOutputters.push_front(outputter);
m_alwaysOutputters.push_front(adoptedOutputter);
} else {
m_outputters.push_front(outputter);
m_outputters.push_front(adoptedOutputter);
}
outputter->open(kAppName);
// Issue 41
// don't show log unless user requests it, as some users find this
// feature irritating (i.e. when they lose network connectivity).
// in windows the log window can be displayed by selecting "show log"
// from the deskflow system tray icon.
// if this causes problems for other architectures, then a different
// work around should be attempted.
// outputter->show(false);
adoptedOutputter->open(kAppName);
}
void Log::remove(ILogOutputter *outputter)

View File

@ -42,10 +42,12 @@ public:
//! @name manipulators
//@{
//! Add an outputter to the head of the list
//! Add an outputter to the head of the list and adopts it.
/*!
Inserts an outputter to the head of the outputter list. When the
logger writes a message, it goes to the outputter at the head of
Inserts an outputter to the head of the outputter list. The outputter
is deleted when Log destructor is called.
When the logger writes a message, it goes to the outputter at the head of
the outputter list. If that outputter's \c write() method returns
true then it also goes to the next outputter, as so on until an
outputter returns false or there are no more outputters. Outputters
@ -57,7 +59,7 @@ public:
By default, the logger has one outputter installed which writes to
the console.
*/
void insert(ILogOutputter *adopted, bool alwaysAtHead = false);
void insert(ILogOutputter *adoptedOutputter, bool alwaysAtHead = false);
//! Remove an outputter from the list
/*!

View File

@ -178,6 +178,17 @@ std::string toHex(const std::string &subject, int width, const char fill)
return ss.str();
}
std::string toHex(const std::vector<uint8_t> &input, int width, const char fill)
{
std::stringstream ss;
ss << std::hex;
for (unsigned int i = 0; i < input.size(); i++) {
ss << std::setw(width) << std::setfill(fill) << static_cast<int>(input[i]);
}
return ss.str();
}
// clang-format off
int fromHexChar(char c)
{

View File

@ -65,6 +65,15 @@ Return a new hexString
*/
std::string toHex(const std::string &subject, int width, const char fill = '0');
/**
* @brief toHex Convert each value in input into a hex string
* @param input vector of uint8_t
* @param width
* @param fill fill character 0 is default
* @return a hex string
*/
std::string toHex(const std::vector<uint8_t> &input, int width, const char fill = '0');
/**
* @brief fromHexChar Convert a single char to its hexidecmal value
* @param c input char 0-F

53
src/lib/base/finally.h Normal file
View File

@ -0,0 +1,53 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2025 Deskflow Developers
* SPDX-FileCopyrightText: (C) 2021 Barrier Contributors
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#pragma once
#include <utility>
namespace deskflow {
/**
* @brief The `FinalAction` class implements a common pattern for calling an action at the end of a function.
*/
template <class Callable> class FinalAction
{
public:
FinalAction() noexcept
{
}
FinalAction(Callable callable) noexcept : m_callable{callable}
{
}
~FinalAction() noexcept
{
if (!m_invoked) {
m_callable();
}
}
FinalAction(FinalAction &&other) noexcept : m_callable{std::move(other.m_callable)}
{
std::swap(m_invoked, other.m_invoked);
}
FinalAction(const FinalAction &) = delete;
FinalAction &operator=(const FinalAction &) = delete;
private:
bool m_invoked = false;
Callable m_callable;
};
template <class Callable> inline FinalAction<Callable> finally(Callable &&callable) noexcept
{
return FinalAction<Callable>(std::forward<Callable>(callable));
}
} // namespace deskflow

View File

@ -1,5 +1,6 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2025 Deskflow Developers
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
@ -132,10 +133,10 @@ SystemLogger::SystemLogger(const char *title, bool blockConsole) : m_stop(NULL)
{
// redirect log messages
if (blockConsole) {
m_stop = new StopLogOutputter;
m_stop = new StopLogOutputter; // NOSONAR - Adopted by `Log`
CLOG->insert(m_stop);
}
m_syslog = new SystemLogOutputter;
m_syslog = new SystemLogOutputter; // NOSONAR - Adopted by `Log`
m_syslog->open(title);
CLOG->insert(m_syslog);
}
@ -150,55 +151,6 @@ SystemLogger::~SystemLogger()
}
}
//
// BufferedLogOutputter
//
BufferedLogOutputter::BufferedLogOutputter(uint32_t maxBufferSize) : m_maxBufferSize(maxBufferSize)
{
// do nothing
}
BufferedLogOutputter::~BufferedLogOutputter()
{
// do nothing
}
BufferedLogOutputter::const_iterator BufferedLogOutputter::begin() const
{
return m_buffer.begin();
}
BufferedLogOutputter::const_iterator BufferedLogOutputter::end() const
{
return m_buffer.end();
}
void BufferedLogOutputter::open(const char *)
{
// do nothing
}
void BufferedLogOutputter::close()
{
// remove all elements from the buffer
m_buffer.clear();
}
void BufferedLogOutputter::show(bool)
{
// do nothing
}
bool BufferedLogOutputter::write(ELevel, const char *message)
{
while (m_buffer.size() >= m_maxBufferSize) {
m_buffer.pop_front();
}
m_buffer.push_back(std::string(message));
return true;
}
//
// FileLogOutputter
//

Some files were not shown because too many files have changed in this diff Show More