Compare commits
294 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0096283779 | |||
| 0751639f93 | |||
| d719df1642 | |||
| 7abaca76af | |||
| 5ee3fc41bd | |||
| cab1eb9cee | |||
| 51db919d8f | |||
| 314899ac7d | |||
| 632c3462ec | |||
| d6f8cdf51d | |||
| 59173d6405 | |||
| d597d023b1 | |||
| 807e60ded2 | |||
| 0b4a2e0e5b | |||
| 9eabbb690c | |||
| 3eb3969a01 | |||
| d2ac36f3ed | |||
| e6a374369b | |||
| 9c56fa5dda | |||
| 6875969255 | |||
| aa1eaf601c | |||
| f77213af04 | |||
| a4f1a382d3 | |||
| 647201cd37 | |||
| e24b1c4b68 | |||
| 475b895755 | |||
| 593e53370a | |||
| be6a4f6b4d | |||
| 929131d10b | |||
| 767919b342 | |||
| 4224215991 | |||
| 45090d6b85 | |||
| 476f3ba243 | |||
| a33574e1bd | |||
| 456afaa13e | |||
| 17f12d8334 | |||
| 723671c2e5 | |||
| 5a90b51e97 | |||
| fe12972e83 | |||
| 9bdb4252e5 | |||
| c73729e72e | |||
| 04805d9a7e | |||
| 293c5e394c | |||
| 3cf0fb89ef | |||
| 52b0c1f061 | |||
| c224cd4661 | |||
| 635962618f | |||
| 0ff72441e6 | |||
| bdffda9a2f | |||
| cac63937ff | |||
| 12fbc2fd57 | |||
| 06324a941a | |||
| 8dd9e17e72 | |||
| a5e5bbc2e4 | |||
| 34f6186941 | |||
| 486b5a491f | |||
| 037fee0e59 | |||
| a9e0c62c24 | |||
| 43a51434ce | |||
| eaa4c71d6e | |||
| 393a006773 | |||
| 332e6c4a4d | |||
| 63e87c16d1 | |||
| 14cb921d4c | |||
| de583145d0 | |||
| 0309d35aef | |||
| c4704649ea | |||
| e4e332c13f | |||
| 33edb6ce01 | |||
| 49173b11b9 | |||
| 81392fe758 | |||
| 3ae2b3a571 | |||
| 2aee6d8812 | |||
| db3b18b36d | |||
| 89c199b630 | |||
| d023c8ef77 | |||
| af383decca | |||
| 8526facbe9 | |||
| 2b3ecd39c6 | |||
| 49589ae4aa | |||
| 8ce6a07d18 | |||
| a8eb772b68 | |||
| 0916009601 | |||
| f5cb636b31 | |||
| 7ced794317 | |||
| 7c279ec72d | |||
| 83a8d1c4ac | |||
| 84a9367124 | |||
| aaeef7905a | |||
| a0d0936433 | |||
| 8f53b88bb6 | |||
| d8b4fab9a3 | |||
| 9d867f6146 | |||
| 632be4b240 | |||
| b8c6d1b58f | |||
| 139dbf61f3 | |||
| e512125595 | |||
| ae37543a37 | |||
| 8a80c52208 | |||
| 38dc845c72 | |||
| b56a282a9c | |||
| d742901775 | |||
| 287d70a138 | |||
| 6c0843d088 | |||
| cbcaafe764 | |||
| 29a86cfbac | |||
| d7506697c8 | |||
| 6c2457d60b | |||
| 30d9034a0f | |||
| a2acfb0678 | |||
| 7fa326234e | |||
| baaa02cda2 | |||
| 231e5c0bc5 | |||
| 78cbe4b775 | |||
| a1a7c8f3ff | |||
| 501726d471 | |||
| b51dec01ad | |||
| 1c907991af | |||
| 0c3c913989 | |||
| 4479b90d37 | |||
| 8a139f0e3d | |||
| 810322623b | |||
| 245f9db5c8 | |||
| 807f32975a | |||
| 5365e34f08 | |||
| 55a7fa3266 | |||
| 118f867fd1 | |||
| 13dc055405 | |||
| 99dae58fd3 | |||
| e9ccd513f7 | |||
| 903401796e | |||
| 97863bda7c | |||
| 0c94adf03c | |||
| d643e4b189 | |||
| c8734755c5 | |||
| edea3b0df1 | |||
| f4264d71a1 | |||
| 6ffd0eb471 | |||
| 7619928d56 | |||
| d70c7fe720 | |||
| b26ca77ff1 | |||
| 68db2c3484 | |||
| 81c19c6ee8 | |||
| 1276a4a29c | |||
| d97f4d87ad | |||
| d5cbd002a9 | |||
| 31a6fd23e7 | |||
| f6c6d4e3a7 | |||
| 5801b92636 | |||
| b427ac91c2 | |||
| e87c596fbe | |||
| 35b4749627 | |||
| 6b2a28600a | |||
| 600378b72d | |||
| 8e24689f72 | |||
| 07f9c4ba47 | |||
| 9d476e143e | |||
| 6bcdd4ebe7 | |||
| 9085468d1c | |||
| 7bace4d36d | |||
| ca0d095283 | |||
| ace5b54912 | |||
| c99767c8b7 | |||
| 297b781578 | |||
| 8c4dc001bf | |||
| 9ca13a65d1 | |||
| 73566c061d | |||
| ed3118b81a | |||
| cc209b9b1f | |||
| ee22c31f32 | |||
| f376b049e4 | |||
| 57e3ff1fab | |||
| c39f69b64d | |||
| 218a506970 | |||
| 57cb7227a4 | |||
| 6aabb1e858 | |||
| 9aec1ad479 | |||
| c8d4a2186a | |||
| f68744a36d | |||
| 183d660186 | |||
| e20ef3ae55 | |||
| 0bfb95996a | |||
| 7d27031723 | |||
| ada495c681 | |||
| e91b9867e0 | |||
| d483dc38bd | |||
| 56dd5492b4 | |||
| 67c7ba6dae | |||
| 1138e3b1fb | |||
| 6523911e4d | |||
| a52552b821 | |||
| bd2188beb1 | |||
| edc0c0d7a0 | |||
| 95586c88fd | |||
| d7174a3a2f | |||
| 2289ed5845 | |||
| 2192636d2b | |||
| 6194868e89 | |||
| 00f53c1aac | |||
| 59df2db7b7 | |||
| 35f0e9e6e4 | |||
| 3b3d9e14fd | |||
| b3f179a08a | |||
| f3fca87e19 | |||
| a3093fa046 | |||
| c00ebbd6c1 | |||
| 09457793b4 | |||
| d436aa3001 | |||
| ec4851d326 | |||
| f338e5e7a8 | |||
| 55b48a5db7 | |||
| 352a871729 | |||
| b103f28202 | |||
| 39b49acb56 | |||
| 5d4fbc8ea6 | |||
| 3dfa3d5069 | |||
| 6d9c66b03f | |||
| 02b2b82c7f | |||
| aac086ad2a | |||
| 0d3f7248ed | |||
| da6e110b69 | |||
| a298cc84ad | |||
| d8348152ec | |||
| 572953d5ba | |||
| a23856ee09 | |||
| 637adc60b2 | |||
| 0ca847334e | |||
| d06d6a5003 | |||
| 6d856b674b | |||
| bcfc121c37 | |||
| b2ec2f1a34 | |||
| df9d5ded1c | |||
| f11dae97d4 | |||
| 3fdc5288eb | |||
| 955f9652fb | |||
| 9dedf25ecc | |||
| ee3dffc4f8 | |||
| 8123166e66 | |||
| 29626d6694 | |||
| 996af86b9b | |||
| 84fbe48d35 | |||
| 11423ef5a1 | |||
| 7cc108d87c | |||
| af70ff98b7 | |||
| b6f7497c44 | |||
| f6602baa36 | |||
| 72091c6ac4 | |||
| fb5f80857b | |||
| 6c7bdf3e07 | |||
| 1df01d3cf1 | |||
| 2bebdbaf4d | |||
| 63d65bb47b | |||
| 60dc4c0cd8 | |||
| 78d1c5222f | |||
| 6e3426855d | |||
| f49f5f790c | |||
| 4eaf6fda62 | |||
| ebc6186fe7 | |||
| 48f824ca31 | |||
| d6ace78a58 | |||
| 41fda741b3 | |||
| 793ea5f81c | |||
| 285abc7bb7 | |||
| d6c9897748 | |||
| ed4ecc2d81 | |||
| 794017402d | |||
| 4034302bfb | |||
| eab87e3869 | |||
| 294348b42b | |||
| 71b6f07220 | |||
| 9addada64c | |||
| b6196f147a | |||
| 2c4a68ebcf | |||
| d8f480b981 | |||
| 80afb92af1 | |||
| f5f3bc0475 | |||
| 17c7b0f8bf | |||
| fcaadc2cd4 | |||
| e3642f0955 | |||
| 07d837a39b | |||
| 1202145bb8 | |||
| abc963f886 | |||
| 4988196c47 | |||
| 8a2b6bd688 | |||
| 901dacf593 | |||
| c62b4ec068 | |||
| c8408c4823 | |||
| 8657532ca2 | |||
| 64b277a5df | |||
| cd7d53d2bd | |||
| d740574bd4 | |||
| 84ae597d69 | |||
| 16ef088c27 | |||
| 7e4b6b82f4 |
21
.github/actions/install-dependencies/action.yml
vendored
21
.github/actions/install-dependencies/action.yml
vendored
@ -27,11 +27,10 @@ runs:
|
||||
|
||||
steps:
|
||||
- name: Install Depends
|
||||
if: ${{ runner.os != 'Windows' }}
|
||||
run: |
|
||||
if [ "$RUNNER_OS" == "Windows" ]; then
|
||||
echo "Window not supported yet"
|
||||
elif [ "$RUNNER_OS" == "macOS" ]; then
|
||||
brew install cmake googletest ninja openssl --quiet
|
||||
if [ "$RUNNER_OS" == "macOS" ]; then
|
||||
brew install googletest openssl --quiet
|
||||
elif [ "$RUNNER_OS" == "Linux" ]; then
|
||||
if [ ${{inputs.like}} == "debian" ]; then
|
||||
apt update -qqq > /dev/null
|
||||
@ -58,7 +57,7 @@ runs:
|
||||
elif [ ${{ inputs.like }} == "arch" ]; then
|
||||
pacman -Syu --noconfirm base-devel cmake ninja \
|
||||
gcc openssl glib2 libxtst libxkbfile gtest libei libportal \
|
||||
qt6-base qt6-tools gtk3 tomlplusplus cli11 help2man
|
||||
qt6-base qt6-tools qt6-svg gtk3 tomlplusplus cli11 help2man
|
||||
else
|
||||
echo "Unknown like"
|
||||
fi
|
||||
@ -70,29 +69,23 @@ runs:
|
||||
- name: Install Qt
|
||||
if: ${{runner.os != 'Linux' }}
|
||||
uses: jurplel/install-qt-action@v4
|
||||
env:
|
||||
AQT_CONFIG: ${{ github.workspace }}/.github/actions/install-dependencies/aqt.ini
|
||||
with:
|
||||
dir: ${{inputs.qt-install-dir}}
|
||||
version: ${{inputs.qt-version}}
|
||||
cache: true
|
||||
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
|
||||
# downloads directly from the `ninja-build` GitHub project releases.
|
||||
- name: Install Ninja
|
||||
if: ${{ runner.os == 'Windows' }}
|
||||
uses: seanmiddleditch/gha-setup-ninja@master
|
||||
|
||||
- name: Build and cache vcpkg
|
||||
if: ${{ runner.os == 'Windows' }}
|
||||
id: vcpkg
|
||||
uses: johnwason/vcpkg-action@v6
|
||||
uses: sithlord48/vcpkg-action@v7
|
||||
with:
|
||||
pkgs: gtest openssl
|
||||
extra-args: --classic
|
||||
triplet: x64-windows-release
|
||||
token: ${{ github.token }}
|
||||
github-binarycache: true
|
||||
|
||||
- name: Install Wix
|
||||
if: ${{ runner.os == 'Windows' }}
|
||||
|
||||
14
.github/actions/install-dependencies/aqt.ini
vendored
Normal file
14
.github/actions/install-dependencies/aqt.ini
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
[aqt]
|
||||
# Using this mirror instead of download.qt.io because of timeouts in CI
|
||||
baseurl: https://qt.mirror.constant.com
|
||||
|
||||
[requests]
|
||||
hash_algorithm: sha1
|
||||
|
||||
[mirrors]
|
||||
trusted_mirrors:
|
||||
https://qt.mirror.constant.com
|
||||
fallbacks:
|
||||
https://qt.mirror.constant.com
|
||||
https://mirrors.ocf.berkeley.edu
|
||||
https://download.qt.io
|
||||
20
.github/actions/run-tests/action.yml
vendored
20
.github/actions/run-tests/action.yml
vendored
@ -15,12 +15,12 @@ runs:
|
||||
using: "composite"
|
||||
|
||||
steps:
|
||||
- name: Unit tests
|
||||
- name: Unit Tests
|
||||
id: unittests
|
||||
env:
|
||||
QT_QPA_PLATFORM: offscreen
|
||||
run: |
|
||||
./${{ inputs.bin-dir }}/unittests
|
||||
ctest --test-dir "build/src/unittests" --output-on-failure
|
||||
result=$?
|
||||
|
||||
if [ $result -ne 0 ]; then
|
||||
@ -29,16 +29,16 @@ runs:
|
||||
shell: bash
|
||||
continue-on-error: true
|
||||
|
||||
- name: Integration tests
|
||||
id: integtests
|
||||
- name: Legacy Tests
|
||||
id: legacytests
|
||||
env:
|
||||
QT_QPA_PLATFORM: offscreen
|
||||
run: |
|
||||
./${{ inputs.bin-dir }}/integtests
|
||||
./${{ inputs.bin-dir }}/legacytests
|
||||
result=$?
|
||||
|
||||
if [ $result -ne 0 ]; then
|
||||
echo "Integration tests failed with code: $result" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Legacy tests failed with code: $result" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
shell: bash
|
||||
continue-on-error: true
|
||||
@ -49,11 +49,11 @@ runs:
|
||||
pass="✅ Pass"
|
||||
fail="❌ Fail"
|
||||
unittests_outcome="${{ steps.unittests.outcome }}"
|
||||
integtests_outcome="${{ steps.integtests.outcome }}"
|
||||
legacytests_outcome="${{ steps.legacytests.outcome }}"
|
||||
unittests=$( [ "$unittests_outcome" = "success" ] && echo $pass || echo $fail )
|
||||
integtests=$( [ "$integtests_outcome" = "success" ] && echo $pass || echo $fail )
|
||||
legacytests=$( [ "$legacytests_outcome" = "success" ] && echo $pass || echo $fail )
|
||||
echo "unittests=$unittests" >> $GITHUB_OUTPUT
|
||||
echo "integtests=$integtests" >> $GITHUB_OUTPUT
|
||||
echo "legacytests=$legacytests" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- name: Summary row
|
||||
@ -64,7 +64,7 @@ runs:
|
||||
row=""
|
||||
row+="| ${{ inputs.job }} "
|
||||
row+="| ${{ steps.results.outputs.unittests }} "
|
||||
row+="| ${{ steps.results.outputs.integtests }} |"
|
||||
row+="| ${{ steps.results.outputs.legacytests }} "
|
||||
echo "$row" > $file
|
||||
|
||||
echo "file=$file" > $GITHUB_OUTPUT
|
||||
|
||||
26
.github/workflows/continuous-integration.yml
vendored
26
.github/workflows/continuous-integration.yml
vendored
@ -28,7 +28,7 @@ env:
|
||||
GIT_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
PACKAGE_PREFIX: "deskflow"
|
||||
PACKAGE_PATH: ./dist
|
||||
CMAKE_CONFIGURE: "cmake -Bbuild -DCMAKE_BUILD_TYPE=Release -DCMAKE_COMPILE_WARNING_AS_ERROR=ON"
|
||||
CMAKE_CONFIGURE: "cmake -Bbuild -DCMAKE_BUILD_TYPE=Release -DSKIP_BUILD_TESTS=ON -DCMAKE_COMPILE_WARNING_AS_ERROR=ON"
|
||||
|
||||
jobs:
|
||||
# Always run this job, even if not on PR, since other jobs need it.
|
||||
@ -138,14 +138,13 @@ jobs:
|
||||
- name: "macos-14-arm64"
|
||||
runs-on: "macos-14"
|
||||
timeout: 10
|
||||
arch: arm64
|
||||
config-args: "-DCMAKE_OSX_ARCHITECTURES=\"arm64\""
|
||||
config-args: "-DCMAKE_OSX_ARCHITECTURES=\"arm64\" -DCMAKE_OSX_SYSROOT=/Applications/Xcode_15.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"
|
||||
qt-install-dir: "/Users/runner"
|
||||
|
||||
- name: "macos-13-x64"
|
||||
runs-on: macos-13
|
||||
timeout: 20
|
||||
config-args: "-DCMAKE_OSX_ARCHITECTURES=\"x86_64\""
|
||||
config-args: "-DCMAKE_OSX_ARCHITECTURES=\"x86_64\" -DCMAKE_OSX_SYSROOT=/Applications/Xcode_15.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"
|
||||
qt-install-dir: "/Users/runner"
|
||||
|
||||
- name: "debian-13-x86_64"
|
||||
@ -162,6 +161,20 @@ jobs:
|
||||
timeout: 20
|
||||
config-args: "-G Ninja -DCMAKE_INSTALL_PREFIX=/usr"
|
||||
|
||||
- name: "fedora-42-x86_64"
|
||||
runs-on: ubuntu-latest
|
||||
container: fedora:42
|
||||
like: "fedora"
|
||||
timeout: 20
|
||||
config-args: "-G Ninja -DCMAKE_INSTALL_PREFIX=/usr"
|
||||
|
||||
- name: "fedora-42-arm64"
|
||||
runs-on: ubuntu-24.04-arm
|
||||
container: fedora:42
|
||||
like: "fedora"
|
||||
timeout: 20
|
||||
config-args: "-G Ninja -DCMAKE_INSTALL_PREFIX=/usr"
|
||||
|
||||
- name: "fedora-41-x86_64"
|
||||
runs-on: ubuntu-latest
|
||||
container: fedora:41
|
||||
@ -329,8 +342,7 @@ jobs:
|
||||
cmake --build build -j16
|
||||
# Integration tests are flakey by nature, make them optional.
|
||||
export QT_QPA_PLATFORM=offscreen
|
||||
./build/bin/unittests
|
||||
./build/bin/integtests || true
|
||||
./build/bin/unittests || true
|
||||
flatpak:
|
||||
needs: lint-check
|
||||
name: flatpak-${{matrix.flatpak.arch}}
|
||||
@ -363,7 +375,7 @@ jobs:
|
||||
run: flatpak-builder-lint manifest deploy/linux/flatpak/org.deskflow.deskflow.yml
|
||||
|
||||
- name: Build
|
||||
uses: flathub-infra/flatpak-github-actions/flatpak-builder@53987ffa5f687586936d85fdce3f440848bea04d
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@v6
|
||||
with:
|
||||
bundle: deskflow-${{env.DESKFLOW_PACKAGE_VERSION}}-linux-${{matrix.flatpak.arch}}.flatpak
|
||||
manifest-path: deploy/linux/flatpak/org.deskflow.deskflow.yml
|
||||
|
||||
19
.github/workflows/sonarcloud-analysis.yml
vendored
19
.github/workflows/sonarcloud-analysis.yml
vendored
@ -44,28 +44,27 @@ jobs:
|
||||
-G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE="Debug" \
|
||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||
-DSKIP_BUILD_TESTS=ON \
|
||||
-DENABLE_COVERAGE=ON
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
build-wrapper-linux-x86-64 --out-dir bw-output cmake --build build -j${CPU_CORE_COUNT}
|
||||
|
||||
- name: Unit tests coverage
|
||||
- name: Test coverage
|
||||
shell: bash
|
||||
env:
|
||||
QT_QPA_PLATFORM: offscreen
|
||||
run: cmake --build build --target coverage-unittests
|
||||
|
||||
- name: Integration tests coverage
|
||||
env:
|
||||
QT_QPA_PLATFORM: offscreen
|
||||
run: cmake --build build --target coverage-integtests
|
||||
run: |
|
||||
tests=(`cmake --build build --target help | grep -o "^coverage-[^:]*"`)
|
||||
for i in "${tests[@]}"; do
|
||||
cmake --build build --target "$i"
|
||||
done
|
||||
|
||||
- name: Get coverage report paths
|
||||
id: coverage-paths
|
||||
run: |
|
||||
unittests=$(find build -name coverage-unittests.xml)
|
||||
integtests=$(find build -name coverage-integtests.xml)
|
||||
paths="${unittests}${integtests:+,$integtests}"
|
||||
paths=$(ls -w 0 -m build/coverage-*.xml | sed 's/ //g')
|
||||
if [ -z "$paths" ]; then
|
||||
echo "Error: No coverage files found"
|
||||
exit 1
|
||||
|
||||
19
.github/workflows/valgrind-analysis.yml
vendored
19
.github/workflows/valgrind-analysis.yml
vendored
@ -31,16 +31,10 @@ jobs:
|
||||
run: cmake --build build -j8
|
||||
|
||||
- name: Valgrind unit tests
|
||||
id: unittests
|
||||
id: legacytests
|
||||
uses: ./.github/actions/run-valgrind
|
||||
with:
|
||||
executable: ./build/bin/unittests
|
||||
|
||||
- name: Valgrind integration tests
|
||||
id: integtests
|
||||
uses: ./.github/actions/run-valgrind
|
||||
with:
|
||||
executable: ./build/bin/integtests
|
||||
executable: ./build/bin/legacytests
|
||||
|
||||
- name: Set job summary
|
||||
run: |
|
||||
@ -48,14 +42,9 @@ jobs:
|
||||
message=$(cat <<EOF
|
||||
## Valgrind summary
|
||||
|
||||
### Unit tests
|
||||
### legacytests Unit tests
|
||||
$backticks
|
||||
${{ steps.unittests.outputs.summary }}
|
||||
$backticks
|
||||
|
||||
### Integration tests
|
||||
$backticks
|
||||
${{ steps.integtests.outputs.summary }}
|
||||
${{ steps.legacytests.outputs.summary }}
|
||||
$backticks
|
||||
EOF
|
||||
)
|
||||
|
||||
@ -18,8 +18,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# Fallback for when git can not be found
|
||||
set(DESKFLOW_VERSION_MAJOR 1)
|
||||
set(DESKFLOW_VERSION_MINOR 21)
|
||||
set(DESKFLOW_VERSION_PATCH 2)
|
||||
set(DESKFLOW_VERSION_MINOR 22)
|
||||
set(DESKFLOW_VERSION_PATCH 0)
|
||||
set(DESKFLOW_VERSION_TWEAK 0)
|
||||
|
||||
# Get the version from git if it's a git repository
|
||||
@ -95,6 +95,22 @@ set(REQUIRED_LIBEI_VERSION 1.3)
|
||||
set(REQUIRED_LIBPORTAL_VERSION 0.8)
|
||||
set(REQUIRED_QT_VERSION 6.7.0)
|
||||
|
||||
if (WIN32)
|
||||
# VSCMD_ARG_TGT_ARCH is set on CI
|
||||
if ("$ENV{VSCMD_ARG_TGT_ARCH}" STREQUAL "")
|
||||
# NOT on CI
|
||||
if (CMAKE_SYSTEM_PROCESSOR MATCHES "[Aa][Rr][Mm]64")
|
||||
set(BUILD_ARCHITECTURE arm64)
|
||||
else()
|
||||
set(BUILD_ARCHITECTURE x64)
|
||||
endif()
|
||||
else()
|
||||
set (BUILD_ARCHITECTURE $ENV{VSCMD_ARG_TGT_ARCH})
|
||||
endif()
|
||||
else()
|
||||
set (BUILD_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR})
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
# On Windows, require that the same MSVC runtime is used as on the host.
|
||||
# Mitigates things like access violations caused by accidental ABI-compatibility breakage.
|
||||
@ -102,7 +118,7 @@ if (MSVC)
|
||||
cmake_host_system_information(
|
||||
RESULT REQUIRED_MSVC_RUNTIME_MINOR
|
||||
QUERY WINDOWS_REGISTRY
|
||||
"HKLM/SOFTWARE/Microsoft/VisualStudio/${REQUIRED_MSVC_RUNTIME_MAJOR}.0/VC/Runtimes/x64"
|
||||
"HKLM/SOFTWARE/Microsoft/VisualStudio/${REQUIRED_MSVC_RUNTIME_MAJOR}.0/VC/Runtimes/${BUILD_ARCHITECTURE}"
|
||||
VALUE "Minor")
|
||||
if (REQUIRED_MSVC_RUNTIME_MINOR)
|
||||
message(STATUS "MSVC runtime: ${REQUIRED_MSVC_RUNTIME_MAJOR}.${REQUIRED_MSVC_RUNTIME_MINOR}")
|
||||
|
||||
13
CONTRIBUTING.md
Normal file
13
CONTRIBUTING.md
Normal file
@ -0,0 +1,13 @@
|
||||
# Contributing to Deskflow
|
||||
|
||||
Thanks for your interest in contributing to Deskflow! We welcome all kinds of contributions — bug reports, feature suggestions, documentation improvements, and code.
|
||||
|
||||
## Read the Full Guidelines
|
||||
|
||||
To keep this repository clean and contribution-friendly, we've outlined our full contributing guidelines on the Deskflow Wiki:
|
||||
|
||||
👉 [How to Contribute to Deskflow](https://github.com/deskflow/deskflow/wiki/Contributing)
|
||||
|
||||
Please take a moment to read through the page before opening an issue or submitting a pull request.
|
||||
|
||||
Thanks again for helping make Deskflow better!
|
||||
89
README.md
89
README.md
@ -1,28 +1,22 @@
|
||||

|
||||
|
||||
> [!TIP]
|
||||
> [Synergy](https://symless.com/synergy) sponsors the Deskflow project by contributing code and providing financial support.
|
||||
>
|
||||
> - [**Bounties**](https://github.com/deskflow/deskflow/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22%F0%9F%92%8E%20bounty%22) - Earn while contributing to open source
|
||||
> - [**Rewarded**](https://github.com/deskflow/deskflow/issues?q=label%3A%22%F0%9F%92%B0%20rewarded%22%20) - Issues with a rewarded bounty
|
||||
>
|
||||
> **Deskflow** is the official upstream project for Synergy.
|
||||
> Purchasing a Synergy license is one way to support Deskflow’s growth and sustainability.
|
||||
> Learn more: [Relationship with Synergy](https://github.com/deskflow/deskflow/wiki/Relationship-with-Synergy)
|
||||
|
||||
**Deskflow** is a free and open source keyboard and mouse sharing app.
|
||||
Use the keyboard, mouse, or trackpad of one computer to control nearby computers,
|
||||
and work seamlessly between them.
|
||||
It's like a software KVM (but without the video).
|
||||
TLS encryption is enabled by default. Wayland is supported. Clipboard sharing is supported.
|
||||
|
||||
[](https://github.com/deskflow/deskflow/releases/latest) [](https://github.com/deskflow/deskflow/releases/continuous) [](https://flathub.org/apps/org.deskflow.deskflow)
|
||||
## Download
|
||||
|
||||
To use Deskflow you can use one of our [packages](https://github.com/deskflow/deskflow/releases), install `deskflow` (if available in your package repository), or [build it](#build-quick-start) yourself from source.
|
||||
[](https://github.com/deskflow/deskflow/releases/latest) [](https://github.com/deskflow/deskflow/releases/continuous) [](https://flathub.org/apps/org.deskflow.deskflow)
|
||||
|
||||
> [!TIP]
|
||||
> For macOS users, the easiest way to install and stay up to date is to use [Homebrew](https://brew.sh) with our [homebrew-tap](https://github.com/deskflow/homebrew-tap).
|
||||
|
||||
To use Deskflow, download one of our [packages](https://github.com/deskflow/deskflow/releases), install `deskflow` (from your package repository), or [build it](https://github.com/deskflow/deskflow/wiki/Building) from source.
|
||||
|
||||
## Stats
|
||||
|
||||
[](https://github.com/deskflow/deskflow/commits/master/)
|
||||
[](https://github.com/deskflow/deskflow/commits/master/)
|
||||
[](LICENSE)
|
||||
@ -36,27 +30,16 @@ To use Deskflow you can use one of our [packages](https://github.com/deskflow/de
|
||||
[](https://github.com/deskflow/deskflow/actions/workflows/continuous-integration.yml)
|
||||
[](https://github.com/deskflow/deskflow/actions/workflows/codeql-analysis.yml)
|
||||
[](https://github.com/deskflow/deskflow/actions/workflows/sonarcloud-analysis.yml)
|
||||
## Project Values
|
||||
|
||||
- Motivated by the community interests (not business-driven)
|
||||
- Privacy by default (e.g. update check is off by default)
|
||||
- Leading edge releases (we don't focus on supporting older systems)
|
||||
- Decisions are discussed and documented publicly with majority rule
|
||||
- Have fun; we don't need to worry about impressing anyone
|
||||
## Contribute
|
||||
|
||||
## Ways to get involved
|
||||
[](https://github.com/deskflow/deskflow/labels/good%20first%20issue) [](https://github.com/deskflow/deskflow/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22%F0%9F%92%8E%20bounty%22) [](https://github.com/deskflow/deskflow/issues?q=label%3A%22%F0%9F%92%B0%20rewarded%22%20sort%3Aupdated-desc)
|
||||
|
||||
> [!TIP]
|
||||
> Join us! Real-time discussion on Matrix: [`#deskflow:matrix.org`](https://matrix.to/#/#deskflow:matrix.org)
|
||||
>
|
||||
> Alternatively, we have [other ways](https://github.com/deskflow/deskflow/wiki/Chat-with-us) to communicate.
|
||||
>
|
||||
Here are a few ways to join in with the project and get involved:
|
||||
* Build the latest `master` version (see below) and [report a bug](https://github.com/deskflow/deskflow/issues)
|
||||
* [Submit a PR](https://github.com/deskflow/deskflow/wiki/Contributing) (pull request) with a bug fix or improvement
|
||||
* [Let us know](https://github.com/deskflow/deskflow/issues) if you have an idea for an improvement
|
||||
There are many ways to contribute to the Deskflow project.
|
||||
|
||||
## Build Quick Start
|
||||
We're a friendly, active, and welcoming community focused on building a great app.
|
||||
|
||||
Read our [Contributing](https://github.com/deskflow/deskflow/wiki/Contributing) page to get started.
|
||||
|
||||
For instructions on building Deskflow, use the wiki page: [Building](https://github.com/deskflow/deskflow/wiki/Building)
|
||||
|
||||
@ -65,11 +48,11 @@ For instructions on building Deskflow, use the wiki page: [Building](https://git
|
||||
We support all major operating systems, including Windows, macOS, Linux, and Unix-like BSD-derived.
|
||||
|
||||
> [!NOTE]
|
||||
> On Windows, you will need to install the
|
||||
> On Windows, you will need to install the
|
||||
> [Microsoft Visual C++ Redistributable](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170#latest-microsoft-visual-c-redistributable-version).
|
||||
> Download latest: [`vc_redist.x64.exe`](https://aka.ms/vs/17/release/vc_redist.x64.exe)
|
||||
|
||||
Windows 10 or higher is required.
|
||||
Windows 10 or higher is required.
|
||||
|
||||
macOS 12 or higher is required.
|
||||
|
||||
@ -102,46 +85,39 @@ macOS users who download directly from releases may need to run `xattr -c /Appli
|
||||
It is recommend to install Deskflow using [Homebrew](https://brew.sh) from our [homebrew-tap](https://github.com/deskflow/homebrew-tap)
|
||||
|
||||
To add our tap, run:
|
||||
|
||||
```
|
||||
brew tap deskflow/homebrew-tap
|
||||
```
|
||||
|
||||
Then install either:
|
||||
|
||||
- Stable: `brew install deskflow`
|
||||
- Continuous: `brew install deskflow-dev`
|
||||
|
||||
|
||||
|
||||
## Collaborative Projects
|
||||
## Similar Projects
|
||||
|
||||
In the open source developer community, similar projects collaborate for the improvement of all
|
||||
mouse and keyboard sharing tools. We aim for idea sharing and interoperability.
|
||||
|
||||
* [**Lan Mouse**](https://github.com/feschber/lan-mouse) -
|
||||
- [**Lan Mouse**](https://github.com/feschber/lan-mouse) -
|
||||
Rust implementation with the goal of having native front-ends and interoperability with
|
||||
Deskflow/Synergy.
|
||||
* [**Input Leap**](https://github.com/input-leap/input-leap) -
|
||||
- [**Input Leap**](https://github.com/input-leap/input-leap) -
|
||||
Deskflow/Synergy-derivative with the goal of continuing what Barrier started, after Barrier
|
||||
became a dead fork.
|
||||
* [**Synergy**](https://github.com/deskflow/deskflow/wiki/Relationship-with-Synergy) -
|
||||
Downstream commercial fork and Deskflow sponsor, geared toward adapting to customer
|
||||
needs, offering business and enterprise licensing.
|
||||
- [**Synergy**](https://symless.com/synergy) -
|
||||
Downstream commercial fork. Synergy sponsors Deskflow with financial support and contributes code ([learn more](https://github.com/deskflow/deskflow/wiki/Relationship-with-Synergy)).
|
||||
|
||||
## FAQ
|
||||
|
||||
### What is the relationship with Synergy?
|
||||
|
||||
[](https://github.com/deskflow/deskflow/wiki/Relationship-with-Synergy)
|
||||
|
||||
Synergy sponsors the Deskflow project by contributing code and providing financial support while maintaining its customer-oriented code downstream.
|
||||
|
||||
Learn more: [Relationship with Synergy](https://github.com/deskflow/deskflow/wiki/Relationship-with-Synergy)
|
||||
|
||||
### Is Deskflow compatible with Synergy, Input Leap, or Barrier?
|
||||
|
||||
Yes, Deskflow has network compatibility with all forks:
|
||||
|
||||
- Requires Deskflow >= v1.17.0.96
|
||||
- Deskflow will *just work* with Input Leap and Barrier (server or client).
|
||||
- Connecting a Deskflow client to a Synergy 1 server will also *just work*.
|
||||
- Deskflow will _just work_ with Input Leap and Barrier (server or client).
|
||||
- Connecting a Deskflow client to a Synergy 1 server will also _just work_.
|
||||
- To connect a Synergy 1 client, you need to select the Synergy protocol in the Deskflow server settings.
|
||||
|
||||
_Note:_ Only Synergy 1 is compatible with Deskflow (Synergy 3 is not yet compatible).
|
||||
@ -153,20 +129,20 @@ We would love to see compatibility with Lan Mouse. This may be quite an effort a
|
||||
### If I want to solve issues in Deskflow do I need to contribute to a fork?
|
||||
|
||||
We welcome PRs (pull requests) from the community. If you'd like to make a change, please feel
|
||||
free to [start a discussion](https://github.com/deskflow/deskflow/discussions) or
|
||||
free to [start a discussion](https://github.com/deskflow/deskflow/discussions) or
|
||||
[open a PR](https://github.com/deskflow/deskflow/wiki/Contributing).
|
||||
|
||||
### Is clipboard sharing supported?
|
||||
|
||||
Absolutely. The clipboard-sharing feature is a cornerstone feature of the product and we are
|
||||
Absolutely. The clipboard-sharing feature is a cornerstone feature of the product and we are
|
||||
committed to maintaining and improving that feature.
|
||||
|
||||
### Is Wayland for Linux supported?
|
||||
|
||||
Yes! Wayland (the Linux display server protocol aimed to become the successor of the X Window
|
||||
Yes! Wayland (the Linux display server protocol aimed to become the successor of the X Window
|
||||
System) is an important platform for us.
|
||||
The [`libei`](https://gitlab.freedesktop.org/libinput/libei) and
|
||||
[`libportal`](https://github.com/flatpak/libportal) libraries enable
|
||||
The [`libei`](https://gitlab.freedesktop.org/libinput/libei) and
|
||||
[`libportal`](https://github.com/flatpak/libportal) libraries enable
|
||||
Wayland support for Deskflow. We would like to give special thanks to Peter Hutterer,
|
||||
who is the author of `libei`, a major contributor to `libportal`, and the author of the Wayland
|
||||
implementation in Deskflow. Others such as Olivier Fourdan and Povilas Kanapickas helped with the
|
||||
@ -184,9 +160,12 @@ wiki.
|
||||
|
||||

|
||||
|
||||
|
||||
## Deskflow Contributors
|
||||
|
||||
[](https://symless.com/synergy)
|
||||
|
||||
[Synergy](https://symless.com/synergy) sponsors the Deskflow project by contributing code and providing financial support ([learn more](https://github.com/deskflow/deskflow/wiki/Relationship-with-Synergy)).
|
||||
|
||||
Deskflow is made by possible by these contributors.
|
||||
|
||||
<a href = "https://github.com/deskflow/deskflow/graphs/contributors">
|
||||
|
||||
@ -43,13 +43,7 @@ SPDX-FileCopyrightText = "Deskflow Developers"
|
||||
SPDX-License-Identifier = "MIT"
|
||||
|
||||
[[annotations]]
|
||||
path = "README.md"
|
||||
precedence = "override"
|
||||
SPDX-FileCopyrightText = "Deskflow Developers"
|
||||
SPDX-License-Identifier = "MIT"
|
||||
|
||||
[[annotations]]
|
||||
path = "SECURITY.md"
|
||||
path = "**/*.md"
|
||||
precedence = "override"
|
||||
SPDX-FileCopyrightText = "Deskflow Developers"
|
||||
SPDX-License-Identifier = "MIT"
|
||||
|
||||
@ -46,7 +46,7 @@ macro(configure_libs)
|
||||
message(STATUS "Enabling code coverage")
|
||||
include(cmake/CodeCoverage.cmake)
|
||||
append_coverage_compiler_flags()
|
||||
set(test_exclude subprojects/* build/* src/test/*)
|
||||
set(test_exclude subprojects/* build/* src/unittests/*)
|
||||
set(test_src ${PROJECT_SOURCE_DIR}/src)
|
||||
|
||||
# Apparently solves the bug in gcov where it returns negative counts and confuses gcovr.
|
||||
@ -55,15 +55,8 @@ macro(configure_libs)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-update=atomic")
|
||||
|
||||
setup_target_for_coverage_gcovr_xml(
|
||||
NAME coverage-integtests
|
||||
EXECUTABLE integtests
|
||||
BASE_DIRECTORY ${test_src}
|
||||
EXCLUDE ${test_exclude}
|
||||
)
|
||||
|
||||
setup_target_for_coverage_gcovr_xml(
|
||||
NAME coverage-unittests
|
||||
EXECUTABLE unittests
|
||||
NAME coverage-legacytests
|
||||
EXECUTABLE legacytests
|
||||
BASE_DIRECTORY ${test_src}
|
||||
EXCLUDE ${test_exclude}
|
||||
)
|
||||
|
||||
@ -12,24 +12,30 @@ license=(LicenseRef-GPL-2.0-only-WITH-OpenSSL-Exception)
|
||||
conflicts=('synergy-git' 'synergy-1.6' 'synergy1-bin' 'synergy2-bin' 'synergy3-bin' 'synergy3-beta-bin' 'synergy3-stable-bin' 'barrier' 'barrier-git' 'barrier-headless' 'barrier-headless-git' 'input-leap' 'input-leap-git' 'input-leap-headless-git' 'input-leap-headless' 'waynergy' 'waynergy-git' 'qsynergy' 'slim-synergy' 'quicksynergy' 'deskflow')
|
||||
provides=("deskflow-git${pkgver}")
|
||||
depends=(
|
||||
'gcc-libs'
|
||||
'glibc'
|
||||
'openssl'
|
||||
'libx11'
|
||||
'libxi'
|
||||
'libxkbfile'
|
||||
'libxext'
|
||||
'libxtst'
|
||||
'libxinerama'
|
||||
'libxkbcommon-x11'
|
||||
'hicolor-icon-theme'
|
||||
'qt6-base'
|
||||
'qt6-tools'
|
||||
'libei'
|
||||
'libportal'
|
||||
'tomlplusplus'
|
||||
'cli11'
|
||||
gcc-libs
|
||||
glib2
|
||||
glibc
|
||||
hicolor-icon-theme
|
||||
libei
|
||||
libglvnd
|
||||
libice
|
||||
libportal
|
||||
libsm
|
||||
libx11
|
||||
libxext
|
||||
libxi
|
||||
libxinerama
|
||||
libxkbcommon
|
||||
libxkbcommon-x11
|
||||
libxkbfile
|
||||
libxrandr
|
||||
libxtst
|
||||
openssl
|
||||
qt6-base
|
||||
qt6-svg
|
||||
tomlplusplus
|
||||
)
|
||||
|
||||
options=('!debug')
|
||||
|
||||
package() {
|
||||
|
||||
@ -100,9 +100,9 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
if("${DISTRO_NAME}" STREQUAL "")
|
||||
set(DISTRO_NAME "linux")
|
||||
endif()
|
||||
set(OS_STRING "${DISTRO_NAME}-${CN_STRING}${CMAKE_SYSTEM_PROCESSOR}")
|
||||
set(OS_STRING "${DISTRO_NAME}-${CN_STRING}${BUILD_ARCHITECTURE}")
|
||||
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "|.*BSD")
|
||||
message(STATUS "BSD packaging not yet supported")
|
||||
set(OS_STRING ${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR})
|
||||
set(OS_STRING ${CMAKE_SYSTEM_NAME}-${BUILD_ARCHITECTURE})
|
||||
endif()
|
||||
|
||||
41
deploy/linux/flatpak/libportal-qt69.patch
Normal file
41
deploy/linux/flatpak/libportal-qt69.patch
Normal file
@ -0,0 +1,41 @@
|
||||
From 796053d2eebe4532aad6bd3fd80cdf3b197806ec Mon Sep 17 00:00:00 2001
|
||||
From: Jan Grulich <jgrulich@redhat.com>
|
||||
Date: Thu, 27 Mar 2025 09:38:10 +0100
|
||||
Subject: [PATCH] qt6: fix build against Qt 6.9+
|
||||
|
||||
QGenericUnixServices was renamed to QDesktopUnixServices in Qt 6.9.
|
||||
|
||||
Upstream change: https://codereview.qt-project.org/c/qt/qtbase/+/609639
|
||||
---
|
||||
libportal/portal-qt6.cpp | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/libportal/portal-qt6.cpp b/libportal/portal-qt6.cpp
|
||||
index d38a4e30..34f0d72a 100644
|
||||
--- a/libportal/portal-qt6.cpp
|
||||
+++ b/libportal/portal-qt6.cpp
|
||||
@@ -31,8 +31,12 @@
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
|
||||
#include <qpa/qplatformintegration.h>
|
||||
#include <private/qguiapplication_p.h>
|
||||
+#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
|
||||
+#include <private/qdesktopunixservices_p.h>
|
||||
+#else
|
||||
#include <private/qgenericunixservices_p.h>
|
||||
#endif
|
||||
+#endif
|
||||
|
||||
static gboolean
|
||||
_xdp_parent_export_qt (XdpParent *parent,
|
||||
@@ -45,7 +49,11 @@ _xdp_parent_export_qt (XdpParent *parent,
|
||||
}
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
|
||||
+#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
|
||||
+ if (const auto services = dynamic_cast<QDesktopUnixServices*>(QGuiApplicationPrivate::platformIntegration()->services()))
|
||||
+#else
|
||||
if (const auto services = dynamic_cast<QGenericUnixServices*>(QGuiApplicationPrivate::platformIntegration()->services()))
|
||||
+#endif
|
||||
{
|
||||
g_autofree char *handle = g_strdup(services->portalWindowIdentifier(w).toUtf8().constData());
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
app-id: org.deskflow.deskflow
|
||||
runtime: org.kde.Platform
|
||||
runtime-version: "6.8"
|
||||
runtime-version: "6.9"
|
||||
sdk: org.kde.Sdk
|
||||
command: deskflow
|
||||
finish-args:
|
||||
@ -46,8 +46,8 @@ modules:
|
||||
sources:
|
||||
- type: git
|
||||
url: https://gitlab.freedesktop.org/libinput/libei
|
||||
tag: 1.4.0
|
||||
commit: 5d6d8e6590df210b75559a889baa9459c68d9366
|
||||
tag: 1.4.1
|
||||
commit: 9e0413cbc7d3ae6656266890425f152589ddf74d
|
||||
- name: libportal
|
||||
buildsystem: meson
|
||||
config-opts:
|
||||
@ -61,6 +61,8 @@ modules:
|
||||
url: https://github.com/flatpak/libportal.git
|
||||
tag: 0.9.1
|
||||
commit: 8f5dc8d192f6e31dafe69e35219e3b707bde71ce
|
||||
- type: patch
|
||||
path: libportal-qt69.patch
|
||||
- name: cli11
|
||||
buildsystem: cmake-ninja
|
||||
config-opts:
|
||||
@ -68,8 +70,8 @@ modules:
|
||||
sources:
|
||||
- type: git
|
||||
url: https://github.com/CLIUtils/CLI11
|
||||
tag: v2.4.2
|
||||
commit: 6c7b07a878ad834957b98d0f9ce1dbe0cb204fc9
|
||||
tag: v2.5.0
|
||||
commit: 4160d259d961cd393fd8d67590a8c7d210207348
|
||||
- name: tomlplusplus
|
||||
buildsystem: cmake-ninja
|
||||
sources:
|
||||
|
||||
@ -42,7 +42,31 @@
|
||||
</branding>
|
||||
<content_rating type="oars-1.0" />
|
||||
<releases>
|
||||
<release version="1.21.2" date="2025-04-07" urgency="high">
|
||||
<release version="1.22.0" date="2025-05-28" urgency="high">
|
||||
<description>
|
||||
<p>This stable release fixes a issues found in the previous version. For the full changelog see the release page.</p>
|
||||
<ul>
|
||||
<li>Remove: Broken drag and drop file transfer support</li>
|
||||
<li>Remove: DESKFLOW_RESET_ALL and --no-reset. reset settings is now done by passing the --reset option instead</li>
|
||||
<li>Continue migration to Qt by using more Qt classes in more places</li>
|
||||
<li>Retire SHA1 generation and use SHA256 always to compare</li>
|
||||
<li>Add missing accelerators for gui controls</li>
|
||||
<li>unittests binary is now legacytests</li>
|
||||
<li>integtests have been remove and replaced with Qt based tests run during build</li>
|
||||
<li>Fix: Potential XDG-Portal release issue</li>
|
||||
<li>Fix: Issue where the first start dialog could hang in the background</li>
|
||||
<li>Fix: Edge cases that could cause incorrect settings causing client / server process to crash</li>
|
||||
<li>Fix: Default server config file is Deskflow-server.conf</li>
|
||||
<li>Backport: Event Types from downstream</li>
|
||||
<li>Backport: Cleaner error handling from downstream</li>
|
||||
<li>Improve Windows Daemon</li>
|
||||
<li>Better detection of arm on windows, in build and installer</li>
|
||||
<li>Chore: Clean up sonar scan code smells</li>
|
||||
</ul>
|
||||
</description>
|
||||
<url>https://github.com/deskflow/deskflow/releases/tag/v1.22.0</url>
|
||||
</release>/
|
||||
<release version="1.21.2" date="2025-04-07" urgency="high">
|
||||
<description>
|
||||
<p>This stable release fixes a few critical bugs in 1.21.1. For the full changelog see the release page.</p>
|
||||
<ul>
|
||||
|
||||
@ -11,7 +11,7 @@ install(CODE "execute_process(COMMAND
|
||||
-timestamp -codesign=-
|
||||
)")
|
||||
|
||||
set(OS_STRING "macos-${CMAKE_SYSTEM_PROCESSOR}")
|
||||
set(OS_STRING "macos-${BUILD_ARCHITECTURE}")
|
||||
set(CPACK_PACKAGE_ICON "${MY_DIR}/dmg-volume.icns")
|
||||
set(CPACK_DMG_BACKGROUND_IMAGE "${MY_DIR}/dmg-background.tiff")
|
||||
set(CPACK_DMG_DS_STORE_SETUP_SCRIPT "${MY_DIR}/generate_ds_store.applescript")
|
||||
|
||||
@ -19,14 +19,7 @@ set(CPACK_PRE_BUILD_SCRIPTS ${CMAKE_CURRENT_BINARY_DIR}/pre-cpack.cmake)
|
||||
configure_file(${MY_DIR}/cpack-options.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/cpack-options.cmake @ONLY)
|
||||
set(CPACK_PROJECT_CONFIG_FILE ${CMAKE_CURRENT_BINARY_DIR}/cpack-options.cmake)
|
||||
|
||||
# Setup OS_STRING
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES AMD64)
|
||||
set(OS_STRING "win-x64")
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES ARM64)
|
||||
set(OS_STRING "win-arm64")
|
||||
else()
|
||||
set(OS_STRING "win-${CMAKE_SYSTEM_PROCESSOR}")
|
||||
endif()
|
||||
set(OS_STRING "win-${BUILD_ARCHITECTURE}")
|
||||
|
||||
list(APPEND CPACK_GENERATOR "7Z")
|
||||
|
||||
|
||||
@ -34,7 +34,7 @@ static std::string s_logMessageBuffer; // NOSONAR - Must be mutable.
|
||||
|
||||
extern "C" __declspec(dllexport) UINT __stdcall CheckVCRedist(MSIHANDLE hInstall)
|
||||
{
|
||||
const auto kKeyName = TEXT("SOFTWARE\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes\\x64");
|
||||
const auto kKeyName = TEXT(kRegKey);
|
||||
const auto kValueName = TEXT("Minor");
|
||||
const auto kProperty = "VC_REDIST_VERSION_OK";
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#pragma once
|
||||
|
||||
const auto kAppId = "@CMAKE_PROJECT_NAME@";
|
||||
const auto kRegKey = "SOFTWARE\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes\\@BUILD_ARCHITECTURE@";
|
||||
|
||||
// clang-format off
|
||||
const auto kWindowsRuntimeMajor = @REQUIRED_MSVC_RUNTIME_MAJOR@;
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
<RegistrySearch
|
||||
Id="FindVCRedist"
|
||||
Root="HKLM"
|
||||
Key="SOFTWARE\Microsoft\VisualStudio\@REQUIRED_MSVC_RUNTIME_MAJOR@.0\VC\Runtimes\x64"
|
||||
Key="SOFTWARE\Microsoft\VisualStudio\@REQUIRED_MSVC_RUNTIME_MAJOR@.0\VC\Runtimes\@BUILD_ARCHITECTURE@"
|
||||
Name="Installed"
|
||||
Type="raw" />
|
||||
</Property>
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
sonar.organization=deskflow
|
||||
sonar.projectKey=deskflow_deskflow
|
||||
sonar.sources=src/apps,src/lib
|
||||
sonar.tests=src/test
|
||||
sonar.tests=src/unittests
|
||||
sonar.exclusions=subprojects/**,build/**
|
||||
sonar.coverage.exclusions=subprojects/**,src/test/**,src/apps/deskflow-gui/**,src/apps/res/**
|
||||
sonar.coverage.exclusions=subprojects/**,src/unittests/**,src/apps/deskflow-gui/**,src/apps/res/**
|
||||
sonar.cpd.exclusions=**/*Test*.cpp
|
||||
sonar.host.url=https://sonarcloud.io
|
||||
sonar.cfamily.compile-commands=build/compile_commands.json
|
||||
|
||||
@ -11,5 +11,6 @@ add_subdirectory(apps)
|
||||
|
||||
option(BUILD_TESTS "Build tests" ON)
|
||||
if(BUILD_TESTS)
|
||||
add_subdirectory(test)
|
||||
add_subdirectory(unittests)
|
||||
endif()
|
||||
|
||||
|
||||
@ -14,10 +14,10 @@ function(generate_app_man TARGET)
|
||||
if(HELP2MAN)
|
||||
add_custom_command(
|
||||
TARGET ${target} POST_BUILD
|
||||
COMMAND QT_QPA_PLATFORM=minimal ${HELP2MAN}
|
||||
COMMAND QT_QPA_PLATFORM=minimal PATH=$<TARGET_FILE_DIR:${target}>:${PATH} ${HELP2MAN}
|
||||
--include ${CMAKE_SOURCE_DIR}/src/apps/res/manpage.txt
|
||||
--no-info
|
||||
$<TARGET_FILE:${target}>
|
||||
${target}
|
||||
-o $<TARGET_FILE_DIR:${target}>/${target}.1
|
||||
)
|
||||
install(
|
||||
|
||||
@ -13,15 +13,20 @@
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
#include "arch/win32/ArchMiscWindows.h"
|
||||
#include <QCoreApplication>
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
#if SYSAPI_WIN32
|
||||
// HACK to make sure settings gets the correct qApp path
|
||||
QCoreApplication m(argc, argv);
|
||||
m.deleteLater();
|
||||
|
||||
ArchMiscWindows::guardRuntimeVersion();
|
||||
|
||||
// record window instance for tray icon, etc
|
||||
ArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL));
|
||||
ArchMiscWindows::setInstanceWin32(GetModuleHandle(nullptr));
|
||||
#endif
|
||||
|
||||
Arch arch;
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
#include "arch/win32/ArchMiscWindows.h"
|
||||
#include <QCoreApplication>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
@ -39,7 +40,11 @@ bool isClient(int argc, char **argv)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
#if SYSAPI_WIN32
|
||||
ArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL));
|
||||
// HACK to make sure settings gets the correct qApp path
|
||||
QCoreApplication m(argc, argv);
|
||||
m.deleteLater();
|
||||
|
||||
ArchMiscWindows::setInstanceWin32(GetModuleHandle(nullptr));
|
||||
#endif
|
||||
|
||||
Arch arch;
|
||||
|
||||
@ -53,16 +53,15 @@ int main(int argc, char *argv[])
|
||||
QApplication app(argc, argv);
|
||||
|
||||
// Add Command Line Options
|
||||
QCommandLineOption helpOption = QCommandLineOption("help", "Display Help on the command line");
|
||||
QCommandLineOption versionOption = QCommandLineOption("version", "Display version information");
|
||||
QCommandLineOption noResetOption =
|
||||
QCommandLineOption("no-reset", "Prevent settings reset if DESKFLOW_RESET_ALL is set");
|
||||
auto helpOption = QCommandLineOption("help", "Display Help on the command line");
|
||||
auto versionOption = QCommandLineOption("version", "Display version information");
|
||||
auto resetOption = QCommandLineOption("reset", "Reset all settings");
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
|
||||
parser.addOption(helpOption);
|
||||
parser.addOption(versionOption);
|
||||
parser.addOption(noResetOption);
|
||||
parser.addOption(resetOption);
|
||||
parser.parse(QCoreApplication::arguments());
|
||||
|
||||
const auto header = QStringLiteral("%1: %2\n").arg(kAppName, kDisplayVersion);
|
||||
@ -123,7 +122,7 @@ int main(int argc, char *argv[])
|
||||
"Please drag %1 to the Applications folder, "
|
||||
"and open it from there."
|
||||
);
|
||||
QMessageBox::information(NULL, kAppName, msgBody.arg(kAppName));
|
||||
QMessageBox::information(nullptr, kAppName, msgBody.arg(kAppName));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -133,8 +132,7 @@ int main(int argc, char *argv[])
|
||||
#endif
|
||||
|
||||
// --no-reset
|
||||
const auto resetEnvVar = QVariant(qEnvironmentVariable("DESKFLOW_RESET_ALL")).toBool();
|
||||
if (resetEnvVar && !parser.isSet(noResetOption)) {
|
||||
if (parser.isSet(resetOption)) {
|
||||
diagnostic::clearSettings(false);
|
||||
}
|
||||
|
||||
@ -159,7 +157,7 @@ bool checkMacAssistiveDevices()
|
||||
|
||||
const void *keys[] = {kAXTrustedCheckOptionPrompt};
|
||||
const void *trueValue[] = {kCFBooleanTrue};
|
||||
CFDictionaryRef options = CFDictionaryCreate(NULL, keys, trueValue, 1, NULL, NULL);
|
||||
CFDictionaryRef options = CFDictionaryCreate(nullptr, keys, trueValue, 1, nullptr, nullptr);
|
||||
|
||||
bool result = AXIsProcessTrustedWithOptions(options);
|
||||
CFRelease(options);
|
||||
|
||||
@ -13,15 +13,20 @@
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
#include "arch/win32/ArchMiscWindows.h"
|
||||
#include <QCoreApplication>
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
#if SYSAPI_WIN32
|
||||
// HACK to make sure settings gets the correct qApp path
|
||||
QCoreApplication m(argc, argv);
|
||||
m.deleteLater();
|
||||
|
||||
ArchMiscWindows::guardRuntimeVersion();
|
||||
|
||||
// record window instance for tray icon, etc
|
||||
ArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL));
|
||||
ArchMiscWindows::setInstanceWin32(GetModuleHandle(nullptr));
|
||||
#endif
|
||||
|
||||
Arch arch;
|
||||
@ -30,30 +35,6 @@ 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);
|
||||
}
|
||||
|
||||
@ -15,11 +15,11 @@
|
||||
// Arch
|
||||
//
|
||||
|
||||
Arch *Arch::s_instance = NULL;
|
||||
Arch *Arch::s_instance = nullptr;
|
||||
|
||||
Arch::Arch()
|
||||
{
|
||||
assert(s_instance == NULL);
|
||||
assert(s_instance == nullptr);
|
||||
s_instance = this;
|
||||
}
|
||||
|
||||
@ -28,10 +28,6 @@ Arch::Arch(Arch *arch)
|
||||
s_instance = arch;
|
||||
}
|
||||
|
||||
Arch::~Arch()
|
||||
{
|
||||
}
|
||||
|
||||
void Arch::init()
|
||||
{
|
||||
ARCH_NETWORK::init();
|
||||
@ -42,6 +38,6 @@ void Arch::init()
|
||||
|
||||
Arch *Arch::getInstance()
|
||||
{
|
||||
assert(s_instance != NULL);
|
||||
assert(s_instance != nullptr);
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
@ -24,27 +24,24 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "arch/ArchString.h"
|
||||
#include "common/Common.h"
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
|
||||
#include "arch/win32/ArchConsoleWindows.h"
|
||||
#include "arch/win32/ArchDaemonWindows.h"
|
||||
#include "arch/win32/ArchLogWindows.h"
|
||||
#include "arch/win32/ArchMultithreadWindows.h"
|
||||
#include "arch/win32/ArchNetworkWinsock.h"
|
||||
#include "arch/win32/ArchSleepWindows.h"
|
||||
#include "arch/win32/ArchStringWindows.h"
|
||||
#include "arch/win32/ArchTimeWindows.h"
|
||||
|
||||
#elif SYSAPI_UNIX
|
||||
|
||||
#include "arch/unix/ArchConsoleUnix.h"
|
||||
#include "arch/unix/ArchDaemonUnix.h"
|
||||
#include "arch/unix/ArchLogUnix.h"
|
||||
#include "arch/unix/ArchNetworkBSD.h"
|
||||
#include "arch/unix/ArchSleepUnix.h"
|
||||
#include "arch/unix/ArchStringUnix.h"
|
||||
#include "arch/unix/ArchTimeUnix.h"
|
||||
|
||||
#if HAVE_PTHREAD
|
||||
@ -69,26 +66,25 @@ to each method to those implementations. Clients should use the
|
||||
exactly one of these objects before attempting to call any method,
|
||||
typically at the beginning of \c main().
|
||||
*/
|
||||
class Arch : public ARCH_CONSOLE,
|
||||
public ARCH_DAEMON,
|
||||
class Arch : public ARCH_DAEMON,
|
||||
public ARCH_LOG,
|
||||
public ARCH_MULTITHREAD,
|
||||
public ARCH_NETWORK,
|
||||
public ARCH_SLEEP,
|
||||
public ARCH_STRING,
|
||||
public ArchString,
|
||||
public ARCH_TIME
|
||||
{
|
||||
public:
|
||||
Arch();
|
||||
Arch(Arch *arch);
|
||||
virtual ~Arch();
|
||||
explicit Arch(Arch *arch);
|
||||
~Arch() override = default;
|
||||
|
||||
//! Call init on other arch classes.
|
||||
/*!
|
||||
Some arch classes depend on others to exist first. When init is called
|
||||
these classes will have ARCH available for use.
|
||||
*/
|
||||
virtual void init();
|
||||
void init() override;
|
||||
|
||||
//
|
||||
// accessors
|
||||
@ -114,7 +110,7 @@ private:
|
||||
class ArchMutexLock
|
||||
{
|
||||
public:
|
||||
ArchMutexLock(ArchMutex mutex) : m_mutex(mutex)
|
||||
explicit ArchMutexLock(ArchMutex mutex) : m_mutex(mutex)
|
||||
{
|
||||
ARCH->lockMutex(m_mutex);
|
||||
}
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "arch/ArchConsoleStd.h"
|
||||
#include "base/Log.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
void ArchConsoleStd::writeConsole(ELevel level, const char *str)
|
||||
{
|
||||
if ((level >= kFATAL) && (level <= kWARNING))
|
||||
std::cerr << str << std::endl;
|
||||
else
|
||||
std::cout << str << std::endl;
|
||||
|
||||
std::cout.flush();
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "arch/IArchConsole.h"
|
||||
|
||||
//! Cross platform implementation of IArchConsole
|
||||
class ArchConsoleStd : public IArchConsole
|
||||
{
|
||||
public:
|
||||
ArchConsoleStd()
|
||||
{
|
||||
}
|
||||
virtual ~ArchConsoleStd()
|
||||
{
|
||||
}
|
||||
|
||||
// IArchConsole overrides
|
||||
virtual void openConsole(const char *title)
|
||||
{
|
||||
}
|
||||
virtual void closeConsole()
|
||||
{
|
||||
}
|
||||
virtual void showConsole(bool)
|
||||
{
|
||||
}
|
||||
virtual void writeConsole(ELevel level, const char *);
|
||||
};
|
||||
@ -11,16 +11,6 @@
|
||||
// ArchDaemonNone
|
||||
//
|
||||
|
||||
ArchDaemonNone::ArchDaemonNone()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
ArchDaemonNone::~ArchDaemonNone()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void ArchDaemonNone::installDaemon(const char *, const char *, const char *, const char *, const char *)
|
||||
{
|
||||
// do nothing
|
||||
@ -31,7 +21,7 @@ void ArchDaemonNone::uninstallDaemon(const char *)
|
||||
// do nothing
|
||||
}
|
||||
|
||||
int ArchDaemonNone::daemonize(const char *name, DaemonFunc func)
|
||||
int ArchDaemonNone::daemonize(const char *name, DaemonFunc const &func)
|
||||
{
|
||||
// simply forward the call to func. obviously, this doesn't
|
||||
// do any daemonizing.
|
||||
@ -50,10 +40,12 @@ bool ArchDaemonNone::isDaemonInstalled(const char *)
|
||||
|
||||
void ArchDaemonNone::installDaemon()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void ArchDaemonNone::uninstallDaemon()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
std::string ArchDaemonNone::commandLine() const
|
||||
|
||||
@ -21,18 +21,18 @@ function and returns its result.
|
||||
class ArchDaemonNone : public IArchDaemon
|
||||
{
|
||||
public:
|
||||
ArchDaemonNone();
|
||||
virtual ~ArchDaemonNone();
|
||||
ArchDaemonNone() = default;
|
||||
~ArchDaemonNone() override = default;
|
||||
|
||||
// IArchDaemon overrides
|
||||
virtual void installDaemon(
|
||||
void installDaemon(
|
||||
const char *name, const char *description, const char *pathname, const char *commandLine, const char *dependencies
|
||||
);
|
||||
virtual void uninstallDaemon(const char *name);
|
||||
virtual int daemonize(const char *name, DaemonFunc func);
|
||||
virtual bool canInstallDaemon(const char *name);
|
||||
virtual bool isDaemonInstalled(const char *name);
|
||||
virtual void installDaemon();
|
||||
virtual void uninstallDaemon();
|
||||
virtual std::string commandLine() const;
|
||||
) override;
|
||||
void uninstallDaemon(const char *name) override;
|
||||
int daemonize(const char *name, DaemonFunc const &func) override;
|
||||
bool canInstallDaemon(const char *name) override;
|
||||
bool isDaemonInstalled(const char *name) override;
|
||||
void installDaemon() override;
|
||||
void uninstallDaemon() override;
|
||||
std::string commandLine() const override;
|
||||
};
|
||||
|
||||
@ -5,45 +5,44 @@
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "arch/IArchString.h"
|
||||
#include "arch/ArchString.h"
|
||||
#include "arch/Arch.h"
|
||||
#include "common/Common.h"
|
||||
|
||||
#include <climits>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
static ArchMutex s_mutex = NULL;
|
||||
static ArchMutex s_mutex = nullptr;
|
||||
|
||||
//
|
||||
// use C library non-reentrant multibyte conversion with mutex
|
||||
//
|
||||
|
||||
IArchString::~IArchString()
|
||||
ArchString::~ArchString()
|
||||
{
|
||||
if (s_mutex != NULL) {
|
||||
if (s_mutex != nullptr) {
|
||||
ARCH->closeMutex(s_mutex);
|
||||
s_mutex = NULL;
|
||||
s_mutex = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int IArchString::convStringWCToMB(char *dst, const wchar_t *src, uint32_t n, bool *errors)
|
||||
int ArchString::convStringWCToMB(char *dst, const wchar_t *src, uint32_t n, bool *errors) const
|
||||
{
|
||||
ptrdiff_t len = 0;
|
||||
|
||||
bool dummyErrors;
|
||||
if (errors == NULL) {
|
||||
if (errors == nullptr) {
|
||||
errors = &dummyErrors;
|
||||
}
|
||||
*errors = false;
|
||||
|
||||
if (s_mutex == NULL) {
|
||||
if (s_mutex == nullptr) {
|
||||
s_mutex = ARCH->newMutex();
|
||||
}
|
||||
|
||||
ARCH->lockMutex(s_mutex);
|
||||
|
||||
if (dst == NULL) {
|
||||
if (dst == nullptr) {
|
||||
char dummy[MB_LEN_MAX];
|
||||
const wchar_t *scan = src;
|
||||
for (; n > 0; --n) {
|
||||
@ -55,16 +54,14 @@ int IArchString::convStringWCToMB(char *dst, const wchar_t *src, uint32_t n, boo
|
||||
len += mblen;
|
||||
++scan;
|
||||
}
|
||||
ptrdiff_t mblen = wctomb(dummy, L'\0');
|
||||
if (mblen != -1) {
|
||||
if (ptrdiff_t mblen = wctomb(dummy, L'\0'); mblen != -1) {
|
||||
len += mblen - 1;
|
||||
}
|
||||
} else {
|
||||
char *dst0 = dst;
|
||||
const char *dst0 = dst;
|
||||
const wchar_t *scan = src;
|
||||
for (; n > 0; --n) {
|
||||
ptrdiff_t mblen = wctomb(dst, *scan);
|
||||
if (mblen == -1) {
|
||||
if (ptrdiff_t mblen = wctomb(dst, *scan); mblen == -1) {
|
||||
*errors = true;
|
||||
*dst++ = '?';
|
||||
} else {
|
||||
@ -72,8 +69,7 @@ int IArchString::convStringWCToMB(char *dst, const wchar_t *src, uint32_t n, boo
|
||||
}
|
||||
++scan;
|
||||
}
|
||||
ptrdiff_t mblen = wctomb(dst, L'\0');
|
||||
if (mblen != -1) {
|
||||
if (ptrdiff_t mblen = wctomb(dst, L'\0'); mblen != -1) {
|
||||
// don't include nul terminator
|
||||
dst += mblen - 1;
|
||||
}
|
||||
@ -84,28 +80,36 @@ int IArchString::convStringWCToMB(char *dst, const wchar_t *src, uint32_t n, boo
|
||||
return static_cast<int>(len);
|
||||
}
|
||||
|
||||
int IArchString::convStringMBToWC(wchar_t *dst, const char *src, uint32_t n, bool *errors)
|
||||
ArchString::EWideCharEncoding ArchString::getWideCharEncoding() const
|
||||
{
|
||||
#ifdef SYSAPI_WIN32
|
||||
return EWideCharEncoding::kUTF16;
|
||||
#else
|
||||
return EWideCharEncoding::kUCS4;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ArchString::convStringMBToWC(wchar_t *dst, const char *src, uint32_t n, bool *errors) const
|
||||
{
|
||||
ptrdiff_t len = 0;
|
||||
wchar_t dummy;
|
||||
|
||||
bool dummyErrors;
|
||||
if (errors == NULL) {
|
||||
if (errors == nullptr) {
|
||||
errors = &dummyErrors;
|
||||
}
|
||||
*errors = false;
|
||||
|
||||
if (s_mutex == NULL) {
|
||||
if (s_mutex == nullptr) {
|
||||
s_mutex = ARCH->newMutex();
|
||||
}
|
||||
|
||||
ARCH->lockMutex(s_mutex);
|
||||
|
||||
if (dst == NULL) {
|
||||
if (dst == nullptr) {
|
||||
const char *scan = src;
|
||||
while (n > 0) {
|
||||
ptrdiff_t mblen = mbtowc(&dummy, scan, n);
|
||||
switch (mblen) {
|
||||
switch (ptrdiff_t mblen = mbtowc(&dummy, scan, n); mblen) {
|
||||
case -2:
|
||||
// incomplete last character. convert to unknown character.
|
||||
*errors = true;
|
||||
@ -137,11 +141,10 @@ int IArchString::convStringMBToWC(wchar_t *dst, const char *src, uint32_t n, boo
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wchar_t *dst0 = dst;
|
||||
const wchar_t *dst0 = dst;
|
||||
const char *scan = src;
|
||||
while (n > 0) {
|
||||
ptrdiff_t mblen = mbtowc(dst, scan, n);
|
||||
switch (mblen) {
|
||||
switch (ptrdiff_t mblen = mbtowc(dst, scan, n); mblen) {
|
||||
case -2:
|
||||
// incomplete character. convert to unknown character.
|
||||
*errors = true;
|
||||
@ -18,22 +18,22 @@
|
||||
This interface defines the string operations required by
|
||||
deskflow. Each architecture must implement this interface.
|
||||
*/
|
||||
class IArchString : public IInterface
|
||||
class ArchString : public IInterface
|
||||
{
|
||||
public:
|
||||
IArchString() = default;
|
||||
IArchString(const IArchString &) = delete;
|
||||
IArchString(IArchString &&) = delete;
|
||||
virtual ~IArchString();
|
||||
ArchString() = default;
|
||||
ArchString(const ArchString &) = delete;
|
||||
ArchString(ArchString &&) = delete;
|
||||
~ArchString() override;
|
||||
|
||||
IArchString &operator=(const IArchString &) = delete;
|
||||
IArchString &operator=(IArchString &&) = delete;
|
||||
ArchString &operator=(const ArchString &) = delete;
|
||||
ArchString &operator=(ArchString &&) = delete;
|
||||
|
||||
//! Wide character encodings
|
||||
/*!
|
||||
The known wide character encodings
|
||||
*/
|
||||
enum EWideCharEncoding
|
||||
enum class EWideCharEncoding : uint8_t
|
||||
{
|
||||
kUCS2, //!< The UCS-2 encoding
|
||||
kUCS4, //!< The UCS-4 encoding
|
||||
@ -46,13 +46,13 @@ public:
|
||||
//@{
|
||||
|
||||
//! Convert multibyte string to wide character string
|
||||
virtual int convStringMBToWC(wchar_t *, const char *, uint32_t n, bool *errors);
|
||||
int convStringMBToWC(wchar_t *, const char *, uint32_t n, bool *errors) const;
|
||||
|
||||
//! Convert wide character string to multibyte string
|
||||
virtual int convStringWCToMB(char *, const wchar_t *, uint32_t n, bool *errors);
|
||||
int convStringWCToMB(char *, const wchar_t *, uint32_t n, bool *errors) const;
|
||||
|
||||
//! Return the architecture's native wide character encoding
|
||||
virtual EWideCharEncoding getWideCharEncoding() = 0;
|
||||
EWideCharEncoding getWideCharEncoding() const;
|
||||
|
||||
//@}
|
||||
};
|
||||
@ -6,8 +6,6 @@
|
||||
# Platform Specific Code
|
||||
if(WIN32)
|
||||
set(PLATFORM_CODE
|
||||
win32/ArchConsoleWindows.cpp
|
||||
win32/ArchConsoleWindows.h
|
||||
win32/ArchDaemonWindows.cpp
|
||||
win32/ArchDaemonWindows.h
|
||||
win32/ArchLogWindows.cpp
|
||||
@ -20,8 +18,6 @@ if(WIN32)
|
||||
win32/ArchNetworkWinsock.h
|
||||
win32/ArchSleepWindows.cpp
|
||||
win32/ArchSleepWindows.h
|
||||
win32/ArchStringWindows.cpp
|
||||
win32/ArchStringWindows.h
|
||||
win32/ArchTimeWindows.cpp
|
||||
win32/ArchTimeWindows.h
|
||||
win32/XArchWindows.cpp
|
||||
@ -30,8 +26,6 @@ if(WIN32)
|
||||
|
||||
elseif(UNIX)
|
||||
set(PLATFORM_CODE
|
||||
unix/ArchConsoleUnix.cpp
|
||||
unix/ArchConsoleUnix.h
|
||||
unix/ArchDaemonUnix.cpp
|
||||
unix/ArchDaemonUnix.h
|
||||
unix/ArchLogUnix.cpp
|
||||
@ -42,8 +36,6 @@ elseif(UNIX)
|
||||
unix/ArchNetworkBSD.h
|
||||
unix/ArchSleepUnix.cpp
|
||||
unix/ArchSleepUnix.h
|
||||
unix/ArchStringUnix.cpp
|
||||
unix/ArchStringUnix.h
|
||||
unix/ArchTimeUnix.cpp
|
||||
unix/ArchTimeUnix.h
|
||||
unix/XArchUnix.cpp
|
||||
@ -54,18 +46,15 @@ endif()
|
||||
add_library(arch STATIC ${PLATFORM_CODE}
|
||||
Arch.cpp
|
||||
Arch.h
|
||||
ArchConsoleStd.cpp
|
||||
ArchConsoleStd.h
|
||||
ArchDaemonNone.cpp
|
||||
ArchDaemonNone.h
|
||||
IArchConsole.h
|
||||
IArchDaemon.h
|
||||
IArchLog.h
|
||||
IArchMultithread.h
|
||||
IArchNetwork.h
|
||||
IArchSleep.h
|
||||
IArchString.cpp
|
||||
IArchString.h
|
||||
ArchString.cpp
|
||||
ArchString.h
|
||||
IArchTime.h
|
||||
XArch.h
|
||||
)
|
||||
|
||||
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/ELevel.h"
|
||||
#include "common/IInterface.h"
|
||||
|
||||
//! Interface for architecture dependent console output
|
||||
/*!
|
||||
This interface defines the console operations required by
|
||||
deskflow. Each architecture must implement this interface.
|
||||
*/
|
||||
class IArchConsole : public IInterface
|
||||
{
|
||||
public:
|
||||
//! @name manipulators
|
||||
//@{
|
||||
|
||||
//! Open the console
|
||||
/*!
|
||||
Opens the console for writing. The console is opened automatically
|
||||
on the first write so calling this method is optional. Uses \c title
|
||||
for the console's title if appropriate for the architecture. Calling
|
||||
this method on an already open console must have no effect.
|
||||
*/
|
||||
virtual void openConsole(const char *title) = 0;
|
||||
|
||||
//! Close the console
|
||||
/*!
|
||||
Close the console. Calling this method on an already closed console
|
||||
must have no effect.
|
||||
*/
|
||||
virtual void closeConsole() = 0;
|
||||
|
||||
//! Show the console
|
||||
/*!
|
||||
Causes the console to become visible. This generally only makes sense
|
||||
for a console in a graphical user interface. Other implementations
|
||||
will do nothing. Iff \p showIfEmpty is \c false then the implementation
|
||||
may optionally only show the console if it's not empty.
|
||||
*/
|
||||
virtual void showConsole(bool showIfEmpty) = 0;
|
||||
|
||||
//! Write to the console
|
||||
/*!
|
||||
Writes the given string to the console, opening it if necessary.
|
||||
*/
|
||||
virtual void writeConsole(ELevel, const char *) = 0;
|
||||
|
||||
//@}
|
||||
};
|
||||
@ -34,7 +34,7 @@ public:
|
||||
\c commandLine should \b not include the name of program as the
|
||||
first argument. If \c allUsers is true then the daemon will be
|
||||
installed to start at boot time, otherwise it will be installed to
|
||||
start when the current user logs in. If \p dependencies is not NULL
|
||||
start when the current user logs in. If \p dependencies is not nullptr
|
||||
then it's a concatenation of NUL terminated other daemon names
|
||||
followed by a NUL; the daemon will be configured to startup after
|
||||
the listed daemons. Throws an \c XArchDaemon exception on failure.
|
||||
@ -88,7 +88,7 @@ public:
|
||||
\c ArchMiscWindows::daemonFailed() to indicate startup failure.
|
||||
</ul>
|
||||
*/
|
||||
virtual int daemonize(const char *name, DaemonFunc func) = 0;
|
||||
virtual int daemonize(const char *name, DaemonFunc const &func) = 0;
|
||||
|
||||
//! Check if user has permission to install the daemon
|
||||
/*!
|
||||
|
||||
@ -61,7 +61,7 @@ class IArchMultithread : public IInterface
|
||||
{
|
||||
public:
|
||||
//! Type of thread entry point
|
||||
typedef void *(*ThreadFunc)(void *);
|
||||
using ThreadFunc = void *(*)(void *);
|
||||
//! Type of thread identifier
|
||||
using ThreadID = unsigned int;
|
||||
//! Types of signals
|
||||
@ -78,7 +78,7 @@ public:
|
||||
kNUM_SIGNALS
|
||||
};
|
||||
//! Type of signal handler function
|
||||
typedef void (*SignalFunc)(ESignal, void *userData);
|
||||
using SignalFunc = void (*)(ESignal, void *userData);
|
||||
|
||||
//! @name manipulators
|
||||
//@{
|
||||
@ -247,7 +247,7 @@ public:
|
||||
//! Set the interrupt handler
|
||||
/*!
|
||||
Sets the function to call on receipt of an external interrupt.
|
||||
By default and when \p func is NULL, the main thread is cancelled.
|
||||
By default and when \p func is nullptr, the main thread is cancelled.
|
||||
*/
|
||||
virtual void setSignalHandler(ESignal, SignalFunc func, void *userData) = 0;
|
||||
|
||||
|
||||
@ -149,10 +149,10 @@ public:
|
||||
/*!
|
||||
Accepts a connection on socket \c s, returning a new socket for the
|
||||
connection and filling in \c addr with the address of the remote
|
||||
end. \c addr may be NULL if the remote address isn't required.
|
||||
end. \c addr may be nullptr if the remote address isn't required.
|
||||
The original socket \c s is unaffected and remains in the listening
|
||||
state. The new socket shares most of the properties of \c s except
|
||||
it's not in the listening state and it's connected. Returns NULL
|
||||
it's not in the listening state and it's connected. Returns nullptr
|
||||
if there are no pending connection requests.
|
||||
*/
|
||||
virtual ArchSocket acceptSocket(ArchSocket s, ArchNetAddress *addr) = 0;
|
||||
|
||||
@ -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
|
||||
@ -18,7 +19,7 @@ Exceptions derived from this class are used by the multithreading
|
||||
library to perform stack unwinding when a thread terminates. These
|
||||
exceptions must always be rethrown by clients when caught.
|
||||
*/
|
||||
class XThread
|
||||
class XThread : public std::exception
|
||||
{
|
||||
};
|
||||
|
||||
@ -45,134 +46,160 @@ cleanup but before leaving or returning from the handler.
|
||||
} catch (...) { \
|
||||
}
|
||||
|
||||
//! Lazy error message string evaluation
|
||||
/*!
|
||||
This class encapsulates platform dependent error string lookup.
|
||||
Platforms subclass this type, taking an appropriate error code
|
||||
type in the c'tor and overriding eval() to return the error
|
||||
string for that error code.
|
||||
*/
|
||||
class XArchEval
|
||||
{
|
||||
public:
|
||||
XArchEval()
|
||||
{
|
||||
}
|
||||
virtual ~XArchEval() throw()
|
||||
{
|
||||
}
|
||||
|
||||
virtual std::string eval() const = 0;
|
||||
};
|
||||
|
||||
//! Generic exception architecture dependent library
|
||||
class XArch : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
XArch(XArchEval *adopted) : std::runtime_error(adopted->eval())
|
||||
{
|
||||
delete adopted;
|
||||
}
|
||||
XArch(const std::string &msg) : std::runtime_error(msg)
|
||||
{
|
||||
}
|
||||
virtual ~XArch() throw()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// Macro to declare XArch derived types
|
||||
#define XARCH_SUBCLASS(name_, super_) \
|
||||
class name_ : public super_ \
|
||||
{ \
|
||||
public: \
|
||||
name_(XArchEval *adoptedEvaluator) : super_(adoptedEvaluator) \
|
||||
{ \
|
||||
} \
|
||||
name_(const std::string &msg) : super_(msg) \
|
||||
{ \
|
||||
} \
|
||||
}
|
||||
|
||||
//! Generic network exception
|
||||
/*!
|
||||
Exceptions derived from this class are used by the networking
|
||||
library to indicate various errors.
|
||||
*/
|
||||
XARCH_SUBCLASS(XArchNetwork, XArch);
|
||||
class XArchNetwork : public std::runtime_error
|
||||
{
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
//! Operation was interrupted
|
||||
XARCH_SUBCLASS(XArchNetworkInterrupted, XArchNetwork);
|
||||
class XArchNetworkInterrupted : public XArchNetwork
|
||||
{
|
||||
using XArchNetwork::XArchNetwork;
|
||||
};
|
||||
|
||||
//! Network insufficient permission
|
||||
XARCH_SUBCLASS(XArchNetworkAccess, XArchNetwork);
|
||||
class XArchNetworkAccess : public XArchNetwork
|
||||
{
|
||||
using XArchNetwork::XArchNetwork;
|
||||
};
|
||||
|
||||
//! Network insufficient resources
|
||||
XARCH_SUBCLASS(XArchNetworkResource, XArchNetwork);
|
||||
class XArchNetworkResource : public XArchNetwork
|
||||
{
|
||||
using XArchNetwork::XArchNetwork;
|
||||
};
|
||||
|
||||
//! No support for requested network resource/service
|
||||
XARCH_SUBCLASS(XArchNetworkSupport, XArchNetwork);
|
||||
class XArchNetworkSupport : public XArchNetwork
|
||||
{
|
||||
using XArchNetwork::XArchNetwork;
|
||||
};
|
||||
|
||||
//! Network I/O error
|
||||
XARCH_SUBCLASS(XArchNetworkIO, XArchNetwork);
|
||||
class XArchNetworkIO : public XArchNetwork
|
||||
{
|
||||
using XArchNetwork::XArchNetwork;
|
||||
};
|
||||
|
||||
//! Network address is unavailable or not local
|
||||
XARCH_SUBCLASS(XArchNetworkNoAddress, XArchNetwork);
|
||||
class XArchNetworkNoAddress : public XArchNetwork
|
||||
{
|
||||
using XArchNetwork::XArchNetwork;
|
||||
};
|
||||
|
||||
//! Network address in use
|
||||
XARCH_SUBCLASS(XArchNetworkAddressInUse, XArchNetwork);
|
||||
class XArchNetworkAddressInUse : public XArchNetwork
|
||||
{
|
||||
using XArchNetwork::XArchNetwork;
|
||||
};
|
||||
|
||||
//! No route to address
|
||||
XARCH_SUBCLASS(XArchNetworkNoRoute, XArchNetwork);
|
||||
class XArchNetworkNoRoute : public XArchNetwork
|
||||
{
|
||||
using XArchNetwork::XArchNetwork;
|
||||
};
|
||||
|
||||
//! Socket not connected
|
||||
XARCH_SUBCLASS(XArchNetworkNotConnected, XArchNetwork);
|
||||
class XArchNetworkNotConnected : public XArchNetwork
|
||||
{
|
||||
using XArchNetwork::XArchNetwork;
|
||||
};
|
||||
|
||||
//! Remote read end of socket has closed
|
||||
XARCH_SUBCLASS(XArchNetworkShutdown, XArchNetwork);
|
||||
class XArchNetworkShutdown : public XArchNetwork
|
||||
{
|
||||
using XArchNetwork::XArchNetwork;
|
||||
};
|
||||
|
||||
//! Remote end of socket has disconnected
|
||||
XARCH_SUBCLASS(XArchNetworkDisconnected, XArchNetwork);
|
||||
class XArchNetworkDisconnected : public XArchNetwork
|
||||
{
|
||||
using XArchNetwork::XArchNetwork;
|
||||
};
|
||||
|
||||
//! Remote end of socket refused connection
|
||||
XARCH_SUBCLASS(XArchNetworkConnectionRefused, XArchNetwork);
|
||||
class XArchNetworkConnectionRefused : public XArchNetwork
|
||||
{
|
||||
using XArchNetwork::XArchNetwork;
|
||||
};
|
||||
|
||||
//! Remote end of socket is not responding
|
||||
XARCH_SUBCLASS(XArchNetworkTimedOut, XArchNetwork);
|
||||
class XArchNetworkTimedOut : public XArchNetwork
|
||||
{
|
||||
using XArchNetwork::XArchNetwork;
|
||||
};
|
||||
|
||||
//! Generic network name lookup erros
|
||||
XARCH_SUBCLASS(XArchNetworkName, XArchNetwork);
|
||||
class XArchNetworkName : public XArchNetwork
|
||||
{
|
||||
using XArchNetwork::XArchNetwork;
|
||||
};
|
||||
|
||||
//! The named host is unknown
|
||||
XARCH_SUBCLASS(XArchNetworkNameUnknown, XArchNetworkName);
|
||||
class XArchNetworkNameUnknown : public XArchNetworkName
|
||||
{
|
||||
using XArchNetworkName::XArchNetworkName;
|
||||
};
|
||||
|
||||
//! The named host is known but has no address
|
||||
XARCH_SUBCLASS(XArchNetworkNameNoAddress, XArchNetworkName);
|
||||
class XArchNetworkNameNoAddress : public XArchNetworkName
|
||||
{
|
||||
using XArchNetworkName::XArchNetworkName;
|
||||
};
|
||||
|
||||
//! Non-recoverable name server error
|
||||
XARCH_SUBCLASS(XArchNetworkNameFailure, XArchNetworkName);
|
||||
class XArchNetworkNameFailure : public XArchNetworkName
|
||||
{
|
||||
using XArchNetworkName::XArchNetworkName;
|
||||
};
|
||||
|
||||
//! Temporary name server error
|
||||
XARCH_SUBCLASS(XArchNetworkNameUnavailable, XArchNetworkName);
|
||||
class XArchNetworkNameUnavailable : public XArchNetworkName
|
||||
{
|
||||
using XArchNetworkName::XArchNetworkName;
|
||||
};
|
||||
|
||||
//! The named host is known but no supported address
|
||||
XARCH_SUBCLASS(XArchNetworkNameUnsupported, XArchNetworkName);
|
||||
class XArchNetworkNameUnsupported : public XArchNetworkName
|
||||
{
|
||||
using XArchNetworkName::XArchNetworkName;
|
||||
};
|
||||
|
||||
//! Generic daemon exception
|
||||
/*!
|
||||
Exceptions derived from this class are used by the daemon
|
||||
library to indicate various errors.
|
||||
*/
|
||||
XARCH_SUBCLASS(XArchDaemon, XArch);
|
||||
class XArchDaemon : public std::runtime_error
|
||||
{
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
//! Could not daemonize
|
||||
XARCH_SUBCLASS(XArchDaemonFailed, XArchDaemon);
|
||||
class XArchDaemonFailed : public XArchDaemon
|
||||
{
|
||||
using XArchDaemon::XArchDaemon;
|
||||
};
|
||||
|
||||
//! Could not install daemon
|
||||
XARCH_SUBCLASS(XArchDaemonInstallFailed, XArchDaemon);
|
||||
class XArchDaemonInstallFailed : public XArchDaemon
|
||||
{
|
||||
using XArchDaemon::XArchDaemon;
|
||||
};
|
||||
|
||||
//! Could not uninstall daemon
|
||||
XARCH_SUBCLASS(XArchDaemonUninstallFailed, XArchDaemon);
|
||||
class XArchDaemonUninstallFailed : public XArchDaemon
|
||||
{
|
||||
using XArchDaemon::XArchDaemon;
|
||||
};
|
||||
|
||||
//! Attempted to uninstall a daemon that was not installed
|
||||
XARCH_SUBCLASS(XArchDaemonUninstallNotInstalled, XArchDaemonUninstallFailed);
|
||||
class XArchDaemonUninstallNotInstalled : public XArchDaemonFailed
|
||||
{
|
||||
using XArchDaemonFailed::XArchDaemonFailed;
|
||||
};
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "arch/unix/ArchConsoleUnix.h"
|
||||
|
||||
ArchConsoleUnix::ArchConsoleUnix()
|
||||
{
|
||||
}
|
||||
|
||||
ArchConsoleUnix::~ArchConsoleUnix()
|
||||
{
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "arch/ArchConsoleStd.h"
|
||||
|
||||
#define ARCH_CONSOLE ArchConsoleUnix
|
||||
|
||||
class ArchConsoleUnix : public ArchConsoleStd
|
||||
{
|
||||
public:
|
||||
ArchConsoleUnix();
|
||||
virtual ~ArchConsoleUnix();
|
||||
};
|
||||
@ -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
|
||||
@ -7,6 +8,7 @@
|
||||
|
||||
#include "arch/unix/ArchDaemonUnix.h"
|
||||
|
||||
#include "arch/XArch.h"
|
||||
#include "arch/unix/XArchUnix.h"
|
||||
#include "base/Log.h"
|
||||
|
||||
@ -21,16 +23,6 @@
|
||||
// ArchDaemonUnix
|
||||
//
|
||||
|
||||
ArchDaemonUnix::ArchDaemonUnix()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
ArchDaemonUnix::~ArchDaemonUnix()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
// In Mac OS X, fork()'d child processes can't use most APIs (the frameworks
|
||||
@ -49,12 +41,12 @@ int execSelfNonDaemonized()
|
||||
|
||||
bool alreadyDaemonized()
|
||||
{
|
||||
return getenv("_DESKFLOW_DAEMONIZED") != NULL;
|
||||
return getenv("_DESKFLOW_DAEMONIZED") != nullptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int ArchDaemonUnix::daemonize(const char *name, DaemonFunc func)
|
||||
int ArchDaemonUnix::daemonize(const char *name, DaemonFunc const &func)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
if (alreadyDaemonized())
|
||||
@ -66,7 +58,7 @@ int ArchDaemonUnix::daemonize(const char *name, DaemonFunc func)
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
// failed
|
||||
throw XArchDaemonFailed(new XArchEvalUnix(errno));
|
||||
throw XArchDaemonFailed(errorToString(errno));
|
||||
|
||||
case 0:
|
||||
// child
|
||||
@ -84,8 +76,7 @@ int ArchDaemonUnix::daemonize(const char *name, DaemonFunc func)
|
||||
// NB: don't run chdir on apple; causes strange behaviour.
|
||||
// chdir to root so we don't keep mounted filesystems points busy
|
||||
// TODO: this is a bit of a hack - can we find a better solution?
|
||||
int chdirErr = chdir("/");
|
||||
if (chdirErr)
|
||||
if (int chdirErr = chdir("/"); chdirErr)
|
||||
// NB: file logging actually isn't working at this point!
|
||||
LOG((CLOG_ERR "chdir error: %i", chdirErr));
|
||||
#endif
|
||||
@ -103,9 +94,7 @@ int ArchDaemonUnix::daemonize(const char *name, DaemonFunc func)
|
||||
open("/dev/null", O_RDONLY);
|
||||
open("/dev/null", O_RDWR);
|
||||
|
||||
int dupErr = dup(1);
|
||||
|
||||
if (dupErr < 0) {
|
||||
if (int dupErr = dup(1); dupErr < 0) {
|
||||
// NB: file logging actually isn't working at this point!
|
||||
LOG((CLOG_ERR "dup error: %i", dupErr));
|
||||
}
|
||||
|
||||
@ -16,9 +16,9 @@
|
||||
class ArchDaemonUnix : public ArchDaemonNone
|
||||
{
|
||||
public:
|
||||
ArchDaemonUnix();
|
||||
virtual ~ArchDaemonUnix();
|
||||
ArchDaemonUnix() = default;
|
||||
~ArchDaemonUnix() override = default;
|
||||
|
||||
// IArchDaemon overrides
|
||||
virtual int daemonize(const char *name, DaemonFunc func);
|
||||
int daemonize(const char *name, DaemonFunc const &func) override;
|
||||
};
|
||||
|
||||
@ -13,16 +13,6 @@
|
||||
// ArchLogUnix
|
||||
//
|
||||
|
||||
ArchLogUnix::ArchLogUnix()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
ArchLogUnix::~ArchLogUnix()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void ArchLogUnix::openLog(const char *name)
|
||||
{
|
||||
openlog(name, 0, LOG_DAEMON);
|
||||
|
||||
@ -15,12 +15,12 @@
|
||||
class ArchLogUnix : public IArchLog
|
||||
{
|
||||
public:
|
||||
ArchLogUnix();
|
||||
virtual ~ArchLogUnix();
|
||||
ArchLogUnix() = default;
|
||||
~ArchLogUnix() override = default;
|
||||
|
||||
// IArchLog overrides
|
||||
virtual void openLog(const char *name);
|
||||
virtual void closeLog();
|
||||
virtual void showLog(bool);
|
||||
virtual void writeLog(ELevel, const char *);
|
||||
void openLog(const char *name) override;
|
||||
void closeLog() override;
|
||||
void showLog(bool) override;
|
||||
void writeLog(ELevel, const char *) override;
|
||||
};
|
||||
|
||||
@ -52,51 +52,37 @@ static void setSignalSet(sigset_t *sigset)
|
||||
class ArchThreadImpl
|
||||
{
|
||||
public:
|
||||
ArchThreadImpl();
|
||||
ArchThreadImpl() = default;
|
||||
|
||||
public:
|
||||
int m_refCount;
|
||||
IArchMultithread::ThreadID m_id;
|
||||
int m_refCount = 1;
|
||||
IArchMultithread::ThreadID m_id = 0;
|
||||
pthread_t m_thread;
|
||||
IArchMultithread::ThreadFunc m_func;
|
||||
void *m_userData;
|
||||
bool m_cancel;
|
||||
bool m_cancelling;
|
||||
bool m_exited;
|
||||
void *m_result;
|
||||
void *m_networkData;
|
||||
IArchMultithread::ThreadFunc m_func = nullptr;
|
||||
void *m_userData = nullptr;
|
||||
bool m_cancel = false;
|
||||
bool m_cancelling = false;
|
||||
bool m_exited = false;
|
||||
void *m_result = nullptr;
|
||||
void *m_networkData = nullptr;
|
||||
};
|
||||
|
||||
ArchThreadImpl::ArchThreadImpl()
|
||||
: m_refCount(1),
|
||||
m_id(0),
|
||||
m_func(NULL),
|
||||
m_userData(NULL),
|
||||
m_cancel(false),
|
||||
m_cancelling(false),
|
||||
m_exited(false),
|
||||
m_result(NULL),
|
||||
m_networkData(NULL)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
//
|
||||
// ArchMultithreadPosix
|
||||
//
|
||||
|
||||
ArchMultithreadPosix *ArchMultithreadPosix::s_instance = NULL;
|
||||
ArchMultithreadPosix *ArchMultithreadPosix::s_instance = nullptr;
|
||||
|
||||
ArchMultithreadPosix::ArchMultithreadPosix() : m_newThreadCalled(false), m_nextID(0)
|
||||
ArchMultithreadPosix::ArchMultithreadPosix()
|
||||
{
|
||||
assert(s_instance == NULL);
|
||||
assert(s_instance == nullptr);
|
||||
|
||||
s_instance = this;
|
||||
|
||||
// no signal handlers
|
||||
for (size_t i = 0; i < kNUM_SIGNALS; ++i) {
|
||||
m_signalFunc[i] = NULL;
|
||||
m_signalUserData[i] = NULL;
|
||||
m_signalFunc[i] = nullptr;
|
||||
m_signalUserData[i] = nullptr;
|
||||
}
|
||||
|
||||
// create mutex for thread list
|
||||
@ -121,25 +107,25 @@ ArchMultithreadPosix::ArchMultithreadPosix() : m_newThreadCalled(false), m_nextI
|
||||
act.sa_flags = 0;
|
||||
#endif
|
||||
act.sa_handler = &threadCancel;
|
||||
sigaction(SIGWAKEUP, &act, NULL);
|
||||
sigaction(SIGWAKEUP, &act, nullptr);
|
||||
|
||||
// set desired signal dispositions. let SIGWAKEUP through but
|
||||
// ignore SIGPIPE (we'll handle EPIPE).
|
||||
sigset_t sigset;
|
||||
sigemptyset(&sigset);
|
||||
sigaddset(&sigset, SIGWAKEUP);
|
||||
pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
|
||||
pthread_sigmask(SIG_UNBLOCK, &sigset, nullptr);
|
||||
sigemptyset(&sigset);
|
||||
sigaddset(&sigset, SIGPIPE);
|
||||
pthread_sigmask(SIG_BLOCK, &sigset, NULL);
|
||||
pthread_sigmask(SIG_BLOCK, &sigset, nullptr);
|
||||
}
|
||||
|
||||
ArchMultithreadPosix::~ArchMultithreadPosix()
|
||||
{
|
||||
assert(s_instance != NULL);
|
||||
assert(s_instance != nullptr);
|
||||
|
||||
closeMutex(m_threadMutex);
|
||||
s_instance = NULL;
|
||||
s_instance = nullptr;
|
||||
}
|
||||
|
||||
void ArchMultithreadPosix::setNetworkDataForCurrentThread(void *data)
|
||||
@ -165,8 +151,8 @@ ArchMultithreadPosix *ArchMultithreadPosix::getInstance()
|
||||
|
||||
ArchCond ArchMultithreadPosix::newCondVar()
|
||||
{
|
||||
ArchCondImpl *cond = new ArchCondImpl;
|
||||
int status = pthread_cond_init(&cond->m_cond, NULL);
|
||||
auto *cond = new ArchCondImpl;
|
||||
int status = pthread_cond_init(&cond->m_cond, nullptr);
|
||||
(void)status;
|
||||
assert(status == 0);
|
||||
return cond;
|
||||
@ -204,8 +190,7 @@ bool ArchMultithreadPosix::waitCondVar(ArchCond cond, ArchMutex mutex, double ti
|
||||
// so we have to return to the caller. since the caller will
|
||||
// always check for spurious wakeups the only drawback here is
|
||||
// performance: we're waking up a lot more than desired.
|
||||
static const double maxCancellationLatency = 0.1;
|
||||
if (timeout < 0.0 || timeout > maxCancellationLatency) {
|
||||
if (static const double maxCancellationLatency = 0.1; timeout < 0.0 || timeout > maxCancellationLatency) {
|
||||
timeout = maxCancellationLatency;
|
||||
}
|
||||
|
||||
@ -214,12 +199,12 @@ bool ArchMultithreadPosix::waitCondVar(ArchCond cond, ArchMutex mutex, double ti
|
||||
|
||||
// get final time
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
gettimeofday(&now, nullptr);
|
||||
struct timespec finalTime;
|
||||
finalTime.tv_sec = now.tv_sec;
|
||||
finalTime.tv_nsec = now.tv_usec * 1000;
|
||||
long timeout_sec = (long)timeout;
|
||||
long timeout_nsec = (long)(1.0e+9 * (timeout - timeout_sec));
|
||||
auto timeout_sec = (long)timeout;
|
||||
auto timeout_nsec = (long)(1.0e+9 * (timeout - timeout_sec));
|
||||
finalTime.tv_sec += timeout_sec;
|
||||
finalTime.tv_nsec += timeout_nsec;
|
||||
if (finalTime.tv_nsec >= 1000000000) {
|
||||
@ -252,7 +237,7 @@ ArchMutex ArchMultithreadPosix::newMutex()
|
||||
pthread_mutexattr_t attr;
|
||||
int status = pthread_mutexattr_init(&attr);
|
||||
assert(status == 0);
|
||||
ArchMutexImpl *mutex = new ArchMutexImpl;
|
||||
auto *mutex = new ArchMutexImpl;
|
||||
status = pthread_mutex_init(&mutex->m_mutex, &attr);
|
||||
assert(status == 0);
|
||||
return mutex;
|
||||
@ -312,7 +297,7 @@ void ArchMultithreadPosix::unlockMutex(ArchMutex mutex)
|
||||
|
||||
ArchThread ArchMultithreadPosix::newThread(ThreadFunc func, void *data)
|
||||
{
|
||||
assert(func != NULL);
|
||||
assert(func != nullptr);
|
||||
|
||||
// initialize signal handler. we do this here instead of the
|
||||
// constructor so we can avoid daemonizing (using fork())
|
||||
@ -331,12 +316,12 @@ ArchThread ArchMultithreadPosix::newThread(ThreadFunc func, void *data)
|
||||
lockMutex(m_threadMutex);
|
||||
|
||||
// create thread impl for new thread
|
||||
ArchThreadImpl *thread = new ArchThreadImpl;
|
||||
auto *thread = new ArchThreadImpl;
|
||||
thread->m_func = func;
|
||||
thread->m_userData = data;
|
||||
|
||||
// create the thread. pthread_create() on RedHat 7.2 smp fails
|
||||
// if passed a NULL attr so use a default attr.
|
||||
// if passed a nullptr attr so use a default attr.
|
||||
pthread_attr_t attr;
|
||||
int status = pthread_attr_init(&attr);
|
||||
if (status == 0) {
|
||||
@ -348,7 +333,7 @@ ArchThread ArchMultithreadPosix::newThread(ThreadFunc func, void *data)
|
||||
if (status != 0) {
|
||||
// failed to start thread so clean up
|
||||
delete thread;
|
||||
thread = NULL;
|
||||
thread = nullptr;
|
||||
} else {
|
||||
// add thread to list
|
||||
insert(thread);
|
||||
@ -368,18 +353,18 @@ ArchThread ArchMultithreadPosix::newCurrentThread()
|
||||
lockMutex(m_threadMutex);
|
||||
ArchThreadImpl *thread = find(pthread_self());
|
||||
unlockMutex(m_threadMutex);
|
||||
assert(thread != NULL);
|
||||
assert(thread != nullptr);
|
||||
return thread;
|
||||
}
|
||||
|
||||
void ArchMultithreadPosix::closeThread(ArchThread thread)
|
||||
{
|
||||
assert(thread != NULL);
|
||||
assert(thread != nullptr);
|
||||
|
||||
// decrement ref count and clean up thread if no more references
|
||||
if (--thread->m_refCount == 0) {
|
||||
// detach from thread (unless it's the main thread)
|
||||
if (thread->m_func != NULL) {
|
||||
if (thread->m_func != nullptr) {
|
||||
pthread_detach(thread->m_thread);
|
||||
}
|
||||
|
||||
@ -402,7 +387,7 @@ ArchThread ArchMultithreadPosix::copyThread(ArchThread thread)
|
||||
|
||||
void ArchMultithreadPosix::cancelThread(ArchThread thread)
|
||||
{
|
||||
assert(thread != NULL);
|
||||
assert(thread != nullptr);
|
||||
|
||||
// set cancel and wakeup flags if thread can be cancelled
|
||||
bool wakeup = false;
|
||||
@ -421,7 +406,7 @@ void ArchMultithreadPosix::cancelThread(ArchThread thread)
|
||||
|
||||
void ArchMultithreadPosix::setPriorityOfThread(ArchThread thread, int /*n*/)
|
||||
{
|
||||
assert(thread != NULL);
|
||||
assert(thread != nullptr);
|
||||
|
||||
// FIXME
|
||||
}
|
||||
@ -439,7 +424,7 @@ void ArchMultithreadPosix::testCancelThread()
|
||||
|
||||
bool ArchMultithreadPosix::wait(ArchThread target, double timeout)
|
||||
{
|
||||
assert(target != NULL);
|
||||
assert(target != nullptr);
|
||||
|
||||
lockMutex(m_threadMutex);
|
||||
|
||||
@ -528,7 +513,7 @@ void ArchMultithreadPosix::setSignalHandler(ESignal signal, SignalFunc func, voi
|
||||
void ArchMultithreadPosix::raiseSignal(ESignal signal)
|
||||
{
|
||||
lockMutex(m_threadMutex);
|
||||
if (m_signalFunc[signal] != NULL) {
|
||||
if (m_signalFunc[signal] != nullptr) {
|
||||
m_signalFunc[signal](signal, m_signalUserData[signal]);
|
||||
pthread_kill(m_mainThread->m_thread, SIGWAKEUP);
|
||||
} else if (signal == kINTERRUPT || signal == kTERMINATE) {
|
||||
@ -541,7 +526,8 @@ void ArchMultithreadPosix::startSignalHandler()
|
||||
{
|
||||
// set signal mask. the main thread blocks these signals and
|
||||
// the signal handler thread will listen for them.
|
||||
sigset_t sigset, oldsigset;
|
||||
sigset_t sigset;
|
||||
sigset_t oldsigset;
|
||||
setSignalSet(&sigset);
|
||||
pthread_sigmask(SIG_BLOCK, &sigset, &oldsigset);
|
||||
|
||||
@ -552,20 +538,20 @@ void ArchMultithreadPosix::startSignalHandler()
|
||||
pthread_attr_t attr;
|
||||
int status = pthread_attr_init(&attr);
|
||||
if (status == 0) {
|
||||
status = pthread_create(&m_signalThread, &attr, &ArchMultithreadPosix::threadSignalHandler, NULL);
|
||||
status = pthread_create(&m_signalThread, &attr, &ArchMultithreadPosix::threadSignalHandler, nullptr);
|
||||
pthread_attr_destroy(&attr);
|
||||
}
|
||||
if (status != 0) {
|
||||
// can't create thread to wait for signal so don't block
|
||||
// the signals.
|
||||
pthread_sigmask(SIG_UNBLOCK, &oldsigset, NULL);
|
||||
pthread_sigmask(SIG_UNBLOCK, &oldsigset, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
ArchThreadImpl *ArchMultithreadPosix::find(pthread_t thread)
|
||||
{
|
||||
ArchThreadImpl *impl = findNoRef(thread);
|
||||
if (impl != NULL) {
|
||||
if (impl != nullptr) {
|
||||
refThread(impl);
|
||||
}
|
||||
return impl;
|
||||
@ -579,15 +565,15 @@ ArchThreadImpl *ArchMultithreadPosix::findNoRef(pthread_t thread)
|
||||
return *index;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ArchMultithreadPosix::insert(ArchThreadImpl *thread)
|
||||
{
|
||||
assert(thread != NULL);
|
||||
assert(thread != nullptr);
|
||||
|
||||
// thread shouldn't already be on the list
|
||||
assert(findNoRef(thread->m_thread) == NULL);
|
||||
assert(findNoRef(thread->m_thread) == nullptr);
|
||||
|
||||
// set thread id. note that we don't worry about m_nextID
|
||||
// wrapping back to 0 and duplicating thread ID's since the
|
||||
@ -599,9 +585,9 @@ void ArchMultithreadPosix::insert(ArchThreadImpl *thread)
|
||||
m_threadList.push_back(thread);
|
||||
}
|
||||
|
||||
void ArchMultithreadPosix::erase(ArchThreadImpl *thread)
|
||||
void ArchMultithreadPosix::erase(const ArchThreadImpl *thread)
|
||||
{
|
||||
for (ThreadList::iterator index = m_threadList.begin(); index != m_threadList.end(); ++index) {
|
||||
for (auto index = m_threadList.begin(); index != m_threadList.end(); ++index) {
|
||||
if (*index == thread) {
|
||||
m_threadList.erase(index);
|
||||
break;
|
||||
@ -611,14 +597,14 @@ void ArchMultithreadPosix::erase(ArchThreadImpl *thread)
|
||||
|
||||
void ArchMultithreadPosix::refThread(ArchThreadImpl *thread)
|
||||
{
|
||||
assert(thread != NULL);
|
||||
assert(findNoRef(thread->m_thread) != NULL);
|
||||
assert(thread != nullptr);
|
||||
assert(findNoRef(thread->m_thread) != nullptr);
|
||||
++thread->m_refCount;
|
||||
}
|
||||
|
||||
void ArchMultithreadPosix::testCancelThreadImpl(ArchThreadImpl *thread)
|
||||
{
|
||||
assert(thread != NULL);
|
||||
assert(thread != nullptr);
|
||||
|
||||
// update cancel state
|
||||
lockMutex(m_threadMutex);
|
||||
@ -639,17 +625,17 @@ void ArchMultithreadPosix::testCancelThreadImpl(ArchThreadImpl *thread)
|
||||
void *ArchMultithreadPosix::threadFunc(void *vrep)
|
||||
{
|
||||
// get the thread
|
||||
ArchThreadImpl *thread = static_cast<ArchThreadImpl *>(vrep);
|
||||
auto *thread = static_cast<ArchThreadImpl *>(vrep);
|
||||
|
||||
// setup pthreads
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, nullptr);
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, nullptr);
|
||||
|
||||
// run thread
|
||||
s_instance->doThreadFunc(thread);
|
||||
|
||||
// terminate the thread
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ArchMultithreadPosix::doThreadFunc(ArchThread thread)
|
||||
@ -748,5 +734,5 @@ void *ArchMultithreadPosix::threadSignalHandler(void *)
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ public:
|
||||
ArchMultithreadPosix();
|
||||
ArchMultithreadPosix(ArchMultithreadPosix const &) = delete;
|
||||
ArchMultithreadPosix(ArchMultithreadPosix &&) = delete;
|
||||
virtual ~ArchMultithreadPosix();
|
||||
~ArchMultithreadPosix() override;
|
||||
|
||||
ArchMultithreadPosix &operator=(ArchMultithreadPosix const &) = delete;
|
||||
ArchMultithreadPosix &operator=(ArchMultithreadPosix &&) = delete;
|
||||
@ -54,29 +54,29 @@ public:
|
||||
//@}
|
||||
|
||||
// IArchMultithread overrides
|
||||
virtual ArchCond newCondVar();
|
||||
virtual void closeCondVar(ArchCond);
|
||||
virtual void signalCondVar(ArchCond);
|
||||
virtual void broadcastCondVar(ArchCond);
|
||||
virtual bool waitCondVar(ArchCond, ArchMutex, double timeout);
|
||||
virtual ArchMutex newMutex();
|
||||
virtual void closeMutex(ArchMutex);
|
||||
virtual void lockMutex(ArchMutex);
|
||||
virtual void unlockMutex(ArchMutex);
|
||||
virtual ArchThread newThread(ThreadFunc, void *);
|
||||
virtual ArchThread newCurrentThread();
|
||||
virtual ArchThread copyThread(ArchThread);
|
||||
virtual void closeThread(ArchThread);
|
||||
virtual void cancelThread(ArchThread);
|
||||
virtual void setPriorityOfThread(ArchThread, int n);
|
||||
virtual void testCancelThread();
|
||||
virtual bool wait(ArchThread, double timeout);
|
||||
virtual bool isSameThread(ArchThread, ArchThread);
|
||||
virtual bool isExitedThread(ArchThread);
|
||||
virtual void *getResultOfThread(ArchThread);
|
||||
virtual ThreadID getIDOfThread(ArchThread);
|
||||
virtual void setSignalHandler(ESignal, SignalFunc, void *);
|
||||
virtual void raiseSignal(ESignal);
|
||||
ArchCond newCondVar() override;
|
||||
void closeCondVar(ArchCond) override;
|
||||
void signalCondVar(ArchCond) override;
|
||||
void broadcastCondVar(ArchCond) override;
|
||||
bool waitCondVar(ArchCond, ArchMutex, double timeout) override;
|
||||
ArchMutex newMutex() override;
|
||||
void closeMutex(ArchMutex) override;
|
||||
void lockMutex(ArchMutex) override;
|
||||
void unlockMutex(ArchMutex) override;
|
||||
ArchThread newThread(ThreadFunc, void *) final;
|
||||
ArchThread newCurrentThread() override;
|
||||
ArchThread copyThread(ArchThread) override;
|
||||
void closeThread(ArchThread) final;
|
||||
void cancelThread(ArchThread) override;
|
||||
void setPriorityOfThread(ArchThread, int n) override;
|
||||
void testCancelThread() override;
|
||||
bool wait(ArchThread, double timeout) override;
|
||||
bool isSameThread(ArchThread, ArchThread) override;
|
||||
bool isExitedThread(ArchThread) override;
|
||||
void *getResultOfThread(ArchThread) override;
|
||||
ThreadID getIDOfThread(ArchThread) override;
|
||||
void setSignalHandler(ESignal, SignalFunc, void *) override;
|
||||
void raiseSignal(ESignal) override;
|
||||
|
||||
private:
|
||||
void startSignalHandler();
|
||||
@ -84,7 +84,7 @@ private:
|
||||
ArchThreadImpl *find(pthread_t thread);
|
||||
ArchThreadImpl *findNoRef(pthread_t thread);
|
||||
void insert(ArchThreadImpl *thread);
|
||||
void erase(ArchThreadImpl *thread);
|
||||
void erase(const ArchThreadImpl *thread);
|
||||
|
||||
void refThread(ArchThreadImpl *rep);
|
||||
void testCancelThreadImpl(ArchThreadImpl *rep);
|
||||
@ -99,12 +99,12 @@ private:
|
||||
|
||||
static ArchMultithreadPosix *s_instance;
|
||||
|
||||
bool m_newThreadCalled;
|
||||
bool m_newThreadCalled = false;
|
||||
|
||||
ArchMutex m_threadMutex;
|
||||
ArchThread m_mainThread;
|
||||
ThreadList m_threadList;
|
||||
ThreadID m_nextID;
|
||||
ThreadID m_nextID = 0;
|
||||
|
||||
pthread_t m_signalThread;
|
||||
SignalFunc m_signalFunc[kNUM_SIGNALS];
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "arch/unix/ArchNetworkBSD.h"
|
||||
|
||||
#include "arch/Arch.h"
|
||||
#include "arch/XArch.h"
|
||||
#include "arch/unix/ArchMultithreadPosix.h"
|
||||
#include "arch/unix/XArchUnix.h"
|
||||
|
||||
@ -65,7 +66,6 @@ static in_addr_t inet_aton(const char *cp, struct in_addr *inp)
|
||||
|
||||
void ArchNetworkBSD::Deps::sleep(double seconds)
|
||||
{
|
||||
//
|
||||
ARCH->sleep(seconds);
|
||||
}
|
||||
|
||||
@ -131,7 +131,7 @@ ArchSocket ArchNetworkBSD::newSocket(EAddressFamily family, ESocketType type)
|
||||
|
||||
ArchSocket ArchNetworkBSD::copySocket(ArchSocket s)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(s != nullptr);
|
||||
|
||||
// ref the socket and return it
|
||||
ARCH->lockMutex(m_mutex);
|
||||
@ -142,7 +142,7 @@ ArchSocket ArchNetworkBSD::copySocket(ArchSocket s)
|
||||
|
||||
void ArchNetworkBSD::closeSocket(ArchSocket s)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(s != nullptr);
|
||||
|
||||
// unref the socket and note if it should be released
|
||||
ARCH->lockMutex(m_mutex);
|
||||
@ -165,30 +165,26 @@ void ArchNetworkBSD::closeSocket(ArchSocket s)
|
||||
|
||||
void ArchNetworkBSD::closeSocketForRead(ArchSocket s)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(s != nullptr);
|
||||
|
||||
if (shutdown(s->m_fd, 0) == -1) {
|
||||
if (errno != ENOTCONN) {
|
||||
throwError(errno);
|
||||
}
|
||||
if ((shutdown(s->m_fd, 0) == -1) && (errno != ENOTCONN)) {
|
||||
throwError(errno);
|
||||
}
|
||||
}
|
||||
|
||||
void ArchNetworkBSD::closeSocketForWrite(ArchSocket s)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(s != nullptr);
|
||||
|
||||
if (shutdown(s->m_fd, 1) == -1) {
|
||||
if (errno != ENOTCONN) {
|
||||
throwError(errno);
|
||||
}
|
||||
if ((shutdown(s->m_fd, 1) == -1) && (errno != ENOTCONN)) {
|
||||
throwError(errno);
|
||||
}
|
||||
}
|
||||
|
||||
void ArchNetworkBSD::bindSocket(ArchSocket s, ArchNetAddress addr)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(addr != NULL);
|
||||
assert(s != nullptr);
|
||||
assert(addr != nullptr);
|
||||
|
||||
if (bind(s->m_fd, TYPED_ADDR(struct sockaddr, addr), addr->m_len) == -1) {
|
||||
throwError(errno);
|
||||
@ -197,7 +193,7 @@ void ArchNetworkBSD::bindSocket(ArchSocket s, ArchNetAddress addr)
|
||||
|
||||
void ArchNetworkBSD::listenOnSocket(ArchSocket s)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(s != nullptr);
|
||||
|
||||
// hardcoding backlog
|
||||
if (listen(s->m_fd, 3) == -1) {
|
||||
@ -207,9 +203,9 @@ void ArchNetworkBSD::listenOnSocket(ArchSocket s)
|
||||
|
||||
ArchSocket ArchNetworkBSD::acceptSocket(ArchSocket s, ArchNetAddress *addr)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(s != nullptr);
|
||||
|
||||
// if user passed NULL in addr then use scratch space
|
||||
// if user passed nullptr in addr then use scratch space
|
||||
ArchNetAddress dummy;
|
||||
if (addr == nullptr) {
|
||||
addr = &dummy;
|
||||
@ -258,8 +254,8 @@ ArchSocket ArchNetworkBSD::acceptSocket(ArchSocket s, ArchNetAddress *addr)
|
||||
|
||||
bool ArchNetworkBSD::connectSocket(ArchSocket s, ArchNetAddress addr)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(addr != NULL);
|
||||
assert(s != nullptr);
|
||||
assert(addr != nullptr);
|
||||
|
||||
if (connect(s->m_fd, TYPED_ADDR(struct sockaddr, addr), addr->m_len) == -1) {
|
||||
if (errno == EISCONN) {
|
||||
@ -372,7 +368,7 @@ void ArchNetworkBSD::unblockPollSocket(ArchThread thread)
|
||||
|
||||
size_t ArchNetworkBSD::readSocket(ArchSocket s, void *buf, size_t len)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(s != nullptr);
|
||||
|
||||
ssize_t n = read(s->m_fd, buf, len);
|
||||
if (n == -1) {
|
||||
@ -386,7 +382,7 @@ size_t ArchNetworkBSD::readSocket(ArchSocket s, void *buf, size_t len)
|
||||
|
||||
size_t ArchNetworkBSD::writeSocket(ArchSocket s, const void *buf, size_t len)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(s != nullptr);
|
||||
|
||||
ssize_t n = write(s->m_fd, buf, len);
|
||||
if (n == -1) {
|
||||
@ -400,12 +396,12 @@ size_t ArchNetworkBSD::writeSocket(ArchSocket s, const void *buf, size_t len)
|
||||
|
||||
void ArchNetworkBSD::throwErrorOnSocket(ArchSocket s)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(s != nullptr);
|
||||
|
||||
// get the error from the socket layer
|
||||
int err = 0;
|
||||
auto size = static_cast<socklen_t>(sizeof(err));
|
||||
if (getsockopt(s->m_fd, SOL_SOCKET, SO_ERROR, reinterpret_cast<optval_t *>(&err), &size) == -1) {
|
||||
if (auto size = static_cast<socklen_t>(sizeof(err));
|
||||
getsockopt(s->m_fd, SOL_SOCKET, SO_ERROR, reinterpret_cast<optval_t *>(&err), &size) == -1) {
|
||||
err = errno;
|
||||
}
|
||||
|
||||
@ -415,7 +411,7 @@ void ArchNetworkBSD::throwErrorOnSocket(ArchSocket s)
|
||||
}
|
||||
}
|
||||
|
||||
void ArchNetworkBSD::setBlockingOnSocket(int fd, bool blocking)
|
||||
void ArchNetworkBSD::setBlockingOnSocket(int fd, bool blocking) const
|
||||
{
|
||||
assert(fd != -1);
|
||||
|
||||
@ -435,7 +431,7 @@ void ArchNetworkBSD::setBlockingOnSocket(int fd, bool blocking)
|
||||
|
||||
bool ArchNetworkBSD::setNoDelayOnSocket(ArchSocket s, bool noDelay)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(s != nullptr);
|
||||
|
||||
// get old state
|
||||
int oflag;
|
||||
@ -455,7 +451,7 @@ bool ArchNetworkBSD::setNoDelayOnSocket(ArchSocket s, bool noDelay)
|
||||
|
||||
bool ArchNetworkBSD::setReuseAddrOnSocket(ArchSocket s, bool reuse)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(s != nullptr);
|
||||
|
||||
// get old state
|
||||
int oflag;
|
||||
@ -501,7 +497,7 @@ ArchNetAddress ArchNetworkBSD::newAnyAddr(EAddressFamily family)
|
||||
}
|
||||
|
||||
case kINET6: {
|
||||
struct sockaddr_in6 *ipAddr = TYPED_ADDR(struct sockaddr_in6, addr);
|
||||
auto *ipAddr = TYPED_ADDR(struct sockaddr_in6, addr);
|
||||
ipAddr->sin6_family = AF_INET6;
|
||||
ipAddr->sin6_port = 0;
|
||||
memcpy(&ipAddr->sin6_addr, &in6addr_any, sizeof(in6addr_any));
|
||||
@ -518,7 +514,7 @@ ArchNetAddress ArchNetworkBSD::newAnyAddr(EAddressFamily family)
|
||||
|
||||
ArchNetAddress ArchNetworkBSD::copyAddr(ArchNetAddress addr)
|
||||
{
|
||||
assert(addr != NULL);
|
||||
assert(addr != nullptr);
|
||||
|
||||
// allocate and copy address
|
||||
return new ArchNetAddressImpl(*addr);
|
||||
@ -545,8 +541,8 @@ std::vector<ArchNetAddress> ArchNetworkBSD::nameToAddr(const std::string &name)
|
||||
// done with static buffer
|
||||
ARCH->lockMutex(m_mutex);
|
||||
struct addrinfo *pResult = nullptr;
|
||||
int ret = getaddrinfo(name.c_str(), nullptr, &hints, &pResult);
|
||||
if (ret != 0) {
|
||||
|
||||
if (int ret = getaddrinfo(name.c_str(), nullptr, &hints, &pResult); ret != 0) {
|
||||
ARCH->unlockMutex(m_mutex);
|
||||
throwNameError(ret);
|
||||
}
|
||||
@ -572,22 +568,23 @@ std::vector<ArchNetAddress> ArchNetworkBSD::nameToAddr(const std::string &name)
|
||||
|
||||
void ArchNetworkBSD::closeAddr(ArchNetAddress addr)
|
||||
{
|
||||
assert(addr != NULL);
|
||||
assert(addr != nullptr);
|
||||
|
||||
delete addr;
|
||||
}
|
||||
|
||||
std::string ArchNetworkBSD::addrToName(ArchNetAddress addr)
|
||||
{
|
||||
assert(addr != NULL);
|
||||
assert(addr != nullptr);
|
||||
|
||||
// mutexed name lookup (ugh)
|
||||
ARCH->lockMutex(m_mutex);
|
||||
char host[1024];
|
||||
char service[20];
|
||||
int ret =
|
||||
getnameinfo(TYPED_ADDR(struct sockaddr, addr), addr->m_len, host, sizeof(host), service, sizeof(service), 0);
|
||||
if (ret != 0) {
|
||||
|
||||
if (int ret =
|
||||
getnameinfo(TYPED_ADDR(struct sockaddr, addr), addr->m_len, host, sizeof(host), service, sizeof(service), 0);
|
||||
ret != 0) {
|
||||
ARCH->unlockMutex(m_mutex);
|
||||
throwNameError(ret);
|
||||
}
|
||||
@ -603,11 +600,11 @@ std::string ArchNetworkBSD::addrToName(ArchNetAddress addr)
|
||||
|
||||
std::string ArchNetworkBSD::addrToString(ArchNetAddress addr)
|
||||
{
|
||||
assert(addr != NULL);
|
||||
assert(addr != nullptr);
|
||||
|
||||
switch (getAddrFamily(addr)) {
|
||||
case kINET: {
|
||||
auto *ipAddr = TYPED_ADDR(struct sockaddr_in, addr);
|
||||
const auto *ipAddr = TYPED_ADDR(struct sockaddr_in, addr);
|
||||
ARCH->lockMutex(m_mutex);
|
||||
std::string s = inet_ntoa(ipAddr->sin_addr);
|
||||
ARCH->unlockMutex(m_mutex);
|
||||
@ -616,7 +613,7 @@ std::string ArchNetworkBSD::addrToString(ArchNetAddress addr)
|
||||
|
||||
case kINET6: {
|
||||
char strAddr[INET6_ADDRSTRLEN];
|
||||
struct sockaddr_in6 *ipAddr = TYPED_ADDR(struct sockaddr_in6, addr);
|
||||
const auto *ipAddr = TYPED_ADDR(struct sockaddr_in6, addr);
|
||||
ARCH->lockMutex(m_mutex);
|
||||
inet_ntop(AF_INET6, &ipAddr->sin6_addr, strAddr, INET6_ADDRSTRLEN);
|
||||
ARCH->unlockMutex(m_mutex);
|
||||
@ -631,7 +628,7 @@ std::string ArchNetworkBSD::addrToString(ArchNetAddress addr)
|
||||
|
||||
IArchNetwork::EAddressFamily ArchNetworkBSD::getAddrFamily(ArchNetAddress addr)
|
||||
{
|
||||
assert(addr != NULL);
|
||||
assert(addr != nullptr);
|
||||
|
||||
switch (addr->m_addr.ss_family) {
|
||||
case AF_INET:
|
||||
@ -646,7 +643,7 @@ IArchNetwork::EAddressFamily ArchNetworkBSD::getAddrFamily(ArchNetAddress addr)
|
||||
|
||||
void ArchNetworkBSD::setAddrPort(ArchNetAddress addr, int port)
|
||||
{
|
||||
assert(addr != NULL);
|
||||
assert(addr != nullptr);
|
||||
|
||||
switch (getAddrFamily(addr)) {
|
||||
case kINET: {
|
||||
@ -656,7 +653,7 @@ void ArchNetworkBSD::setAddrPort(ArchNetAddress addr, int port)
|
||||
}
|
||||
|
||||
case kINET6: {
|
||||
struct sockaddr_in6 *ipAddr = TYPED_ADDR(struct sockaddr_in6, addr);
|
||||
auto *ipAddr = TYPED_ADDR(struct sockaddr_in6, addr);
|
||||
ipAddr->sin6_port = htons(port);
|
||||
break;
|
||||
}
|
||||
@ -669,16 +666,16 @@ void ArchNetworkBSD::setAddrPort(ArchNetAddress addr, int port)
|
||||
|
||||
int ArchNetworkBSD::getAddrPort(ArchNetAddress addr)
|
||||
{
|
||||
assert(addr != NULL);
|
||||
assert(addr != nullptr);
|
||||
|
||||
switch (getAddrFamily(addr)) {
|
||||
case kINET: {
|
||||
auto *ipAddr = TYPED_ADDR(struct sockaddr_in, addr);
|
||||
const auto *ipAddr = TYPED_ADDR(struct sockaddr_in, addr);
|
||||
return ntohs(ipAddr->sin_port);
|
||||
}
|
||||
|
||||
case kINET6: {
|
||||
struct sockaddr_in6 *ipAddr = TYPED_ADDR(struct sockaddr_in6, addr);
|
||||
const auto *ipAddr = TYPED_ADDR(struct sockaddr_in6, addr);
|
||||
return ntohs(ipAddr->sin6_port);
|
||||
}
|
||||
|
||||
@ -690,16 +687,16 @@ int ArchNetworkBSD::getAddrPort(ArchNetAddress addr)
|
||||
|
||||
bool ArchNetworkBSD::isAnyAddr(ArchNetAddress addr)
|
||||
{
|
||||
assert(addr != NULL);
|
||||
assert(addr != nullptr);
|
||||
|
||||
switch (getAddrFamily(addr)) {
|
||||
case kINET: {
|
||||
auto *ipAddr = TYPED_ADDR(struct sockaddr_in, addr);
|
||||
const auto *ipAddr = TYPED_ADDR(struct sockaddr_in, addr);
|
||||
return (ipAddr->sin_addr.s_addr == INADDR_ANY && addr->m_len == static_cast<socklen_t>(sizeof(struct sockaddr_in)));
|
||||
}
|
||||
|
||||
case kINET6: {
|
||||
struct sockaddr_in6 *ipAddr = TYPED_ADDR(struct sockaddr_in6, addr);
|
||||
const auto *ipAddr = TYPED_ADDR(struct sockaddr_in6, addr);
|
||||
return (
|
||||
addr->m_len == (socklen_t)sizeof(struct sockaddr_in6) &&
|
||||
memcmp(
|
||||
@ -750,16 +747,16 @@ const int *ArchNetworkBSD::getUnblockPipeForThread(ArchThread thread)
|
||||
return unblockPipe;
|
||||
}
|
||||
|
||||
void ArchNetworkBSD::throwError(int err)
|
||||
void ArchNetworkBSD::throwError(int err) const
|
||||
{
|
||||
switch (err) {
|
||||
case EINTR:
|
||||
ARCH->testCancelThread();
|
||||
throw XArchNetworkInterrupted(new XArchEvalUnix(err));
|
||||
throw XArchNetworkInterrupted(errorToString(err));
|
||||
|
||||
case EACCES:
|
||||
case EPERM:
|
||||
throw XArchNetworkAccess(new XArchEvalUnix(err));
|
||||
throw XArchNetworkAccess(errorToString(err));
|
||||
|
||||
case ENFILE:
|
||||
case EMFILE:
|
||||
@ -770,7 +767,7 @@ void ArchNetworkBSD::throwError(int err)
|
||||
#if defined(ENOSR)
|
||||
case ENOSR:
|
||||
#endif
|
||||
throw XArchNetworkResource(new XArchEvalUnix(err));
|
||||
throw XArchNetworkResource(errorToString(err));
|
||||
|
||||
case EPROTOTYPE:
|
||||
case EPROTONOSUPPORT:
|
||||
@ -784,44 +781,44 @@ void ArchNetworkBSD::throwError(int err)
|
||||
#if defined(ENOPKG)
|
||||
case ENOPKG:
|
||||
#endif
|
||||
throw XArchNetworkSupport(new XArchEvalUnix(err));
|
||||
throw XArchNetworkSupport(errorToString(err));
|
||||
|
||||
case EIO:
|
||||
throw XArchNetworkIO(new XArchEvalUnix(err));
|
||||
throw XArchNetworkIO(errorToString(err));
|
||||
|
||||
case EADDRNOTAVAIL:
|
||||
throw XArchNetworkNoAddress(new XArchEvalUnix(err));
|
||||
throw XArchNetworkNoAddress(errorToString(err));
|
||||
|
||||
case EADDRINUSE:
|
||||
throw XArchNetworkAddressInUse(new XArchEvalUnix(err));
|
||||
throw XArchNetworkAddressInUse(errorToString(err));
|
||||
|
||||
case EHOSTUNREACH:
|
||||
case ENETUNREACH:
|
||||
throw XArchNetworkNoRoute(new XArchEvalUnix(err));
|
||||
throw XArchNetworkNoRoute(errorToString(err));
|
||||
|
||||
case ENOTCONN:
|
||||
throw XArchNetworkNotConnected(new XArchEvalUnix(err));
|
||||
throw XArchNetworkNotConnected(errorToString(err));
|
||||
|
||||
case EPIPE:
|
||||
throw XArchNetworkShutdown(new XArchEvalUnix(err));
|
||||
throw XArchNetworkShutdown(errorToString(err));
|
||||
|
||||
case ECONNABORTED:
|
||||
case ECONNRESET:
|
||||
throw XArchNetworkDisconnected(new XArchEvalUnix(err));
|
||||
throw XArchNetworkDisconnected(errorToString(err));
|
||||
|
||||
case ECONNREFUSED:
|
||||
throw XArchNetworkConnectionRefused(new XArchEvalUnix(err));
|
||||
throw XArchNetworkConnectionRefused(errorToString(err));
|
||||
|
||||
case EHOSTDOWN:
|
||||
case ETIMEDOUT:
|
||||
throw XArchNetworkTimedOut(new XArchEvalUnix(err));
|
||||
throw XArchNetworkTimedOut(errorToString(err));
|
||||
|
||||
default:
|
||||
throw XArchNetwork(new XArchEvalUnix(err));
|
||||
throw XArchNetwork(errorToString(err));
|
||||
}
|
||||
}
|
||||
|
||||
void ArchNetworkBSD::throwNameError(int err)
|
||||
void ArchNetworkBSD::throwNameError(int err) const
|
||||
{
|
||||
static const char *s_msg[] = {
|
||||
"The specified host is unknown", "The requested name is valid but does not have an IP address",
|
||||
|
||||
@ -55,6 +55,7 @@ class ArchNetAddressImpl
|
||||
public:
|
||||
ArchNetAddressImpl() : m_len(sizeof(m_addr))
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public:
|
||||
@ -122,9 +123,9 @@ public:
|
||||
private:
|
||||
const int *getUnblockPipe();
|
||||
const int *getUnblockPipeForThread(ArchThread);
|
||||
void setBlockingOnSocket(int fd, bool blocking);
|
||||
void throwError(int);
|
||||
void throwNameError(int);
|
||||
void setBlockingOnSocket(int fd, bool blocking) const;
|
||||
void throwError(int) const;
|
||||
void throwNameError(int) const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<Deps> m_pDeps;
|
||||
|
||||
@ -35,16 +35,6 @@
|
||||
// ArchSleepUnix
|
||||
//
|
||||
|
||||
ArchSleepUnix::ArchSleepUnix()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
ArchSleepUnix::~ArchSleepUnix()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void ArchSleepUnix::sleep(double timeout)
|
||||
{
|
||||
ARCH->testCancelThread();
|
||||
@ -70,7 +60,7 @@ void ArchSleepUnix::sleep(double timeout)
|
||||
timeout2.tv_sec = static_cast<int>(timeLeft);
|
||||
timeout2.tv_usec = static_cast<int>(1.0e+6 * (timeLeft - timeout2.tv_sec));
|
||||
select(
|
||||
(SELECT_TYPE_ARG1)0, SELECT_TYPE_ARG234 NULL, SELECT_TYPE_ARG234 NULL, SELECT_TYPE_ARG234 NULL,
|
||||
(SELECT_TYPE_ARG1)0, SELECT_TYPE_ARG234 nullptr, SELECT_TYPE_ARG234 nullptr, SELECT_TYPE_ARG234 nullptr,
|
||||
SELECT_TYPE_ARG5 & timeout2
|
||||
);
|
||||
ARCH->testCancelThread();
|
||||
|
||||
@ -15,9 +15,9 @@
|
||||
class ArchSleepUnix : public IArchSleep
|
||||
{
|
||||
public:
|
||||
ArchSleepUnix();
|
||||
virtual ~ArchSleepUnix();
|
||||
ArchSleepUnix() = default;
|
||||
~ArchSleepUnix() override = default;
|
||||
|
||||
// IArchSleep overrides
|
||||
virtual void sleep(double timeout);
|
||||
void sleep(double timeout) override;
|
||||
};
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "arch/unix/ArchStringUnix.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
//
|
||||
// ArchStringUnix
|
||||
//
|
||||
|
||||
ArchStringUnix::ArchStringUnix()
|
||||
{
|
||||
}
|
||||
|
||||
ArchStringUnix::~ArchStringUnix()
|
||||
{
|
||||
}
|
||||
|
||||
IArchString::EWideCharEncoding ArchStringUnix::getWideCharEncoding()
|
||||
{
|
||||
return kUCS4;
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "arch/IArchString.h"
|
||||
|
||||
#define ARCH_STRING ArchStringUnix
|
||||
|
||||
//! Unix implementation of IArchString
|
||||
class ArchStringUnix : public IArchString
|
||||
{
|
||||
public:
|
||||
ArchStringUnix();
|
||||
virtual ~ArchStringUnix();
|
||||
|
||||
// IArchString overrides
|
||||
virtual EWideCharEncoding getWideCharEncoding();
|
||||
};
|
||||
@ -22,19 +22,9 @@
|
||||
// ArchTimeUnix
|
||||
//
|
||||
|
||||
ArchTimeUnix::ArchTimeUnix()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
ArchTimeUnix::~ArchTimeUnix()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
double ArchTimeUnix::time()
|
||||
{
|
||||
struct timeval t;
|
||||
gettimeofday(&t, NULL);
|
||||
gettimeofday(&t, nullptr);
|
||||
return (double)t.tv_sec + 1.0e-6 * (double)t.tv_usec;
|
||||
}
|
||||
|
||||
@ -15,9 +15,9 @@
|
||||
class ArchTimeUnix : public IArchTime
|
||||
{
|
||||
public:
|
||||
ArchTimeUnix();
|
||||
virtual ~ArchTimeUnix();
|
||||
ArchTimeUnix() = default;
|
||||
~ArchTimeUnix() override = default;
|
||||
|
||||
// IArchTime overrides
|
||||
virtual double time();
|
||||
double time() override;
|
||||
};
|
||||
|
||||
@ -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
|
||||
@ -9,12 +10,8 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
//
|
||||
// XArchEvalUnix
|
||||
//
|
||||
|
||||
std::string XArchEvalUnix::eval() const
|
||||
std::string errorToString(int error)
|
||||
{
|
||||
// FIXME -- not thread safe
|
||||
return strerror(m_error);
|
||||
return std::strerror(error);
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -7,21 +8,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "arch/XArch.h"
|
||||
#include <string>
|
||||
|
||||
//! Lazy error message string evaluation for unix
|
||||
class XArchEvalUnix : public XArchEval
|
||||
{
|
||||
public:
|
||||
XArchEvalUnix(int error) : m_error(error)
|
||||
{
|
||||
}
|
||||
virtual ~XArchEvalUnix() throw()
|
||||
{
|
||||
}
|
||||
|
||||
virtual std::string eval() const;
|
||||
|
||||
private:
|
||||
int m_error;
|
||||
};
|
||||
std::string errorToString(int error);
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "arch/win32/ArchConsoleWindows.h"
|
||||
|
||||
ArchConsoleWindows::ArchConsoleWindows()
|
||||
{
|
||||
}
|
||||
|
||||
ArchConsoleWindows::~ArchConsoleWindows()
|
||||
{
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "arch/ArchConsoleStd.h"
|
||||
|
||||
#define ARCH_CONSOLE ArchConsoleWindows
|
||||
|
||||
class ArchConsoleWindows : public ArchConsoleStd
|
||||
{
|
||||
public:
|
||||
ArchConsoleWindows();
|
||||
virtual ~ArchConsoleWindows();
|
||||
};
|
||||
@ -8,6 +8,7 @@
|
||||
#include "arch/win32/ArchDaemonWindows.h"
|
||||
|
||||
#include "arch/Arch.h"
|
||||
#include "arch/XArch.h"
|
||||
#include "arch/win32/ArchMiscWindows.h"
|
||||
#include "arch/win32/XArchWindows.h"
|
||||
#include "base/Log.h"
|
||||
@ -16,34 +17,29 @@
|
||||
// ArchDaemonWindows
|
||||
//
|
||||
|
||||
ArchDaemonWindows *ArchDaemonWindows::s_daemon = NULL;
|
||||
ArchDaemonWindows *ArchDaemonWindows::s_daemon = nullptr;
|
||||
|
||||
ArchDaemonWindows::ArchDaemonWindows() : m_daemonThreadID(0)
|
||||
{
|
||||
m_quitMessage = RegisterWindowMessage("DeskflowDaemonExit");
|
||||
}
|
||||
|
||||
ArchDaemonWindows::~ArchDaemonWindows()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
int ArchDaemonWindows::runDaemon(RunFunc runFunc)
|
||||
{
|
||||
assert(s_daemon != NULL);
|
||||
assert(s_daemon != nullptr);
|
||||
return s_daemon->doRunDaemon(runFunc);
|
||||
}
|
||||
|
||||
void ArchDaemonWindows::daemonRunning(bool running)
|
||||
{
|
||||
if (s_daemon != NULL) {
|
||||
if (s_daemon != nullptr) {
|
||||
s_daemon->doDaemonRunning(running);
|
||||
}
|
||||
}
|
||||
|
||||
UINT ArchDaemonWindows::getDaemonQuitMessage()
|
||||
{
|
||||
if (s_daemon != NULL) {
|
||||
if (s_daemon != nullptr) {
|
||||
return s_daemon->doGetDaemonQuitMessage();
|
||||
} else {
|
||||
return 0;
|
||||
@ -52,7 +48,7 @@ UINT ArchDaemonWindows::getDaemonQuitMessage()
|
||||
|
||||
void ArchDaemonWindows::daemonFailed(int result)
|
||||
{
|
||||
assert(s_daemon != NULL);
|
||||
assert(s_daemon != nullptr);
|
||||
throw XArchDaemonRunFailed(result);
|
||||
}
|
||||
|
||||
@ -63,24 +59,24 @@ void ArchDaemonWindows::installDaemon(
|
||||
LOG_DEBUG("installing windows service: %s", name);
|
||||
|
||||
// open service manager
|
||||
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE);
|
||||
if (mgr == NULL) {
|
||||
SC_HANDLE mgr = OpenSCManager(nullptr, nullptr, GENERIC_WRITE);
|
||||
if (mgr == nullptr) {
|
||||
// can't open service manager
|
||||
throw XArchDaemonInstallFailed(new XArchEvalWindows);
|
||||
throw XArchDaemonInstallFailed(windowsErrorToString(GetLastError()));
|
||||
}
|
||||
|
||||
// create the service
|
||||
SC_HANDLE service = CreateService(
|
||||
mgr, name, name, 0, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, SERVICE_AUTO_START,
|
||||
SERVICE_ERROR_NORMAL, pathname, NULL, NULL, dependencies, NULL, NULL
|
||||
SERVICE_ERROR_NORMAL, pathname, nullptr, nullptr, dependencies, nullptr, nullptr
|
||||
);
|
||||
|
||||
if (service == NULL) {
|
||||
if (service == nullptr) {
|
||||
// can't create service
|
||||
DWORD err = GetLastError();
|
||||
if (err != ERROR_SERVICE_EXISTS) {
|
||||
CloseServiceHandle(mgr);
|
||||
throw XArchDaemonInstallFailed(new XArchEvalWindows(err));
|
||||
throw XArchDaemonInstallFailed(windowsErrorToString(err));
|
||||
}
|
||||
} else {
|
||||
// done with service (but only try to close if not null)
|
||||
@ -93,7 +89,7 @@ void ArchDaemonWindows::installDaemon(
|
||||
// open the registry key for this service
|
||||
HKEY key = openNTServicesKey();
|
||||
key = ArchMiscWindows::addKey(key, name);
|
||||
if (key == NULL) {
|
||||
if (key == nullptr) {
|
||||
// can't open key
|
||||
DWORD err = GetLastError();
|
||||
try {
|
||||
@ -101,7 +97,7 @@ void ArchDaemonWindows::installDaemon(
|
||||
} catch (...) {
|
||||
// ignore
|
||||
}
|
||||
throw XArchDaemonInstallFailed(new XArchEvalWindows(err));
|
||||
throw XArchDaemonInstallFailed(windowsErrorToString(err));
|
||||
}
|
||||
|
||||
// set the description
|
||||
@ -109,7 +105,7 @@ void ArchDaemonWindows::installDaemon(
|
||||
|
||||
// set command line
|
||||
key = ArchMiscWindows::addKey(key, _T("Parameters"));
|
||||
if (key == NULL) {
|
||||
if (key == nullptr) {
|
||||
// can't open key
|
||||
DWORD err = GetLastError();
|
||||
ArchMiscWindows::closeKey(key);
|
||||
@ -118,7 +114,7 @@ void ArchDaemonWindows::installDaemon(
|
||||
} catch (...) {
|
||||
// ignore
|
||||
}
|
||||
throw XArchDaemonInstallFailed(new XArchEvalWindows(err));
|
||||
throw XArchDaemonInstallFailed(windowsErrorToString(err));
|
||||
}
|
||||
ArchMiscWindows::setValue(key, _T("CommandLine"), commandLine);
|
||||
|
||||
@ -133,27 +129,27 @@ void ArchDaemonWindows::uninstallDaemon(const char *name)
|
||||
// remove parameters for this service. ignore failures.
|
||||
HKEY key = openNTServicesKey();
|
||||
key = ArchMiscWindows::openKey(key, name);
|
||||
if (key != NULL) {
|
||||
if (key != nullptr) {
|
||||
ArchMiscWindows::deleteKey(key, _T("Parameters"));
|
||||
ArchMiscWindows::closeKey(key);
|
||||
}
|
||||
|
||||
// open service manager
|
||||
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE);
|
||||
if (mgr == NULL) {
|
||||
SC_HANDLE mgr = OpenSCManager(nullptr, nullptr, GENERIC_WRITE);
|
||||
if (mgr == nullptr) {
|
||||
// can't open service manager
|
||||
throw XArchDaemonUninstallFailed(new XArchEvalWindows);
|
||||
throw XArchDaemonUninstallFailed(windowsErrorToString(GetLastError()));
|
||||
}
|
||||
|
||||
// open the service. oddly, you must open a service to delete it.
|
||||
SC_HANDLE service = OpenService(mgr, name, DELETE | SERVICE_STOP);
|
||||
if (service == NULL) {
|
||||
if (service == nullptr) {
|
||||
DWORD err = GetLastError();
|
||||
CloseServiceHandle(mgr);
|
||||
if (err != ERROR_SERVICE_DOES_NOT_EXIST) {
|
||||
throw XArchDaemonUninstallFailed(new XArchEvalWindows(err));
|
||||
throw XArchDaemonUninstallFailed(windowsErrorToString(err));
|
||||
}
|
||||
throw XArchDaemonUninstallNotInstalled(new XArchEvalWindows(err));
|
||||
throw XArchDaemonUninstallNotInstalled(windowsErrorToString(err));
|
||||
}
|
||||
|
||||
// stop the service. we don't care if we fail.
|
||||
@ -186,16 +182,16 @@ void ArchDaemonWindows::uninstallDaemon(const char *name)
|
||||
return;
|
||||
}
|
||||
if (err != ERROR_SERVICE_MARKED_FOR_DELETE) {
|
||||
throw XArchDaemonUninstallFailed(new XArchEvalWindows(err));
|
||||
throw XArchDaemonUninstallFailed(windowsErrorToString(err));
|
||||
}
|
||||
throw XArchDaemonUninstallNotInstalled(new XArchEvalWindows(err));
|
||||
throw XArchDaemonUninstallNotInstalled(windowsErrorToString(err));
|
||||
}
|
||||
}
|
||||
|
||||
int ArchDaemonWindows::daemonize(const char *name, DaemonFunc func)
|
||||
int ArchDaemonWindows::daemonize(const char *name, DaemonFunc const &func)
|
||||
{
|
||||
assert(name != NULL);
|
||||
assert(func != NULL);
|
||||
assert(name != nullptr);
|
||||
assert(func != nullptr);
|
||||
|
||||
// save daemon function
|
||||
m_daemonFunc = func;
|
||||
@ -204,27 +200,27 @@ int ArchDaemonWindows::daemonize(const char *name, DaemonFunc func)
|
||||
SERVICE_TABLE_ENTRY entry[2];
|
||||
entry[0].lpServiceName = const_cast<char *>(name);
|
||||
entry[0].lpServiceProc = &ArchDaemonWindows::serviceMainEntry;
|
||||
entry[1].lpServiceName = NULL;
|
||||
entry[1].lpServiceProc = NULL;
|
||||
entry[1].lpServiceName = nullptr;
|
||||
entry[1].lpServiceProc = nullptr;
|
||||
|
||||
// hook us up to the service control manager. this won't return
|
||||
// (if successful) until the processes have terminated.
|
||||
s_daemon = this;
|
||||
if (StartServiceCtrlDispatcher(entry) == 0) {
|
||||
// StartServiceCtrlDispatcher failed
|
||||
s_daemon = NULL;
|
||||
throw XArchDaemonFailed(new XArchEvalWindows);
|
||||
s_daemon = nullptr;
|
||||
throw XArchDaemonFailed(windowsErrorToString(GetLastError()));
|
||||
}
|
||||
|
||||
s_daemon = NULL;
|
||||
s_daemon = nullptr;
|
||||
return m_daemonResult;
|
||||
}
|
||||
|
||||
bool ArchDaemonWindows::canInstallDaemon(const char * /*name*/)
|
||||
{
|
||||
// check if we can open service manager for write
|
||||
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE);
|
||||
if (mgr == NULL) {
|
||||
SC_HANDLE mgr = OpenSCManager(nullptr, nullptr, GENERIC_WRITE);
|
||||
if (mgr == nullptr) {
|
||||
return false;
|
||||
}
|
||||
CloseServiceHandle(mgr);
|
||||
@ -233,14 +229,14 @@ bool ArchDaemonWindows::canInstallDaemon(const char * /*name*/)
|
||||
HKEY key = openNTServicesKey();
|
||||
ArchMiscWindows::closeKey(key);
|
||||
|
||||
return (key != NULL);
|
||||
return (key != nullptr);
|
||||
}
|
||||
|
||||
bool ArchDaemonWindows::isDaemonInstalled(const char *name)
|
||||
{
|
||||
// open service manager
|
||||
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_READ);
|
||||
if (mgr == NULL) {
|
||||
SC_HANDLE mgr = OpenSCManager(nullptr, nullptr, GENERIC_READ);
|
||||
if (mgr == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -248,17 +244,17 @@ bool ArchDaemonWindows::isDaemonInstalled(const char *name)
|
||||
SC_HANDLE service = OpenService(mgr, name, GENERIC_READ);
|
||||
|
||||
// clean up
|
||||
if (service != NULL) {
|
||||
if (service != nullptr) {
|
||||
CloseServiceHandle(service);
|
||||
}
|
||||
CloseServiceHandle(mgr);
|
||||
|
||||
return (service != NULL);
|
||||
return (service != nullptr);
|
||||
}
|
||||
|
||||
HKEY ArchDaemonWindows::openNTServicesKey()
|
||||
{
|
||||
static const char *s_keyNames[] = {_T("SYSTEM"), _T("CurrentControlSet"), _T("Services"), NULL};
|
||||
static const char *s_keyNames[] = {_T("SYSTEM"), _T("CurrentControlSet"), _T("Services"), nullptr};
|
||||
|
||||
return ArchMiscWindows::addKey(HKEY_LOCAL_MACHINE, s_keyNames);
|
||||
}
|
||||
@ -279,12 +275,12 @@ bool ArchDaemonWindows::isRunState(DWORD state)
|
||||
int ArchDaemonWindows::doRunDaemon(RunFunc run)
|
||||
{
|
||||
// should only be called from DaemonFunc
|
||||
assert(m_serviceMutex != NULL);
|
||||
assert(run != NULL);
|
||||
assert(m_serviceMutex != nullptr);
|
||||
assert(run != nullptr);
|
||||
|
||||
// create message queue for this thread
|
||||
MSG dummy;
|
||||
PeekMessage(&dummy, NULL, 0, 0, PM_NOREMOVE);
|
||||
PeekMessage(&dummy, nullptr, 0, 0, PM_NOREMOVE);
|
||||
|
||||
int result = 0;
|
||||
ARCH->lockMutex(m_serviceMutex);
|
||||
@ -348,7 +344,7 @@ void ArchDaemonWindows::setStatus(DWORD state)
|
||||
|
||||
void ArchDaemonWindows::setStatus(DWORD state, DWORD step, DWORD waitHint)
|
||||
{
|
||||
assert(s_daemon != NULL);
|
||||
assert(s_daemon != nullptr);
|
||||
|
||||
LOG_DEBUG("setting service status: state=%d, step=%d, waitHint=%d", state, step, waitHint);
|
||||
|
||||
@ -365,7 +361,7 @@ void ArchDaemonWindows::setStatus(DWORD state, DWORD step, DWORD waitHint)
|
||||
|
||||
void ArchDaemonWindows::setStatusError(DWORD error)
|
||||
{
|
||||
assert(s_daemon != NULL);
|
||||
assert(s_daemon != nullptr);
|
||||
|
||||
SERVICE_STATUS status;
|
||||
status.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;
|
||||
@ -413,7 +409,7 @@ void ArchDaemonWindows::serviceMain(DWORD argc, LPTSTR *argvIn)
|
||||
HKEY key = openNTServicesKey();
|
||||
key = ArchMiscWindows::openKey(key, argvIn[0]);
|
||||
key = ArchMiscWindows::openKey(key, _T("Parameters"));
|
||||
if (key != NULL) {
|
||||
if (key != nullptr) {
|
||||
commandLine = ArchMiscWindows::readValueString(key, _T("CommandLine"));
|
||||
}
|
||||
|
||||
@ -498,14 +494,14 @@ void WINAPI ArchDaemonWindows::serviceMainEntry(DWORD argc, LPTSTR *argv)
|
||||
|
||||
void ArchDaemonWindows::serviceHandler(DWORD ctrl)
|
||||
{
|
||||
assert(m_serviceMutex != NULL);
|
||||
assert(m_serviceCondVar != NULL);
|
||||
assert(m_serviceMutex != nullptr);
|
||||
assert(m_serviceCondVar != nullptr);
|
||||
|
||||
ARCH->lockMutex(m_serviceMutex);
|
||||
|
||||
// ignore request if service is already stopped
|
||||
if (s_daemon == NULL || m_serviceState == SERVICE_STOPPED) {
|
||||
if (s_daemon != NULL) {
|
||||
if (s_daemon == nullptr || m_serviceState == SERVICE_STOPPED) {
|
||||
if (s_daemon != nullptr) {
|
||||
setStatus(m_serviceState);
|
||||
}
|
||||
ARCH->unlockMutex(m_serviceMutex);
|
||||
@ -560,39 +556,39 @@ void WINAPI ArchDaemonWindows::serviceHandlerEntry(DWORD ctrl)
|
||||
void ArchDaemonWindows::start(const char *name)
|
||||
{
|
||||
// open service manager
|
||||
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_READ);
|
||||
if (mgr == NULL) {
|
||||
throw XArchDaemonFailed(new XArchEvalWindows());
|
||||
SC_HANDLE mgr = OpenSCManager(nullptr, nullptr, GENERIC_READ);
|
||||
if (mgr == nullptr) {
|
||||
throw XArchDaemonFailed(windowsErrorToString(GetLastError()));
|
||||
}
|
||||
|
||||
// open the service
|
||||
SC_HANDLE service = OpenService(mgr, name, SERVICE_START);
|
||||
|
||||
if (service == NULL) {
|
||||
if (service == nullptr) {
|
||||
CloseServiceHandle(mgr);
|
||||
throw XArchDaemonFailed(new XArchEvalWindows());
|
||||
throw XArchDaemonFailed(windowsErrorToString(GetLastError()));
|
||||
}
|
||||
|
||||
// start the service
|
||||
if (!StartService(service, 0, NULL)) {
|
||||
throw XArchDaemonFailed(new XArchEvalWindows());
|
||||
if (!StartService(service, 0, nullptr)) {
|
||||
throw XArchDaemonFailed(windowsErrorToString(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
void ArchDaemonWindows::stop(const char *name)
|
||||
{
|
||||
// open service manager
|
||||
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_READ);
|
||||
if (mgr == NULL) {
|
||||
throw XArchDaemonFailed(new XArchEvalWindows());
|
||||
SC_HANDLE mgr = OpenSCManager(nullptr, nullptr, GENERIC_READ);
|
||||
if (mgr == nullptr) {
|
||||
throw XArchDaemonFailed(windowsErrorToString(GetLastError()));
|
||||
}
|
||||
|
||||
// open the service
|
||||
SC_HANDLE service = OpenService(mgr, name, SERVICE_STOP | SERVICE_QUERY_STATUS);
|
||||
|
||||
if (service == NULL) {
|
||||
if (service == nullptr) {
|
||||
CloseServiceHandle(mgr);
|
||||
throw XArchDaemonFailed(new XArchEvalWindows());
|
||||
throw XArchDaemonFailed(windowsErrorToString(GetLastError()));
|
||||
}
|
||||
|
||||
// ask the service to stop, asynchronously
|
||||
@ -600,7 +596,7 @@ void ArchDaemonWindows::stop(const char *name)
|
||||
if (!ControlService(service, SERVICE_CONTROL_STOP, &ss)) {
|
||||
DWORD dwErrCode = GetLastError();
|
||||
if (dwErrCode != ERROR_SERVICE_NOT_ACTIVE) {
|
||||
throw XArchDaemonFailed(new XArchEvalWindows());
|
||||
throw XArchDaemonFailed(windowsErrorToString(GetLastError()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ public:
|
||||
using RunFunc = std::function<int()>;
|
||||
|
||||
ArchDaemonWindows();
|
||||
virtual ~ArchDaemonWindows();
|
||||
~ArchDaemonWindows() override = default;
|
||||
|
||||
//! Run the daemon
|
||||
/*!
|
||||
@ -68,15 +68,15 @@ public:
|
||||
static UINT getDaemonQuitMessage();
|
||||
|
||||
// IArchDaemon overrides
|
||||
virtual void installDaemon(
|
||||
void installDaemon(
|
||||
const char *name, const char *description, const char *pathname, const char *commandLine, const char *dependencies
|
||||
);
|
||||
virtual void uninstallDaemon(const char *name);
|
||||
virtual void installDaemon();
|
||||
virtual void uninstallDaemon();
|
||||
virtual int daemonize(const char *name, DaemonFunc func);
|
||||
virtual bool canInstallDaemon(const char *name);
|
||||
virtual bool isDaemonInstalled(const char *name);
|
||||
) override;
|
||||
void uninstallDaemon(const char *name) override;
|
||||
void installDaemon() override;
|
||||
void uninstallDaemon() override;
|
||||
int daemonize(const char *name, DaemonFunc const &func) override;
|
||||
bool canInstallDaemon(const char *name) override;
|
||||
bool isDaemonInstalled(const char *name) override;
|
||||
std::string commandLine() const
|
||||
{
|
||||
return m_commandLine;
|
||||
|
||||
@ -14,28 +14,23 @@
|
||||
// ArchLogWindows
|
||||
//
|
||||
|
||||
ArchLogWindows::ArchLogWindows() : m_eventLog(NULL)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
ArchLogWindows::~ArchLogWindows()
|
||||
ArchLogWindows::ArchLogWindows() : m_eventLog(nullptr)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void ArchLogWindows::openLog(const char *name)
|
||||
{
|
||||
if (m_eventLog == NULL) {
|
||||
m_eventLog = RegisterEventSource(NULL, name);
|
||||
if (m_eventLog == nullptr) {
|
||||
m_eventLog = RegisterEventSource(nullptr, name);
|
||||
}
|
||||
}
|
||||
|
||||
void ArchLogWindows::closeLog()
|
||||
{
|
||||
if (m_eventLog != NULL) {
|
||||
if (m_eventLog != nullptr) {
|
||||
DeregisterEventSource(m_eventLog);
|
||||
m_eventLog = NULL;
|
||||
m_eventLog = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,7 +41,7 @@ void ArchLogWindows::showLog(bool)
|
||||
|
||||
void ArchLogWindows::writeLog(ELevel level, const char *msg)
|
||||
{
|
||||
if (m_eventLog != NULL) {
|
||||
if (m_eventLog != nullptr) {
|
||||
// convert priority
|
||||
WORD type;
|
||||
switch (level) {
|
||||
@ -72,9 +67,9 @@ void ArchLogWindows::writeLog(ELevel level, const char *msg)
|
||||
ReportEvent(
|
||||
m_eventLog, type, static_cast<WORD>(level),
|
||||
0, // event ID
|
||||
NULL, 0,
|
||||
nullptr, 0,
|
||||
(DWORD)strlen(msg) + 1, // raw data size
|
||||
NULL,
|
||||
nullptr,
|
||||
const_cast<char *>(msg)
|
||||
); // raw data
|
||||
}
|
||||
|
||||
@ -19,13 +19,13 @@ class ArchLogWindows : public IArchLog
|
||||
{
|
||||
public:
|
||||
ArchLogWindows();
|
||||
virtual ~ArchLogWindows();
|
||||
~ArchLogWindows() override = default;
|
||||
|
||||
// IArchLog overrides
|
||||
virtual void openLog(const char *name);
|
||||
virtual void closeLog();
|
||||
virtual void showLog(bool showIfEmpty);
|
||||
virtual void writeLog(ELevel, const char *);
|
||||
void openLog(const char *name) override;
|
||||
void closeLog() override;
|
||||
void showLog(bool showIfEmpty) override;
|
||||
void writeLog(ELevel, const char *) override;
|
||||
|
||||
private:
|
||||
HANDLE m_eventLog;
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
#include "arch/win32/ArchMiscWindows.h"
|
||||
|
||||
#include "arch/XArch.h"
|
||||
#include "arch/win32/ArchDaemonWindows.h"
|
||||
#include "arch/win32/XArchWindows.h"
|
||||
#include "base/Log.h"
|
||||
@ -31,7 +32,7 @@ void errorMessageBox(const char *message, const char *title = "Fatal Error");
|
||||
std::string getBinaryName()
|
||||
{
|
||||
std::array<char, MAX_PATH> buffer;
|
||||
if (!GetModuleFileNameA(NULL, buffer.data(), MAX_PATH)) {
|
||||
if (!GetModuleFileNameA(nullptr, buffer.data(), MAX_PATH)) {
|
||||
errorMessageBox("Failed to get binary name.");
|
||||
abort();
|
||||
}
|
||||
@ -52,10 +53,10 @@ const std::string s_binaryName = getBinaryName();
|
||||
//
|
||||
|
||||
DWORD ArchMiscWindows::s_busyState = 0;
|
||||
ArchMiscWindows::STES_t ArchMiscWindows::s_stes = NULL;
|
||||
HICON ArchMiscWindows::s_largeIcon = NULL;
|
||||
HICON ArchMiscWindows::s_smallIcon = NULL;
|
||||
HINSTANCE ArchMiscWindows::s_instanceWin32 = NULL;
|
||||
ArchMiscWindows::STES_t ArchMiscWindows::s_stes = nullptr;
|
||||
HICON ArchMiscWindows::s_largeIcon = nullptr;
|
||||
HICON ArchMiscWindows::s_smallIcon = nullptr;
|
||||
HINSTANCE ArchMiscWindows::s_instanceWin32 = nullptr;
|
||||
|
||||
void ArchMiscWindows::init()
|
||||
{
|
||||
@ -105,9 +106,9 @@ HKEY ArchMiscWindows::addKey(HKEY key, const TCHAR *const *keyNames)
|
||||
|
||||
HKEY ArchMiscWindows::openKey(HKEY key, const TCHAR *keyName, bool create)
|
||||
{
|
||||
// ignore if parent is NULL
|
||||
if (key == NULL) {
|
||||
return NULL;
|
||||
// ignore if parent is nullptr
|
||||
if (key == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// open next key
|
||||
@ -115,11 +116,11 @@ HKEY ArchMiscWindows::openKey(HKEY key, const TCHAR *keyName, bool create)
|
||||
LSTATUS result = RegOpenKeyEx(key, keyName, 0, KEY_WRITE | KEY_QUERY_VALUE, &newKey);
|
||||
if (result != ERROR_SUCCESS && create) {
|
||||
DWORD disp;
|
||||
result = RegCreateKeyEx(key, keyName, 0, NULL, 0, KEY_WRITE | KEY_QUERY_VALUE, NULL, &newKey, &disp);
|
||||
result = RegCreateKeyEx(key, keyName, 0, nullptr, 0, KEY_WRITE | KEY_QUERY_VALUE, nullptr, &newKey, &disp);
|
||||
}
|
||||
if (result != ERROR_SUCCESS) {
|
||||
RegCloseKey(key);
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// switch to new key
|
||||
@ -129,7 +130,7 @@ HKEY ArchMiscWindows::openKey(HKEY key, const TCHAR *keyName, bool create)
|
||||
|
||||
HKEY ArchMiscWindows::openKey(HKEY key, const TCHAR *const *keyNames, bool create)
|
||||
{
|
||||
for (size_t i = 0; key != NULL && keyNames[i] != NULL; ++i) {
|
||||
for (size_t i = 0; key != nullptr && keyNames[i] != nullptr; ++i) {
|
||||
// open next key
|
||||
key = openKey(key, keyNames[i], create);
|
||||
}
|
||||
@ -138,17 +139,17 @@ HKEY ArchMiscWindows::openKey(HKEY key, const TCHAR *const *keyNames, bool creat
|
||||
|
||||
void ArchMiscWindows::closeKey(HKEY key)
|
||||
{
|
||||
assert(key != NULL);
|
||||
if (key == NULL)
|
||||
assert(key != nullptr);
|
||||
if (key == nullptr)
|
||||
return;
|
||||
RegCloseKey(key);
|
||||
}
|
||||
|
||||
void ArchMiscWindows::deleteKey(HKEY key, const TCHAR *name)
|
||||
{
|
||||
assert(key != NULL);
|
||||
assert(name != NULL);
|
||||
if (key == NULL || name == NULL)
|
||||
assert(key != nullptr);
|
||||
assert(name != nullptr);
|
||||
if (key == nullptr || name == nullptr)
|
||||
return;
|
||||
RegDeleteKey(key, name);
|
||||
}
|
||||
@ -156,7 +157,7 @@ void ArchMiscWindows::deleteKey(HKEY key, const TCHAR *name)
|
||||
ArchMiscWindows::EValueType ArchMiscWindows::typeOfValue(HKEY key, const TCHAR *name)
|
||||
{
|
||||
DWORD type;
|
||||
LONG result = RegQueryValueEx(key, name, 0, &type, NULL, NULL);
|
||||
LONG result = RegQueryValueEx(key, name, 0, &type, nullptr, nullptr);
|
||||
if (result != ERROR_SUCCESS) {
|
||||
return kNO_VALUE;
|
||||
}
|
||||
@ -177,8 +178,8 @@ ArchMiscWindows::EValueType ArchMiscWindows::typeOfValue(HKEY key, const TCHAR *
|
||||
|
||||
void ArchMiscWindows::setValue(HKEY key, const TCHAR *name, const std::string &value)
|
||||
{
|
||||
assert(key != NULL);
|
||||
if (key == NULL) {
|
||||
assert(key != nullptr);
|
||||
if (key == nullptr) {
|
||||
// TODO: throw exception
|
||||
return;
|
||||
}
|
||||
@ -187,8 +188,8 @@ void ArchMiscWindows::setValue(HKEY key, const TCHAR *name, const std::string &v
|
||||
|
||||
void ArchMiscWindows::setValue(HKEY key, const TCHAR *name, DWORD value)
|
||||
{
|
||||
assert(key != NULL);
|
||||
if (key == NULL) {
|
||||
assert(key != nullptr);
|
||||
if (key == nullptr) {
|
||||
// TODO: throw exception
|
||||
return;
|
||||
}
|
||||
@ -200,7 +201,7 @@ std::string ArchMiscWindows::readBinaryOrString(HKEY key, const TCHAR *name, DWO
|
||||
// get the size of the string
|
||||
DWORD actualType;
|
||||
DWORD size = 0;
|
||||
LONG result = RegQueryValueEx(key, name, 0, &actualType, NULL, &size);
|
||||
LONG result = RegQueryValueEx(key, name, 0, &actualType, nullptr, &size);
|
||||
if (result != ERROR_SUCCESS || actualType != type) {
|
||||
return std::string();
|
||||
}
|
||||
@ -263,12 +264,12 @@ void ArchMiscWindows::removeBusyState(DWORD busyModes)
|
||||
void ArchMiscWindows::setThreadExecutionState(DWORD busyModes)
|
||||
{
|
||||
// look up function dynamically so we work on older systems
|
||||
if (s_stes == NULL) {
|
||||
if (s_stes == nullptr) {
|
||||
HINSTANCE kernel = LoadLibrary("kernel32.dll");
|
||||
if (kernel != NULL) {
|
||||
if (kernel != nullptr) {
|
||||
s_stes = reinterpret_cast<STES_t>(GetProcAddress(kernel, "SetThreadExecutionState"));
|
||||
}
|
||||
if (s_stes == NULL) {
|
||||
if (s_stes == nullptr) {
|
||||
s_stes = &ArchMiscWindows::dummySetThreadExecutionState;
|
||||
}
|
||||
}
|
||||
@ -301,12 +302,12 @@ void ArchMiscWindows::wakeupDisplay()
|
||||
// We can't use ::setThreadExecutionState here because it sets
|
||||
// ES_CONTINUOUS, which we don't want.
|
||||
|
||||
if (s_stes == NULL) {
|
||||
if (s_stes == nullptr) {
|
||||
HINSTANCE kernel = LoadLibrary("kernel32.dll");
|
||||
if (kernel != NULL) {
|
||||
if (kernel != nullptr) {
|
||||
s_stes = reinterpret_cast<STES_t>(GetProcAddress(kernel, "SetThreadExecutionState"));
|
||||
}
|
||||
if (s_stes == NULL) {
|
||||
if (s_stes == nullptr) {
|
||||
s_stes = &ArchMiscWindows::dummySetThreadExecutionState;
|
||||
}
|
||||
}
|
||||
@ -394,13 +395,13 @@ BOOL WINAPI ArchMiscWindows::getProcessEntry(PROCESSENTRY32 &entry, DWORD proces
|
||||
HINSTANCE
|
||||
ArchMiscWindows::instanceWin32()
|
||||
{
|
||||
assert(s_instanceWin32 != NULL);
|
||||
assert(s_instanceWin32 != nullptr);
|
||||
return s_instanceWin32;
|
||||
}
|
||||
|
||||
void ArchMiscWindows::setInstanceWin32(HINSTANCE instance)
|
||||
{
|
||||
assert(instance != NULL);
|
||||
assert(instance != nullptr);
|
||||
s_instanceWin32 = instance;
|
||||
}
|
||||
|
||||
@ -409,7 +410,7 @@ 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());
|
||||
throw std::runtime_error(windowsErrorToString(GetLastError()));
|
||||
}
|
||||
|
||||
DWORD size;
|
||||
@ -530,7 +531,7 @@ bool ArchMiscWindows::isProcessElevated()
|
||||
|
||||
HANDLE hToken = nullptr;
|
||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
|
||||
throw XArch(new XArchEvalWindows());
|
||||
throw std::runtime_error(windowsErrorToString(GetLastError()));
|
||||
}
|
||||
|
||||
TOKEN_ELEVATION elevation;
|
||||
@ -538,7 +539,7 @@ bool ArchMiscWindows::isProcessElevated()
|
||||
try {
|
||||
DWORD dwSize = sizeof(TOKEN_ELEVATION);
|
||||
if (!GetTokenInformation(hToken, TokenElevation, &elevation, sizeof(elevation), &dwSize)) {
|
||||
throw XArch(new XArchEvalWindows());
|
||||
throw std::runtime_error(windowsErrorToString(GetLastError()));
|
||||
}
|
||||
} catch (...) {
|
||||
CloseHandle(hToken);
|
||||
|
||||
@ -50,16 +50,16 @@ public:
|
||||
|
||||
ArchThreadImpl::ArchThreadImpl()
|
||||
: m_refCount(1),
|
||||
m_thread(NULL),
|
||||
m_thread(nullptr),
|
||||
m_id(0),
|
||||
m_func(NULL),
|
||||
m_userData(NULL),
|
||||
m_func(nullptr),
|
||||
m_userData(nullptr),
|
||||
m_cancelling(false),
|
||||
m_result(NULL),
|
||||
m_networkData(NULL)
|
||||
m_result(nullptr),
|
||||
m_networkData(nullptr)
|
||||
{
|
||||
m_exit = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
m_cancel = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
m_exit = CreateEvent(nullptr, TRUE, FALSE, nullptr);
|
||||
m_cancel = CreateEvent(nullptr, TRUE, FALSE, nullptr);
|
||||
}
|
||||
|
||||
ArchThreadImpl::~ArchThreadImpl()
|
||||
@ -72,17 +72,17 @@ ArchThreadImpl::~ArchThreadImpl()
|
||||
// ArchMultithreadWindows
|
||||
//
|
||||
|
||||
ArchMultithreadWindows *ArchMultithreadWindows::s_instance = NULL;
|
||||
ArchMultithreadWindows *ArchMultithreadWindows::s_instance = nullptr;
|
||||
|
||||
ArchMultithreadWindows::ArchMultithreadWindows()
|
||||
{
|
||||
assert(s_instance == NULL);
|
||||
assert(s_instance == nullptr);
|
||||
s_instance = this;
|
||||
|
||||
// no signal handlers
|
||||
for (size_t i = 0; i < kNUM_SIGNALS; ++i) {
|
||||
m_signalFunc[i] = NULL;
|
||||
m_signalUserData[i] = NULL;
|
||||
m_signalFunc[i] = nullptr;
|
||||
m_signalUserData[i] = nullptr;
|
||||
}
|
||||
|
||||
// create mutex for thread list
|
||||
@ -91,14 +91,14 @@ ArchMultithreadWindows::ArchMultithreadWindows()
|
||||
// create thread for calling (main) thread and add it to our
|
||||
// list. no need to lock the mutex since we're the only thread.
|
||||
m_mainThread = new ArchThreadImpl;
|
||||
m_mainThread->m_thread = NULL;
|
||||
m_mainThread->m_thread = nullptr;
|
||||
m_mainThread->m_id = GetCurrentThreadId();
|
||||
insert(m_mainThread);
|
||||
}
|
||||
|
||||
ArchMultithreadWindows::~ArchMultithreadWindows()
|
||||
{
|
||||
s_instance = NULL;
|
||||
s_instance = nullptr;
|
||||
|
||||
// clean up thread list
|
||||
for (ThreadList::iterator index = m_threadList.begin(); index != m_threadList.end(); ++index) {
|
||||
@ -142,8 +142,8 @@ ArchMultithreadWindows *ArchMultithreadWindows::getInstance()
|
||||
ArchCond ArchMultithreadWindows::newCondVar()
|
||||
{
|
||||
ArchCondImpl *cond = new ArchCondImpl;
|
||||
cond->m_events[ArchCondImpl::kSignal] = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
cond->m_events[ArchCondImpl::kBroadcast] = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
cond->m_events[ArchCondImpl::kSignal] = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
cond->m_events[ArchCondImpl::kBroadcast] = CreateEvent(nullptr, TRUE, FALSE, nullptr);
|
||||
cond->m_waitCountMutex = newMutex();
|
||||
cond->m_waitCount = 0;
|
||||
return cond;
|
||||
@ -272,14 +272,14 @@ ArchThread ArchMultithreadWindows::newThread(ThreadFunc func, void *data)
|
||||
|
||||
// create thread
|
||||
unsigned int id = 0;
|
||||
thread->m_thread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, threadFunc, (void *)thread, 0, &id));
|
||||
thread->m_thread = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, threadFunc, (void *)thread, 0, &id));
|
||||
thread->m_id = static_cast<DWORD>(id);
|
||||
|
||||
// check if thread was started
|
||||
if (thread->m_thread == 0) {
|
||||
// failed to start thread so clean up
|
||||
delete thread;
|
||||
thread = NULL;
|
||||
thread = nullptr;
|
||||
} else {
|
||||
// add thread to list
|
||||
insert(thread);
|
||||
@ -299,18 +299,18 @@ ArchThread ArchMultithreadWindows::newCurrentThread()
|
||||
lockMutex(m_threadMutex);
|
||||
ArchThreadImpl *thread = find(GetCurrentThreadId());
|
||||
unlockMutex(m_threadMutex);
|
||||
assert(thread != NULL);
|
||||
assert(thread != nullptr);
|
||||
return thread;
|
||||
}
|
||||
|
||||
void ArchMultithreadWindows::closeThread(ArchThread thread)
|
||||
{
|
||||
assert(thread != NULL);
|
||||
assert(thread != nullptr);
|
||||
|
||||
// decrement ref count and clean up thread if no more references
|
||||
if (--thread->m_refCount == 0) {
|
||||
// close the handle (main thread has a NULL handle)
|
||||
if (thread->m_thread != NULL) {
|
||||
// close the handle (main thread has a nullptr handle)
|
||||
if (thread->m_thread != nullptr) {
|
||||
CloseHandle(thread->m_thread);
|
||||
}
|
||||
|
||||
@ -333,7 +333,7 @@ ArchThread ArchMultithreadWindows::copyThread(ArchThread thread)
|
||||
|
||||
void ArchMultithreadWindows::cancelThread(ArchThread thread)
|
||||
{
|
||||
assert(thread != NULL);
|
||||
assert(thread != nullptr);
|
||||
|
||||
// set cancel flag
|
||||
SetEvent(thread->m_cancel);
|
||||
@ -380,7 +380,7 @@ void ArchMultithreadWindows::setPriorityOfThread(ArchThread thread, int n)
|
||||
#endif
|
||||
static const size_t s_pBase = 8; // index of normal priority
|
||||
|
||||
assert(thread != NULL);
|
||||
assert(thread != nullptr);
|
||||
|
||||
size_t index;
|
||||
if (n > 0 && s_pBase < (size_t)n) {
|
||||
@ -410,7 +410,7 @@ void ArchMultithreadWindows::testCancelThread()
|
||||
|
||||
bool ArchMultithreadWindows::wait(ArchThread target, double timeout)
|
||||
{
|
||||
assert(target != NULL);
|
||||
assert(target != nullptr);
|
||||
|
||||
lockMutex(m_threadMutex);
|
||||
|
||||
@ -502,7 +502,7 @@ void ArchMultithreadWindows::setSignalHandler(ESignal signal, SignalFunc func, v
|
||||
void ArchMultithreadWindows::raiseSignal(ESignal signal)
|
||||
{
|
||||
lockMutex(m_threadMutex);
|
||||
if (m_signalFunc[signal] != NULL) {
|
||||
if (m_signalFunc[signal] != nullptr) {
|
||||
m_signalFunc[signal](signal, m_signalUserData[signal]);
|
||||
ARCH->unblockPollSocket(m_mainThread);
|
||||
} else if (signal == kINTERRUPT || signal == kTERMINATE) {
|
||||
@ -514,7 +514,7 @@ void ArchMultithreadWindows::raiseSignal(ESignal signal)
|
||||
ArchThreadImpl *ArchMultithreadWindows::find(DWORD id)
|
||||
{
|
||||
ArchThreadImpl *impl = findNoRef(id);
|
||||
if (impl != NULL) {
|
||||
if (impl != nullptr) {
|
||||
refThread(impl);
|
||||
}
|
||||
return impl;
|
||||
@ -523,13 +523,13 @@ ArchThreadImpl *ArchMultithreadWindows::find(DWORD id)
|
||||
ArchThreadImpl *ArchMultithreadWindows::findNoRef(DWORD id)
|
||||
{
|
||||
ArchThreadImpl *impl = findNoRefOrCreate(id);
|
||||
if (impl == NULL) {
|
||||
if (impl == nullptr) {
|
||||
// create thread for calling thread which isn't in our list and
|
||||
// add it to the list. this won't normally happen but it can if
|
||||
// the system calls us under a new thread, like it does when we
|
||||
// run as a service.
|
||||
impl = new ArchThreadImpl;
|
||||
impl->m_thread = NULL;
|
||||
impl->m_thread = nullptr;
|
||||
impl->m_id = GetCurrentThreadId();
|
||||
insert(impl);
|
||||
}
|
||||
@ -544,15 +544,15 @@ ArchThreadImpl *ArchMultithreadWindows::findNoRefOrCreate(DWORD id)
|
||||
return *index;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ArchMultithreadWindows::insert(ArchThreadImpl *thread)
|
||||
{
|
||||
assert(thread != NULL);
|
||||
assert(thread != nullptr);
|
||||
|
||||
// thread shouldn't already be on the list
|
||||
assert(findNoRefOrCreate(thread->m_id) == NULL);
|
||||
assert(findNoRefOrCreate(thread->m_id) == nullptr);
|
||||
|
||||
// append to list
|
||||
m_threadList.push_back(thread);
|
||||
@ -570,14 +570,14 @@ void ArchMultithreadWindows::erase(ArchThreadImpl *thread)
|
||||
|
||||
void ArchMultithreadWindows::refThread(ArchThreadImpl *thread)
|
||||
{
|
||||
assert(thread != NULL);
|
||||
assert(findNoRefOrCreate(thread->m_id) != NULL);
|
||||
assert(thread != nullptr);
|
||||
assert(findNoRefOrCreate(thread->m_id) != nullptr);
|
||||
++thread->m_refCount;
|
||||
}
|
||||
|
||||
void ArchMultithreadWindows::testCancelThreadImpl(ArchThreadImpl *thread)
|
||||
{
|
||||
assert(thread != NULL);
|
||||
assert(thread != nullptr);
|
||||
|
||||
// poll cancel event. return if not set.
|
||||
const DWORD result = WaitForSingleObject(thread->m_cancel, 0);
|
||||
@ -616,7 +616,7 @@ void ArchMultithreadWindows::doThreadFunc(ArchThread thread)
|
||||
lockMutex(m_threadMutex);
|
||||
unlockMutex(m_threadMutex);
|
||||
|
||||
void *result = NULL;
|
||||
void *result = nullptr;
|
||||
try {
|
||||
// go
|
||||
result = (*thread->m_func)(thread->m_userData);
|
||||
|
||||
@ -41,7 +41,7 @@ class ArchMultithreadWindows : public IArchMultithread
|
||||
{
|
||||
public:
|
||||
ArchMultithreadWindows();
|
||||
virtual ~ArchMultithreadWindows();
|
||||
~ArchMultithreadWindows() override;
|
||||
|
||||
//! @name manipulators
|
||||
//@{
|
||||
@ -61,29 +61,29 @@ public:
|
||||
//@}
|
||||
|
||||
// IArchMultithread overrides
|
||||
virtual ArchCond newCondVar();
|
||||
virtual void closeCondVar(ArchCond);
|
||||
virtual void signalCondVar(ArchCond);
|
||||
virtual void broadcastCondVar(ArchCond);
|
||||
virtual bool waitCondVar(ArchCond, ArchMutex, double timeout);
|
||||
virtual ArchMutex newMutex();
|
||||
virtual void closeMutex(ArchMutex);
|
||||
virtual void lockMutex(ArchMutex);
|
||||
virtual void unlockMutex(ArchMutex);
|
||||
virtual ArchThread newThread(ThreadFunc, void *);
|
||||
virtual ArchThread newCurrentThread();
|
||||
virtual ArchThread copyThread(ArchThread);
|
||||
virtual void closeThread(ArchThread);
|
||||
virtual void cancelThread(ArchThread);
|
||||
virtual void setPriorityOfThread(ArchThread, int n);
|
||||
virtual void testCancelThread();
|
||||
virtual bool wait(ArchThread, double timeout);
|
||||
virtual bool isSameThread(ArchThread, ArchThread);
|
||||
virtual bool isExitedThread(ArchThread);
|
||||
virtual void *getResultOfThread(ArchThread);
|
||||
virtual ThreadID getIDOfThread(ArchThread);
|
||||
virtual void setSignalHandler(ESignal, SignalFunc, void *);
|
||||
virtual void raiseSignal(ESignal);
|
||||
ArchCond newCondVar() override;
|
||||
void closeCondVar(ArchCond) override;
|
||||
void signalCondVar(ArchCond) override;
|
||||
void broadcastCondVar(ArchCond) override;
|
||||
bool waitCondVar(ArchCond, ArchMutex, double timeout) override;
|
||||
ArchMutex newMutex() override;
|
||||
void closeMutex(ArchMutex) override;
|
||||
void lockMutex(ArchMutex) override;
|
||||
void unlockMutex(ArchMutex) override;
|
||||
ArchThread newThread(ThreadFunc, void *) override;
|
||||
ArchThread newCurrentThread() override;
|
||||
ArchThread copyThread(ArchThread) override;
|
||||
void closeThread(ArchThread) override;
|
||||
void cancelThread(ArchThread) override;
|
||||
void setPriorityOfThread(ArchThread, int n) override;
|
||||
void testCancelThread() override;
|
||||
bool wait(ArchThread, double timeout) override;
|
||||
bool isSameThread(ArchThread, ArchThread) override;
|
||||
bool isExitedThread(ArchThread) override;
|
||||
void *getResultOfThread(ArchThread) override;
|
||||
ThreadID getIDOfThread(ArchThread) override;
|
||||
void setSignalHandler(ESignal, SignalFunc, void *) override;
|
||||
void raiseSignal(ESignal) override;
|
||||
|
||||
private:
|
||||
ArchThreadImpl *find(DWORD id);
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "arch/win32/ArchNetworkWinsock.h"
|
||||
#include "arch/Arch.h"
|
||||
#include "arch/IArchMultithread.h"
|
||||
#include "arch/XArch.h"
|
||||
#include "arch/win32/ArchMultithreadWindows.h"
|
||||
#include "arch/win32/XArchWindows.h"
|
||||
|
||||
@ -58,7 +59,7 @@ static int(PASCAL FAR *WSAEnumNetworkEvents_winsock)(SOCKET, WSAEVENT, LPWSANETW
|
||||
|
||||
#define setfunc(var, name, type) var = (type)netGetProcAddress(module, #name)
|
||||
|
||||
static HMODULE s_networkModule = NULL;
|
||||
static HMODULE s_networkModule = nullptr;
|
||||
|
||||
static FARPROC netGetProcAddress(HMODULE module, LPCSTR name)
|
||||
{
|
||||
@ -81,20 +82,20 @@ ArchNetAddressImpl *ArchNetAddressImpl::alloc(size_t size)
|
||||
// ArchNetworkWinsock
|
||||
//
|
||||
|
||||
ArchNetworkWinsock::ArchNetworkWinsock() : m_mutex(NULL)
|
||||
ArchNetworkWinsock::ArchNetworkWinsock() : m_mutex(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
ArchNetworkWinsock::~ArchNetworkWinsock()
|
||||
{
|
||||
if (s_networkModule != NULL) {
|
||||
if (s_networkModule != nullptr) {
|
||||
WSACleanup_winsock();
|
||||
::FreeLibrary(s_networkModule);
|
||||
|
||||
WSACleanup_winsock = NULL;
|
||||
s_networkModule = NULL;
|
||||
WSACleanup_winsock = nullptr;
|
||||
s_networkModule = nullptr;
|
||||
}
|
||||
if (m_mutex != NULL) {
|
||||
if (m_mutex != nullptr) {
|
||||
ARCH->closeMutex(m_mutex);
|
||||
}
|
||||
|
||||
@ -108,8 +109,8 @@ void ArchNetworkWinsock::init()
|
||||
{
|
||||
static const char *s_library[] = {"ws2_32.dll"};
|
||||
|
||||
assert(WSACleanup_winsock == NULL);
|
||||
assert(s_networkModule == NULL);
|
||||
assert(WSACleanup_winsock == nullptr);
|
||||
assert(s_networkModule == nullptr);
|
||||
|
||||
// try each winsock library
|
||||
for (size_t i = 0; i < sizeof(s_library) / sizeof(s_library[0]); ++i) {
|
||||
@ -128,7 +129,7 @@ void ArchNetworkWinsock::init()
|
||||
|
||||
void ArchNetworkWinsock::initModule(HMODULE module)
|
||||
{
|
||||
if (module == NULL) {
|
||||
if (module == nullptr) {
|
||||
throw XArchNetworkSupport("");
|
||||
}
|
||||
|
||||
@ -141,7 +142,7 @@ void ArchNetworkWinsock::initModule(HMODULE module)
|
||||
WSADATA data;
|
||||
int err = startup(version, &data);
|
||||
if (data.wVersion != version) {
|
||||
throw XArchNetworkSupport(new XArchEvalWinsock(err));
|
||||
throw XArchNetworkSupport(winsockErrorToString(err));
|
||||
}
|
||||
if (err != 0) {
|
||||
// some other initialization error
|
||||
@ -229,7 +230,7 @@ ArchSocket ArchNetworkWinsock::newSocket(EAddressFamily family, ESocketType type
|
||||
|
||||
ArchSocket ArchNetworkWinsock::copySocket(ArchSocket s)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(s != nullptr);
|
||||
|
||||
// ref the socket and return it
|
||||
ARCH->lockMutex(m_mutex);
|
||||
@ -240,7 +241,7 @@ ArchSocket ArchNetworkWinsock::copySocket(ArchSocket s)
|
||||
|
||||
void ArchNetworkWinsock::closeSocket(ArchSocket s)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(s != nullptr);
|
||||
|
||||
// unref the socket and note if it should be released
|
||||
ARCH->lockMutex(m_mutex);
|
||||
@ -264,7 +265,7 @@ void ArchNetworkWinsock::closeSocket(ArchSocket s)
|
||||
|
||||
void ArchNetworkWinsock::closeSocketForRead(ArchSocket s)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(s != nullptr);
|
||||
|
||||
if (shutdown_winsock(s->m_socket, SD_RECEIVE) == SOCKET_ERROR) {
|
||||
if (getsockerror_winsock() != WSAENOTCONN) {
|
||||
@ -275,7 +276,7 @@ void ArchNetworkWinsock::closeSocketForRead(ArchSocket s)
|
||||
|
||||
void ArchNetworkWinsock::closeSocketForWrite(ArchSocket s)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(s != nullptr);
|
||||
|
||||
if (shutdown_winsock(s->m_socket, SD_SEND) == SOCKET_ERROR) {
|
||||
if (getsockerror_winsock() != WSAENOTCONN) {
|
||||
@ -286,8 +287,8 @@ void ArchNetworkWinsock::closeSocketForWrite(ArchSocket s)
|
||||
|
||||
void ArchNetworkWinsock::bindSocket(ArchSocket s, ArchNetAddress addr)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(addr != NULL);
|
||||
assert(s != nullptr);
|
||||
assert(addr != nullptr);
|
||||
|
||||
if (bind_winsock(s->m_socket, TYPED_ADDR(struct sockaddr, addr), addr->m_len) == SOCKET_ERROR) {
|
||||
throwError(getsockerror_winsock());
|
||||
@ -296,7 +297,7 @@ void ArchNetworkWinsock::bindSocket(ArchSocket s, ArchNetAddress addr)
|
||||
|
||||
void ArchNetworkWinsock::listenOnSocket(ArchSocket s)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(s != nullptr);
|
||||
|
||||
// hardcoding backlog
|
||||
if (listen_winsock(s->m_socket, 3) == SOCKET_ERROR) {
|
||||
@ -306,7 +307,7 @@ void ArchNetworkWinsock::listenOnSocket(ArchSocket s)
|
||||
|
||||
ArchSocket ArchNetworkWinsock::acceptSocket(ArchSocket s, ArchNetAddress *const addr)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(s != nullptr);
|
||||
|
||||
// create new socket and temporary address
|
||||
ArchSocketImpl *socket = new ArchSocketImpl;
|
||||
@ -319,10 +320,10 @@ ArchSocket ArchNetworkWinsock::acceptSocket(ArchSocket s, ArchNetAddress *const
|
||||
delete socket;
|
||||
free(tmp);
|
||||
if (addr) {
|
||||
*addr = NULL;
|
||||
*addr = nullptr;
|
||||
}
|
||||
if (err == WSAEWOULDBLOCK) {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
throwError(err);
|
||||
}
|
||||
@ -334,7 +335,7 @@ ArchSocket ArchNetworkWinsock::acceptSocket(ArchSocket s, ArchNetAddress *const
|
||||
delete socket;
|
||||
free(tmp);
|
||||
if (addr) {
|
||||
*addr = NULL;
|
||||
*addr = nullptr;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
@ -346,7 +347,7 @@ ArchSocket ArchNetworkWinsock::acceptSocket(ArchSocket s, ArchNetAddress *const
|
||||
socket->m_pollWrite = true;
|
||||
|
||||
// copy address if requested
|
||||
if (addr != NULL) {
|
||||
if (addr != nullptr) {
|
||||
*addr = ARCH->copyAddr(tmp);
|
||||
}
|
||||
|
||||
@ -356,8 +357,8 @@ ArchSocket ArchNetworkWinsock::acceptSocket(ArchSocket s, ArchNetAddress *const
|
||||
|
||||
bool ArchNetworkWinsock::connectSocket(ArchSocket s, ArchNetAddress addr)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(addr != NULL);
|
||||
assert(s != nullptr);
|
||||
assert(addr != nullptr);
|
||||
|
||||
if (connect_winsock(s->m_socket, TYPED_ADDR(struct sockaddr, addr), addr->m_len) == SOCKET_ERROR) {
|
||||
if (getsockerror_winsock() == WSAEISCONN) {
|
||||
@ -384,7 +385,7 @@ int ArchNetworkWinsock::pollSocket(PollEntry pe[], int num, double timeout)
|
||||
pe[i].m_revents = 0;
|
||||
|
||||
// set invalid flag if socket is bogus then go to next socket
|
||||
if (pe[i].m_socket == NULL) {
|
||||
if (pe[i].m_socket == nullptr) {
|
||||
pe[i].m_revents |= kPOLLNVAL;
|
||||
continue;
|
||||
}
|
||||
@ -428,7 +429,7 @@ int ArchNetworkWinsock::pollSocket(PollEntry pe[], int num, double timeout)
|
||||
ArchThread thread = mt->newCurrentThread();
|
||||
WSAEVENT *unblockEvent = (WSAEVENT *)mt->getNetworkDataForThread(thread);
|
||||
ARCH->closeThread(thread);
|
||||
if (unblockEvent == NULL) {
|
||||
if (unblockEvent == nullptr) {
|
||||
unblockEvent = new WSAEVENT;
|
||||
m_unblockEvents.push_back(unblockEvent);
|
||||
*unblockEvent = WSACreateEvent_winsock();
|
||||
@ -467,7 +468,7 @@ int ArchNetworkWinsock::pollSocket(PollEntry pe[], int num, double timeout)
|
||||
}
|
||||
for (i = 0, n = 0; i < num; ++i) {
|
||||
// skip events we didn't check
|
||||
if (pe[i].m_socket == NULL || (pe[i].m_events & (kPOLLIN | kPOLLOUT)) == 0) {
|
||||
if (pe[i].m_socket == nullptr || (pe[i].m_events & (kPOLLIN | kPOLLOUT)) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -522,14 +523,14 @@ void ArchNetworkWinsock::unblockPollSocket(ArchThread thread)
|
||||
// set the unblock event
|
||||
ArchMultithreadWindows *mt = ArchMultithreadWindows::getInstance();
|
||||
WSAEVENT *unblockEvent = (WSAEVENT *)mt->getNetworkDataForThread(thread);
|
||||
if (unblockEvent != NULL) {
|
||||
if (unblockEvent != nullptr) {
|
||||
WSASetEvent_winsock(*unblockEvent);
|
||||
}
|
||||
}
|
||||
|
||||
size_t ArchNetworkWinsock::readSocket(ArchSocket s, void *buf, size_t len)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(s != nullptr);
|
||||
|
||||
int n = recv_winsock(s->m_socket, buf, (int)len, 0);
|
||||
if (n == SOCKET_ERROR) {
|
||||
@ -544,7 +545,7 @@ size_t ArchNetworkWinsock::readSocket(ArchSocket s, void *buf, size_t len)
|
||||
|
||||
size_t ArchNetworkWinsock::writeSocket(ArchSocket s, const void *buf, size_t len)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(s != nullptr);
|
||||
|
||||
int n = send_winsock(s->m_socket, buf, (int)len, 0);
|
||||
if (n == SOCKET_ERROR) {
|
||||
@ -563,7 +564,7 @@ size_t ArchNetworkWinsock::writeSocket(ArchSocket s, const void *buf, size_t len
|
||||
|
||||
void ArchNetworkWinsock::throwErrorOnSocket(ArchSocket s)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(s != nullptr);
|
||||
|
||||
// get the error from the socket layer
|
||||
int err = 0;
|
||||
@ -590,7 +591,7 @@ void ArchNetworkWinsock::setBlockingOnSocket(SOCKET s, bool blocking)
|
||||
|
||||
bool ArchNetworkWinsock::setNoDelayOnSocket(ArchSocket s, bool noDelay)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(s != nullptr);
|
||||
|
||||
// get old state
|
||||
BOOL oflag;
|
||||
@ -611,7 +612,7 @@ bool ArchNetworkWinsock::setNoDelayOnSocket(ArchSocket s, bool noDelay)
|
||||
|
||||
bool ArchNetworkWinsock::setReuseAddrOnSocket(ArchSocket s, bool reuse)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(s != nullptr);
|
||||
|
||||
// get old state
|
||||
BOOL oflag;
|
||||
@ -643,7 +644,7 @@ std::string ArchNetworkWinsock::getHostName()
|
||||
|
||||
ArchNetAddress ArchNetworkWinsock::newAnyAddr(EAddressFamily family)
|
||||
{
|
||||
ArchNetAddressImpl *addr = NULL;
|
||||
ArchNetAddressImpl *addr = nullptr;
|
||||
switch (family) {
|
||||
case kINET: {
|
||||
addr = ArchNetAddressImpl::alloc(sizeof(struct sockaddr_in));
|
||||
@ -671,7 +672,7 @@ ArchNetAddress ArchNetworkWinsock::newAnyAddr(EAddressFamily family)
|
||||
|
||||
ArchNetAddress ArchNetworkWinsock::copyAddr(ArchNetAddress addr)
|
||||
{
|
||||
assert(addr != NULL);
|
||||
assert(addr != nullptr);
|
||||
|
||||
ArchNetAddressImpl *copy = ArchNetAddressImpl::alloc(addr->m_len);
|
||||
memcpy(TYPED_ADDR(void, copy), TYPED_ADDR(void, addr), addr->m_len);
|
||||
@ -690,7 +691,7 @@ std::vector<ArchNetAddress> ArchNetworkWinsock::nameToAddr(const std::string &na
|
||||
int ret = -1;
|
||||
|
||||
ARCH->lockMutex(m_mutex);
|
||||
if ((ret = getaddrinfo(name.c_str(), NULL, &hints, &pResult)) != 0) {
|
||||
if ((ret = getaddrinfo(name.c_str(), nullptr, &hints, &pResult)) != 0) {
|
||||
ARCH->unlockMutex(m_mutex);
|
||||
throwNameError(ret);
|
||||
}
|
||||
@ -713,21 +714,21 @@ std::vector<ArchNetAddress> ArchNetworkWinsock::nameToAddr(const std::string &na
|
||||
|
||||
void ArchNetworkWinsock::closeAddr(ArchNetAddress addr)
|
||||
{
|
||||
assert(addr != NULL);
|
||||
assert(addr != nullptr);
|
||||
|
||||
free(addr);
|
||||
}
|
||||
|
||||
std::string ArchNetworkWinsock::addrToName(ArchNetAddress addr)
|
||||
{
|
||||
assert(addr != NULL);
|
||||
assert(addr != nullptr);
|
||||
|
||||
char host[1024];
|
||||
char service[20];
|
||||
int ret =
|
||||
getnameinfo(TYPED_ADDR(struct sockaddr, addr), addr->m_len, host, sizeof(host), service, sizeof(service), 0);
|
||||
|
||||
if (ret != NULL) {
|
||||
if (ret != 0) {
|
||||
throwNameError(ret);
|
||||
}
|
||||
|
||||
@ -738,7 +739,7 @@ std::string ArchNetworkWinsock::addrToName(ArchNetAddress addr)
|
||||
|
||||
std::string ArchNetworkWinsock::addrToString(ArchNetAddress addr)
|
||||
{
|
||||
assert(addr != NULL);
|
||||
assert(addr != nullptr);
|
||||
|
||||
switch (getAddrFamily(addr)) {
|
||||
case kINET: {
|
||||
@ -761,7 +762,7 @@ std::string ArchNetworkWinsock::addrToString(ArchNetAddress addr)
|
||||
|
||||
IArchNetwork::EAddressFamily ArchNetworkWinsock::getAddrFamily(ArchNetAddress addr)
|
||||
{
|
||||
assert(addr != NULL);
|
||||
assert(addr != nullptr);
|
||||
|
||||
switch (addr->m_addr.ss_family) {
|
||||
case AF_INET:
|
||||
@ -777,7 +778,7 @@ IArchNetwork::EAddressFamily ArchNetworkWinsock::getAddrFamily(ArchNetAddress ad
|
||||
|
||||
void ArchNetworkWinsock::setAddrPort(ArchNetAddress addr, int port)
|
||||
{
|
||||
assert(addr != NULL);
|
||||
assert(addr != nullptr);
|
||||
|
||||
switch (getAddrFamily(addr)) {
|
||||
case kINET: {
|
||||
@ -800,7 +801,7 @@ void ArchNetworkWinsock::setAddrPort(ArchNetAddress addr, int port)
|
||||
|
||||
int ArchNetworkWinsock::getAddrPort(ArchNetAddress addr)
|
||||
{
|
||||
assert(addr != NULL);
|
||||
assert(addr != nullptr);
|
||||
|
||||
switch (getAddrFamily(addr)) {
|
||||
case kINET: {
|
||||
@ -821,7 +822,7 @@ int ArchNetworkWinsock::getAddrPort(ArchNetAddress addr)
|
||||
|
||||
bool ArchNetworkWinsock::isAnyAddr(ArchNetAddress addr)
|
||||
{
|
||||
assert(addr != NULL);
|
||||
assert(addr != nullptr);
|
||||
|
||||
switch (getAddrFamily(addr)) {
|
||||
case kINET: {
|
||||
@ -851,12 +852,12 @@ void ArchNetworkWinsock::throwError(int err)
|
||||
{
|
||||
switch (err) {
|
||||
case WSAEACCES:
|
||||
throw XArchNetworkAccess(new XArchEvalWinsock(err));
|
||||
throw XArchNetworkAccess(winsockErrorToString(err));
|
||||
|
||||
case WSAEMFILE:
|
||||
case WSAENOBUFS:
|
||||
case WSAENETDOWN:
|
||||
throw XArchNetworkResource(new XArchEvalWinsock(err));
|
||||
throw XArchNetworkResource(winsockErrorToString(err));
|
||||
|
||||
case WSAEPROTOTYPE:
|
||||
case WSAEPROTONOSUPPORT:
|
||||
@ -870,50 +871,50 @@ void ArchNetworkWinsock::throwError(int err)
|
||||
case WSANOTINITIALISED:
|
||||
case WSAVERNOTSUPPORTED:
|
||||
case WSASYSNOTREADY:
|
||||
throw XArchNetworkSupport(new XArchEvalWinsock(err));
|
||||
throw XArchNetworkSupport(winsockErrorToString(err));
|
||||
|
||||
case WSAEADDRNOTAVAIL:
|
||||
throw XArchNetworkNoAddress(new XArchEvalWinsock(err));
|
||||
throw XArchNetworkNoAddress(winsockErrorToString(err));
|
||||
|
||||
case WSAEADDRINUSE:
|
||||
throw XArchNetworkAddressInUse(new XArchEvalWinsock(err));
|
||||
throw XArchNetworkAddressInUse(winsockErrorToString(err));
|
||||
|
||||
case WSAEHOSTUNREACH:
|
||||
case WSAENETUNREACH:
|
||||
throw XArchNetworkNoRoute(new XArchEvalWinsock(err));
|
||||
throw XArchNetworkNoRoute(winsockErrorToString(err));
|
||||
|
||||
case WSAENOTCONN:
|
||||
throw XArchNetworkNotConnected(new XArchEvalWinsock(err));
|
||||
throw XArchNetworkNotConnected(winsockErrorToString(err));
|
||||
|
||||
case WSAEDISCON:
|
||||
throw XArchNetworkShutdown(new XArchEvalWinsock(err));
|
||||
throw XArchNetworkShutdown(winsockErrorToString(err));
|
||||
|
||||
case WSAENETRESET:
|
||||
case WSAECONNABORTED:
|
||||
case WSAECONNRESET:
|
||||
throw XArchNetworkDisconnected(new XArchEvalWinsock(err));
|
||||
throw XArchNetworkDisconnected(winsockErrorToString(err));
|
||||
|
||||
case WSAECONNREFUSED:
|
||||
throw XArchNetworkConnectionRefused(new XArchEvalWinsock(err));
|
||||
throw XArchNetworkConnectionRefused(winsockErrorToString(err));
|
||||
|
||||
case WSAEHOSTDOWN:
|
||||
case WSAETIMEDOUT:
|
||||
throw XArchNetworkTimedOut(new XArchEvalWinsock(err));
|
||||
throw XArchNetworkTimedOut(winsockErrorToString(err));
|
||||
|
||||
case WSAHOST_NOT_FOUND:
|
||||
throw XArchNetworkNameUnknown(new XArchEvalWinsock(err));
|
||||
throw XArchNetworkNameUnknown(winsockErrorToString(err));
|
||||
|
||||
case WSANO_DATA:
|
||||
throw XArchNetworkNameNoAddress(new XArchEvalWinsock(err));
|
||||
throw XArchNetworkNameNoAddress(winsockErrorToString(err));
|
||||
|
||||
case WSANO_RECOVERY:
|
||||
throw XArchNetworkNameFailure(new XArchEvalWinsock(err));
|
||||
throw XArchNetworkNameFailure(winsockErrorToString(err));
|
||||
|
||||
case WSATRY_AGAIN:
|
||||
throw XArchNetworkNameUnavailable(new XArchEvalWinsock(err));
|
||||
throw XArchNetworkNameUnavailable(winsockErrorToString(err));
|
||||
|
||||
default:
|
||||
throw XArchNetwork(new XArchEvalWinsock(err));
|
||||
throw XArchNetwork(winsockErrorToString(err));
|
||||
}
|
||||
}
|
||||
|
||||
@ -921,18 +922,18 @@ void ArchNetworkWinsock::throwNameError(int err)
|
||||
{
|
||||
switch (err) {
|
||||
case WSAHOST_NOT_FOUND:
|
||||
throw XArchNetworkNameUnknown(new XArchEvalWinsock(err));
|
||||
throw XArchNetworkNameUnknown(winsockErrorToString(err));
|
||||
|
||||
case WSANO_DATA:
|
||||
throw XArchNetworkNameNoAddress(new XArchEvalWinsock(err));
|
||||
throw XArchNetworkNameNoAddress(winsockErrorToString(err));
|
||||
|
||||
case WSANO_RECOVERY:
|
||||
throw XArchNetworkNameFailure(new XArchEvalWinsock(err));
|
||||
throw XArchNetworkNameFailure(winsockErrorToString(err));
|
||||
|
||||
case WSATRY_AGAIN:
|
||||
throw XArchNetworkNameUnavailable(new XArchEvalWinsock(err));
|
||||
throw XArchNetworkNameUnavailable(winsockErrorToString(err));
|
||||
|
||||
default:
|
||||
throw XArchNetworkName(new XArchEvalWinsock(err));
|
||||
throw XArchNetworkName(winsockErrorToString(err));
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,39 +52,39 @@ class ArchNetworkWinsock : public IArchNetwork
|
||||
{
|
||||
public:
|
||||
ArchNetworkWinsock();
|
||||
virtual ~ArchNetworkWinsock();
|
||||
~ArchNetworkWinsock() override;
|
||||
|
||||
virtual void init();
|
||||
void init() override;
|
||||
|
||||
// IArchNetwork overrides
|
||||
virtual ArchSocket newSocket(EAddressFamily, ESocketType);
|
||||
virtual ArchSocket copySocket(ArchSocket s);
|
||||
virtual void closeSocket(ArchSocket s);
|
||||
virtual void closeSocketForRead(ArchSocket s);
|
||||
virtual void closeSocketForWrite(ArchSocket s);
|
||||
virtual void bindSocket(ArchSocket s, ArchNetAddress addr);
|
||||
virtual void listenOnSocket(ArchSocket s);
|
||||
virtual ArchSocket acceptSocket(ArchSocket s, ArchNetAddress *addr);
|
||||
virtual bool connectSocket(ArchSocket s, ArchNetAddress name);
|
||||
virtual int pollSocket(PollEntry[], int num, double timeout);
|
||||
virtual void unblockPollSocket(ArchThread thread);
|
||||
virtual size_t readSocket(ArchSocket s, void *buf, size_t len);
|
||||
virtual size_t writeSocket(ArchSocket s, const void *buf, size_t len);
|
||||
virtual void throwErrorOnSocket(ArchSocket);
|
||||
virtual bool setNoDelayOnSocket(ArchSocket, bool noDelay);
|
||||
virtual bool setReuseAddrOnSocket(ArchSocket, bool reuse);
|
||||
virtual std::string getHostName();
|
||||
virtual ArchNetAddress newAnyAddr(EAddressFamily);
|
||||
virtual ArchNetAddress copyAddr(ArchNetAddress);
|
||||
virtual std::vector<ArchNetAddress> nameToAddr(const std::string &);
|
||||
virtual void closeAddr(ArchNetAddress);
|
||||
virtual std::string addrToName(ArchNetAddress);
|
||||
virtual std::string addrToString(ArchNetAddress);
|
||||
virtual EAddressFamily getAddrFamily(ArchNetAddress);
|
||||
virtual void setAddrPort(ArchNetAddress, int port);
|
||||
virtual int getAddrPort(ArchNetAddress);
|
||||
virtual bool isAnyAddr(ArchNetAddress);
|
||||
virtual bool isEqualAddr(ArchNetAddress, ArchNetAddress);
|
||||
ArchSocket newSocket(EAddressFamily, ESocketType) override;
|
||||
ArchSocket copySocket(ArchSocket s) override;
|
||||
void closeSocket(ArchSocket s) override;
|
||||
void closeSocketForRead(ArchSocket s) override;
|
||||
void closeSocketForWrite(ArchSocket s) override;
|
||||
void bindSocket(ArchSocket s, ArchNetAddress addr) override;
|
||||
void listenOnSocket(ArchSocket s) override;
|
||||
ArchSocket acceptSocket(ArchSocket s, ArchNetAddress *addr) override;
|
||||
bool connectSocket(ArchSocket s, ArchNetAddress name) override;
|
||||
int pollSocket(PollEntry[], int num, double timeout) override;
|
||||
void unblockPollSocket(ArchThread thread) override;
|
||||
size_t readSocket(ArchSocket s, void *buf, size_t len) override;
|
||||
size_t writeSocket(ArchSocket s, const void *buf, size_t len) override;
|
||||
void throwErrorOnSocket(ArchSocket) override;
|
||||
bool setNoDelayOnSocket(ArchSocket, bool noDelay) override;
|
||||
bool setReuseAddrOnSocket(ArchSocket, bool reuse) override;
|
||||
std::string getHostName() override;
|
||||
ArchNetAddress newAnyAddr(EAddressFamily) override;
|
||||
ArchNetAddress copyAddr(ArchNetAddress) override;
|
||||
std::vector<ArchNetAddress> nameToAddr(const std::string &) override;
|
||||
void closeAddr(ArchNetAddress) override;
|
||||
std::string addrToName(ArchNetAddress) override;
|
||||
std::string addrToString(ArchNetAddress) override;
|
||||
EAddressFamily getAddrFamily(ArchNetAddress) override;
|
||||
void setAddrPort(ArchNetAddress, int port) override;
|
||||
int getAddrPort(ArchNetAddress) override;
|
||||
bool isAnyAddr(ArchNetAddress) override;
|
||||
bool isEqualAddr(ArchNetAddress, ArchNetAddress) override;
|
||||
|
||||
private:
|
||||
void initModule(HMODULE);
|
||||
|
||||
@ -13,16 +13,6 @@
|
||||
// ArchSleepWindows
|
||||
//
|
||||
|
||||
ArchSleepWindows::ArchSleepWindows()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
ArchSleepWindows::~ArchSleepWindows()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void ArchSleepWindows::sleep(double timeout)
|
||||
{
|
||||
ARCH->testCancelThread();
|
||||
@ -35,7 +25,7 @@ void ArchSleepWindows::sleep(double timeout)
|
||||
// this is windows so that's pretty certain; we'll get a
|
||||
// link error if we're not, though.
|
||||
ArchMultithreadWindows *mt = ArchMultithreadWindows::getInstance();
|
||||
if (mt != NULL) {
|
||||
if (mt != nullptr) {
|
||||
HANDLE cancelEvent = mt->getCancelEventForCurrentThread();
|
||||
WaitForSingleObject(cancelEvent, (DWORD)(1000.0 * timeout));
|
||||
if (timeout == 0.0) {
|
||||
|
||||
@ -15,9 +15,9 @@
|
||||
class ArchSleepWindows : public IArchSleep
|
||||
{
|
||||
public:
|
||||
ArchSleepWindows();
|
||||
virtual ~ArchSleepWindows();
|
||||
ArchSleepWindows() = default;
|
||||
~ArchSleepWindows() override = default;
|
||||
|
||||
// IArchSleep overrides
|
||||
virtual void sleep(double timeout);
|
||||
void sleep(double timeout) override;
|
||||
};
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "arch/win32/ArchStringWindows.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <stdio.h>
|
||||
|
||||
//
|
||||
// ArchStringWindows
|
||||
//
|
||||
|
||||
ArchStringWindows::ArchStringWindows()
|
||||
{
|
||||
}
|
||||
|
||||
ArchStringWindows::~ArchStringWindows()
|
||||
{
|
||||
}
|
||||
|
||||
IArchString::EWideCharEncoding ArchStringWindows::getWideCharEncoding()
|
||||
{
|
||||
return kUTF16;
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "arch/IArchString.h"
|
||||
|
||||
#define ARCH_STRING ArchStringWindows
|
||||
|
||||
//! Win32 implementation of IArchString
|
||||
class ArchStringWindows : public IArchString
|
||||
{
|
||||
public:
|
||||
ArchStringWindows();
|
||||
virtual ~ArchStringWindows();
|
||||
|
||||
// IArchString overrides
|
||||
virtual EWideCharEncoding getWideCharEncoding();
|
||||
};
|
||||
@ -25,8 +25,8 @@
|
||||
typedef WINMMAPI DWORD(WINAPI *PTimeGetTime)(void);
|
||||
|
||||
static double s_freq = 0.0;
|
||||
static HINSTANCE s_mmInstance = NULL;
|
||||
static PTimeGetTime s_tgt = NULL;
|
||||
static HINSTANCE s_mmInstance = nullptr;
|
||||
static PTimeGetTime s_tgt = nullptr;
|
||||
|
||||
//
|
||||
// ArchTimeWindows
|
||||
@ -34,7 +34,7 @@ static PTimeGetTime s_tgt = NULL;
|
||||
|
||||
ArchTimeWindows::ArchTimeWindows()
|
||||
{
|
||||
assert(s_freq == 0.0 || s_mmInstance == NULL);
|
||||
assert(s_freq == 0.0 || s_mmInstance == nullptr);
|
||||
|
||||
LARGE_INTEGER freq;
|
||||
if (QueryPerformanceFrequency(&freq) && freq.QuadPart != 0) {
|
||||
@ -42,7 +42,7 @@ ArchTimeWindows::ArchTimeWindows()
|
||||
} else {
|
||||
// load winmm.dll and get timeGetTime
|
||||
s_mmInstance = LoadLibrary("winmm");
|
||||
if (s_mmInstance != NULL) {
|
||||
if (s_mmInstance != nullptr) {
|
||||
s_tgt = (PTimeGetTime)GetProcAddress(s_mmInstance, "timeGetTime");
|
||||
}
|
||||
}
|
||||
@ -51,10 +51,10 @@ ArchTimeWindows::ArchTimeWindows()
|
||||
ArchTimeWindows::~ArchTimeWindows()
|
||||
{
|
||||
s_freq = 0.0;
|
||||
if (s_mmInstance == NULL) {
|
||||
if (s_mmInstance == nullptr) {
|
||||
FreeLibrary(static_cast<HMODULE>(s_mmInstance));
|
||||
s_tgt = NULL;
|
||||
s_mmInstance = NULL;
|
||||
s_tgt = nullptr;
|
||||
s_mmInstance = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ double ArchTimeWindows::time()
|
||||
LARGE_INTEGER c;
|
||||
QueryPerformanceCounter(&c);
|
||||
return s_freq * static_cast<double>(c.QuadPart);
|
||||
} else if (s_tgt != NULL) {
|
||||
} else if (s_tgt != nullptr) {
|
||||
return 0.001 * static_cast<double>(s_tgt());
|
||||
} else {
|
||||
return 0.001 * static_cast<double>(GetTickCount());
|
||||
|
||||
@ -16,8 +16,8 @@ class ArchTimeWindows : public IArchTime
|
||||
{
|
||||
public:
|
||||
ArchTimeWindows();
|
||||
virtual ~ArchTimeWindows();
|
||||
~ArchTimeWindows() override;
|
||||
|
||||
// IArchTime overrides
|
||||
virtual double time();
|
||||
double time() override;
|
||||
};
|
||||
|
||||
@ -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
|
||||
@ -9,30 +10,22 @@
|
||||
#include "arch/win32/ArchNetworkWinsock.h"
|
||||
#include "base/String.h"
|
||||
|
||||
//
|
||||
// XArchEvalWindows
|
||||
//
|
||||
|
||||
std::string XArchEvalWindows::eval() const throw()
|
||||
std::string windowsErrorToString(DWORD error)
|
||||
{
|
||||
char *cmsg;
|
||||
if (FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, 0, m_error,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&cmsg, 0, NULL
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, 0, error,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&cmsg, 0, nullptr
|
||||
) == 0) {
|
||||
cmsg = NULL;
|
||||
return deskflow::string::sprintf("Unknown error, code %d", m_error);
|
||||
cmsg = nullptr;
|
||||
return deskflow::string::sprintf("Unknown error, code %d", error);
|
||||
}
|
||||
std::string smsg(cmsg);
|
||||
LocalFree(cmsg);
|
||||
return smsg;
|
||||
}
|
||||
|
||||
//
|
||||
// XArchEvalWinsock
|
||||
//
|
||||
|
||||
std::string XArchEvalWinsock::eval() const throw()
|
||||
std::string winsockErrorToString(int error)
|
||||
{
|
||||
// built-in windows function for looking up error message strings
|
||||
// may not look up network error messages correctly. we'll have
|
||||
@ -200,11 +193,11 @@ std::string XArchEvalWinsock::eval() const throw()
|
||||
{WSANO_DATA, "The requested name is valid but does not have an IP address"},
|
||||
|
||||
// end
|
||||
{0, NULL}
|
||||
{0, nullptr}
|
||||
};
|
||||
|
||||
for (unsigned int i = 0; s_netErrorCodes[i].m_code != 0; ++i) {
|
||||
if (s_netErrorCodes[i].m_code == m_error) {
|
||||
if (s_netErrorCodes[i].m_code == error) {
|
||||
return s_netErrorCodes[i].m_msg;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -7,44 +8,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "arch/XArch.h"
|
||||
#include <string>
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
|
||||
//! Lazy error message string evaluation for windows
|
||||
class XArchEvalWindows : public XArchEval
|
||||
{
|
||||
public:
|
||||
XArchEvalWindows() : m_error(GetLastError())
|
||||
{
|
||||
}
|
||||
XArchEvalWindows(DWORD error) : m_error(error)
|
||||
{
|
||||
}
|
||||
virtual ~XArchEvalWindows()
|
||||
{
|
||||
}
|
||||
|
||||
virtual std::string eval() const throw();
|
||||
|
||||
private:
|
||||
DWORD m_error;
|
||||
};
|
||||
|
||||
//! Lazy error message string evaluation for winsock
|
||||
class XArchEvalWinsock : public XArchEval
|
||||
{
|
||||
public:
|
||||
XArchEvalWinsock(int error) : m_error(error)
|
||||
{
|
||||
}
|
||||
virtual ~XArchEvalWinsock()
|
||||
{
|
||||
}
|
||||
|
||||
virtual std::string eval() const throw();
|
||||
|
||||
private:
|
||||
int m_error;
|
||||
};
|
||||
std::string winsockErrorToString(int error);
|
||||
std::string windowsErrorToString(DWORD error);
|
||||
|
||||
@ -9,7 +9,6 @@ add_library(base STATIC
|
||||
Event.h
|
||||
EventQueue.cpp
|
||||
EventQueue.h
|
||||
EventTypes.cpp
|
||||
EventTypes.h
|
||||
FinalAction.h
|
||||
FunctionEventJob.cpp
|
||||
|
||||
@ -10,32 +10,24 @@
|
||||
//
|
||||
// Event
|
||||
//
|
||||
|
||||
Event::Event() : m_type(kUnknown), m_target(NULL), m_data(NULL), m_flags(0), m_dataObject(nullptr)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
Event::Event(Type type, void *target, void *data, Flags flags)
|
||||
Event::Event(EventTypes type, void *target, void *data, Flags flags)
|
||||
: m_type(type),
|
||||
m_target(target),
|
||||
m_data(data),
|
||||
m_flags(flags),
|
||||
m_dataObject(nullptr)
|
||||
m_flags(flags)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
Event::Event(Type type, void *target, EventData *dataObject)
|
||||
Event::Event(EventTypes type, void *target, EventData *dataObject)
|
||||
: m_type(type),
|
||||
m_target(target),
|
||||
m_data(nullptr),
|
||||
m_flags(kNone),
|
||||
m_dataObject(dataObject)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
Event::Type Event::getType() const
|
||||
EventTypes Event::getType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
@ -63,10 +55,10 @@ Event::Flags Event::getFlags() const
|
||||
void Event::deleteData(const Event &event)
|
||||
{
|
||||
switch (event.getType()) {
|
||||
case kUnknown:
|
||||
case kQuit:
|
||||
case kSystem:
|
||||
case kTimer:
|
||||
case EventTypes::Unknown:
|
||||
case EventTypes::Quit:
|
||||
case EventTypes::System:
|
||||
case EventTypes::Timer:
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@ -7,17 +7,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "EventTypes.h"
|
||||
#include "common/Common.h"
|
||||
|
||||
using deskflow::EventTypes;
|
||||
|
||||
class EventData
|
||||
{
|
||||
public:
|
||||
EventData()
|
||||
{
|
||||
}
|
||||
virtual ~EventData()
|
||||
{
|
||||
}
|
||||
EventData() = default;
|
||||
virtual ~EventData() = default;
|
||||
};
|
||||
|
||||
//! Event
|
||||
@ -27,16 +26,6 @@ A \c Event holds an event type and a pointer to event data.
|
||||
class Event
|
||||
{
|
||||
public:
|
||||
using Type = uint32_t;
|
||||
enum
|
||||
{
|
||||
kUnknown, //!< The event type is unknown
|
||||
kQuit, //!< The quit event
|
||||
kSystem, //!< The data points to a system event type
|
||||
kTimer, //!< The data points to timer info
|
||||
kLast //!< Must be last
|
||||
};
|
||||
|
||||
using Flags = uint32_t;
|
||||
enum
|
||||
{
|
||||
@ -45,7 +34,7 @@ public:
|
||||
kDontFreeData = 0x02 //!< Don't free data in deleteData
|
||||
};
|
||||
|
||||
Event();
|
||||
Event() = default;
|
||||
|
||||
//! Create \c Event with data (POD)
|
||||
/*!
|
||||
@ -56,7 +45,7 @@ public:
|
||||
\p target is the intended recipient of the event.
|
||||
\p flags is any combination of \c Flags.
|
||||
*/
|
||||
Event(Type type, void *target = NULL, void *data = NULL, Flags flags = kNone);
|
||||
Event(EventTypes type, void *target = nullptr, void *data = nullptr, Flags flags = kNone);
|
||||
|
||||
//! Create \c Event with non-POD data
|
||||
/*!
|
||||
@ -64,7 +53,7 @@ public:
|
||||
\p target is the intended recipient of the event.
|
||||
\p dataObject with event data
|
||||
*/
|
||||
Event(Type type, void *target, EventData *dataObject);
|
||||
Event(EventTypes type, void *target, EventData *dataObject);
|
||||
|
||||
//! @name manipulators
|
||||
//@{
|
||||
@ -90,7 +79,7 @@ public:
|
||||
/*!
|
||||
Returns the event type.
|
||||
*/
|
||||
Type getType() const;
|
||||
EventTypes getType() const;
|
||||
|
||||
//! Get the event target
|
||||
/*!
|
||||
@ -121,9 +110,9 @@ public:
|
||||
//@}
|
||||
|
||||
private:
|
||||
Type m_type;
|
||||
void *m_target;
|
||||
void *m_data;
|
||||
Flags m_flags;
|
||||
EventData *m_dataObject;
|
||||
EventTypes m_type = EventTypes::Unknown;
|
||||
void *m_target = nullptr;
|
||||
void *m_data = nullptr;
|
||||
Flags m_flags = kNone;
|
||||
EventData *m_dataObject = nullptr;
|
||||
};
|
||||
|
||||
@ -16,72 +16,32 @@
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
EVENT_TYPE_ACCESSOR(Client)
|
||||
EVENT_TYPE_ACCESSOR(IStream)
|
||||
EVENT_TYPE_ACCESSOR(IDataSocket)
|
||||
EVENT_TYPE_ACCESSOR(IListenSocket)
|
||||
EVENT_TYPE_ACCESSOR(ISocket)
|
||||
EVENT_TYPE_ACCESSOR(OSXScreen)
|
||||
EVENT_TYPE_ACCESSOR(ClientListener)
|
||||
EVENT_TYPE_ACCESSOR(ClientProxy)
|
||||
EVENT_TYPE_ACCESSOR(ClientProxyUnknown)
|
||||
EVENT_TYPE_ACCESSOR(Server)
|
||||
EVENT_TYPE_ACCESSOR(ServerApp)
|
||||
EVENT_TYPE_ACCESSOR(IKeyState)
|
||||
EVENT_TYPE_ACCESSOR(IPrimaryScreen)
|
||||
EVENT_TYPE_ACCESSOR(IScreen)
|
||||
EVENT_TYPE_ACCESSOR(Clipboard)
|
||||
EVENT_TYPE_ACCESSOR(File)
|
||||
EVENT_TYPE_ACCESSOR(Ei)
|
||||
|
||||
// interrupt handler. this just adds a quit event to the queue.
|
||||
static void interrupt(Arch::ESignal, void *data)
|
||||
{
|
||||
EventQueue *events = static_cast<EventQueue *>(data);
|
||||
events->addEvent(Event(Event::kQuit));
|
||||
auto *events = static_cast<EventQueue *>(data);
|
||||
events->addEvent(Event(EventTypes::Quit));
|
||||
}
|
||||
|
||||
//
|
||||
// EventQueue
|
||||
//
|
||||
|
||||
EventQueue::EventQueue()
|
||||
: m_systemTarget(0),
|
||||
m_nextType(Event::kLast),
|
||||
m_typesForClient(NULL),
|
||||
m_typesForIStream(NULL),
|
||||
m_typesForIDataSocket(NULL),
|
||||
m_typesForIListenSocket(NULL),
|
||||
m_typesForISocket(NULL),
|
||||
m_typesForOSXScreen(NULL),
|
||||
m_typesForClientListener(NULL),
|
||||
m_typesForClientProxy(NULL),
|
||||
m_typesForClientProxyUnknown(NULL),
|
||||
m_typesForServer(NULL),
|
||||
m_typesForServerApp(NULL),
|
||||
m_typesForIKeyState(NULL),
|
||||
m_typesForIPrimaryScreen(NULL),
|
||||
m_typesForIScreen(NULL),
|
||||
m_typesForClipboard(NULL),
|
||||
m_typesForFile(NULL),
|
||||
m_typesForEi(NULL),
|
||||
m_readyMutex(new Mutex),
|
||||
m_readyCondVar(new CondVar<bool>(m_readyMutex, false))
|
||||
EventQueue::EventQueue() : m_readyMutex(new Mutex), m_readyCondVar(new CondVar<bool>(m_readyMutex, false))
|
||||
{
|
||||
m_mutex = ARCH->newMutex();
|
||||
ARCH->setSignalHandler(Arch::kINTERRUPT, &interrupt, this);
|
||||
ARCH->setSignalHandler(Arch::kTERMINATE, &interrupt, this);
|
||||
m_buffer = new SimpleEventQueueBuffer;
|
||||
m_buffer = std::make_unique<SimpleEventQueueBuffer>();
|
||||
}
|
||||
|
||||
EventQueue::~EventQueue()
|
||||
{
|
||||
delete m_buffer;
|
||||
delete m_readyCondVar;
|
||||
delete m_readyMutex;
|
||||
|
||||
ARCH->setSignalHandler(Arch::kINTERRUPT, NULL, NULL);
|
||||
ARCH->setSignalHandler(Arch::kTERMINATE, NULL, NULL);
|
||||
ARCH->setSignalHandler(Arch::kINTERRUPT, nullptr, nullptr);
|
||||
ARCH->setSignalHandler(Arch::kTERMINATE, nullptr, nullptr);
|
||||
ARCH->closeMutex(m_mutex);
|
||||
}
|
||||
|
||||
@ -96,57 +56,20 @@ void EventQueue::loop()
|
||||
LOG((CLOG_DEBUG "event queue is ready"));
|
||||
while (!m_pending.empty()) {
|
||||
LOG((CLOG_DEBUG "add pending events to buffer"));
|
||||
Event &event = m_pending.front();
|
||||
const Event &event = m_pending.front();
|
||||
addEventToBuffer(event);
|
||||
m_pending.pop();
|
||||
}
|
||||
|
||||
Event event;
|
||||
getEvent(event);
|
||||
while (event.getType() != Event::kQuit) {
|
||||
while (event.getType() != EventTypes::Quit) {
|
||||
dispatchEvent(event);
|
||||
Event::deleteData(event);
|
||||
getEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
Event::Type EventQueue::registerTypeOnce(Event::Type &type, const char *name)
|
||||
{
|
||||
ArchMutexLock lock(m_mutex);
|
||||
if (type == Event::kUnknown) {
|
||||
m_typeMap.insert(std::make_pair(m_nextType, name));
|
||||
m_nameMap.insert(std::make_pair(name, m_nextType));
|
||||
LOG((CLOG_DEBUG1 "registered event type %s as %d", name, m_nextType));
|
||||
type = m_nextType++;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
const char *EventQueue::getTypeName(Event::Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case Event::kUnknown:
|
||||
return "nil";
|
||||
|
||||
case Event::kQuit:
|
||||
return "quit";
|
||||
|
||||
case Event::kSystem:
|
||||
return "system";
|
||||
|
||||
case Event::kTimer:
|
||||
return "timer";
|
||||
|
||||
default:
|
||||
TypeMap::const_iterator i = m_typeMap.find(type);
|
||||
if (i == m_typeMap.end()) {
|
||||
return "<unknown>";
|
||||
} else {
|
||||
return i->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventQueue::adoptBuffer(IEventQueueBuffer *buffer)
|
||||
{
|
||||
ArchMutexLock lock(m_mutex);
|
||||
@ -160,24 +83,22 @@ void EventQueue::adoptBuffer(IEventQueueBuffer *buffer)
|
||||
}
|
||||
|
||||
// discard old buffer and old events
|
||||
delete m_buffer;
|
||||
for (EventTable::iterator i = m_events.begin(); i != m_events.end(); ++i) {
|
||||
m_buffer.reset();
|
||||
for (auto i = m_events.begin(); i != m_events.end(); ++i) {
|
||||
Event::deleteData(i->second);
|
||||
}
|
||||
m_events.clear();
|
||||
m_oldEventIDs.clear();
|
||||
|
||||
// use new buffer
|
||||
m_buffer = buffer;
|
||||
if (m_buffer == NULL) {
|
||||
m_buffer = new SimpleEventQueueBuffer;
|
||||
m_buffer.reset(buffer);
|
||||
if (buffer == nullptr) {
|
||||
m_buffer = std::make_unique<SimpleEventQueueBuffer>();
|
||||
}
|
||||
}
|
||||
|
||||
bool EventQueue::getEvent(Event &event, double timeout)
|
||||
bool EventQueue::processEvent(Event &event, double timeout, Stopwatch &timer)
|
||||
{
|
||||
Stopwatch timer(true);
|
||||
retry:
|
||||
// if no events are waiting then handle timers and then wait
|
||||
while (m_buffer->isEmpty()) {
|
||||
// handle timers first
|
||||
@ -194,8 +115,8 @@ retry:
|
||||
// get time until next timer expires. if there is a timer
|
||||
// and it'll expire before the client's timeout then use
|
||||
// that duration for our timeout instead.
|
||||
double timerTimeout = getNextTimerTimeout();
|
||||
if (timeout < 0.0 || (timerTimeout >= 0.0 && timerTimeout < timeLeft)) {
|
||||
if (double timerTimeout = getNextTimerTimeout();
|
||||
timeout < 0.0 || (timerTimeout >= 0.0 && timerTimeout < timeLeft)) {
|
||||
timeLeft = timerTimeout;
|
||||
}
|
||||
|
||||
@ -212,7 +133,7 @@ retry:
|
||||
// don't want to fail if client isn't expecting that
|
||||
// so if getEvent() fails with an infinite timeout
|
||||
// then just try getting another event.
|
||||
goto retry;
|
||||
processEvent(event, timeout, timer);
|
||||
}
|
||||
return false;
|
||||
|
||||
@ -231,14 +152,20 @@ retry:
|
||||
}
|
||||
}
|
||||
|
||||
bool EventQueue::getEvent(Event &event, double timeout)
|
||||
{
|
||||
Stopwatch timer(true);
|
||||
return processEvent(event, timeout, timer);
|
||||
}
|
||||
|
||||
bool EventQueue::dispatchEvent(const Event &event)
|
||||
{
|
||||
void *target = event.getTarget();
|
||||
IEventJob *job = getHandler(event.getType(), target);
|
||||
if (job == NULL) {
|
||||
job = getHandler(Event::kUnknown, target);
|
||||
if (job == nullptr) {
|
||||
job = getHandler(EventTypes::Unknown, target);
|
||||
}
|
||||
if (job != NULL) {
|
||||
if (job != nullptr) {
|
||||
job->run(event);
|
||||
return true;
|
||||
}
|
||||
@ -249,9 +176,9 @@ void EventQueue::addEvent(const Event &event)
|
||||
{
|
||||
// discard bogus event types
|
||||
switch (event.getType()) {
|
||||
case Event::kUnknown:
|
||||
case Event::kSystem:
|
||||
case Event::kTimer:
|
||||
case EventTypes::Unknown:
|
||||
case EventTypes::System:
|
||||
case EventTypes::Timer:
|
||||
return;
|
||||
|
||||
default:
|
||||
@ -273,7 +200,7 @@ void EventQueue::addEventToBuffer(const Event &event)
|
||||
ArchMutexLock lock(m_mutex);
|
||||
|
||||
// store the event's data locally
|
||||
uint32_t eventID = saveEvent(event);
|
||||
auto eventID = saveEvent(event);
|
||||
|
||||
// add it
|
||||
if (!m_buffer->addEvent(eventID)) {
|
||||
@ -288,7 +215,7 @@ EventQueueTimer *EventQueue::newTimer(double duration, void *target)
|
||||
assert(duration > 0.0);
|
||||
|
||||
EventQueueTimer *timer = m_buffer->newTimer(duration, false);
|
||||
if (target == NULL) {
|
||||
if (target == nullptr) {
|
||||
target = timer;
|
||||
}
|
||||
ArchMutexLock lock(m_mutex);
|
||||
@ -305,7 +232,7 @@ EventQueueTimer *EventQueue::newOneShotTimer(double duration, void *target)
|
||||
assert(duration > 0.0);
|
||||
|
||||
EventQueueTimer *timer = m_buffer->newTimer(duration, true);
|
||||
if (target == NULL) {
|
||||
if (target == nullptr) {
|
||||
target = timer;
|
||||
}
|
||||
ArchMutexLock lock(m_mutex);
|
||||
@ -320,30 +247,27 @@ EventQueueTimer *EventQueue::newOneShotTimer(double duration, void *target)
|
||||
void EventQueue::deleteTimer(EventQueueTimer *timer)
|
||||
{
|
||||
ArchMutexLock lock(m_mutex);
|
||||
for (TimerQueue::iterator index = m_timerQueue.begin(); index != m_timerQueue.end(); ++index) {
|
||||
for (auto index = m_timerQueue.begin(); index != m_timerQueue.end(); ++index) {
|
||||
if (index->getTimer() == timer) {
|
||||
m_timerQueue.erase(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Timers::iterator index = m_timers.find(timer);
|
||||
if (index != m_timers.end()) {
|
||||
if (Timers::iterator index = m_timers.find(timer); index != m_timers.end()) {
|
||||
m_timers.erase(index);
|
||||
}
|
||||
m_buffer->deleteTimer(timer);
|
||||
}
|
||||
|
||||
void EventQueue::adoptHandler(Event::Type type, void *target, IEventJob *handler)
|
||||
void EventQueue::adoptHandler(EventTypes type, void *target, IEventJob *handler)
|
||||
{
|
||||
ArchMutexLock lock(m_mutex);
|
||||
IEventJob *&job = m_handlers[target][type];
|
||||
delete job;
|
||||
job = handler;
|
||||
m_handlers[target][type].reset(handler);
|
||||
}
|
||||
|
||||
void EventQueue::removeHandler(Event::Type type, void *target)
|
||||
void EventQueue::removeHandler(EventTypes type, void *target)
|
||||
{
|
||||
IEventJob *handler = NULL;
|
||||
std::unique_ptr<IEventJob> handler;
|
||||
{
|
||||
ArchMutexLock lock(m_mutex);
|
||||
HandlerTable::iterator index = m_handlers.find(target);
|
||||
@ -351,34 +275,30 @@ void EventQueue::removeHandler(Event::Type type, void *target)
|
||||
TypeHandlerTable &typeHandlers = index->second;
|
||||
TypeHandlerTable::iterator index2 = typeHandlers.find(type);
|
||||
if (index2 != typeHandlers.end()) {
|
||||
handler = index2->second;
|
||||
handler = std::move(index2->second);
|
||||
typeHandlers.erase(index2);
|
||||
}
|
||||
}
|
||||
}
|
||||
delete handler;
|
||||
// handler is erased here. It is done outside of lock in order to avoid potential deadlock.
|
||||
}
|
||||
|
||||
void EventQueue::removeHandlers(void *target)
|
||||
{
|
||||
std::vector<IEventJob *> handlers;
|
||||
std::vector<std::unique_ptr<IEventJob>> handlers;
|
||||
{
|
||||
ArchMutexLock lock(m_mutex);
|
||||
HandlerTable::iterator index = m_handlers.find(target);
|
||||
if (index != m_handlers.end()) {
|
||||
// copy to handlers array and clear table for target
|
||||
TypeHandlerTable &typeHandlers = index->second;
|
||||
for (TypeHandlerTable::iterator index2 = typeHandlers.begin(); index2 != typeHandlers.end(); ++index2) {
|
||||
handlers.push_back(index2->second);
|
||||
for (auto &[key, value] : typeHandlers) {
|
||||
handlers.push_back(std::move(value));
|
||||
}
|
||||
typeHandlers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// delete handlers
|
||||
for (std::vector<IEventJob *>::iterator index = handlers.begin(); index != handlers.end(); ++index) {
|
||||
delete *index;
|
||||
}
|
||||
// handler is erased here. It is done outside of lock in order to avoid potential deadlock.
|
||||
}
|
||||
|
||||
bool EventQueue::isEmpty() const
|
||||
@ -386,18 +306,17 @@ bool EventQueue::isEmpty() const
|
||||
return (m_buffer->isEmpty() && getNextTimerTimeout() != 0.0);
|
||||
}
|
||||
|
||||
IEventJob *EventQueue::getHandler(Event::Type type, void *target) const
|
||||
IEventJob *EventQueue::getHandler(EventTypes type, void *target) const
|
||||
{
|
||||
ArchMutexLock lock(m_mutex);
|
||||
HandlerTable::const_iterator index = m_handlers.find(target);
|
||||
if (index != m_handlers.end()) {
|
||||
if (HandlerTable::const_iterator index = m_handlers.find(target); index != m_handlers.end()) {
|
||||
const TypeHandlerTable &typeHandlers = index->second;
|
||||
TypeHandlerTable::const_iterator index2 = typeHandlers.find(type);
|
||||
if (index2 != typeHandlers.end()) {
|
||||
return index2->second;
|
||||
return index2->second.get();
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t EventQueue::saveEvent(const Event &event)
|
||||
@ -450,7 +369,7 @@ bool EventQueue::hasTimerExpired(Event &event)
|
||||
m_time.reset();
|
||||
|
||||
// countdown elapsed time
|
||||
for (TimerQueue::iterator index = m_timerQueue.begin(); index != m_timerQueue.end(); ++index) {
|
||||
for (auto index = m_timerQueue.begin(); index != m_timerQueue.end(); ++index) {
|
||||
(*index) -= time;
|
||||
}
|
||||
|
||||
@ -465,7 +384,7 @@ bool EventQueue::hasTimerExpired(Event &event)
|
||||
|
||||
// prepare event and reset the timer's clock
|
||||
timer.fillEvent(m_timerEvent);
|
||||
event = Event(Event::kTimer, timer.getTarget(), &m_timerEvent);
|
||||
event = Event(EventTypes::Timer, timer.getTarget(), &m_timerEvent);
|
||||
timer.reset();
|
||||
|
||||
// reinsert timer into queue if it's not a one-shot
|
||||
@ -490,15 +409,6 @@ double EventQueue::getNextTimerTimeout() const
|
||||
return m_timerQueue.top();
|
||||
}
|
||||
|
||||
Event::Type EventQueue::getRegisteredType(const std::string &name) const
|
||||
{
|
||||
NameMap::const_iterator found = m_nameMap.find(name);
|
||||
if (found != m_nameMap.end())
|
||||
return found->second;
|
||||
|
||||
return Event::kUnknown;
|
||||
}
|
||||
|
||||
void *EventQueue::getSystemTarget()
|
||||
{
|
||||
// any unique arbitrary pointer will do
|
||||
@ -531,11 +441,6 @@ EventQueue::Timer::Timer(EventQueueTimer *timer, double timeout, double initialT
|
||||
assert(m_timeout > 0.0);
|
||||
}
|
||||
|
||||
EventQueue::Timer::~Timer()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void EventQueue::Timer::reset()
|
||||
{
|
||||
m_time = m_timeout;
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include "mt/CondVar.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
|
||||
@ -30,29 +31,26 @@ public:
|
||||
EventQueue();
|
||||
EventQueue(EventQueue const &) = delete;
|
||||
EventQueue(EventQueue &&) = delete;
|
||||
virtual ~EventQueue();
|
||||
~EventQueue() override;
|
||||
EventQueue &operator=(EventQueue const &) = delete;
|
||||
EventQueue &operator=(EventQueue &&) = delete;
|
||||
|
||||
// IEventQueue overrides
|
||||
virtual void loop();
|
||||
virtual void adoptBuffer(IEventQueueBuffer *);
|
||||
virtual bool getEvent(Event &event, double timeout = -1.0);
|
||||
virtual bool dispatchEvent(const Event &event);
|
||||
virtual void addEvent(const Event &event);
|
||||
virtual EventQueueTimer *newTimer(double duration, void *target);
|
||||
virtual EventQueueTimer *newOneShotTimer(double duration, void *target);
|
||||
virtual void deleteTimer(EventQueueTimer *);
|
||||
virtual void adoptHandler(Event::Type type, void *target, IEventJob *handler);
|
||||
virtual void removeHandler(Event::Type type, void *target);
|
||||
virtual void removeHandlers(void *target);
|
||||
virtual Event::Type registerTypeOnce(Event::Type &type, const char *name);
|
||||
virtual bool isEmpty() const;
|
||||
virtual IEventJob *getHandler(Event::Type type, void *target) const;
|
||||
virtual const char *getTypeName(Event::Type type);
|
||||
virtual Event::Type getRegisteredType(const std::string &name) const;
|
||||
void *getSystemTarget();
|
||||
virtual void waitForReady() const;
|
||||
void loop() override;
|
||||
void adoptBuffer(IEventQueueBuffer *) override;
|
||||
bool getEvent(Event &event, double timeout = -1.0) override;
|
||||
bool dispatchEvent(const Event &event) override;
|
||||
void addEvent(const Event &event) override;
|
||||
EventQueueTimer *newTimer(double duration, void *target) override;
|
||||
EventQueueTimer *newOneShotTimer(double duration, void *target) override;
|
||||
void deleteTimer(EventQueueTimer *) override;
|
||||
void adoptHandler(EventTypes type, void *target, IEventJob *handler) override;
|
||||
void removeHandler(EventTypes type, void *target) override;
|
||||
void removeHandlers(void *target) override;
|
||||
bool isEmpty() const override;
|
||||
IEventJob *getHandler(EventTypes type, void *target) const override;
|
||||
void *getSystemTarget() override;
|
||||
void waitForReady() const override;
|
||||
|
||||
private:
|
||||
uint32_t saveEvent(const Event &event);
|
||||
@ -61,12 +59,21 @@ private:
|
||||
double getNextTimerTimeout() const;
|
||||
void addEventToBuffer(const Event &event);
|
||||
|
||||
//!
|
||||
//! \brief processEvent Internal event proccessing
|
||||
//! \param event - event to process
|
||||
//! \param timeout - Timeout to stop
|
||||
//! \param timer - StopWatch to use
|
||||
//! \return true if handled
|
||||
//!
|
||||
bool processEvent(Event &event, double timeout, Stopwatch &timer);
|
||||
|
||||
private:
|
||||
class Timer
|
||||
{
|
||||
public:
|
||||
Timer(EventQueueTimer *, double timeout, double initialTime, void *target, bool oneShot);
|
||||
~Timer();
|
||||
~Timer() = default;
|
||||
|
||||
void reset();
|
||||
|
||||
@ -93,21 +100,14 @@ private:
|
||||
using TimerQueue = PriorityQueue<Timer>;
|
||||
using EventTable = std::map<uint32_t, Event>;
|
||||
using EventIDList = std::vector<uint32_t>;
|
||||
using TypeMap = std::map<Event::Type, const char *>;
|
||||
using NameMap = std::map<std::string, Event::Type>;
|
||||
using TypeHandlerTable = std::map<Event::Type, IEventJob *>;
|
||||
using TypeHandlerTable = std::map<EventTypes, std::unique_ptr<IEventJob>>;
|
||||
using HandlerTable = std::map<void *, TypeHandlerTable>;
|
||||
|
||||
int m_systemTarget;
|
||||
int m_systemTarget = 0;
|
||||
ArchMutex m_mutex;
|
||||
|
||||
// registered events
|
||||
Event::Type m_nextType;
|
||||
TypeMap m_typeMap;
|
||||
NameMap m_nameMap;
|
||||
|
||||
// buffer of events
|
||||
IEventQueueBuffer *m_buffer;
|
||||
std::unique_ptr<IEventQueueBuffer> m_buffer;
|
||||
|
||||
// saved events
|
||||
EventTable m_events;
|
||||
@ -122,58 +122,8 @@ private:
|
||||
// event handlers
|
||||
HandlerTable m_handlers;
|
||||
|
||||
public:
|
||||
//
|
||||
// Event type providers.
|
||||
//
|
||||
ClientEvents &forClient();
|
||||
IStreamEvents &forIStream();
|
||||
IDataSocketEvents &forIDataSocket();
|
||||
IListenSocketEvents &forIListenSocket();
|
||||
ISocketEvents &forISocket();
|
||||
OSXScreenEvents &forOSXScreen();
|
||||
ClientListenerEvents &forClientListener();
|
||||
ClientProxyEvents &forClientProxy();
|
||||
ClientProxyUnknownEvents &forClientProxyUnknown();
|
||||
ServerEvents &forServer();
|
||||
ServerAppEvents &forServerApp();
|
||||
IKeyStateEvents &forIKeyState();
|
||||
IPrimaryScreenEvents &forIPrimaryScreen();
|
||||
IScreenEvents &forIScreen();
|
||||
ClipboardEvents &forClipboard();
|
||||
FileEvents &forFile();
|
||||
EiEvents &forEi();
|
||||
|
||||
private:
|
||||
ClientEvents *m_typesForClient;
|
||||
IStreamEvents *m_typesForIStream;
|
||||
IDataSocketEvents *m_typesForIDataSocket;
|
||||
IListenSocketEvents *m_typesForIListenSocket;
|
||||
ISocketEvents *m_typesForISocket;
|
||||
OSXScreenEvents *m_typesForOSXScreen;
|
||||
ClientListenerEvents *m_typesForClientListener;
|
||||
ClientProxyEvents *m_typesForClientProxy;
|
||||
ClientProxyUnknownEvents *m_typesForClientProxyUnknown;
|
||||
ServerEvents *m_typesForServer;
|
||||
ServerAppEvents *m_typesForServerApp;
|
||||
IKeyStateEvents *m_typesForIKeyState;
|
||||
IPrimaryScreenEvents *m_typesForIPrimaryScreen;
|
||||
IScreenEvents *m_typesForIScreen;
|
||||
ClipboardEvents *m_typesForClipboard;
|
||||
FileEvents *m_typesForFile;
|
||||
EiEvents *m_typesForEi;
|
||||
Mutex *m_readyMutex;
|
||||
CondVar<bool> *m_readyCondVar;
|
||||
Mutex *m_readyMutex = nullptr;
|
||||
CondVar<bool> *m_readyCondVar = nullptr;
|
||||
std::queue<Event> m_pending;
|
||||
};
|
||||
|
||||
#define EVENT_TYPE_ACCESSOR(type_) \
|
||||
type_##Events& \
|
||||
EventQueue::for##type_() \
|
||||
{ \
|
||||
if (m_typesFor##type_ == NULL) { \
|
||||
m_typesFor##type_ = new type_##Events(); \
|
||||
m_typesFor##type_->setEvents(dynamic_cast<IEventQueue *>(this)); \
|
||||
} \
|
||||
return *m_typesFor##type_; \
|
||||
}
|
||||
|
||||
@ -1,170 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2013 - 2016 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "base/EventTypes.h"
|
||||
#include "base/IEventQueue.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
EventTypes::EventTypes() : m_events(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
IEventQueue *EventTypes::getEvents() const
|
||||
{
|
||||
assert(m_events != NULL);
|
||||
return m_events;
|
||||
}
|
||||
|
||||
void EventTypes::setEvents(IEventQueue *events)
|
||||
{
|
||||
m_events = events;
|
||||
}
|
||||
|
||||
//
|
||||
// Client
|
||||
//
|
||||
|
||||
REGISTER_EVENT(Client, connected)
|
||||
REGISTER_EVENT(Client, connectionFailed)
|
||||
REGISTER_EVENT(Client, connectionRefused)
|
||||
REGISTER_EVENT(Client, disconnected)
|
||||
|
||||
//
|
||||
// IStream
|
||||
//
|
||||
|
||||
REGISTER_EVENT(IStream, inputReady)
|
||||
REGISTER_EVENT(IStream, outputFlushed)
|
||||
REGISTER_EVENT(IStream, outputError)
|
||||
REGISTER_EVENT(IStream, inputShutdown)
|
||||
REGISTER_EVENT(IStream, outputShutdown)
|
||||
REGISTER_EVENT(IStream, inputFormatError)
|
||||
|
||||
//
|
||||
// IDataSocket
|
||||
//
|
||||
|
||||
REGISTER_EVENT(IDataSocket, connected)
|
||||
REGISTER_EVENT(IDataSocket, secureConnected)
|
||||
REGISTER_EVENT(IDataSocket, connectionFailed)
|
||||
|
||||
//
|
||||
// IListenSocket
|
||||
//
|
||||
|
||||
REGISTER_EVENT(IListenSocket, connecting)
|
||||
|
||||
//
|
||||
// ISocket
|
||||
//
|
||||
|
||||
REGISTER_EVENT(ISocket, disconnected)
|
||||
REGISTER_EVENT(ISocket, stopRetry)
|
||||
|
||||
//
|
||||
// OSXScreen
|
||||
//
|
||||
|
||||
REGISTER_EVENT(OSXScreen, confirmSleep)
|
||||
|
||||
//
|
||||
// ClientListener
|
||||
//
|
||||
|
||||
REGISTER_EVENT(ClientListener, accepted)
|
||||
REGISTER_EVENT(ClientListener, connected)
|
||||
|
||||
//
|
||||
// ClientProxy
|
||||
//
|
||||
|
||||
REGISTER_EVENT(ClientProxy, ready)
|
||||
REGISTER_EVENT(ClientProxy, disconnected)
|
||||
|
||||
//
|
||||
// ClientProxyUnknown
|
||||
//
|
||||
|
||||
REGISTER_EVENT(ClientProxyUnknown, success)
|
||||
REGISTER_EVENT(ClientProxyUnknown, failure)
|
||||
|
||||
//
|
||||
// Server
|
||||
//
|
||||
|
||||
REGISTER_EVENT(Server, error)
|
||||
REGISTER_EVENT(Server, connected)
|
||||
REGISTER_EVENT(Server, disconnected)
|
||||
REGISTER_EVENT(Server, switchToScreen)
|
||||
REGISTER_EVENT(Server, switchInDirection)
|
||||
REGISTER_EVENT(Server, keyboardBroadcast)
|
||||
REGISTER_EVENT(Server, lockCursorToScreen)
|
||||
REGISTER_EVENT(Server, screenSwitched)
|
||||
|
||||
//
|
||||
// ServerApp
|
||||
//
|
||||
|
||||
REGISTER_EVENT(ServerApp, reloadConfig)
|
||||
REGISTER_EVENT(ServerApp, forceReconnect)
|
||||
REGISTER_EVENT(ServerApp, resetServer)
|
||||
|
||||
//
|
||||
// IKeyState
|
||||
//
|
||||
|
||||
REGISTER_EVENT(IKeyState, keyDown)
|
||||
REGISTER_EVENT(IKeyState, keyUp)
|
||||
REGISTER_EVENT(IKeyState, keyRepeat)
|
||||
|
||||
//
|
||||
// IPrimaryScreen
|
||||
//
|
||||
|
||||
REGISTER_EVENT(IPrimaryScreen, buttonDown)
|
||||
REGISTER_EVENT(IPrimaryScreen, buttonUp)
|
||||
REGISTER_EVENT(IPrimaryScreen, motionOnPrimary)
|
||||
REGISTER_EVENT(IPrimaryScreen, motionOnSecondary)
|
||||
REGISTER_EVENT(IPrimaryScreen, wheel)
|
||||
REGISTER_EVENT(IPrimaryScreen, screensaverActivated)
|
||||
REGISTER_EVENT(IPrimaryScreen, screensaverDeactivated)
|
||||
REGISTER_EVENT(IPrimaryScreen, hotKeyDown)
|
||||
REGISTER_EVENT(IPrimaryScreen, hotKeyUp)
|
||||
REGISTER_EVENT(IPrimaryScreen, fakeInputBegin)
|
||||
REGISTER_EVENT(IPrimaryScreen, fakeInputEnd)
|
||||
|
||||
//
|
||||
// IScreen
|
||||
//
|
||||
|
||||
REGISTER_EVENT(IScreen, error)
|
||||
REGISTER_EVENT(IScreen, shapeChanged)
|
||||
REGISTER_EVENT(IScreen, suspend)
|
||||
REGISTER_EVENT(IScreen, resume)
|
||||
|
||||
//
|
||||
// Clipboard
|
||||
//
|
||||
|
||||
REGISTER_EVENT(Clipboard, clipboardGrabbed)
|
||||
REGISTER_EVENT(Clipboard, clipboardChanged)
|
||||
REGISTER_EVENT(Clipboard, clipboardSending)
|
||||
|
||||
//
|
||||
// File
|
||||
//
|
||||
|
||||
REGISTER_EVENT(File, fileChunkSending)
|
||||
REGISTER_EVENT(File, fileReceiveCompleted)
|
||||
REGISTER_EVENT(File, keepAlive)
|
||||
|
||||
//
|
||||
// Ei
|
||||
//
|
||||
|
||||
REGISTER_EVENT(Ei, connected)
|
||||
REGISTER_EVENT(Ei, sessionClosed)
|
||||
@ -1,730 +1,235 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2023 Input-Leap Developers
|
||||
* SPDX-FileCopyrightText: (C) 2013 - 2016 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Event.h"
|
||||
|
||||
class IEventQueue;
|
||||
|
||||
class EventTypes
|
||||
#include <stdint.h>
|
||||
namespace deskflow {
|
||||
enum class EventTypes : uint32_t
|
||||
{
|
||||
public:
|
||||
EventTypes();
|
||||
void setEvents(IEventQueue *events);
|
||||
/** An unknown event type. This type is used as a placeholder for unknown events when
|
||||
filtering events.
|
||||
*/
|
||||
Unknown,
|
||||
|
||||
protected:
|
||||
IEventQueue *getEvents() const;
|
||||
/// Exit has been requested.
|
||||
Quit,
|
||||
|
||||
private:
|
||||
IEventQueue *m_events;
|
||||
};
|
||||
|
||||
#define REGISTER_EVENT(type_, name_) \
|
||||
Event::Type type_##Events::name_() \
|
||||
{ \
|
||||
return getEvents()->registerTypeOnce(m_##name_, __FUNCTION__); \
|
||||
}
|
||||
|
||||
class ClientEvents : public EventTypes
|
||||
{
|
||||
public:
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get connected event type
|
||||
/*!
|
||||
Returns the connected event type. This is sent when the client has
|
||||
successfully connected to the server.
|
||||
*/
|
||||
Event::Type connected();
|
||||
|
||||
//! Get connection failed event type
|
||||
/*!
|
||||
Returns the connection failed event type. This is sent when the
|
||||
server fails for some reason. The event data is a FailInfo*.
|
||||
*/
|
||||
Event::Type connectionFailed();
|
||||
|
||||
//! Get connection refused event type
|
||||
/*!
|
||||
Returns the connection refused event type. This is sent when the
|
||||
server refuses for some reason. The event data is a FailInfo*.
|
||||
*/
|
||||
Event::Type connectionRefused();
|
||||
|
||||
//! Get disconnected event type
|
||||
/*!
|
||||
Returns the disconnected event type. This is sent when the client
|
||||
has disconnected from the server (and only after having successfully
|
||||
connected).
|
||||
*/
|
||||
Event::Type disconnected();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
Event::Type m_connected = Event::kUnknown;
|
||||
Event::Type m_connectionFailed = Event::kUnknown;
|
||||
Event::Type m_connectionRefused = Event::kUnknown;
|
||||
Event::Type m_disconnected = Event::kUnknown;
|
||||
};
|
||||
|
||||
class IStreamEvents : public EventTypes
|
||||
{
|
||||
public:
|
||||
IStreamEvents()
|
||||
: m_inputReady(Event::kUnknown),
|
||||
m_outputFlushed(Event::kUnknown),
|
||||
m_outputError(Event::kUnknown),
|
||||
m_inputShutdown(Event::kUnknown),
|
||||
m_outputShutdown(Event::kUnknown)
|
||||
{
|
||||
}
|
||||
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get input ready event type
|
||||
/*!
|
||||
Returns the input ready event type. A stream sends this event
|
||||
when \c read() will return with data.
|
||||
*/
|
||||
Event::Type inputReady();
|
||||
|
||||
//! Get output flushed event type
|
||||
/*!
|
||||
Returns the output flushed event type. A stream sends this event
|
||||
when the output buffer has been flushed. If there have been no
|
||||
writes since the event was posted, calling \c shutdownOutput() or
|
||||
\c close() will not discard any data and \c flush() will return
|
||||
immediately.
|
||||
*/
|
||||
Event::Type outputFlushed();
|
||||
|
||||
//! Get output error event type
|
||||
/*!
|
||||
Returns the output error event type. A stream sends this event
|
||||
when a write has failed.
|
||||
*/
|
||||
Event::Type outputError();
|
||||
|
||||
//! Get input shutdown event type
|
||||
/*!
|
||||
Returns the input shutdown event type. This is sent when the
|
||||
input side of the stream has shutdown. When the input has
|
||||
shutdown, no more data will ever be available to read.
|
||||
*/
|
||||
Event::Type inputShutdown();
|
||||
|
||||
//! Get output shutdown event type
|
||||
/*!
|
||||
Returns the output shutdown event type. This is sent when the
|
||||
output side of the stream has shutdown. When the output has
|
||||
shutdown, no more data can ever be written to the stream. Any
|
||||
attempt to do so will generate a output error event.
|
||||
*/
|
||||
Event::Type outputShutdown();
|
||||
|
||||
/** Get input format error event type
|
||||
This is sent when a stream receives an irrecoverable input format error.
|
||||
*/
|
||||
Event::Type inputFormatError();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
Event::Type m_inputReady;
|
||||
Event::Type m_outputFlushed;
|
||||
Event::Type m_outputError;
|
||||
Event::Type m_inputShutdown;
|
||||
Event::Type m_outputShutdown;
|
||||
Event::Type m_inputFormatError;
|
||||
};
|
||||
|
||||
class IDataSocketEvents : public EventTypes
|
||||
{
|
||||
public:
|
||||
IDataSocketEvents()
|
||||
: m_connected(Event::kUnknown),
|
||||
m_secureConnected(Event::kUnknown),
|
||||
m_connectionFailed(Event::kUnknown)
|
||||
{
|
||||
}
|
||||
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get connected event type
|
||||
/*!
|
||||
Returns the socket connected event type. A socket sends this
|
||||
event when a remote connection has been established.
|
||||
*/
|
||||
Event::Type connected();
|
||||
|
||||
//! Get secure connected event type
|
||||
/*!
|
||||
Returns the secure socket connected event type. A secure socket sends
|
||||
this event when a remote connection has been established.
|
||||
*/
|
||||
Event::Type secureConnected();
|
||||
|
||||
//! Get connection failed event type
|
||||
/*!
|
||||
Returns the socket connection failed event type. A socket sends
|
||||
this event when an attempt to connect to a remote port has failed.
|
||||
The data is a pointer to a ConnectionFailedInfo.
|
||||
*/
|
||||
Event::Type connectionFailed();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
Event::Type m_connected;
|
||||
Event::Type m_secureConnected;
|
||||
Event::Type m_connectionFailed;
|
||||
};
|
||||
|
||||
class IListenSocketEvents : public EventTypes
|
||||
{
|
||||
public:
|
||||
IListenSocketEvents() : m_connecting(Event::kUnknown)
|
||||
{
|
||||
}
|
||||
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get connecting event type
|
||||
/*!
|
||||
Returns the socket connecting event type. A socket sends this
|
||||
event when a remote connection is waiting to be accepted.
|
||||
*/
|
||||
Event::Type connecting();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
Event::Type m_connecting;
|
||||
};
|
||||
|
||||
class ISocketEvents : public EventTypes
|
||||
{
|
||||
public:
|
||||
ISocketEvents() : m_disconnected(Event::kUnknown), m_stopRetry(Event::kUnknown)
|
||||
{
|
||||
}
|
||||
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get disconnected event type
|
||||
/*!
|
||||
Returns the socket disconnected event type. A socket sends this
|
||||
event when the remote side of the socket has disconnected or
|
||||
shutdown both input and output.
|
||||
*/
|
||||
Event::Type disconnected();
|
||||
|
||||
//! Get stop retry event type
|
||||
/*!
|
||||
Returns the stop retry event type. This is sent when the client
|
||||
doesn't want to reconnect after it disconnects from the server.
|
||||
*/
|
||||
Event::Type stopRetry();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
Event::Type m_disconnected;
|
||||
Event::Type m_stopRetry;
|
||||
};
|
||||
|
||||
class OSXScreenEvents : public EventTypes
|
||||
{
|
||||
public:
|
||||
OSXScreenEvents() : m_confirmSleep(Event::kUnknown)
|
||||
{
|
||||
}
|
||||
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
Event::Type confirmSleep();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
Event::Type m_confirmSleep;
|
||||
};
|
||||
|
||||
class ClientListenerEvents : public EventTypes
|
||||
{
|
||||
public:
|
||||
ClientListenerEvents() : m_accepted(Event::kUnknown), m_connected(Event::kUnknown)
|
||||
{
|
||||
}
|
||||
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get accepted event type
|
||||
/*!
|
||||
Returns the accepted event type. This is sent whenever a server
|
||||
accepts a client.
|
||||
*/
|
||||
Event::Type accepted();
|
||||
|
||||
//! Get connected event type
|
||||
/*!
|
||||
Returns the connected event type. This is sent whenever a
|
||||
a client connects.
|
||||
*/
|
||||
Event::Type connected();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
Event::Type m_accepted;
|
||||
Event::Type m_connected;
|
||||
};
|
||||
|
||||
class ClientProxyEvents : public EventTypes
|
||||
{
|
||||
public:
|
||||
ClientProxyEvents() : m_ready(Event::kUnknown), m_disconnected(Event::kUnknown)
|
||||
{
|
||||
}
|
||||
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get ready event type
|
||||
/*!
|
||||
Returns the ready event type. This is sent when the client has
|
||||
completed the initial handshake. Until it is sent, the client is
|
||||
not fully connected.
|
||||
*/
|
||||
Event::Type ready();
|
||||
|
||||
//! Get disconnect event type
|
||||
/*!
|
||||
Returns the disconnect event type. This is sent when the client
|
||||
disconnects or is disconnected. The target is getEventTarget().
|
||||
*/
|
||||
Event::Type disconnected();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
Event::Type m_ready;
|
||||
Event::Type m_disconnected;
|
||||
};
|
||||
|
||||
class ClientProxyUnknownEvents : public EventTypes
|
||||
{
|
||||
public:
|
||||
ClientProxyUnknownEvents() : m_success(Event::kUnknown), m_failure(Event::kUnknown)
|
||||
{
|
||||
}
|
||||
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get success event type
|
||||
/*!
|
||||
Returns the success event type. This is sent when the client has
|
||||
correctly responded to the hello message. The target is this.
|
||||
*/
|
||||
Event::Type success();
|
||||
|
||||
//! Get failure event type
|
||||
/*!
|
||||
Returns the failure event type. This is sent when a client fails
|
||||
to correctly respond to the hello message. The target is this.
|
||||
*/
|
||||
Event::Type failure();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
Event::Type m_success;
|
||||
Event::Type m_failure;
|
||||
};
|
||||
|
||||
class ServerEvents : public EventTypes
|
||||
{
|
||||
public:
|
||||
ServerEvents()
|
||||
: m_error(Event::kUnknown),
|
||||
m_connected(Event::kUnknown),
|
||||
m_disconnected(Event::kUnknown),
|
||||
m_switchToScreen(Event::kUnknown),
|
||||
m_switchInDirection(Event::kUnknown),
|
||||
m_keyboardBroadcast(Event::kUnknown),
|
||||
m_lockCursorToScreen(Event::kUnknown),
|
||||
m_screenSwitched(Event::kUnknown)
|
||||
{
|
||||
}
|
||||
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get error event type
|
||||
/*!
|
||||
Returns the error event type. This is sent when the server fails
|
||||
for some reason.
|
||||
*/
|
||||
Event::Type error();
|
||||
|
||||
//! Get connected event type
|
||||
/*!
|
||||
Returns the connected event type. This is sent when a client screen
|
||||
has connected. The event data is a \c ScreenConnectedInfo* that
|
||||
indicates the connected screen.
|
||||
*/
|
||||
Event::Type connected();
|
||||
|
||||
//! Get disconnected event type
|
||||
/*!
|
||||
Returns the disconnected event type. This is sent when all the
|
||||
clients have disconnected.
|
||||
*/
|
||||
Event::Type disconnected();
|
||||
|
||||
//! Get switch to screen event type
|
||||
/*!
|
||||
Returns the switch to screen event type. The server responds to this
|
||||
by switching screens. The event data is a \c SwitchToScreenInfo*
|
||||
that indicates the target screen.
|
||||
*/
|
||||
Event::Type switchToScreen();
|
||||
|
||||
//! Get switch in direction event type
|
||||
/*!
|
||||
Returns the switch in direction event type. The server responds to this
|
||||
by switching screens. The event data is a \c SwitchInDirectionInfo*
|
||||
that indicates the target direction.
|
||||
*/
|
||||
Event::Type switchInDirection();
|
||||
|
||||
//! Get keyboard broadcast event type
|
||||
/*!
|
||||
Returns the keyboard broadcast event type. The server responds
|
||||
to this by turning on keyboard broadcasting or turning it off. The
|
||||
event data is a \c KeyboardBroadcastInfo*.
|
||||
*/
|
||||
Event::Type keyboardBroadcast();
|
||||
|
||||
//! Get lock cursor event type
|
||||
/*!
|
||||
Returns the lock cursor event type. The server responds to this
|
||||
by locking the cursor to the active screen or unlocking it. The
|
||||
event data is a \c LockCursorToScreenInfo*.
|
||||
*/
|
||||
Event::Type lockCursorToScreen();
|
||||
|
||||
//! Get screen switched event type
|
||||
/*!
|
||||
Returns the screen switched event type. This is raised when the
|
||||
screen has been switched to a client.
|
||||
*/
|
||||
Event::Type screenSwitched();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
Event::Type m_error;
|
||||
Event::Type m_connected;
|
||||
Event::Type m_disconnected;
|
||||
Event::Type m_switchToScreen;
|
||||
Event::Type m_switchInDirection;
|
||||
Event::Type m_keyboardBroadcast;
|
||||
Event::Type m_lockCursorToScreen;
|
||||
Event::Type m_screenSwitched;
|
||||
};
|
||||
|
||||
class ServerAppEvents : public EventTypes
|
||||
{
|
||||
public:
|
||||
ServerAppEvents() : m_reloadConfig(Event::kUnknown), m_forceReconnect(Event::kUnknown), m_resetServer(Event::kUnknown)
|
||||
{
|
||||
}
|
||||
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
Event::Type reloadConfig();
|
||||
Event::Type forceReconnect();
|
||||
Event::Type resetServer();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
Event::Type m_reloadConfig;
|
||||
Event::Type m_forceReconnect;
|
||||
Event::Type m_resetServer;
|
||||
};
|
||||
|
||||
class IKeyStateEvents : public EventTypes
|
||||
{
|
||||
public:
|
||||
IKeyStateEvents() : m_keyDown(Event::kUnknown), m_keyUp(Event::kUnknown), m_keyRepeat(Event::kUnknown)
|
||||
{
|
||||
}
|
||||
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get key down event type. Event data is KeyInfo*, count == 1.
|
||||
Event::Type keyDown();
|
||||
|
||||
//! Get key up event type. Event data is KeyInfo*, count == 1.
|
||||
Event::Type keyUp();
|
||||
|
||||
//! Get key repeat event type. Event data is KeyInfo*.
|
||||
Event::Type keyRepeat();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
Event::Type m_keyDown;
|
||||
Event::Type m_keyUp;
|
||||
Event::Type m_keyRepeat;
|
||||
};
|
||||
|
||||
class IPrimaryScreenEvents : public EventTypes
|
||||
{
|
||||
public:
|
||||
IPrimaryScreenEvents()
|
||||
: m_buttonDown(Event::kUnknown),
|
||||
m_buttonUp(Event::kUnknown),
|
||||
m_motionOnPrimary(Event::kUnknown),
|
||||
m_motionOnSecondary(Event::kUnknown),
|
||||
m_wheel(Event::kUnknown),
|
||||
m_screensaverActivated(Event::kUnknown),
|
||||
m_screensaverDeactivated(Event::kUnknown),
|
||||
m_hotKeyDown(Event::kUnknown),
|
||||
m_hotKeyUp(Event::kUnknown),
|
||||
m_fakeInputBegin(Event::kUnknown),
|
||||
m_fakeInputEnd(Event::kUnknown)
|
||||
{
|
||||
}
|
||||
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! button down event type. Event data is ButtonInfo*.
|
||||
Event::Type buttonDown();
|
||||
|
||||
//! button up event type. Event data is ButtonInfo*.
|
||||
Event::Type buttonUp();
|
||||
|
||||
//! mouse motion on the primary screen event type
|
||||
/*!
|
||||
Event data is MotionInfo* and the values are an absolute position.
|
||||
*/
|
||||
Event::Type motionOnPrimary();
|
||||
|
||||
//! mouse motion on a secondary screen event type
|
||||
/*!
|
||||
Event data is MotionInfo* and the values are motion deltas not
|
||||
absolute coordinates.
|
||||
*/
|
||||
Event::Type motionOnSecondary();
|
||||
|
||||
//! mouse wheel event type. Event data is WheelInfo*.
|
||||
Event::Type wheel();
|
||||
|
||||
//! screensaver activated event type
|
||||
Event::Type screensaverActivated();
|
||||
|
||||
//! screensaver deactivated event type
|
||||
Event::Type screensaverDeactivated();
|
||||
|
||||
//! hot key down event type. Event data is HotKeyInfo*.
|
||||
Event::Type hotKeyDown();
|
||||
|
||||
//! hot key up event type. Event data is HotKeyInfo*.
|
||||
Event::Type hotKeyUp();
|
||||
|
||||
//! start of fake input event type
|
||||
Event::Type fakeInputBegin();
|
||||
|
||||
//! end of fake input event type
|
||||
Event::Type fakeInputEnd();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
Event::Type m_buttonDown;
|
||||
Event::Type m_buttonUp;
|
||||
Event::Type m_motionOnPrimary;
|
||||
Event::Type m_motionOnSecondary;
|
||||
Event::Type m_wheel;
|
||||
Event::Type m_screensaverActivated;
|
||||
Event::Type m_screensaverDeactivated;
|
||||
Event::Type m_hotKeyDown;
|
||||
Event::Type m_hotKeyUp;
|
||||
Event::Type m_fakeInputBegin;
|
||||
Event::Type m_fakeInputEnd;
|
||||
};
|
||||
|
||||
class IScreenEvents : public EventTypes
|
||||
{
|
||||
public:
|
||||
IScreenEvents()
|
||||
: m_error(Event::kUnknown),
|
||||
m_shapeChanged(Event::kUnknown),
|
||||
m_suspend(Event::kUnknown),
|
||||
m_resume(Event::kUnknown)
|
||||
{
|
||||
}
|
||||
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get error event type
|
||||
/*!
|
||||
Returns the error event type. This is sent whenever the screen has
|
||||
failed for some reason (e.g. the X Windows server died).
|
||||
*/
|
||||
Event::Type error();
|
||||
|
||||
//! Get shape changed event type
|
||||
/*!
|
||||
Returns the shape changed event type. This is sent whenever the
|
||||
screen's shape changes.
|
||||
*/
|
||||
Event::Type shapeChanged();
|
||||
|
||||
//! Get suspend event type
|
||||
/*!
|
||||
Returns the suspend event type. This is sent whenever the system goes
|
||||
to sleep or a user session is deactivated (fast user switching).
|
||||
*/
|
||||
Event::Type suspend();
|
||||
|
||||
//! Get resume event type
|
||||
/*!
|
||||
Returns the resume event type. This is sent whenever the system wakes
|
||||
up or a user session is activated (fast user switching).
|
||||
*/
|
||||
Event::Type resume();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
Event::Type m_error;
|
||||
Event::Type m_shapeChanged;
|
||||
Event::Type m_suspend;
|
||||
Event::Type m_resume;
|
||||
};
|
||||
|
||||
class ClipboardEvents : public EventTypes
|
||||
{
|
||||
public:
|
||||
ClipboardEvents()
|
||||
: m_clipboardGrabbed(Event::kUnknown),
|
||||
m_clipboardChanged(Event::kUnknown),
|
||||
m_clipboardSending(Event::kUnknown)
|
||||
{
|
||||
}
|
||||
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get clipboard grabbed event type
|
||||
/*!
|
||||
Returns the clipboard grabbed event type. This is sent whenever the
|
||||
clipboard is grabbed by some other application so we don't own it
|
||||
anymore. The data is a pointer to a ClipboardInfo.
|
||||
*/
|
||||
Event::Type clipboardGrabbed();
|
||||
|
||||
//! Get clipboard changed event type
|
||||
/*!
|
||||
Returns the clipboard changed event type. This is sent whenever the
|
||||
contents of the clipboard has changed. The data is a pointer to a
|
||||
IScreen::ClipboardInfo.
|
||||
*/
|
||||
Event::Type clipboardChanged();
|
||||
|
||||
//! Clipboard sending event type
|
||||
/*!
|
||||
Returns the clipboard sending event type. This is used to send
|
||||
clipboard chunks.
|
||||
*/
|
||||
Event::Type clipboardSending();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
Event::Type m_clipboardGrabbed;
|
||||
Event::Type m_clipboardChanged;
|
||||
Event::Type m_clipboardSending;
|
||||
};
|
||||
|
||||
class FileEvents : public EventTypes
|
||||
{
|
||||
public:
|
||||
FileEvents()
|
||||
: m_fileChunkSending(Event::kUnknown),
|
||||
m_fileReceiveCompleted(Event::kUnknown),
|
||||
m_keepAlive(Event::kUnknown)
|
||||
{
|
||||
}
|
||||
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Sending a file chunk
|
||||
Event::Type fileChunkSending();
|
||||
|
||||
//! Completed receiving a file
|
||||
Event::Type fileReceiveCompleted();
|
||||
|
||||
//! Send a keep alive
|
||||
Event::Type keepAlive();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
Event::Type m_fileChunkSending;
|
||||
Event::Type m_fileReceiveCompleted;
|
||||
Event::Type m_keepAlive;
|
||||
};
|
||||
|
||||
class EiEvents : public EventTypes
|
||||
{
|
||||
public:
|
||||
EiEvents() : m_connected(Event::kUnknown), m_sessionClosed(Event::kUnknown)
|
||||
{
|
||||
}
|
||||
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get connected event type
|
||||
/*!
|
||||
This event is sent whenever connection to EIS is established and a file
|
||||
descriptor for reading events is available.
|
||||
*/
|
||||
Event::Type connected();
|
||||
|
||||
//! Get session closed event type
|
||||
/*!
|
||||
This event is sent whenever the portal session managing our EIS connection
|
||||
is closed.
|
||||
*/
|
||||
Event::Type sessionClosed();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
Event::Type m_connected;
|
||||
Event::Type m_sessionClosed;
|
||||
/// This event is sent when system event occurs. The data is a pointer to system event type
|
||||
System,
|
||||
|
||||
/// This event is sent when a timer event occurs. The data is pointer to TimerInfo.
|
||||
Timer,
|
||||
|
||||
/// This event is sent when the client has successfully connected to the server.
|
||||
ClientConnected,
|
||||
|
||||
/** This event is sent when the server refuses the client */
|
||||
ClientConnectionRefused,
|
||||
|
||||
/** This event is sent when the server fails for some reason.
|
||||
The event data is a pointer to FailInfo.
|
||||
*/
|
||||
ClientConnectionFailed,
|
||||
|
||||
/** This event is sent when the client has disconnected from the server (and only after having
|
||||
successfully connected).
|
||||
*/
|
||||
ClientDisconnected,
|
||||
|
||||
/// A stream sends this event when \c read() will return with data.
|
||||
StreamInputReady,
|
||||
|
||||
/** A stream sends this event when the output buffer has been flushed. If there have been no
|
||||
writes since the event was posted, calling \c shutdownOutput() or close() will not discard
|
||||
any data and \c flush() will return immediately.
|
||||
*/
|
||||
StreamOutputFlushed,
|
||||
|
||||
/// A stream sends this event when a write has failed.
|
||||
StreamOutputError,
|
||||
|
||||
/** This event is sent when the input side of the stream has shutdown. When the input has
|
||||
shutdown, no more data will ever be available to read.
|
||||
*/
|
||||
StreamInputShutdown,
|
||||
|
||||
/** This event is sent when the output side of the stream has shutdown. When the output has
|
||||
shutdown, no more data can ever be written to the stream. Any attempt to do so will
|
||||
generate a output error event.
|
||||
*/
|
||||
StreamOutputShutdown,
|
||||
|
||||
/// This event is sent when a stream receives an irrecoverable input format error.
|
||||
StreamInputFormatError,
|
||||
|
||||
/// A socket sends this event when a remote connection has been established.
|
||||
DataSocketConnected,
|
||||
|
||||
/// A secure socket sends this event when a remote connection has been established.
|
||||
DataSocketSecureConnected,
|
||||
|
||||
/** A socket sends this event when an attempt to connect to a remote port has failed.
|
||||
The data is a pointer to a ConnectionFailedInfo.
|
||||
*/
|
||||
DataSocketConnectionFailed,
|
||||
|
||||
/// A socket sends this event when a remote connection is waiting to be accepted.
|
||||
ListenSocketConnecting,
|
||||
|
||||
/** A socket sends this event when the remote side of the socket has disconnected or
|
||||
shutdown both input and output.
|
||||
*/
|
||||
SocketDisconnected,
|
||||
|
||||
/// This is sent when the client doesn't want to reconnect after it disconnects from the server.
|
||||
SocketStopRetry,
|
||||
|
||||
OsxScreenConfirmSleep,
|
||||
|
||||
/// This event is sent whenever a server accepts a client.
|
||||
ClientListenerAccepted,
|
||||
|
||||
/** This event is sent when the client has completed the initial handshake. Until it is sent,
|
||||
the client is not fully connected.
|
||||
*/
|
||||
ClientProxyReady,
|
||||
|
||||
/** This event is sent when the client disconnects or is disconnected. The target is
|
||||
getEventTarget().
|
||||
*/
|
||||
ClientProxyDisconnected,
|
||||
|
||||
/** This event is sent when the client has correctly responded to the hello message.
|
||||
The target is this.
|
||||
*/
|
||||
ClientProxyUnknownSuccess,
|
||||
|
||||
/** This event is sent when a client fails to correctly respond to the hello message.
|
||||
The target is this.
|
||||
*/
|
||||
ClientProxyUnknownFailure,
|
||||
|
||||
/** This event is sent when a client screen has connected.
|
||||
The event data is a pointer to ScreenConnectedInfo that indicates the connected screen.
|
||||
*/
|
||||
ServerConnected,
|
||||
|
||||
/// This is event sent when all the clients have disconnected.
|
||||
ServerDisconnected,
|
||||
|
||||
/** This event is sent to inform the server to switch screens.
|
||||
The event data is a pointer to SwitchToScreenInfo that indicates the target screen.
|
||||
*/
|
||||
ServerSwitchToScreen,
|
||||
|
||||
/// This event is sent to inform the server to toggle screens. These is no event data.
|
||||
ServerToggleScreen,
|
||||
|
||||
/** This event is sent to inform the server to switch screens.
|
||||
The event data is a pointer to SwitchInDirectionInfo that indicates the target direction.
|
||||
*/
|
||||
ServerSwitchInDirection,
|
||||
|
||||
/** This event is sent to inform the server to turn keyboard broadcasting on or off.
|
||||
The event data is a pointer to KeyboardBroadcastInfo.
|
||||
*/
|
||||
ServerKeyboardBroadcast,
|
||||
|
||||
/** This event is sent to inform the server to lock the cursor to the active screen or to
|
||||
unlock it. The event data is a pointer to LockCursorToScreenInfo.
|
||||
*/
|
||||
ServerLockCursorToScreen,
|
||||
|
||||
/// This event is sent when the screen has been switched to a client.
|
||||
ServerScreenSwitched,
|
||||
|
||||
ServerAppReloadConfig,
|
||||
ServerAppForceReconnect,
|
||||
ServerAppResetServer,
|
||||
|
||||
/// This event is sent when key is down. Event data is a pointer to KeyInfo (count == 1)
|
||||
KeyStateKeyDown,
|
||||
/// This event is sent when key is up. Event data is a pointer to KeyInfo (count == 1)
|
||||
KeyStateKeyUp,
|
||||
/// This event is sent when key is repeated. Event data is a pointer to KeyInfo.
|
||||
KeyStateKeyRepeat,
|
||||
|
||||
/// This event is sent when button is down. Event data is a pointer to ButtonInfo
|
||||
PrimaryScreenButtonDown,
|
||||
|
||||
/// This event is sent when button is up. Event data is a pointer to ButtonInfo
|
||||
PrimaryScreenButtonUp,
|
||||
|
||||
/** This event is sent when mouse moves on primary screen.
|
||||
Event data is a pointer to MotionInfo, the values are absolute position.
|
||||
*/
|
||||
PrimaryScreenMotionOnPrimary,
|
||||
|
||||
/** This event is sent when mouse moves on secondary screen.
|
||||
Event data is a pointer to MotionInfo, the values are relative motion deltas.
|
||||
*/
|
||||
PrimaryScreenMotionOnSecondary,
|
||||
|
||||
/// This event is sent when mouse wheel is rotated. Event data is a pointer to WheelInfo.
|
||||
PrimaryScreenWheel,
|
||||
|
||||
/// This event is sent when screensaver is activated.
|
||||
PrimaryScreenSaverActivated,
|
||||
|
||||
/// This event is sent when screensaver is deactivated.
|
||||
PrimaryScreenSaverDeactivated,
|
||||
|
||||
/// This event is sent when hotkey is down. Event data is a pointer to HotKeyInfo.
|
||||
PrimaryScreenHotkeyDown,
|
||||
|
||||
/// This event is sent when hotkey is up. Event data is a pointer to HotKeyInfo.
|
||||
PrimaryScreenHotkeyUp,
|
||||
|
||||
/// This event is sent when fake input begins.
|
||||
PrimaryScreenFakeInputBegin,
|
||||
|
||||
/// This event is sent when fake input ends.
|
||||
PrimaryScreenFakeInputEnd,
|
||||
|
||||
/** This event is sent whenever the screen has failed for some reason (e.g. the X Windows
|
||||
server died).
|
||||
*/
|
||||
ScreenError,
|
||||
|
||||
/// This event is sent whenever the screen's shape changes.
|
||||
ScreenShapeChanged,
|
||||
|
||||
/** This event is sent whenever the system goes to sleep or a user session is deactivated (fast
|
||||
user switching).
|
||||
*/
|
||||
ScreenSuspend,
|
||||
|
||||
/** This event is sent whenever the system wakes up or a user session is activated (fast user
|
||||
switching).
|
||||
*/
|
||||
ScreenResume,
|
||||
|
||||
/** This event is sent whenever the clipboard is grabbed by some other application so we
|
||||
don't own it anymore. The data is a pointer to a ClipboardInfo.
|
||||
*/
|
||||
ClipboardGrabbed,
|
||||
|
||||
/** This event is sent whenever the contents of the clipboard has changed.
|
||||
The data is a pointer to a ClipboardInfo.
|
||||
*/
|
||||
ClipboardChanged,
|
||||
|
||||
/// This event is sent whenever a clipboard chunk is transferred.
|
||||
ClipboardSending,
|
||||
|
||||
/// Start libEI
|
||||
EIConnected,
|
||||
/// Stop libEi
|
||||
EISessionClosed
|
||||
};
|
||||
} // namespace deskflow
|
||||
|
||||
@ -15,12 +15,11 @@ namespace deskflow {
|
||||
template <class Callable> class FinalAction
|
||||
{
|
||||
public:
|
||||
FinalAction() noexcept
|
||||
{
|
||||
}
|
||||
FinalAction() noexcept = default;
|
||||
|
||||
FinalAction(Callable callable) noexcept : m_callable{callable}
|
||||
explicit FinalAction(Callable callable) noexcept : m_callable{callable}
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
~FinalAction() noexcept
|
||||
|
||||
@ -16,14 +16,9 @@ FunctionEventJob::FunctionEventJob(void (*func)(const Event &, void *), void *ar
|
||||
// do nothing
|
||||
}
|
||||
|
||||
FunctionEventJob::~FunctionEventJob()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void FunctionEventJob::run(const Event &event)
|
||||
{
|
||||
if (m_func != NULL) {
|
||||
if (m_func != nullptr) {
|
||||
m_func(event, m_arg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,11 +17,11 @@ class FunctionEventJob : public IEventJob
|
||||
{
|
||||
public:
|
||||
//! run() invokes \c func(arg)
|
||||
FunctionEventJob(void (*func)(const Event &, void *), void *arg = NULL);
|
||||
virtual ~FunctionEventJob();
|
||||
FunctionEventJob(void (*func)(const Event &, void *), void *arg = nullptr);
|
||||
~FunctionEventJob() override = default;
|
||||
|
||||
// IEventJob overrides
|
||||
virtual void run(const Event &);
|
||||
void run(const Event &) override;
|
||||
|
||||
private:
|
||||
void (*m_func)(const Event &, void *);
|
||||
|
||||
@ -16,14 +16,9 @@ FunctionJob::FunctionJob(void (*func)(void *), void *arg) : m_func(func), m_arg(
|
||||
// do nothing
|
||||
}
|
||||
|
||||
FunctionJob::~FunctionJob()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void FunctionJob::run()
|
||||
{
|
||||
if (m_func != NULL) {
|
||||
if (m_func != nullptr) {
|
||||
m_func(m_arg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,11 +17,11 @@ class FunctionJob : public IJob
|
||||
{
|
||||
public:
|
||||
//! run() invokes \c func(arg)
|
||||
FunctionJob(void (*func)(void *), void *arg = NULL);
|
||||
virtual ~FunctionJob();
|
||||
FunctionJob(void (*func)(void *), void *arg = nullptr);
|
||||
~FunctionJob() override = default;
|
||||
|
||||
// IJob overrides
|
||||
virtual void run();
|
||||
void run() override;
|
||||
|
||||
private:
|
||||
void (*m_func)(void *);
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "base/Event.h"
|
||||
#include "base/EventTypes.h"
|
||||
#include "common/IInterface.h"
|
||||
#include <string>
|
||||
|
||||
@ -18,25 +19,6 @@ class IEventQueueBuffer;
|
||||
// IEventQueueBuffer.
|
||||
class EventQueueTimer;
|
||||
|
||||
// Event type registration classes.
|
||||
class ClientEvents;
|
||||
class IStreamEvents;
|
||||
class IDataSocketEvents;
|
||||
class IListenSocketEvents;
|
||||
class ISocketEvents;
|
||||
class OSXScreenEvents;
|
||||
class ClientListenerEvents;
|
||||
class ClientProxyEvents;
|
||||
class ClientProxyUnknownEvents;
|
||||
class ServerEvents;
|
||||
class ServerAppEvents;
|
||||
class IKeyStateEvents;
|
||||
class IPrimaryScreenEvents;
|
||||
class IScreenEvents;
|
||||
class ClipboardEvents;
|
||||
class FileEvents;
|
||||
class EiEvents;
|
||||
|
||||
//! Event queue interface
|
||||
/*!
|
||||
An event queue provides a queue of Events. Clients can block waiting
|
||||
@ -98,7 +80,7 @@ public:
|
||||
is returned the data points to a \c TimerEvent. The client must pass
|
||||
the returned timer to \c deleteTimer() (whether or not the timer has
|
||||
expired) to release the timer. The returned timer event uses the
|
||||
given \p target. If \p target is NULL it uses the returned timer as
|
||||
given \p target. If \p target is nullptr it uses the returned timer as
|
||||
the target.
|
||||
|
||||
Events for a single timer don't accumulate in the queue, even if the
|
||||
@ -117,7 +99,7 @@ public:
|
||||
The c_count member of the \c TimerEvent is always 1. The client
|
||||
must pass the returned timer to \c deleteTimer() (whether or not the
|
||||
timer has expired) to release the timer. The returned timer event
|
||||
uses the given \p target. If \p target is NULL it uses the returned
|
||||
uses the given \p target. If \p target is nullptr it uses the returned
|
||||
timer as the target.
|
||||
*/
|
||||
virtual EventQueueTimer *newOneShotTimer(double duration, void *target) = 0;
|
||||
@ -137,14 +119,14 @@ public:
|
||||
of type \p type. If no such handler exists it will use the handler
|
||||
for \p target and type \p kUnknown if it exists.
|
||||
*/
|
||||
virtual void adoptHandler(Event::Type type, void *target, IEventJob *handler) = 0;
|
||||
virtual void adoptHandler(EventTypes type, void *target, IEventJob *handler) = 0;
|
||||
|
||||
//! Unregister an event handler for an event type
|
||||
/*!
|
||||
Unregisters an event handler for the \p type, \p target pair and
|
||||
deletes it.
|
||||
*/
|
||||
virtual void removeHandler(Event::Type type, void *target) = 0;
|
||||
virtual void removeHandler(EventTypes type, void *target) = 0;
|
||||
|
||||
//! Unregister all event handlers for an event target
|
||||
/*!
|
||||
@ -152,14 +134,6 @@ public:
|
||||
*/
|
||||
virtual void removeHandlers(void *target) = 0;
|
||||
|
||||
//! Creates a new event type
|
||||
/*!
|
||||
If \p type contains \c kUnknown then it is set to a unique event
|
||||
type id otherwise it is left alone. The final value of \p type
|
||||
is returned.
|
||||
*/
|
||||
virtual Event::Type registerTypeOnce(Event::Type &type, const char *name) = 0;
|
||||
|
||||
//! Wait for event queue to become ready
|
||||
/*!
|
||||
Blocks on the current thread until the event queue is ready for events to
|
||||
@ -181,50 +155,15 @@ public:
|
||||
//! Get an event handler
|
||||
/*!
|
||||
Finds and returns the event handler for the \p type, \p target pair
|
||||
if it exists, otherwise it returns NULL.
|
||||
if it exists, otherwise it returns nullptr.
|
||||
*/
|
||||
virtual IEventJob *getHandler(Event::Type type, void *target) const = 0;
|
||||
|
||||
//! Get name for event
|
||||
/*!
|
||||
Returns the name for the event \p type. This is primarily for
|
||||
debugging.
|
||||
*/
|
||||
virtual const char *getTypeName(Event::Type type) = 0;
|
||||
|
||||
//! Get an event type by name
|
||||
/*!
|
||||
Returns the registered type for an event for a given name.
|
||||
*/
|
||||
virtual Event::Type getRegisteredType(const std::string &name) const = 0;
|
||||
virtual IEventJob *getHandler(EventTypes type, void *target) const = 0;
|
||||
|
||||
//! Get the system event type target
|
||||
/*!
|
||||
Returns the target to use for dispatching \c Event::kSystem events.
|
||||
Returns the target to use for dispatching \c EventTypes::System events.
|
||||
*/
|
||||
virtual void *getSystemTarget() = 0;
|
||||
|
||||
//@}
|
||||
|
||||
//
|
||||
// Event type providers.
|
||||
//
|
||||
|
||||
virtual ClientEvents &forClient() = 0;
|
||||
virtual IStreamEvents &forIStream() = 0;
|
||||
virtual IDataSocketEvents &forIDataSocket() = 0;
|
||||
virtual IListenSocketEvents &forIListenSocket() = 0;
|
||||
virtual ISocketEvents &forISocket() = 0;
|
||||
virtual OSXScreenEvents &forOSXScreen() = 0;
|
||||
virtual ClientListenerEvents &forClientListener() = 0;
|
||||
virtual ClientProxyEvents &forClientProxy() = 0;
|
||||
virtual ClientProxyUnknownEvents &forClientProxyUnknown() = 0;
|
||||
virtual ServerEvents &forServer() = 0;
|
||||
virtual ServerAppEvents &forServerApp() = 0;
|
||||
virtual IKeyStateEvents &forIKeyState() = 0;
|
||||
virtual IPrimaryScreenEvents &forIPrimaryScreen() = 0;
|
||||
virtual IScreenEvents &forIScreen() = 0;
|
||||
virtual ClipboardEvents &forClipboard() = 0;
|
||||
virtual FileEvents &forFile() = 0;
|
||||
virtual EiEvents &forEi() = 0;
|
||||
};
|
||||
|
||||
@ -77,7 +77,7 @@ public:
|
||||
/*!
|
||||
Create and return a timer object. The object is opaque and is
|
||||
used only by the buffer but it must be a valid object (i.e.
|
||||
not NULL).
|
||||
not nullptr).
|
||||
*/
|
||||
virtual EventQueueTimer *newTimer(double duration, bool oneShot) const = 0;
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ static const char *g_priority[] = {"FATAL", "ERROR", "WARNING", "NOTE", "INF
|
||||
"DEBUG1", "DEBUG2", "DEBUG3", "DEBUG4", "DEBUG5"};
|
||||
|
||||
// number of priorities
|
||||
static const int g_numPriority = (int)(sizeof(g_priority) / sizeof(g_priority[0]));
|
||||
static const int g_numPriority = 11;
|
||||
|
||||
// if NDEBUG (not debug) is not specified, i.e. you're building in debug,
|
||||
// then set default log level to DEBUG, otherwise the max level is INFO.
|
||||
@ -115,12 +115,12 @@ std::vector<char> makeMessage(const char *filename, int lineNumber, const char *
|
||||
// Log
|
||||
//
|
||||
|
||||
Log *Log::s_log = NULL;
|
||||
Log *Log::s_log = nullptr;
|
||||
|
||||
Log::Log(bool singleton)
|
||||
{
|
||||
if (singleton) {
|
||||
assert(s_log == NULL);
|
||||
assert(s_log == nullptr);
|
||||
}
|
||||
|
||||
// create mutex for multithread safe operation
|
||||
@ -143,10 +143,10 @@ Log::Log(Log *src)
|
||||
Log::~Log()
|
||||
{
|
||||
// clean up
|
||||
for (OutputterList::iterator index = m_outputters.begin(); index != m_outputters.end(); ++index) {
|
||||
for (auto index = m_outputters.begin(); index != m_outputters.end(); ++index) {
|
||||
delete *index;
|
||||
}
|
||||
for (OutputterList::iterator index = m_alwaysOutputters.begin(); index != m_alwaysOutputters.end(); ++index) {
|
||||
for (auto index = m_alwaysOutputters.begin(); index != m_alwaysOutputters.end(); ++index) {
|
||||
delete *index;
|
||||
}
|
||||
ARCH->closeMutex(m_mutex);
|
||||
@ -154,7 +154,7 @@ Log::~Log()
|
||||
|
||||
Log *Log::getInstance()
|
||||
{
|
||||
assert(s_log != NULL);
|
||||
assert(s_log != nullptr);
|
||||
return s_log;
|
||||
}
|
||||
|
||||
@ -210,7 +210,7 @@ void Log::print(const char *file, int line, const char *fmt, ...)
|
||||
|
||||
void Log::insert(ILogOutputter *adoptedOutputter, bool alwaysAtHead)
|
||||
{
|
||||
assert(adoptedOutputter != NULL);
|
||||
assert(adoptedOutputter != nullptr);
|
||||
|
||||
ArchMutexLock lock(m_mutex);
|
||||
if (alwaysAtHead) {
|
||||
@ -241,7 +241,7 @@ void Log::pop_front(bool alwaysAtHead)
|
||||
|
||||
bool Log::setFilter(const char *maxPriority)
|
||||
{
|
||||
if (maxPriority != NULL) {
|
||||
if (maxPriority != nullptr) {
|
||||
for (int i = 0; i < g_numPriority; ++i) {
|
||||
if (strcmp(maxPriority, g_priority[i]) == 0) {
|
||||
setFilter(i);
|
||||
@ -265,10 +265,10 @@ int Log::getFilter() const
|
||||
return m_maxPriority;
|
||||
}
|
||||
|
||||
void Log::output(ELevel priority, char *msg)
|
||||
void Log::output(ELevel priority, const char *msg)
|
||||
{
|
||||
assert(priority >= -1 && priority < g_numPriority);
|
||||
assert(msg != NULL);
|
||||
assert(msg != nullptr);
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
|
||||
@ -27,8 +27,8 @@ LOGC() provide convenient access.
|
||||
class Log
|
||||
{
|
||||
public:
|
||||
Log(bool singleton = true);
|
||||
Log(Log *src);
|
||||
explicit Log(bool singleton = true);
|
||||
explicit Log(Log *src);
|
||||
Log(Log const &) = delete;
|
||||
Log(Log &&) = delete;
|
||||
~Log();
|
||||
@ -79,7 +79,7 @@ public:
|
||||
Set the filter. Messages below this priority are discarded.
|
||||
The default priority is 4 (INFO) (unless built without NDEBUG
|
||||
in which case it's 5 (DEBUG)). setFilter(const char*) returns
|
||||
true if the priority \c name was recognized; if \c name is NULL
|
||||
true if the priority \c name was recognized; if \c name is nullptr
|
||||
then it simply returns true.
|
||||
*/
|
||||
bool setFilter(const char *name);
|
||||
@ -94,7 +94,7 @@ public:
|
||||
//! Print a log message
|
||||
/*!
|
||||
Print a log message using the printf-like \c format and arguments
|
||||
preceded by the filename and line number. If \c file is NULL then
|
||||
preceded by the filename and line number. If \c file is nullptr then
|
||||
neither the file nor the line are printed.
|
||||
*/
|
||||
void print(const char *file, int line, const char *format, ...);
|
||||
@ -121,7 +121,7 @@ public:
|
||||
//@}
|
||||
|
||||
private:
|
||||
void output(ELevel priority, char *msg);
|
||||
void output(ELevel priority, const char *msg);
|
||||
|
||||
private:
|
||||
using OutputterList = std::list<ILogOutputter *>;
|
||||
@ -182,7 +182,7 @@ otherwise it expands to a call that doesn't.
|
||||
#define LOGC(_a1, _a2) \
|
||||
if (_a1) \
|
||||
CLOG->print _a2
|
||||
#define CLOG_TRACE NULL, 0,
|
||||
#define CLOG_TRACE nullptr, 0,
|
||||
#else
|
||||
#define LOG(_a1) CLOG->print _a1
|
||||
#define LOGC(_a1, _a2) \
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#include "base/String.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
enum EFileLogOutputter
|
||||
{
|
||||
@ -22,16 +23,6 @@ enum EFileLogOutputter
|
||||
// StopLogOutputter
|
||||
//
|
||||
|
||||
StopLogOutputter::StopLogOutputter()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
StopLogOutputter::~StopLogOutputter()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void StopLogOutputter::open(const char *)
|
||||
{
|
||||
// do nothing
|
||||
@ -56,53 +47,40 @@ bool StopLogOutputter::write(ELevel, const char *)
|
||||
// ConsoleLogOutputter
|
||||
//
|
||||
|
||||
ConsoleLogOutputter::ConsoleLogOutputter()
|
||||
{
|
||||
}
|
||||
|
||||
ConsoleLogOutputter::~ConsoleLogOutputter()
|
||||
{
|
||||
}
|
||||
|
||||
void ConsoleLogOutputter::open(const char *title)
|
||||
{
|
||||
ARCH->openConsole(title);
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void ConsoleLogOutputter::close()
|
||||
{
|
||||
ARCH->closeConsole();
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void ConsoleLogOutputter::show(bool showIfEmpty)
|
||||
{
|
||||
ARCH->showConsole(showIfEmpty);
|
||||
// do nothing
|
||||
}
|
||||
|
||||
bool ConsoleLogOutputter::write(ELevel level, const char *msg)
|
||||
{
|
||||
ARCH->writeConsole(level, msg);
|
||||
if ((level >= kFATAL) && (level <= kWARNING))
|
||||
std::cerr << msg << std::endl;
|
||||
else
|
||||
std::cout << msg << std::endl;
|
||||
std::cout.flush();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConsoleLogOutputter::flush()
|
||||
void ConsoleLogOutputter::flush() const
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
//
|
||||
// SystemLogOutputter
|
||||
//
|
||||
|
||||
SystemLogOutputter::SystemLogOutputter()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
SystemLogOutputter::~SystemLogOutputter()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void SystemLogOutputter::open(const char *title)
|
||||
{
|
||||
ARCH->openLog(title);
|
||||
@ -128,7 +106,7 @@ bool SystemLogOutputter::write(ELevel level, const char *msg)
|
||||
// SystemLogger
|
||||
//
|
||||
|
||||
SystemLogger::SystemLogger(const char *title, bool blockConsole) : m_stop(NULL)
|
||||
SystemLogger::SystemLogger(const char *title, bool blockConsole)
|
||||
{
|
||||
// redirect log messages
|
||||
if (blockConsole) {
|
||||
@ -144,7 +122,7 @@ SystemLogger::~SystemLogger()
|
||||
{
|
||||
CLOG->remove(m_syslog);
|
||||
delete m_syslog;
|
||||
if (m_stop != NULL) {
|
||||
if (m_stop != nullptr) {
|
||||
CLOG->remove(m_stop);
|
||||
delete m_stop;
|
||||
}
|
||||
@ -159,13 +137,9 @@ FileLogOutputter::FileLogOutputter(const char *logFile)
|
||||
setLogFilename(logFile);
|
||||
}
|
||||
|
||||
FileLogOutputter::~FileLogOutputter()
|
||||
{
|
||||
}
|
||||
|
||||
void FileLogOutputter::setLogFilename(const char *logFile)
|
||||
{
|
||||
assert(logFile != NULL);
|
||||
assert(logFile != nullptr);
|
||||
m_fileName = logFile;
|
||||
}
|
||||
|
||||
@ -197,12 +171,15 @@ bool FileLogOutputter::write(ELevel level, const char *message)
|
||||
|
||||
void FileLogOutputter::open(const char *title)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void FileLogOutputter::close()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void FileLogOutputter::show(bool showIfEmpty)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@ -21,14 +21,14 @@ this to prevent already inserted outputters from writing.
|
||||
class StopLogOutputter : public ILogOutputter
|
||||
{
|
||||
public:
|
||||
StopLogOutputter();
|
||||
virtual ~StopLogOutputter();
|
||||
StopLogOutputter() = default;
|
||||
~StopLogOutputter() override = default;
|
||||
|
||||
// ILogOutputter overrides
|
||||
virtual void open(const char *title);
|
||||
virtual void close();
|
||||
virtual void show(bool showIfEmpty);
|
||||
virtual bool write(ELevel level, const char *message);
|
||||
void open(const char *title) override;
|
||||
void close() override;
|
||||
void show(bool showIfEmpty) override;
|
||||
bool write(ELevel level, const char *message) override;
|
||||
};
|
||||
|
||||
//! Write log to console
|
||||
@ -39,15 +39,15 @@ message is ignored.
|
||||
class ConsoleLogOutputter : public ILogOutputter
|
||||
{
|
||||
public:
|
||||
ConsoleLogOutputter();
|
||||
virtual ~ConsoleLogOutputter();
|
||||
ConsoleLogOutputter() = default;
|
||||
~ConsoleLogOutputter() override = default;
|
||||
|
||||
// ILogOutputter overrides
|
||||
virtual void open(const char *title);
|
||||
virtual void close();
|
||||
virtual void show(bool showIfEmpty);
|
||||
virtual bool write(ELevel level, const char *message);
|
||||
virtual void flush();
|
||||
void open(const char *title) override;
|
||||
void close() override;
|
||||
void show(bool showIfEmpty) override;
|
||||
bool write(ELevel level, const char *message) override;
|
||||
void flush() const;
|
||||
};
|
||||
|
||||
//! Write log to file
|
||||
@ -59,14 +59,14 @@ message is ignored.
|
||||
class FileLogOutputter : public ILogOutputter
|
||||
{
|
||||
public:
|
||||
FileLogOutputter(const char *logFile);
|
||||
virtual ~FileLogOutputter();
|
||||
explicit FileLogOutputter(const char *logFile);
|
||||
~FileLogOutputter() override = default;
|
||||
|
||||
// ILogOutputter overrides
|
||||
virtual void open(const char *title);
|
||||
virtual void close();
|
||||
virtual void show(bool showIfEmpty);
|
||||
virtual bool write(ELevel level, const char *message);
|
||||
void open(const char *title) override;
|
||||
void close() override;
|
||||
void show(bool showIfEmpty) override;
|
||||
bool write(ELevel level, const char *message) override;
|
||||
|
||||
void setLogFilename(const char *title);
|
||||
|
||||
@ -81,14 +81,14 @@ This outputter writes output to the system log.
|
||||
class SystemLogOutputter : public ILogOutputter
|
||||
{
|
||||
public:
|
||||
SystemLogOutputter();
|
||||
virtual ~SystemLogOutputter();
|
||||
SystemLogOutputter() = default;
|
||||
~SystemLogOutputter() override = default;
|
||||
|
||||
// ILogOutputter overrides
|
||||
virtual void open(const char *title);
|
||||
virtual void close();
|
||||
virtual void show(bool showIfEmpty);
|
||||
virtual bool write(ELevel level, const char *message);
|
||||
void open(const char *title) override;
|
||||
void close() override;
|
||||
void show(bool showIfEmpty) override;
|
||||
bool write(ELevel level, const char *message) override;
|
||||
};
|
||||
|
||||
//! Write log to system log only
|
||||
@ -111,6 +111,6 @@ public:
|
||||
SystemLogger &operator=(SystemLogger &&) = delete;
|
||||
|
||||
private:
|
||||
ILogOutputter *m_syslog;
|
||||
ILogOutputter *m_stop;
|
||||
ILogOutputter *m_syslog = nullptr;
|
||||
ILogOutputter *m_stop = nullptr;
|
||||
};
|
||||
|
||||
@ -20,7 +20,7 @@ std::wstring path(const std::string &filePath)
|
||||
{
|
||||
std::wstring result;
|
||||
|
||||
auto length = MultiByteToWideChar(CP_UTF8, 0, filePath.c_str(), static_cast<int>(filePath.length()), NULL, 0);
|
||||
auto length = MultiByteToWideChar(CP_UTF8, 0, filePath.c_str(), static_cast<int>(filePath.length()), nullptr, 0);
|
||||
if (length > 0) {
|
||||
result.resize(length);
|
||||
MultiByteToWideChar(CP_UTF8, 0, filePath.c_str(), static_cast<int>(filePath.length()), &result[0], length);
|
||||
|
||||
@ -32,16 +32,12 @@ public:
|
||||
using const_iterator = Container::const_iterator;
|
||||
using container_type = Container;
|
||||
|
||||
PriorityQueue()
|
||||
{
|
||||
}
|
||||
PriorityQueue(Container &swappedIn)
|
||||
PriorityQueue() = default;
|
||||
explicit PriorityQueue(Container &swappedIn)
|
||||
{
|
||||
swap(swappedIn);
|
||||
}
|
||||
~PriorityQueue()
|
||||
{
|
||||
}
|
||||
~PriorityQueue() = default;
|
||||
|
||||
//! @name manipulators
|
||||
//@{
|
||||
|
||||
@ -21,7 +21,6 @@ SimpleEventQueueBuffer::SimpleEventQueueBuffer()
|
||||
{
|
||||
m_queueMutex = ARCH->newMutex();
|
||||
m_queueReadyCond = ARCH->newCondVar();
|
||||
m_queueReady = false;
|
||||
}
|
||||
|
||||
SimpleEventQueueBuffer::~SimpleEventQueueBuffer()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user