mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-02-18 22:59:26 +08:00
Compare commits
76 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9c5e0d26b | ||
|
|
03999d900e | ||
|
|
b24551da7b | ||
|
|
bc461fe99b | ||
|
|
25e438a663 | ||
|
|
1f5aeda41d | ||
|
|
9114743577 | ||
|
|
7830a9e9f3 | ||
|
|
5fa8485130 | ||
|
|
ed9cb37283 | ||
|
|
e4b270a581 | ||
|
|
9dd9c45afc | ||
|
|
e163b75407 | ||
|
|
10ff3e6937 | ||
|
|
acae6d6558 | ||
|
|
d025ca1d81 | ||
|
|
e5aa31eb4c | ||
|
|
771cc565ab | ||
|
|
db3bdb16a1 | ||
|
|
c06e1d74b4 | ||
|
|
b544a2889b | ||
|
|
9c45636875 | ||
|
|
827b5f6a4c | ||
|
|
b0791ba183 | ||
|
|
b24b381575 | ||
|
|
0751005073 | ||
|
|
fe06cf77da | ||
|
|
d57cf204c8 | ||
|
|
63e22b7685 | ||
|
|
a02d2bb4ac | ||
|
|
0f7d78c263 | ||
|
|
0e321bd845 | ||
|
|
875b738222 | ||
|
|
b39e851262 | ||
|
|
ec466d459f | ||
|
|
d4a712bb32 | ||
|
|
1c17fddf51 | ||
|
|
3c838e7a92 | ||
|
|
8f44787ba3 | ||
|
|
12e15b5a37 | ||
|
|
588103c6dc | ||
|
|
2ce9b108ed | ||
|
|
93e3107881 | ||
|
|
468bdd6cc6 | ||
|
|
d5c5825ffd | ||
|
|
fe4094777f | ||
|
|
f13ef48cec | ||
|
|
a23822074e | ||
|
|
3d17bf4990 | ||
|
|
fd67be4a16 | ||
|
|
e6edf39305 | ||
|
|
34d2c62781 | ||
|
|
bd0a33e467 | ||
|
|
b8d36b6558 | ||
|
|
f38d89aaee | ||
|
|
773b9d6645 | ||
|
|
dea99ffb3a | ||
|
|
3251045e22 | ||
|
|
dc58c85e30 | ||
|
|
5a2a94d2cc | ||
|
|
f330953f4f | ||
|
|
8d4c86fe7f | ||
|
|
f8c2713c5b | ||
|
|
082a66b282 | ||
|
|
743b0ce8ce | ||
|
|
9d9b67aca5 | ||
|
|
d60b5a6ca0 | ||
|
|
e0ed6ee986 | ||
|
|
d3f0c80e94 | ||
|
|
b32ff87c6e | ||
|
|
b91b49229a | ||
|
|
afc8bb71dc | ||
|
|
4f86169f7f | ||
|
|
2cf43042e6 | ||
|
|
734fb8d6f7 | ||
|
|
3c7f6d3127 |
2
.github/workflows/bridge.yml
vendored
2
.github/workflows/bridge.yml
vendored
@@ -73,7 +73,7 @@ jobs:
|
||||
- name: Install flutter rust bridge deps
|
||||
shell: bash
|
||||
run: |
|
||||
cargo install flutter_rust_bridge_codegen --version ${{ env.FLUTTER_RUST_BRIDGE_VERSION }} --features "uuid"
|
||||
cargo install flutter_rust_bridge_codegen --version ${{ env.FLUTTER_RUST_BRIDGE_VERSION }} --features "uuid" --locked
|
||||
pushd flutter && sed -i -e 's/extended_text: 14.0.0/extended_text: 13.0.0/g' pubspec.yaml && flutter pub get && popd
|
||||
|
||||
- name: Run flutter rust bridge
|
||||
|
||||
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@@ -4,9 +4,9 @@ env:
|
||||
# MIN_SUPPORTED_RUST_VERSION: "1.46.0"
|
||||
# CICD_INTERMEDIATES_DIR: "_cicd-intermediates"
|
||||
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
||||
# vcpkg version: 2024.06.15
|
||||
# vcpkg version: 2024.11.16
|
||||
# for multiarch gcc compatibility
|
||||
VCPKG_COMMIT_ID: "f7423ee180c4b7f40d43402c2feb3859161ef625"
|
||||
VCPKG_COMMIT_ID: "b2cb0da531c2f1f740045bfe7c4dac59f0b2b69c"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
52
.github/workflows/flutter-build.yml
vendored
52
.github/workflows/flutter-build.yml
vendored
@@ -31,10 +31,10 @@ env:
|
||||
FLUTTER_ELINUX_VERSION: "3.16.9"
|
||||
TAG_NAME: "${{ inputs.upload-tag }}"
|
||||
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
||||
# vcpkg version: 2024.07.12
|
||||
VCPKG_COMMIT_ID: "1de2026f28ead93ff1773e6e680387643e914ea1"
|
||||
VERSION: "1.3.3"
|
||||
NDK_VERSION: "r27b"
|
||||
# vcpkg version: 2024.11.16
|
||||
VCPKG_COMMIT_ID: "b2cb0da531c2f1f740045bfe7c4dac59f0b2b69c"
|
||||
VERSION: "1.3.6"
|
||||
NDK_VERSION: "r27c"
|
||||
#signing keys env variable checks
|
||||
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"
|
||||
MACOS_P12_BASE64: "${{ secrets.MACOS_P12_BASE64 }}"
|
||||
@@ -107,7 +107,6 @@ jobs:
|
||||
|
||||
# https://github.com/flutter/flutter/issues/155685
|
||||
- name: Replace engine with rustdesk custom flutter engine
|
||||
if: false
|
||||
run: |
|
||||
flutter doctor -v
|
||||
flutter precache --windows
|
||||
@@ -157,6 +156,7 @@ jobs:
|
||||
done
|
||||
exit 1
|
||||
fi
|
||||
head -n 100 "${VCPKG_ROOT}/buildtrees/ffmpeg/build-${{ matrix.job.vcpkg-triplet }}-rel-out.log" || true
|
||||
shell: bash
|
||||
|
||||
- name: Build rustdesk
|
||||
@@ -317,6 +317,7 @@ jobs:
|
||||
done
|
||||
exit 1
|
||||
fi
|
||||
head -n 100 "${VCPKG_ROOT}/buildtrees/ffmpeg/build-${{ matrix.job.vcpkg-triplet }}-rel-out.log" || true
|
||||
shell: bash
|
||||
|
||||
- name: Build rustdesk
|
||||
@@ -520,6 +521,7 @@ jobs:
|
||||
done
|
||||
exit 1
|
||||
fi
|
||||
head -n 100 "${VCPKG_ROOT}/buildtrees/ffmpeg/build-${{ matrix.job.vcpkg-triplet }}-rel-out.log" || true
|
||||
shell: bash
|
||||
|
||||
- name: Install Rust toolchain
|
||||
@@ -638,6 +640,7 @@ jobs:
|
||||
os: macos-13, #macos-latest or macos-14 use M1 now, https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#:~:text=14%20GB-,macos%2Dlatest%20or%20macos%2D14,-The%20macos%2Dlatestlabel
|
||||
extra-build-args: "",
|
||||
arch: x86_64,
|
||||
vcpkg-triplet: x64-osx,
|
||||
}
|
||||
- {
|
||||
target: aarch64-apple-darwin,
|
||||
@@ -645,6 +648,7 @@ jobs:
|
||||
# extra-build-args: "--disable-flutter-texture-render", # disable this for mac, because we see a lot of users reporting flickering both on arm and x64, and we can not confirm if texture rendering has better performance if htere is no vram, https://github.com/rustdesk/rustdesk/issues/6296
|
||||
extra-build-args: "--screencapturekit",
|
||||
arch: aarch64,
|
||||
vcpkg-triplet: arm64-osx,
|
||||
}
|
||||
steps:
|
||||
- name: Export GitHub Actions cache environment variables
|
||||
@@ -756,6 +760,7 @@ jobs:
|
||||
done
|
||||
exit 1
|
||||
fi
|
||||
head -n 100 "${VCPKG_ROOT}/buildtrees/ffmpeg/build-${{ matrix.job.vcpkg-triplet }}-rel-out.log" || true
|
||||
|
||||
- name: Show version information (Rust, cargo, Clang)
|
||||
shell: bash
|
||||
@@ -932,7 +937,6 @@ jobs:
|
||||
libpam0g-dev \
|
||||
libpulse-dev \
|
||||
libva-dev \
|
||||
libvdpau-dev \
|
||||
libxcb-randr0-dev \
|
||||
libxcb-shape0-dev \
|
||||
libxcb-xfixes0-dev \
|
||||
@@ -1033,7 +1037,7 @@ jobs:
|
||||
ANDROID_NDK_ROOT: ${{ steps.setup-ndk.outputs.ndk-path }}
|
||||
run: |
|
||||
rustup target add ${{ matrix.job.target }}
|
||||
cargo install cargo-ndk --version ${{ env.CARGO_NDK_VERSION }}
|
||||
cargo install cargo-ndk --version ${{ env.CARGO_NDK_VERSION }} --locked
|
||||
case ${{ matrix.job.target }} in
|
||||
aarch64-linux-android)
|
||||
./flutter/ndk_arm64.sh
|
||||
@@ -1209,7 +1213,6 @@ jobs:
|
||||
libpam0g-dev \
|
||||
libpulse-dev \
|
||||
libva-dev \
|
||||
libvdpau-dev \
|
||||
libxcb-randr0-dev \
|
||||
libxcb-shape0-dev \
|
||||
libxcb-xfixes0-dev \
|
||||
@@ -1441,7 +1444,7 @@ jobs:
|
||||
- name: Install vcpkg dependencies
|
||||
if: matrix.job.arch == 'x86_64' || env.UPLOAD_ARTIFACT == 'true'
|
||||
run: |
|
||||
sudo apt install -y libva-dev libvdpau-dev
|
||||
sudo apt install -y libva-dev && apt show libva-dev
|
||||
if ! $VCPKG_ROOT/vcpkg \
|
||||
install \
|
||||
--triplet ${{ matrix.job.vcpkg-triplet }} \
|
||||
@@ -1455,6 +1458,7 @@ jobs:
|
||||
done
|
||||
exit 1
|
||||
fi
|
||||
head -n 100 "${VCPKG_ROOT}/buildtrees/ffmpeg/build-${{ matrix.job.vcpkg-triplet }}-rel-out.log" || true
|
||||
shell: bash
|
||||
|
||||
- name: Restore bridge files
|
||||
@@ -1499,7 +1503,6 @@ jobs:
|
||||
libpam0g-dev \
|
||||
libpulse-dev \
|
||||
libva-dev \
|
||||
libvdpau-dev \
|
||||
libxcb-randr0-dev \
|
||||
libxcb-shape0-dev \
|
||||
libxcb-xfixes0-dev \
|
||||
@@ -1772,7 +1775,6 @@ jobs:
|
||||
libpam0g-dev \
|
||||
libpulse-dev \
|
||||
libva-dev \
|
||||
libvdpau-dev \
|
||||
libxcb-randr0-dev \
|
||||
libxcb-shape0-dev \
|
||||
libxcb-xfixes0-dev \
|
||||
@@ -1850,6 +1852,8 @@ jobs:
|
||||
cat ~/.cargo/config
|
||||
# install dependencies from vcpkg
|
||||
export VCPKG_ROOT=/opt/artifacts/vcpkg
|
||||
# remove this when support higher version
|
||||
export USE_AOM_391=1
|
||||
if ! $VCPKG_ROOT/vcpkg install --triplet ${{ matrix.job.vcpkg-triplet }} --x-install-root="$VCPKG_ROOT/installed"; then
|
||||
find "${VCPKG_ROOT}/" -name "*.log" | while read -r _1; do
|
||||
echo "$_1:"
|
||||
@@ -1860,6 +1864,7 @@ jobs:
|
||||
done
|
||||
exit 1
|
||||
fi
|
||||
head -n 100 "${VCPKG_ROOT}/buildtrees/ffmpeg/build-${{ matrix.job.vcpkg-triplet }}-rel-out.log" || true
|
||||
# build rustdesk
|
||||
python3 ./res/inline-sciter.py
|
||||
export CARGO_INCREMENTAL=0
|
||||
@@ -2006,36 +2011,17 @@ jobs:
|
||||
shell: /bin/bash
|
||||
install: |
|
||||
apt-get update -y
|
||||
apt-get install -y \
|
||||
curl \
|
||||
git \
|
||||
rpm \
|
||||
wget
|
||||
apt-get install -y git flatpak flatpak-builder
|
||||
run: |
|
||||
# disable git safe.directory
|
||||
git config --global --add safe.directory "*"
|
||||
pushd /workspace
|
||||
# install
|
||||
apt-get update -y
|
||||
apt-get install -y \
|
||||
cmake \
|
||||
curl \
|
||||
flatpak \
|
||||
flatpak-builder \
|
||||
gcc \
|
||||
git \
|
||||
g++ \
|
||||
libgtk-3-dev \
|
||||
nasm \
|
||||
wget
|
||||
# flatpak deps
|
||||
flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
||||
flatpak --user install -y flathub org.freedesktop.Platform/${{ matrix.job.arch }}/23.08
|
||||
flatpak --user install -y flathub org.freedesktop.Sdk/${{ matrix.job.arch }}/23.08
|
||||
flatpak --user remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
|
||||
# package
|
||||
pushd flatpak
|
||||
git clone https://github.com/flathub/shared-modules.git --depth=1
|
||||
flatpak-builder --user --force-clean --repo=repo ./build ./rustdesk.json
|
||||
flatpak-builder --user --install-deps-from=flathub -y --force-clean --repo=repo ./build ./rustdesk.json
|
||||
flatpak build-bundle ./repo rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}${{ matrix.job.suffix }}.flatpak com.rustdesk.RustDesk
|
||||
|
||||
- name: Publish flatpak package
|
||||
|
||||
12
.github/workflows/playground.yml
vendored
12
.github/workflows/playground.yml
vendored
@@ -16,9 +16,9 @@ env:
|
||||
FLUTTER_ELINUX_VERSION: "3.16.9"
|
||||
TAG_NAME: "nightly"
|
||||
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
||||
# vcpkg version: 2024.06.15
|
||||
VCPKG_COMMIT_ID: "f7423ee180c4b7f40d43402c2feb3859161ef625"
|
||||
VERSION: "1.3.3"
|
||||
# vcpkg version: 2024.11.16
|
||||
VCPKG_COMMIT_ID: "b2cb0da531c2f1f740045bfe7c4dac59f0b2b69c"
|
||||
VERSION: "1.3.6"
|
||||
NDK_VERSION: "r26d"
|
||||
#signing keys env variable checks
|
||||
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"
|
||||
@@ -149,7 +149,7 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i '' 's/3.1.0/2.17.0/g' flutter/pubspec.yaml;
|
||||
cargo install flutter_rust_bridge_codegen --version ${{ matrix.job.bridge }} --features "uuid"
|
||||
cargo install flutter_rust_bridge_codegen --version ${{ matrix.job.bridge }} --features "uuid" --locked
|
||||
# below works for mac to make buildable on 3.13.9
|
||||
# pushd flutter/lib; find . -name "*.dart" | xargs -I{} sed -i '' 's/textScaler: TextScaler.linear(\(.*\)),/textScaleFactor: \1,/g' {}; popd;
|
||||
pushd flutter && flutter pub get && popd
|
||||
@@ -302,7 +302,7 @@ jobs:
|
||||
- name: Install flutter rust bridge deps
|
||||
run: |
|
||||
git config --global core.longpaths true
|
||||
cargo install flutter_rust_bridge_codegen --version ${{ env.FLUTTER_RUST_BRIDGE_VERSION }} --features "uuid"
|
||||
cargo install flutter_rust_bridge_codegen --version ${{ env.FLUTTER_RUST_BRIDGE_VERSION }} --features "uuid" --locked
|
||||
sed -i 's/uni_links_desktop/#uni_links_desktop/g' flutter/pubspec.yaml
|
||||
pushd flutter/lib; find . | grep dart | xargs sed -i 's/textScaler: TextScaler.linear(\(.*\)),/textScaleFactor: \1,/g'; popd;
|
||||
pushd flutter ; flutter pub get ; popd
|
||||
@@ -347,7 +347,7 @@ jobs:
|
||||
ANDROID_NDK_ROOT: ${{ steps.setup-ndk.outputs.ndk-path }}
|
||||
run: |
|
||||
rustup target add ${{ matrix.job.target }}
|
||||
cargo install cargo-ndk --version ${{ env.CARGO_NDK_VERSION }}
|
||||
cargo install cargo-ndk --version ${{ env.CARGO_NDK_VERSION }} --locked
|
||||
case ${{ matrix.job.target }} in
|
||||
aarch64-linux-android)
|
||||
./flutter/ndk_arm64.sh
|
||||
|
||||
18
Cargo.lock
generated
18
Cargo.lock
generated
@@ -1290,7 +1290,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "cpal"
|
||||
version = "0.15.3"
|
||||
source = "git+https://github.com/rustdesk-org/cpal?branch=osx-screencapturekit#4d318ff778063ce14669fd4bd67a1673653fc6e5"
|
||||
source = "git+https://github.com/rustdesk-org/cpal?branch=osx-screencapturekit#6b374bcaed076750ca8fce6da518ab39b882e14a"
|
||||
dependencies = [
|
||||
"alsa",
|
||||
"cidre",
|
||||
@@ -3064,8 +3064,8 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "hwcodec"
|
||||
version = "0.7.0"
|
||||
source = "git+https://github.com/rustdesk-org/hwcodec#da7dab48df19edb5a7138ff9e01bf9f148b523da"
|
||||
version = "0.7.1"
|
||||
source = "git+https://github.com/rustdesk-org/hwcodec#3e7c0dc755f8a77bbed3b2a9921553a511fd7bb5"
|
||||
dependencies = [
|
||||
"bindgen 0.59.2",
|
||||
"cc",
|
||||
@@ -3519,7 +3519,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"windows-targets 0.48.5",
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5219,7 +5219,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rdev"
|
||||
version = "0.5.0-2"
|
||||
source = "git+https://github.com/rustdesk-org/rdev#961d25cc00c6b3ef80f444e6a7bed9872e2c35ea"
|
||||
source = "git+https://github.com/rustdesk-org/rdev#f9b60b1dd0f3300a1b797d7a74c116683cd232c8"
|
||||
dependencies = [
|
||||
"cocoa 0.24.1",
|
||||
"core-foundation 0.9.4",
|
||||
@@ -5466,7 +5466,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rust-pulsectl"
|
||||
version = "0.2.12"
|
||||
source = "git+https://github.com/open-trade/pulsectl#5e68f4c2b7c644fa321984688602d71e8ad0bba3"
|
||||
source = "git+https://github.com/rustdesk-org/pulsectl#aa34dde499aa912a3abc5289cc0b547bd07dd6e2"
|
||||
dependencies = [
|
||||
"libpulse-binding",
|
||||
]
|
||||
@@ -5494,7 +5494,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustdesk"
|
||||
version = "1.3.3"
|
||||
version = "1.3.6"
|
||||
dependencies = [
|
||||
"android-wakelock",
|
||||
"android_logger",
|
||||
@@ -5594,7 +5594,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustdesk-portable-packer"
|
||||
version = "1.3.3"
|
||||
version = "1.3.6"
|
||||
dependencies = [
|
||||
"brotli",
|
||||
"dirs 5.0.1",
|
||||
@@ -5813,7 +5813,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "sciter-rs"
|
||||
version = "0.5.57"
|
||||
source = "git+https://github.com/open-trade/rust-sciter?branch=dyn#5322f3a755a0e6bf999fbc60d1efc35246c0f821"
|
||||
source = "git+https://github.com/rustdesk-org/rust-sciter?branch=dyn#5322f3a755a0e6bf999fbc60d1efc35246c0f821"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"libc",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rustdesk"
|
||||
version = "1.3.3"
|
||||
version = "1.3.6"
|
||||
authors = ["rustdesk <info@rustdesk.com>"]
|
||||
edition = "2021"
|
||||
build= "build.rs"
|
||||
@@ -78,12 +78,15 @@ fon = "0.6"
|
||||
zip = "0.6"
|
||||
shutdown_hooks = "0.1"
|
||||
totp-rs = { version = "5.4", default-features = false, features = ["gen_secret", "otpauth"] }
|
||||
|
||||
[target.'cfg(not(target_os = "linux"))'.dependencies]
|
||||
# https://github.com/rustdesk/rustdesk/discussions/10197, not use cpal on linux
|
||||
cpal = { git = "https://github.com/rustdesk-org/cpal", branch = "osx-screencapturekit" }
|
||||
ringbuf = "0.3"
|
||||
|
||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||
mac_address = "1.1"
|
||||
sciter-rs = { git = "https://github.com/open-trade/rust-sciter", branch = "dyn" }
|
||||
sciter-rs = { git = "https://github.com/rustdesk-org/rust-sciter", branch = "dyn" }
|
||||
sys-locale = "0.3"
|
||||
enigo = { path = "libs/enigo", features = [ "with_serde" ] }
|
||||
clipboard = { path = "libs/clipboard" }
|
||||
@@ -149,7 +152,7 @@ reqwest = { git = "https://github.com/rustdesk-org/reqwest", features = ["blocki
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
psimple = { package = "libpulse-simple-binding", version = "2.27" }
|
||||
pulse = { package = "libpulse-binding", version = "2.27" }
|
||||
rust-pulsectl = { git = "https://github.com/open-trade/pulsectl" }
|
||||
rust-pulsectl = { git = "https://github.com/rustdesk-org/pulsectl" }
|
||||
async-process = "1.7"
|
||||
evdev = { git="https://github.com/rustdesk-org/evdev" }
|
||||
dbus = "0.9"
|
||||
|
||||
11
Dockerfile
11
Dockerfile
@@ -2,6 +2,7 @@ FROM debian:bullseye-slim
|
||||
|
||||
WORKDIR /
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ENV VCPKG_FORCE_SYSTEM_BINARIES=1
|
||||
RUN apt update -y && \
|
||||
apt install --yes --no-install-recommends \
|
||||
g++ \
|
||||
@@ -21,7 +22,8 @@ RUN apt update -y && \
|
||||
libpam0g-dev \
|
||||
libpulse-dev \
|
||||
make \
|
||||
cmake \
|
||||
wget \
|
||||
libssl-dev \
|
||||
unzip \
|
||||
zip \
|
||||
sudo \
|
||||
@@ -31,6 +33,13 @@ RUN apt update -y && \
|
||||
ninja-build && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN wget https://github.com/Kitware/CMake/releases/download/v3.30.6/cmake-3.30.6.tar.gz --no-check-certificate && \
|
||||
tar xzf cmake-3.30.6.tar.gz && \
|
||||
cd cmake-3.30.6 && \
|
||||
./configure --prefix=/usr/local && \
|
||||
make && \
|
||||
make install
|
||||
|
||||
RUN git clone --branch 2023.04.15 --depth=1 https://github.com/microsoft/vcpkg && \
|
||||
/vcpkg/bootstrap-vcpkg.sh -disableMetrics && \
|
||||
/vcpkg/vcpkg --disable-metrics install libvpx libyuv opus aom
|
||||
|
||||
@@ -25,9 +25,12 @@ RustDesk welcomes contribution from everyone. See [CONTRIBUTING.md](docs/CONTRIB
|
||||
|
||||
[**NIGHTLY BUILD**](https://github.com/rustdesk/rustdesk/releases/tag/nightly)
|
||||
|
||||
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
|
||||
[<img src="https://f-droid.org/badge/get-it-on.png"
|
||||
alt="Get it on F-Droid"
|
||||
height="80">](https://f-droid.org/en/packages/com.carriez.flutter_hbb)
|
||||
[<img src="https://flathub.org/api/badge?svg&locale=en"
|
||||
alt="Get it on Flathub"
|
||||
height="80">](https://flathub.org/apps/com.rustdesk.RustDesk)
|
||||
|
||||
## Dependencies
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ AppDir:
|
||||
id: rustdesk
|
||||
name: rustdesk
|
||||
icon: rustdesk
|
||||
version: 1.3.3
|
||||
exec: usr/lib/rustdesk/rustdesk
|
||||
version: 1.3.6
|
||||
exec: usr/share/rustdesk/rustdesk
|
||||
exec_args: $@
|
||||
apt:
|
||||
arch:
|
||||
@@ -47,9 +47,9 @@ AppDir:
|
||||
- libasound2
|
||||
- libsystemd0
|
||||
- curl
|
||||
- libva2
|
||||
- libva-drm2
|
||||
- libva-x11-2
|
||||
- libvdpau1
|
||||
- libgstreamer-plugins-base1.0-0
|
||||
- gstreamer1.0-pipewire
|
||||
- libwayland-client0
|
||||
@@ -77,7 +77,7 @@ AppDir:
|
||||
env:
|
||||
GIO_MODULE_DIR: /lib64/gio/modules:/usr/lib/aarch64-linux-gnu/gio/modules:$APPDIR/usr/lib/aarch64-linux-gnu/gio/modules
|
||||
GDK_BACKEND: x11
|
||||
APPDIR_LIBRARY_PATH: /lib64:/usr/lib/aarch64-linux-gnu:$APPDIR/lib/aarch64-linux-gnu:$APPDIR/lib/aarch64-linux-gnu/security:$APPDIR/lib/systemd:$APPDIR/usr/lib/aarch64-linux-gnu:$APPDIR/usr/lib/aarch64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders:$APPDIR/usr/lib/aarch64-linux-gnu/gstreamer-1.0:$APPDIR/usr/lib/aarch64-linux-gnu/gtk-3.0/3.0.0/immodules:$APPDIR/usr/lib/aarch64-linux-gnu/gtk-3.0/3.0.0/printbackends:$APPDIR/usr/lib/aarch64-linux-gnu/krb5/plugins/preauth:$APPDIR/usr/lib/aarch64-linux-gnu/libcanberra-0.30:$APPDIR/usr/lib/aarch64-linux-gnu/pulseaudio:$APPDIR/usr/lib/aarch64-linux-gnu/sasl2:$APPDIR/usr/lib/aarch64-linux-gnu/vdpau:$APPDIR/usr/lib/rustdesk/lib:$APPDIR/lib/aarch64
|
||||
APPDIR_LIBRARY_PATH: /lib64:/usr/lib/aarch64-linux-gnu:$APPDIR/lib/aarch64-linux-gnu:$APPDIR/lib/aarch64-linux-gnu/security:$APPDIR/lib/systemd:$APPDIR/usr/lib/aarch64-linux-gnu:$APPDIR/usr/lib/aarch64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders:$APPDIR/usr/lib/aarch64-linux-gnu/gstreamer-1.0:$APPDIR/usr/lib/aarch64-linux-gnu/gtk-3.0/3.0.0/immodules:$APPDIR/usr/lib/aarch64-linux-gnu/gtk-3.0/3.0.0/printbackends:$APPDIR/usr/lib/aarch64-linux-gnu/krb5/plugins/preauth:$APPDIR/usr/lib/aarch64-linux-gnu/libcanberra-0.30:$APPDIR/usr/lib/aarch64-linux-gnu/pulseaudio:$APPDIR/usr/lib/aarch64-linux-gnu/sasl2:$APPDIR/usr/lib/aarch64-linux-gnu/vdpau:$APPDIR/usr/share/rustdesk/lib:$APPDIR/lib/aarch64
|
||||
GST_PLUGIN_PATH: /lib64/gstreamer-1.0:/usr/lib/aarch64-linux-gnu/gstreamer-1.0:$APPDIR/usr/lib/aarch64-linux-gnu/gstreamer-1.0
|
||||
GST_PLUGIN_SYSTEM_PATH: /lib64/gstreamer-1.0:/usr/lib/aarch64-linux-gnu/gstreamer-1.0:$APPDIR/usr/lib/aarch64-linux-gnu/gstreamer-1.0
|
||||
test:
|
||||
|
||||
@@ -18,8 +18,8 @@ AppDir:
|
||||
id: rustdesk
|
||||
name: rustdesk
|
||||
icon: rustdesk
|
||||
version: 1.3.3
|
||||
exec: usr/lib/rustdesk/rustdesk
|
||||
version: 1.3.6
|
||||
exec: usr/share/rustdesk/rustdesk
|
||||
exec_args: $@
|
||||
apt:
|
||||
arch:
|
||||
@@ -50,9 +50,9 @@ AppDir:
|
||||
- libasound2
|
||||
- libsystemd0
|
||||
- curl
|
||||
- libva2
|
||||
- libva-drm2
|
||||
- libva-x11-2
|
||||
- libvdpau1
|
||||
- libgstreamer-plugins-base1.0-0
|
||||
- gstreamer1.0-pipewire
|
||||
- libwayland-client0
|
||||
@@ -80,7 +80,7 @@ AppDir:
|
||||
env:
|
||||
GIO_MODULE_DIR: /lib64/gio/modules:/usr/lib/x86_64-linux-gnu/gio/modules:$APPDIR/usr/lib/x86_64-linux-gnu/gio/modules
|
||||
GDK_BACKEND: x11
|
||||
APPDIR_LIBRARY_PATH: /lib64:/usr/lib/x86_64-linux-gnu:$APPDIR/lib/x86_64-linux-gnu:$APPDIR/lib/x86_64-linux-gnu/security:$APPDIR/lib/systemd:$APPDIR/usr/lib/x86_64-linux-gnu:$APPDIR/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders:$APPDIR/usr/lib/x86_64-linux-gnu/gstreamer-1.0:$APPDIR/usr/lib/x86_64-linux-gnu/gtk-3.0/3.0.0/immodules:$APPDIR/usr/lib/x86_64-linux-gnu/gtk-3.0/3.0.0/printbackends:$APPDIR/usr/lib/x86_64-linux-gnu/krb5/plugins/preauth:$APPDIR/usr/lib/x86_64-linux-gnu/libcanberra-0.30:$APPDIR/usr/lib/x86_64-linux-gnu/pulseaudio:$APPDIR/usr/lib/x86_64-linux-gnu/sasl2:$APPDIR/usr/lib/x86_64-linux-gnu/vdpau:$APPDIR/usr/lib/rustdesk/lib:$APPDIR/lib/x86_64
|
||||
APPDIR_LIBRARY_PATH: /lib64:/usr/lib/x86_64-linux-gnu:$APPDIR/lib/x86_64-linux-gnu:$APPDIR/lib/x86_64-linux-gnu/security:$APPDIR/lib/systemd:$APPDIR/usr/lib/x86_64-linux-gnu:$APPDIR/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders:$APPDIR/usr/lib/x86_64-linux-gnu/gstreamer-1.0:$APPDIR/usr/lib/x86_64-linux-gnu/gtk-3.0/3.0.0/immodules:$APPDIR/usr/lib/x86_64-linux-gnu/gtk-3.0/3.0.0/printbackends:$APPDIR/usr/lib/x86_64-linux-gnu/krb5/plugins/preauth:$APPDIR/usr/lib/x86_64-linux-gnu/libcanberra-0.30:$APPDIR/usr/lib/x86_64-linux-gnu/pulseaudio:$APPDIR/usr/lib/x86_64-linux-gnu/sasl2:$APPDIR/usr/lib/x86_64-linux-gnu/vdpau:$APPDIR/usr/share/rustdesk/lib:$APPDIR/lib/x86_64
|
||||
GST_PLUGIN_PATH: /lib64/gstreamer-1.0:/usr/lib/x86_64-linux-gnu/gstreamer-1.0:$APPDIR/usr/lib/x86_64-linux-gnu/gstreamer-1.0
|
||||
GST_PLUGIN_SYSTEM_PATH: /lib64/gstreamer-1.0:/usr/lib/x86_64-linux-gnu/gstreamer-1.0:$APPDIR/usr/lib/x86_64-linux-gnu/gstreamer-1.0
|
||||
test:
|
||||
|
||||
20
build.py
20
build.py
@@ -111,7 +111,7 @@ def make_parser():
|
||||
'--hwcodec',
|
||||
action='store_true',
|
||||
help='Enable feature hwcodec' + (
|
||||
'' if windows or osx else ', need libva-dev, libvdpau-dev.')
|
||||
'' if windows or osx else ', need libva-dev.')
|
||||
)
|
||||
parser.add_argument(
|
||||
'--vram',
|
||||
@@ -298,7 +298,7 @@ Version: %s
|
||||
Architecture: %s
|
||||
Maintainer: rustdesk <info@rustdesk.com>
|
||||
Homepage: https://rustdesk.com
|
||||
Depends: libgtk-3-0, libxcb-randr0, libxdo3, libxfixes3, libxcb-shape0, libxcb-xfixes0, libasound2, libsystemd0, curl, libva-drm2, libva-x11-2, libvdpau1, libgstreamer-plugins-base1.0-0, libpam0g, gstreamer1.0-pipewire%s
|
||||
Depends: libgtk-3-0, libxcb-randr0, libxdo3, libxfixes3, libxcb-shape0, libxcb-xfixes0, libasound2, libsystemd0, curl, libva2, libva-drm2, libva-x11-2, libgstreamer-plugins-base1.0-0, libpam0g, gstreamer1.0-pipewire%s
|
||||
Recommends: libayatana-appindicator3-1
|
||||
Description: A remote control software.
|
||||
|
||||
@@ -321,7 +321,7 @@ def build_flutter_deb(version, features):
|
||||
os.chdir('flutter')
|
||||
system2('flutter build linux --release')
|
||||
system2('mkdir -p tmpdeb/usr/bin/')
|
||||
system2('mkdir -p tmpdeb/usr/lib/rustdesk')
|
||||
system2('mkdir -p tmpdeb/usr/share/rustdesk')
|
||||
system2('mkdir -p tmpdeb/etc/rustdesk/')
|
||||
system2('mkdir -p tmpdeb/etc/pam.d/')
|
||||
system2('mkdir -p tmpdeb/usr/share/rustdesk/files/systemd/')
|
||||
@@ -331,7 +331,7 @@ def build_flutter_deb(version, features):
|
||||
system2('mkdir -p tmpdeb/usr/share/polkit-1/actions')
|
||||
system2('rm tmpdeb/usr/bin/rustdesk || true')
|
||||
system2(
|
||||
f'cp -r {flutter_build_dir}/* tmpdeb/usr/lib/rustdesk/')
|
||||
f'cp -r {flutter_build_dir}/* tmpdeb/usr/share/rustdesk/')
|
||||
system2(
|
||||
'cp ../res/rustdesk.service tmpdeb/usr/share/rustdesk/files/systemd/')
|
||||
system2(
|
||||
@@ -366,7 +366,7 @@ def build_flutter_deb(version, features):
|
||||
def build_deb_from_folder(version, binary_folder):
|
||||
os.chdir('flutter')
|
||||
system2('mkdir -p tmpdeb/usr/bin/')
|
||||
system2('mkdir -p tmpdeb/usr/lib/rustdesk')
|
||||
system2('mkdir -p tmpdeb/usr/share/rustdesk')
|
||||
system2('mkdir -p tmpdeb/usr/share/rustdesk/files/systemd/')
|
||||
system2('mkdir -p tmpdeb/usr/share/icons/hicolor/256x256/apps/')
|
||||
system2('mkdir -p tmpdeb/usr/share/icons/hicolor/scalable/apps/')
|
||||
@@ -374,7 +374,7 @@ def build_deb_from_folder(version, binary_folder):
|
||||
system2('mkdir -p tmpdeb/usr/share/polkit-1/actions')
|
||||
system2('rm tmpdeb/usr/bin/rustdesk || true')
|
||||
system2(
|
||||
f'cp -r ../{binary_folder}/* tmpdeb/usr/lib/rustdesk/')
|
||||
f'cp -r ../{binary_folder}/* tmpdeb/usr/share/rustdesk/')
|
||||
system2(
|
||||
'cp ../res/rustdesk.service tmpdeb/usr/share/rustdesk/files/systemd/')
|
||||
system2(
|
||||
@@ -621,14 +621,14 @@ def main():
|
||||
os.system('mkdir -p tmpdeb/etc/pam.d/')
|
||||
os.system('cp pam.d/rustdesk.debian tmpdeb/etc/pam.d/rustdesk')
|
||||
system2('strip tmpdeb/usr/bin/rustdesk')
|
||||
system2('mkdir -p tmpdeb/usr/lib/rustdesk')
|
||||
system2('mv tmpdeb/usr/bin/rustdesk tmpdeb/usr/lib/rustdesk/')
|
||||
system2('cp libsciter-gtk.so tmpdeb/usr/lib/rustdesk/')
|
||||
system2('mkdir -p tmpdeb/usr/share/rustdesk')
|
||||
system2('mv tmpdeb/usr/bin/rustdesk tmpdeb/usr/share/rustdesk/')
|
||||
system2('cp libsciter-gtk.so tmpdeb/usr/share/rustdesk/')
|
||||
md5_file('usr/share/rustdesk/files/systemd/rustdesk.service')
|
||||
md5_file('etc/rustdesk/startwm.sh')
|
||||
md5_file('etc/X11/rustdesk/xorg.conf')
|
||||
md5_file('etc/pam.d/rustdesk')
|
||||
md5_file('usr/lib/rustdesk/libsciter-gtk.so')
|
||||
md5_file('usr/share/rustdesk/libsciter-gtk.so')
|
||||
system2('dpkg-deb -b tmpdeb rustdesk.deb; /bin/rm -rf tmpdeb/')
|
||||
os.rename('rustdesk.deb', 'rustdesk-%s.deb' % version)
|
||||
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
<b>README를 모국어로 번역하기 위한 당신의 도움의 필요합니다.</b>
|
||||
</p>
|
||||
|
||||
Chat with us: [Discord](https://discord.gg/nDceKgxnkV) | [Twitter](https://twitter.com/rustdesk) | [Reddit](https://www.reddit.com/r/rustdesk)
|
||||
채팅하기: [Discord](https://discord.gg/nDceKgxnkV) | [Twitter](https://twitter.com/rustdesk) | [Reddit](https://www.reddit.com/r/rustdesk)
|
||||
|
||||
|
||||
[](https://ko-fi.com/I2I04VU09)
|
||||
|
||||
Rust로 작성되었고, 설정없이 바로 사용할 수 있는 원격 데스트탑 소프트웨어입니다. 자신의 데이터를 완전히 컨트롤할 수 있고, 보안의 염려도 없습니다. 우리의 rendezvous/relay 서버를 사용해도, [스스로 설정](https://rustdesk.com/server)하는 것도, [스스로 rendezvous/relay 서버를 작성할 수도 있습니다](https://github.com/rustdesk/rustdesk-server-demo).
|
||||
Rust로 작성되었고, 설정없이 바로 사용할 수 있는 원격 데스트탑 소프트웨어입니다. 자신의 데이터를 완전히 컨트롤할 수 있고, 보안의 염려도 없습니다. 우리의 rendezvous/relay 서버를 사용해도, [직접 설정](https://rustdesk.com/server)하거나 [직접 rendezvous/relay 서버를 작성할 수도 있습니다](https://github.com/rustdesk/rustdesk-server-demo).
|
||||
|
||||

|
||||
|
||||
@@ -43,9 +43,9 @@ RustDesk는 모든 기여를 환영합니다. 기여하고자 한다면 [`docs/C
|
||||
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
|
||||
- Linux/MacOS: vcpkg install libvpx libyuv opus aom
|
||||
|
||||
- run `cargo run`
|
||||
- 실행 `cargo run`
|
||||
|
||||
## [Build](https://rustdesk.com/docs/en/dev/build/)
|
||||
## [빌드](https://rustdesk.com/docs/en/dev/build/)
|
||||
|
||||
## Linux에서 빌드 순서
|
||||
|
||||
@@ -67,7 +67,7 @@ sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-
|
||||
sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-config clang gtk3 xdotool libxcb libxfixes alsa-lib pipewire
|
||||
```
|
||||
|
||||
### Install vcpkg
|
||||
### vcpkg 설치
|
||||
|
||||
```sh
|
||||
git clone https://github.com/microsoft/vcpkg
|
||||
@@ -79,7 +79,7 @@ export VCPKG_ROOT=$HOME/vcpkg
|
||||
vcpkg/vcpkg install libvpx libyuv opus aom
|
||||
```
|
||||
|
||||
### Fix libvpx (For Fedora)
|
||||
### libvpx 수정 (For Fedora용)
|
||||
|
||||
```sh
|
||||
cd vcpkg/buildtrees/libvpx/src
|
||||
@@ -92,7 +92,7 @@ cp libvpx.a $HOME/vcpkg/installed/x64-linux/lib/
|
||||
cd
|
||||
```
|
||||
|
||||
### Build
|
||||
### 빌드
|
||||
|
||||
```sh
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
@@ -107,7 +107,7 @@ VCPKG_ROOT=$HOME/vcpkg cargo run
|
||||
|
||||
## Docker에 빌드하는 방법
|
||||
|
||||
레포지토리를 클론하고, Docker 컨테이너 구성하는 것으로 시작합니다.
|
||||
리포지토리를 클론하고, Docker 컨테이너 구성하는 것으로 시작합니다.
|
||||
|
||||
```sh
|
||||
git clone https://github.com/rustdesk/rustdesk
|
||||
@@ -115,13 +115,13 @@ cd rustdesk
|
||||
docker build -t "rustdesk-builder" .
|
||||
```
|
||||
|
||||
이후, 애플리케이션을 빌드할 필요가 있을 때마다, 이하의 커맨드를 실행합니다.
|
||||
이후, 애플리케이션을 빌드할 필요가 있을 때마다, 아래의의 명령을 실행합니다.
|
||||
|
||||
```sh
|
||||
docker run --rm -it -v $PWD:/home/user/rustdesk -v rustdesk-git-cache:/home/user/.cargo/git -v rustdesk-registry-cache:/home/user/.cargo/registry -e PUID="$(id -u)" -e PGID="$(id -g)" rustdesk-builder
|
||||
```
|
||||
|
||||
첫 빌드에서는 의존관계가 캐시될 때까지 시간이 걸릴 수 있습니다만, 이후의 빌드때는 빨라집니다. 더불어 빌드 커맨드에 다른 인수를 지정할 필요가 있다면, 커맨드 끝에 있는 `<OPTIONAL-ARGS>` 에 지정할 수 있습니다. 예를 들어 최적화된 출시 버전을 빌드하고 싶다면 이렇게 상기한 커맨드 뒤에 `--release` 를 붙여 실행합니다. 성공했다면 실행파일은 시스템 타겟 폴더에 담겨지고, 다음 커맨드로 실행할 수 있습니다.
|
||||
첫 빌드에서는 의존관계가 캐시될 때까지 시간이 걸릴 수 있습니다만, 이후의 빌드때는 빨라집니다. 더불어 빌드 명령에 다른 인수를 지정할 필요가 있다면, 명령 끝에 있는 `<OPTIONAL-ARGS>` 에 지정할 수 있습니다. 예를 들어 최적화된 출시 버전을 빌드하고 싶다면 이렇게 상기한 명령 뒤에 `--release` 를 붙여 실행합니다. 성공했다면 실행파일은 시스템 타겟 폴더에 담겨지고, 다음 명령으로 실행할 수 있습니다.
|
||||
|
||||
```sh
|
||||
target/debug/rustdesk
|
||||
@@ -133,9 +133,9 @@ target/debug/rustdesk
|
||||
target/release/rustdesk
|
||||
```
|
||||
|
||||
커맨드를 RustDesk 리포지토리 루트에서 실행한다는 것을 확인해주세요. 그렇게 하지 않으면 애플리케이션이 필요한 리소스를 발견하지 못 할 가능성이 있습니다. 또한 `install`, `run` 같은 cargo 서브커맨드는 호스트가 아니라 컨테이너 프로그램을 설치, 실행을 위함이므로 현재 이 방법은 지원하지 않다는 점을 유념해주시길 바랍니다.
|
||||
명령을 RustDesk 리포지토리 루트에서 실행한다는 것을 확인해주세요. 그렇게 하지 않으면 애플리케이션이 필요한 리소스를 발견하지 못 할 가능성이 있습니다. 또한 `install`, `run` 같은 cargo 하위 명령은 호스트가 아니라 컨테이너 프로그램을 설치, 실행을 위함이므로 현재 이 방법은 지원하지 않다는 점을 유념해주시길 바랍니다.
|
||||
|
||||
## File Structure
|
||||
## 파일 구조
|
||||
|
||||
- **[libs/hbb_common](https://github.com/rustdesk/rustdesk/tree/master/libs/hbb_common)**: 비디오 코덱, 설정, tcp/udp 랩퍼, protobuf, 파일 전송을 위한 fs 함수, 그 외 유틸리티 함수
|
||||
- **[libs/scrap](https://github.com/rustdesk/rustdesk/tree/master/libs/scrap)**: 화면 캡처
|
||||
@@ -143,12 +143,12 @@ target/release/rustdesk
|
||||
- **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)**: GUI
|
||||
- **[src/server](https://github.com/rustdesk/rustdesk/tree/master/src/server)**: 오디오, 클립보드, 입력, 비디오 서비스 그리고 네트워크 연결
|
||||
- **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)**: 피어 접속 시작
|
||||
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: [rustdesk-server](https://github.com/rustdesk/rustdesk-server)와 통신해서 리모트 다이렉트(TCP hole punching) 혹은 relayed 접속
|
||||
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: [rustdesk-server](https://github.com/rustdesk/rustdesk-server)와 통신해서 리모트 다이렉트 (TCP hole punching) 혹은 relayed 접속
|
||||
- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: 플랫폼 고유의 코드
|
||||
- **[flutter](https://github.com/rustdesk/rustdesk/tree/master/flutter)**: Flutter code for mobile
|
||||
- **[flutter/web/js](https://github.com/rustdesk/rustdesk/tree/master/flutter/web/js)**: Javascript for Flutter web client
|
||||
- **[flutter](https://github.com/rustdesk/rustdesk/tree/master/flutter)**: 모바일용 Flutter 코드
|
||||
- **[flutter/web/js](https://github.com/rustdesk/rustdesk/tree/master/flutter/web/js)**: Flutter 웹 클라이언트용 자바스크립트
|
||||
|
||||
## Snapshot
|
||||
## 스냅샷
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -135,8 +135,8 @@ docker build -t "rustdesk-builder" . # 构建容器
|
||||
```
|
||||
在Dockerfile的RUN apt update之前插入两行:
|
||||
|
||||
RUN sed -i "s/deb.debian.org/mirrors.163.com/g" /etc/apt/sources.list
|
||||
RUN sed -i "s/security.debian.org/mirrors.163.com/g" /etc/apt/sources.list
|
||||
RUN sed -i "s|deb.debian.org|mirrors.aliyun.com|g" /etc/apt/sources.list && \
|
||||
sed -i "s|security.debian.org|mirrors.aliyun.com|g" /etc/apt/sources.list
|
||||
```
|
||||
|
||||
2. 修改容器系统中的 cargo 源,在`RUN ./rustup.sh -y`后插入下面代码:
|
||||
|
||||
59
flatpak/com.rustdesk.RustDesk.metainfo.xml
Normal file
59
flatpak/com.rustdesk.RustDesk.metainfo.xml
Normal file
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop-application">
|
||||
<id>com.rustdesk.RustDesk</id>
|
||||
<developer id="com.rustdesk">
|
||||
<name>RustDesk</name>
|
||||
</developer>
|
||||
<launchable type="desktop-id">com.rustdesk.RustDesk.desktop</launchable>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>AGPL-3.0-only</project_license>
|
||||
<name>RustDesk</name>
|
||||
<summary>Secure remote desktop access</summary>
|
||||
<description>
|
||||
<p>
|
||||
RustDesk is a full-featured open source remote control alternative for self-hosting and security with minimal configuration.
|
||||
</p>
|
||||
<ul>
|
||||
<li> Works on Windows, macOS, Linux, iOS, Android, Web. </li>
|
||||
<li> Supports VP8 / VP9 / AV1 software codecs, and H264 / H265 hardware codecs. </li>
|
||||
<li> Own your data, easily set up self-hosting solution on your infrastructure. </li>
|
||||
<li> P2P connection with end-to-end encryption based on NaCl. </li>
|
||||
<li> No administrative privileges or installation needed for Windows, elevate priviledge locally or from remote on demand. </li>
|
||||
<li> We like to keep things simple and will strive to make simpler where possible. </li>
|
||||
</ul>
|
||||
<p>
|
||||
For self-hosting setup instructions please go to our home page.
|
||||
</p>
|
||||
</description>
|
||||
<categories>
|
||||
<category>Utility</category>
|
||||
</categories>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<caption>Remote desktop session</caption>
|
||||
<image>https://user-images.githubusercontent.com/71636191/171661982-430285f0-2e12-4b1d-9957-4a58e375304d.png</image>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<branding>
|
||||
<color type="primary" scheme_preference="light">#d9eaf8</color>
|
||||
<color type="primary" scheme_preference="dark">#0160ee</color>
|
||||
</branding>
|
||||
<url type="homepage">https://rustdesk.com</url>
|
||||
<url type="bugtracker">https://github.com/rustdesk/rustdesk/issues</url>
|
||||
<url type="faq">https://github.com/rustdesk/rustdesk/wiki/FAQ</url>
|
||||
<url type="help">https://rustdesk.com/docs</url>
|
||||
<url type="donation">https://ko-fi.com/rustdesk</url>
|
||||
<url type="vcs-browser">https://github.com/rustdesk/rustdesk</url>
|
||||
<url type="translate">https://github.com/rustdesk/rustdesk/tree/master/src/lang</url>
|
||||
<url type="contribute">https://github.com/rustdesk/rustdesk/blob/master/docs/CONTRIBUTING.md</url>
|
||||
<url type="contact">https://rustdesk.com/docs/en/technical-support</url>
|
||||
<requires>
|
||||
<display_length compare="ge">600</display_length>
|
||||
<internet>always</internet>
|
||||
</requires>
|
||||
<supports>
|
||||
<control>keyboard</control>
|
||||
<control>pointing</control>
|
||||
</supports>
|
||||
<content_rating type="oars-1.1"/>
|
||||
</component>
|
||||
@@ -1,19 +1,30 @@
|
||||
{
|
||||
"id": "com.rustdesk.RustDesk",
|
||||
"runtime": "org.freedesktop.Platform",
|
||||
"runtime-version": "23.08",
|
||||
"runtime-version": "24.08",
|
||||
"sdk": "org.freedesktop.Sdk",
|
||||
"command": "rustdesk",
|
||||
"icon": "share/icons/hicolor/scalable/apps/rustdesk.svg",
|
||||
"cleanup": ["/include", "/lib/pkgconfig", "/share/gtk-doc"],
|
||||
"rename-desktop-file": "rustdesk.desktop",
|
||||
"rename-icon": "rustdesk",
|
||||
"modules": [
|
||||
"shared-modules/libappindicator/libappindicator-gtk3-12.10.json",
|
||||
"xdotool.json",
|
||||
{
|
||||
"name": "pam",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"./configure --disable-selinux --prefix=/app && make -j4 install"
|
||||
],
|
||||
"name": "xdotool",
|
||||
"no-autogen": true,
|
||||
"make-install-args": ["PREFIX=${FLATPAK_DEST}"],
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://github.com/jordansissel/xdotool/releases/download/v3.20211022.1/xdotool-3.20211022.1.tar.gz",
|
||||
"sha256": "96f0facfde6d78eacad35b91b0f46fecd0b35e474c03e00e30da3fdd345f9ada"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "pam",
|
||||
"buildsystem": "autotools",
|
||||
"config-opts": ["--disable-selinux"],
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
@@ -26,32 +37,24 @@
|
||||
"name": "rustdesk",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"bsdtar -zxvf rustdesk.deb",
|
||||
"tar -xvf ./data.tar.xz",
|
||||
"cp -r ./usr/* /app/",
|
||||
"mkdir -p /app/bin && ln -s /app/lib/rustdesk/rustdesk /app/bin/rustdesk",
|
||||
"mv /app/share/applications/rustdesk.desktop /app/share/applications/com.rustdesk.RustDesk.desktop",
|
||||
"mv /app/share/applications/rustdesk-link.desktop /app/share/applications/com.rustdesk.RustDesk-link.desktop",
|
||||
"sed -i '/^Icon=/ c\\Icon=com.rustdesk.RustDesk' /app/share/applications/*.desktop",
|
||||
"mv /app/share/icons/hicolor/scalable/apps/rustdesk.svg /app/share/icons/hicolor/scalable/apps/com.rustdesk.RustDesk.svg",
|
||||
"for size in 16 24 32 48 64 128 256 512; do\n rsvg-convert -w $size -h $size -f png -o $size.png scalable.svg\n install -Dm644 $size.png /app/share/icons/hicolor/${size}x${size}/apps/com.rustdesk.RustDesk.png\n done"
|
||||
"bsdtar -Oxf rustdesk.deb data.tar.xz | bsdtar -xf -",
|
||||
"cp -r usr/* /app/",
|
||||
"mkdir -p /app/bin && ln -s /app/share/rustdesk/rustdesk /app/bin/rustdesk"
|
||||
],
|
||||
"cleanup": ["/include", "/lib/pkgconfig", "/share/gtk-doc"],
|
||||
"sources": [
|
||||
{
|
||||
"type": "file",
|
||||
"path": "./rustdesk.deb"
|
||||
"path": "rustdesk.deb"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"path": "../res/scalable.svg"
|
||||
"path": "com.rustdesk.RustDesk.metainfo.xml"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"finish-args": [
|
||||
"--share=ipc",
|
||||
"--socket=x11",
|
||||
"--socket=fallback-x11",
|
||||
"--socket=wayland",
|
||||
"--share=network",
|
||||
@@ -60,4 +63,4 @@
|
||||
"--socket=pulseaudio",
|
||||
"--talk-name=org.freedesktop.Flatpak"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"name": "xdotool",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"make -j4 && PREFIX=./build make install",
|
||||
"cp -r ./build/* /app/"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://github.com/jordansissel/xdotool/releases/download/v3.20211022.1/xdotool-3.20211022.1.tar.gz",
|
||||
"sha256": "96f0facfde6d78eacad35b91b0f46fecd0b35e474c03e00e30da3fdd345f9ada"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -15,6 +15,13 @@
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||
|
||||
<queries>
|
||||
<intent>
|
||||
<!-- https://developer.android.com/training/package-visibility/use-cases#open-urls-custom-tabs -->
|
||||
<action android:name="android.support.customtabs.action.CustomTabsService" />
|
||||
</intent>
|
||||
</queries>
|
||||
|
||||
<application
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="RustDesk"
|
||||
|
||||
@@ -306,8 +306,8 @@ class FloatingWindowService : Service(), View.OnTouchListener {
|
||||
popupMenu.menu.add(0, idShowRustDesk, 0, translate("Show RustDesk"))
|
||||
// For host side, clipboard sync
|
||||
val idSyncClipboard = 1
|
||||
val isClipboardListenerEnabled = MainActivity.rdClipboardManager?.isListening ?: false
|
||||
if (isClipboardListenerEnabled) {
|
||||
val isServiceSyncEnabled = (MainActivity.rdClipboardManager?.isCaptureStarted ?: false) && FFI.isServiceClipboardEnabled()
|
||||
if (isServiceSyncEnabled) {
|
||||
popupMenu.menu.add(0, idSyncClipboard, 0, translate("Update client clipboard"))
|
||||
}
|
||||
val idStopService = 2
|
||||
|
||||
@@ -103,7 +103,6 @@ class MainActivity : FlutterActivity() {
|
||||
mainService?.let {
|
||||
unbindService(serviceConnection)
|
||||
}
|
||||
rdClipboardManager?.rustEnableServiceClipboard(false)
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
@@ -221,6 +220,10 @@ class MainActivity : FlutterActivity() {
|
||||
result.success(true)
|
||||
|
||||
}
|
||||
"try_sync_clipboard" -> {
|
||||
rdClipboardManager?.syncClipboard(true)
|
||||
result.success(true)
|
||||
}
|
||||
GET_START_ON_BOOT_OPT -> {
|
||||
val prefs = getSharedPreferences(KEY_SHARED_PREFERENCES, MODE_PRIVATE)
|
||||
result.success(prefs.getBoolean(KEY_START_ON_BOOT_OPT, false))
|
||||
@@ -402,13 +405,4 @@ class MainActivity : FlutterActivity() {
|
||||
super.onStart()
|
||||
stopService(Intent(this, FloatingWindowService::class.java))
|
||||
}
|
||||
|
||||
// For client side
|
||||
// When swithing from other app to this app, try to sync clipboard.
|
||||
override fun onWindowFocusChanged(hasFocus: Boolean) {
|
||||
super.onWindowFocusChanged(hasFocus)
|
||||
if (hasFocus) {
|
||||
rdClipboardManager?.syncClipboard(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,6 +433,7 @@ class MainService : Service() {
|
||||
checkMediaPermission()
|
||||
_isStart = true
|
||||
FFI.setFrameRawEnable("video",true)
|
||||
MainActivity.rdClipboardManager?.setCaptureStarted(_isStart)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -441,6 +442,7 @@ class MainService : Service() {
|
||||
Log.d(logTag, "Stop Capture")
|
||||
FFI.setFrameRawEnable("video",false)
|
||||
_isStart = false
|
||||
MainActivity.rdClipboardManager?.setCaptureStarted(_isStart)
|
||||
// release video
|
||||
if (reuseVirtualDisplay) {
|
||||
// The virtual display video projection can be paused by calling `setSurface(null)`.
|
||||
|
||||
@@ -36,19 +36,19 @@ class RdClipboardManager(private val clipboardManager: ClipboardManager) {
|
||||
// though the `lastUpdatedClipData` will be set to null once.
|
||||
private var lastUpdatedClipData: ClipData? = null
|
||||
private var isClientEnabled = true;
|
||||
private var _isListening = false;
|
||||
val isListening: Boolean
|
||||
get() = _isListening
|
||||
private var _isCaptureStarted = false;
|
||||
|
||||
fun checkPrimaryClip(isClient: Boolean, isSync: Boolean) {
|
||||
val isCaptureStarted: Boolean
|
||||
get() = _isCaptureStarted
|
||||
|
||||
fun checkPrimaryClip(isClient: Boolean) {
|
||||
val clipData = clipboardManager.primaryClip
|
||||
if (clipData != null && clipData.itemCount > 0) {
|
||||
// Only handle the first item in the clipboard for now.
|
||||
val clip = clipData.getItemAt(0)
|
||||
val isHostSync = !isClient && isSync
|
||||
// Ignore the `isClipboardDataEqual()` check if it's a host sync operation.
|
||||
// Because it's a action manually triggered by the user.
|
||||
if (!isHostSync) {
|
||||
// Ignore the `isClipboardDataEqual()` check if it's a host operation.
|
||||
// Because it's an action manually triggered by the user.
|
||||
if (isClient) {
|
||||
if (lastUpdatedClipData != null && isClipboardDataEqual(clipData, lastUpdatedClipData!!)) {
|
||||
Log.d(logTag, "Clipboard data is the same as last update, ignore")
|
||||
return
|
||||
@@ -95,13 +95,6 @@ class RdClipboardManager(private val clipboardManager: ClipboardManager) {
|
||||
}
|
||||
}
|
||||
|
||||
private val clipboardListener = object : ClipboardManager.OnPrimaryClipChangedListener {
|
||||
override fun onPrimaryClipChanged() {
|
||||
Log.d(logTag, "onPrimaryClipChanged")
|
||||
checkPrimaryClip(true, false)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isSupportedMimeType(mimeType: String): Boolean {
|
||||
return supportedMimeTypes.contains(mimeType)
|
||||
}
|
||||
@@ -136,43 +129,23 @@ class RdClipboardManager(private val clipboardManager: ClipboardManager) {
|
||||
return true
|
||||
}
|
||||
|
||||
@Keep
|
||||
fun rustEnableServiceClipboard(enable: Boolean) {
|
||||
Log.d(logTag, "rustEnableServiceClipboard: enable: $enable, _isListening: $_isListening")
|
||||
if (enable) {
|
||||
if (!_isListening) {
|
||||
clipboardManager.addPrimaryClipChangedListener(clipboardListener)
|
||||
_isListening = true
|
||||
}
|
||||
} else {
|
||||
if (_isListening) {
|
||||
clipboardManager.removePrimaryClipChangedListener(clipboardListener)
|
||||
_isListening = false
|
||||
lastUpdatedClipData = null
|
||||
}
|
||||
}
|
||||
fun setCaptureStarted(started: Boolean) {
|
||||
_isCaptureStarted = started
|
||||
}
|
||||
|
||||
@Keep
|
||||
fun rustEnableClientClipboard(enable: Boolean) {
|
||||
Log.d(logTag, "rustEnableClientClipboard: enable: $enable")
|
||||
isClientEnabled = enable
|
||||
if (enable) {
|
||||
lastUpdatedClipData = clipboardManager.primaryClip
|
||||
} else {
|
||||
lastUpdatedClipData = null
|
||||
}
|
||||
lastUpdatedClipData = null
|
||||
}
|
||||
|
||||
fun syncClipboard(isClient: Boolean) {
|
||||
Log.d(logTag, "syncClipboard: isClient: $isClient, isClientEnabled: $isClientEnabled, _isListening: $_isListening")
|
||||
Log.d(logTag, "syncClipboard: isClient: $isClient, isClientEnabled: $isClientEnabled")
|
||||
if (isClient && !isClientEnabled) {
|
||||
return
|
||||
}
|
||||
if (!isClient && !_isListening) {
|
||||
return
|
||||
}
|
||||
checkPrimaryClip(isClient, true)
|
||||
checkPrimaryClip(isClient)
|
||||
}
|
||||
|
||||
@Keep
|
||||
|
||||
@@ -24,4 +24,5 @@ object FFI {
|
||||
external fun setCodecInfo(info: String)
|
||||
external fun getLocalOption(key: String): String
|
||||
external fun onClipboardUpdate(clips: ByteBuffer)
|
||||
external fun isServiceClipboardEnabled(): Boolean
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ function build {
|
||||
pushd "$SCRIPTDIR/.."
|
||||
$VCPKG_ROOT/vcpkg install --triplet $VCPKG_TARGET --x-install-root="$VCPKG_ROOT/installed"
|
||||
popd
|
||||
head -n 100 "${VCPKG_ROOT}/buildtrees/ffmpeg/build-$VCPKG_TARGET-rel-out.log" || true
|
||||
echo "*** [$ANDROID_ABI][Finished] Build and install vcpkg dependencies"
|
||||
|
||||
if [ -d "$VCPKG_ROOT/installed/arm-neon-android" ]; then
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -x
|
||||
|
||||
#
|
||||
# Script to build F-Droid release of RustDesk
|
||||
#
|
||||
@@ -23,6 +21,43 @@ set -x
|
||||
# + build: perform actual build of APK file
|
||||
#
|
||||
|
||||
# Start of functions
|
||||
|
||||
# Install Flutter of version `VERSION` from Github repository
|
||||
# into directory `FLUTTER_DIR` and apply patches if needed
|
||||
|
||||
prepare_flutter() {
|
||||
VERSION="${1}"
|
||||
FLUTTER_DIR="${2}"
|
||||
|
||||
if [ ! -f "${FLUTTER_DIR}/bin/flutter" ]; then
|
||||
git clone https://github.com/flutter/flutter "${FLUTTER_DIR}"
|
||||
fi
|
||||
|
||||
pushd "${FLUTTER_DIR}"
|
||||
|
||||
git restore .
|
||||
git checkout "${VERSION}"
|
||||
|
||||
# Patch flutter
|
||||
|
||||
if dpkg --compare-versions "${VERSION}" ge "3.24.4"; then
|
||||
git apply "${ROOTDIR}/.github/patches/flutter_3.24.4_dropdown_menu_enableFilter.diff"
|
||||
fi
|
||||
|
||||
flutter config --no-analytics
|
||||
|
||||
popd # ${FLUTTER_DIR}
|
||||
}
|
||||
|
||||
# Start of script
|
||||
|
||||
set -x
|
||||
|
||||
# Note current working directory as root dir for patches
|
||||
|
||||
ROOTDIR="${PWD}"
|
||||
|
||||
# Parse command-line arguments
|
||||
|
||||
VERNAME="${1}"
|
||||
@@ -82,21 +117,6 @@ export PATH="${PATH}:${HOME}/flutter/bin:${HOME}/depot_tools"
|
||||
|
||||
export VCPKG_ROOT="${HOME}/vcpkg"
|
||||
|
||||
prepare_Flutter() {
|
||||
version="${1}"
|
||||
|
||||
pushd "${HOME}"
|
||||
if [ ! -f "${HOME}/flutter/bin/flutter" ]; then
|
||||
git clone https://github.com/flutter/flutter
|
||||
fi
|
||||
pushd flutter
|
||||
git restore .
|
||||
git checkout "${version}"
|
||||
flutter config --no-analytics
|
||||
popd # flutter
|
||||
popd # ${HOME}
|
||||
}
|
||||
|
||||
# Now act depending on build step
|
||||
|
||||
# NOTE: F-Droid maintainers require explicit declaration of dependencies
|
||||
@@ -116,15 +136,20 @@ prebuild)
|
||||
.env.CARGO_NDK_VERSION \
|
||||
.github/workflows/flutter-build.yml)"
|
||||
|
||||
# Flutter used to compile main Rustdesk library
|
||||
|
||||
FLUTTER_VERSION="$(yq -r \
|
||||
.env.ANDROID_FLUTTER_VERSION \
|
||||
.github/workflows/flutter-build.yml)"
|
||||
|
||||
if [ -z "${FLUTTER_VERSION}" ]; then
|
||||
FLUTTER_VERSION="$(yq -r \
|
||||
.env.FLUTTER_VERSION \
|
||||
.github/workflows/flutter-build.yml)"
|
||||
fi
|
||||
|
||||
# Flutter used to compile Flutter<->Rust bridge files
|
||||
|
||||
FLUTTER_BRIDGE_VERSION="$(yq -r \
|
||||
.env.FLUTTER_VERSION \
|
||||
.github/workflows/bridge.yml)"
|
||||
@@ -207,14 +232,16 @@ prebuild)
|
||||
|
||||
cargo install \
|
||||
cargo-ndk \
|
||||
--version "${CARGO_NDK_VERSION}"
|
||||
--version "${CARGO_NDK_VERSION}" \
|
||||
--locked
|
||||
|
||||
# Install rust bridge generator
|
||||
|
||||
cargo install cargo-expand
|
||||
cargo install flutter_rust_bridge_codegen \
|
||||
--version "${FLUTTER_RUST_BRIDGE_VERSION}" \
|
||||
--features "uuid"
|
||||
--features "uuid" \
|
||||
--locked
|
||||
|
||||
# Populate native vcpkg dependencies
|
||||
|
||||
@@ -277,46 +304,66 @@ prebuild)
|
||||
|
||||
git apply res/fdroid/patches/*.patch
|
||||
|
||||
# Backup .gclient file, for later restore
|
||||
# If Flutter version used to generate bridge files differs from Flutter
|
||||
# version used to compile Rustdesk library, generate bridge using the
|
||||
# `FLUTTER_BRIDGE_VERSION` an restore the pubspec later
|
||||
|
||||
cp flutter-sdk/.gclient flutter-sdk/.gclient.bak
|
||||
if [ "${FLUTTER_VERSION}" != "${FLUTTER_BRIDGE_VERSION}" ]; then
|
||||
# Install Flutter bridge version
|
||||
|
||||
# For FLUTTER_BRIDGE_VERSION
|
||||
sed \
|
||||
-i \
|
||||
-e 's/extended_text: 14.0.0/extended_text: 13.0.0/g' \
|
||||
flutter/pubspec.yaml
|
||||
prepare_flutter "${FLUTTER_BRIDGE_VERSION}" "${HOME}/flutter"
|
||||
|
||||
# Install Flutter bridge version
|
||||
prepare_Flutter "${FLUTTER_BRIDGE_VERSION}"
|
||||
cp flutter-sdk/.gclient.bak flutter-sdk/.gclient
|
||||
sed -i "s/FLUTTER_VERSION_PLACEHOLDER/${FLUTTER_BRIDGE_VERSION}/" flutter-sdk/.gclient
|
||||
# Save changes
|
||||
|
||||
# Download Flutter dependencies
|
||||
pushd flutter
|
||||
flutter clean && flutter packages pub get
|
||||
popd # flutter
|
||||
git add .
|
||||
|
||||
# Generate FFI bindings
|
||||
flutter_rust_bridge_codegen \
|
||||
--rust-input ./src/flutter_ffi.rs \
|
||||
--dart-output ./flutter/lib/generated_bridge.dart
|
||||
# Edit pubspec to make flutter bridge version work
|
||||
|
||||
git restore flutter/pubspec.*
|
||||
sed \
|
||||
-i \
|
||||
-e 's/extended_text: 14.0.0/extended_text: 13.0.0/g' \
|
||||
flutter/pubspec.yaml
|
||||
|
||||
# Install Flutter
|
||||
prepare_Flutter "${FLUTTER_VERSION}"
|
||||
cp flutter-sdk/.gclient.bak flutter-sdk/.gclient
|
||||
sed -i "s/FLUTTER_VERSION_PLACEHOLDER/${FLUTTER_VERSION}/" flutter-sdk/.gclient
|
||||
# Download Flutter dependencies
|
||||
|
||||
pushd flutter
|
||||
|
||||
flutter clean
|
||||
flutter packages pub get
|
||||
|
||||
popd # flutter
|
||||
|
||||
# Generate FFI bindings
|
||||
|
||||
flutter_rust_bridge_codegen \
|
||||
--rust-input ./src/flutter_ffi.rs \
|
||||
--dart-output ./flutter/lib/generated_bridge.dart
|
||||
|
||||
# Add bridge files to save-list
|
||||
|
||||
git add -f ./flutter/lib/generated_bridge.* ./src/bridge_generated.*
|
||||
|
||||
# Restore everything
|
||||
|
||||
git checkout '*'
|
||||
git clean -dffx
|
||||
git reset
|
||||
fi
|
||||
|
||||
# Install Flutter version for RustDesk library build
|
||||
|
||||
prepare_flutter "${FLUTTER_VERSION}" "${HOME}/flutter"
|
||||
|
||||
# gms is not in thoes files now, but we still keep the following line for future reference(maybe).
|
||||
|
||||
sed \
|
||||
-i \
|
||||
-e '/gms/d' \
|
||||
flutter/android/build.gradle \
|
||||
flutter/android/app/build.gradle
|
||||
|
||||
# `firebase_analytics`` is not in thoes files now, but we still keep the following lines.
|
||||
# `firebase_analytics` is not in these files now, but we still keep the following lines.
|
||||
|
||||
sed \
|
||||
-i \
|
||||
-e '/firebase_analytics/d' \
|
||||
@@ -343,9 +390,12 @@ build)
|
||||
# '.github/workflows/flutter-build.yml'
|
||||
#
|
||||
|
||||
# Flutter used to compile main Rustdesk library
|
||||
|
||||
FLUTTER_VERSION="$(yq -r \
|
||||
.env.ANDROID_FLUTTER_VERSION \
|
||||
.github/workflows/flutter-build.yml)"
|
||||
|
||||
if [ -z "${FLUTTER_VERSION}" ]; then
|
||||
FLUTTER_VERSION="$(yq -r \
|
||||
.env.FLUTTER_VERSION \
|
||||
@@ -381,7 +431,8 @@ build)
|
||||
|
||||
pushd flutter
|
||||
|
||||
flutter clean && flutter packages pub get
|
||||
flutter clean
|
||||
flutter packages pub get
|
||||
|
||||
popd # flutter
|
||||
|
||||
|
||||
@@ -2,4 +2,6 @@
|
||||
# https://docs.flutter.dev/deployment/ios
|
||||
# flutter build ipa --release --obfuscate --split-debug-info=./split-debug-info
|
||||
# no obfuscate, because no easy to check errors
|
||||
cd $(dirname $(dirname $(which flutter)))
|
||||
git apply ~/rustdesk/.github/patches/flutter_3.24.4_dropdown_menu_enableFilter.diff
|
||||
flutter build ipa --release
|
||||
|
||||
@@ -133,7 +133,7 @@ SPEC CHECKSUMS:
|
||||
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
|
||||
SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f
|
||||
uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
|
||||
url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812
|
||||
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
|
||||
video_player_avfoundation: 02011213dab73ae3687df27ce441fbbcc82b5579
|
||||
wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import UIKit
|
||||
import Flutter
|
||||
|
||||
@UIApplicationMain
|
||||
@main
|
||||
@objc class AppDelegate: FlutterAppDelegate {
|
||||
override func application(
|
||||
_ application: UIApplication,
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
cd $(dirname $(dirname $(which flutter)))
|
||||
git apply ~/rustdesk/.github/patches/flutter_3.24.4_dropdown_menu_enableFilter.diff
|
||||
cargo build --features flutter,hwcodec --release --target aarch64-apple-ios --lib
|
||||
|
||||
@@ -2730,30 +2730,6 @@ Future<bool> osxRequestAudio() async {
|
||||
return await kMacOSPermChannel.invokeMethod("requestRecordAudio");
|
||||
}
|
||||
|
||||
class DraggableNeverScrollableScrollPhysics extends ScrollPhysics {
|
||||
/// Creates scroll physics that does not let the user scroll.
|
||||
const DraggableNeverScrollableScrollPhysics({super.parent});
|
||||
|
||||
@override
|
||||
DraggableNeverScrollableScrollPhysics applyTo(ScrollPhysics? ancestor) {
|
||||
return DraggableNeverScrollableScrollPhysics(parent: buildParent(ancestor));
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldAcceptUserOffset(ScrollMetrics position) {
|
||||
// TODO: find a better solution to check if the offset change is caused by the scrollbar.
|
||||
// Workaround: when dragging with the scrollbar, it always triggers an [IdleScrollActivity].
|
||||
if (position is ScrollPositionWithSingleContext) {
|
||||
// ignore: invalid_use_of_protected_member, invalid_use_of_visible_for_testing_member
|
||||
return position.activity is IdleScrollActivity;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
bool get allowImplicitScrolling => false;
|
||||
}
|
||||
|
||||
Widget futureBuilder(
|
||||
{required Future? future, required Widget Function(dynamic data) hasData}) {
|
||||
return FutureBuilder(
|
||||
@@ -2833,7 +2809,7 @@ Widget buildRemoteBlock(
|
||||
onExit: (event) => block.value = false,
|
||||
child: Stack(children: [
|
||||
// scope block tab
|
||||
FocusScope(child: child, canRequestFocus: !block.value),
|
||||
preventMouseKeyBuilder(child: child, block: block.value),
|
||||
// mask block click, cm not block click and still use check_click_time to avoid block local click
|
||||
if (mask)
|
||||
Offstage(
|
||||
@@ -2845,6 +2821,11 @@ Widget buildRemoteBlock(
|
||||
));
|
||||
}
|
||||
|
||||
Widget preventMouseKeyBuilder({required Widget child, required bool block}) {
|
||||
return ExcludeFocus(
|
||||
excluding: block, child: AbsorbPointer(child: child, absorbing: block));
|
||||
}
|
||||
|
||||
Widget unreadMessageCountBuilder(RxInt? count,
|
||||
{double? size, double? fontSize}) {
|
||||
return Obx(() => Offstage(
|
||||
@@ -3627,3 +3608,33 @@ List<SubWindowResizeEdge>? get subWindowManagerEnableResizeEdges => isWindows
|
||||
void earlyAssert() {
|
||||
assert('\1' == '1');
|
||||
}
|
||||
|
||||
void checkUpdate() {
|
||||
if (isDesktop || isAndroid) {
|
||||
if (!bind.isCustomClient()) {
|
||||
platformFFI.registerEventHandler(
|
||||
kCheckSoftwareUpdateFinish, kCheckSoftwareUpdateFinish,
|
||||
(Map<String, dynamic> evt) async {
|
||||
if (evt['url'] is String) {
|
||||
stateGlobal.updateUrl.value = evt['url'];
|
||||
}
|
||||
});
|
||||
Timer(const Duration(seconds: 1), () async {
|
||||
bind.mainGetSoftwareUpdateUrl();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/flutter/flutter/issues/153560#issuecomment-2497160535
|
||||
// For TextField, TextFormField
|
||||
extension WorkaroundFreezeLinuxMint on Widget {
|
||||
Widget workaroundFreezeLinuxMint() {
|
||||
// No need to check if is Linux Mint, because this workaround is harmless on other platforms.
|
||||
if (isLinux) {
|
||||
return ExcludeSemantics(child: this);
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ class _AddressBookState extends State<AddressBook> {
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
searchMatchFn: (item, searchValue) {
|
||||
return item.value
|
||||
@@ -556,7 +556,7 @@ class _AddressBookState extends State<AddressBook> {
|
||||
: translate('ID'),
|
||||
errorText: errorMsg,
|
||||
errorMaxLines: 5),
|
||||
))),
|
||||
).workaroundFreezeLinuxMint())),
|
||||
row(
|
||||
lable: Text(
|
||||
translate('Alias'),
|
||||
@@ -569,7 +569,7 @@ class _AddressBookState extends State<AddressBook> {
|
||||
? null
|
||||
: translate('Alias'),
|
||||
),
|
||||
)),
|
||||
).workaroundFreezeLinuxMint()),
|
||||
),
|
||||
if (isCurrentAbShared)
|
||||
row(
|
||||
@@ -598,7 +598,7 @@ class _AddressBookState extends State<AddressBook> {
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
)),
|
||||
if (gFFI.abModel.currentAbTags.isNotEmpty)
|
||||
Align(
|
||||
@@ -704,7 +704,7 @@ class _AddressBookState extends State<AddressBook> {
|
||||
),
|
||||
controller: controller,
|
||||
autofocus: true,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -167,7 +167,7 @@ class ChatPage extends StatelessWidget implements PageShape {
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
).workaroundFreezeLinuxMint();
|
||||
return SelectionArea(child: chat);
|
||||
}),
|
||||
],
|
||||
|
||||
@@ -140,7 +140,7 @@ void changeIdDialog() {
|
||||
msg = '';
|
||||
});
|
||||
},
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
const SizedBox(
|
||||
height: 8.0,
|
||||
),
|
||||
@@ -201,13 +201,14 @@ void changeWhiteList({Function()? callback}) async {
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
maxLines: null,
|
||||
decoration: InputDecoration(
|
||||
errorText: msg.isEmpty ? null : translate(msg),
|
||||
),
|
||||
controller: controller,
|
||||
enabled: !isOptFixed,
|
||||
autofocus: true),
|
||||
maxLines: null,
|
||||
decoration: InputDecoration(
|
||||
errorText: msg.isEmpty ? null : translate(msg),
|
||||
),
|
||||
controller: controller,
|
||||
enabled: !isOptFixed,
|
||||
autofocus: true)
|
||||
.workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -287,22 +288,23 @@ Future<String> changeDirectAccessPort(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
maxLines: null,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
hintText: '21118',
|
||||
isCollapsed: true,
|
||||
prefix: Text('$currentIP : '),
|
||||
suffix: IconButton(
|
||||
padding: EdgeInsets.zero,
|
||||
icon: const Icon(Icons.clear, size: 16),
|
||||
onPressed: () => controller.clear())),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(
|
||||
r'^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$')),
|
||||
],
|
||||
controller: controller,
|
||||
autofocus: true),
|
||||
maxLines: null,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
hintText: '21118',
|
||||
isCollapsed: true,
|
||||
prefix: Text('$currentIP : '),
|
||||
suffix: IconButton(
|
||||
padding: EdgeInsets.zero,
|
||||
icon: const Icon(Icons.clear, size: 16),
|
||||
onPressed: () => controller.clear())),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(
|
||||
r'^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$')),
|
||||
],
|
||||
controller: controller,
|
||||
autofocus: true)
|
||||
.workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -335,21 +337,22 @@ Future<String> changeAutoDisconnectTimeout(String old) async {
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
maxLines: null,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
hintText: '10',
|
||||
isCollapsed: true,
|
||||
suffix: IconButton(
|
||||
padding: EdgeInsets.zero,
|
||||
icon: const Icon(Icons.clear, size: 16),
|
||||
onPressed: () => controller.clear())),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(
|
||||
r'^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$')),
|
||||
],
|
||||
controller: controller,
|
||||
autofocus: true),
|
||||
maxLines: null,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
hintText: '10',
|
||||
isCollapsed: true,
|
||||
suffix: IconButton(
|
||||
padding: EdgeInsets.zero,
|
||||
icon: const Icon(Icons.clear, size: 16),
|
||||
onPressed: () => controller.clear())),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(
|
||||
r'^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$')),
|
||||
],
|
||||
controller: controller,
|
||||
autofocus: true)
|
||||
.workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -427,7 +430,7 @@ class DialogTextField extends StatelessWidget {
|
||||
keyboardType: keyboardType,
|
||||
inputFormatters: inputFormatters,
|
||||
maxLength: maxLength,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
).paddingSymmetric(vertical: 4.0);
|
||||
@@ -1501,7 +1504,7 @@ showAuditDialog(FFI ffi) async {
|
||||
maxLength: 256,
|
||||
controller: controller,
|
||||
focusNode: focusNode,
|
||||
)),
|
||||
).workaroundFreezeLinuxMint()),
|
||||
actions: [
|
||||
dialogButton('Cancel', onPressed: close, isOutline: true),
|
||||
dialogButton('OK', onPressed: submit)
|
||||
@@ -1748,7 +1751,7 @@ void renameDialog(
|
||||
autofocus: true,
|
||||
decoration: InputDecoration(labelText: translate('Name')),
|
||||
validator: validator,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
),
|
||||
// NOT use Offstage to wrap LinearProgressIndicator
|
||||
@@ -1808,7 +1811,7 @@ void changeBot({Function()? callback}) async {
|
||||
decoration: InputDecoration(
|
||||
hintText: translate('Token'),
|
||||
),
|
||||
);
|
||||
).workaroundFreezeLinuxMint();
|
||||
|
||||
return CustomAlertDialog(
|
||||
title: Text(translate("Telegram bot")),
|
||||
@@ -2178,7 +2181,7 @@ void setSharedAbPasswordDialog(String abName, Peer peer) {
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
if (!gFFI.abModel.current.isPersonal())
|
||||
Row(children: [
|
||||
Icon(Icons.info, color: Colors.amber).marginOnly(right: 4),
|
||||
|
||||
@@ -678,7 +678,7 @@ Future<bool?> verificationCodeDialog(
|
||||
labelText: "Email", prefixIcon: Icon(Icons.email)),
|
||||
readOnly: true,
|
||||
controller: TextEditingController(text: user?.email),
|
||||
)),
|
||||
).workaroundFreezeLinuxMint()),
|
||||
isEmailVerification ? const SizedBox(height: 8) : const Offstage(),
|
||||
codeField,
|
||||
/*
|
||||
|
||||
@@ -145,7 +145,7 @@ class _MyGroupState extends State<MyGroup> {
|
||||
border: InputBorder.none,
|
||||
isDense: true,
|
||||
),
|
||||
)),
|
||||
).workaroundFreezeLinuxMint()),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1257,7 +1257,7 @@ void _rdpDialog(String id) async {
|
||||
hintText: '3389'),
|
||||
controller: portController,
|
||||
autofocus: true,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
).marginOnly(bottom: isDesktop ? 8 : 0),
|
||||
@@ -1277,7 +1277,7 @@ void _rdpDialog(String id) async {
|
||||
labelText:
|
||||
isDesktop ? null : translate('Username')),
|
||||
controller: userController,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
).marginOnly(bottom: stateGlobal.isPortrait.isFalse ? 8 : 0)),
|
||||
@@ -1305,7 +1305,7 @@ void _rdpDialog(String id) async {
|
||||
? Icons.visibility_off
|
||||
: Icons.visibility))),
|
||||
controller: passwordController,
|
||||
)),
|
||||
).workaroundFreezeLinuxMint()),
|
||||
),
|
||||
],
|
||||
))
|
||||
|
||||
@@ -743,7 +743,7 @@ class _PeerSearchBarState extends State<PeerSearchBar> {
|
||||
border: InputBorder.none,
|
||||
isDense: true,
|
||||
),
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
// Icon(Icons.close),
|
||||
IconButton(
|
||||
|
||||
@@ -5,7 +5,6 @@ import 'package:dynamic_layouts/dynamic_layouts.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hbb/consts.dart';
|
||||
import 'package:flutter_hbb/desktop/widgets/scroll_wrapper.dart';
|
||||
import 'package:flutter_hbb/models/ab_model.dart';
|
||||
import 'package:flutter_hbb/models/peer_tab_model.dart';
|
||||
import 'package:flutter_hbb/models/state_model.dart';
|
||||
@@ -271,33 +270,24 @@ class _PeersViewState extends State<_PeersView>
|
||||
},
|
||||
)
|
||||
: peerCardUiType.value == PeerUiType.list
|
||||
? DesktopScrollWrapper(
|
||||
scrollController: _scrollController,
|
||||
child: ListView.builder(
|
||||
controller: _scrollController,
|
||||
physics: DraggableNeverScrollableScrollPhysics(),
|
||||
itemCount: peers.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return buildOnePeer(peers[index], false)
|
||||
.marginOnly(
|
||||
right: space,
|
||||
top: index == 0 ? 0 : space / 2,
|
||||
bottom: space / 2);
|
||||
}),
|
||||
? ListView.builder(
|
||||
controller: _scrollController,
|
||||
itemCount: peers.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return buildOnePeer(peers[index], false).marginOnly(
|
||||
right: space,
|
||||
top: index == 0 ? 0 : space / 2,
|
||||
bottom: space / 2);
|
||||
},
|
||||
)
|
||||
: DesktopScrollWrapper(
|
||||
scrollController: _scrollController,
|
||||
child: DynamicGridView.builder(
|
||||
controller: _scrollController,
|
||||
physics: DraggableNeverScrollableScrollPhysics(),
|
||||
gridDelegate: SliverGridDelegateWithWrapping(
|
||||
mainAxisSpacing: space / 2,
|
||||
crossAxisSpacing: space),
|
||||
itemCount: peers.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return buildOnePeer(peers[index], false);
|
||||
}),
|
||||
));
|
||||
: DynamicGridView.builder(
|
||||
gridDelegate: SliverGridDelegateWithWrapping(
|
||||
mainAxisSpacing: space / 2,
|
||||
crossAxisSpacing: space),
|
||||
itemCount: peers.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return buildOnePeer(peers[index], false);
|
||||
}));
|
||||
|
||||
if (updateEvent == UpdateEvent.load) {
|
||||
_curPeers.clear();
|
||||
|
||||
@@ -339,7 +339,9 @@ class _RawTouchGestureDetectorRegionState
|
||||
if (isDesktop || isWebDesktop) {
|
||||
ffi.cursorModel.clearRemoteWindowCoords();
|
||||
}
|
||||
await inputModel.sendMouse('up', MouseButtons.left);
|
||||
if (handleTouch) {
|
||||
await inputModel.sendMouse('up', MouseButtons.left);
|
||||
}
|
||||
}
|
||||
|
||||
// scale + pan event
|
||||
|
||||
@@ -244,10 +244,6 @@ const double kDesktopIconButtonSplashRadius = 20;
|
||||
/// [kMinCursorSize] indicates min cursor (w, h)
|
||||
const int kMinCursorSize = 12;
|
||||
|
||||
/// [kDefaultScrollAmountMultiplier] indicates how many rows can be scrolled after a minimum scroll action of mouse
|
||||
const kDefaultScrollAmountMultiplier = 5.0;
|
||||
const kDefaultScrollDuration = Duration(milliseconds: 50);
|
||||
const kDefaultMouseWheelThrottleDuration = Duration(milliseconds: 50);
|
||||
const kFullScreenEdgeSize = 0.0;
|
||||
const kMaximizeEdgeSize = 0.0;
|
||||
// Do not use kWindowResizeEdgeSize directly. Use `windowResizeEdgeSize` in `common.dart` instead.
|
||||
@@ -579,4 +575,4 @@ extension WindowsTargetExt on int {
|
||||
WindowsTarget get windowsVersion => getWindowsTarget(this);
|
||||
}
|
||||
|
||||
const kCheckSoftwareUpdateFinish = 'check_software_update_finish';
|
||||
const kCheckSoftwareUpdateFinish = 'check_software_update_finish';
|
||||
|
||||
@@ -179,6 +179,9 @@ class _OnlineStatusWidgetState extends State<OnlineStatusWidget> {
|
||||
stateGlobal.svcStatus.value = SvcStatus.notReady;
|
||||
}
|
||||
_svcIsUsingPublicServer.value = await bind.mainIsUsingPublicServer();
|
||||
try {
|
||||
stateGlobal.videoConnCount.value = status['video_conn_count'] as int;
|
||||
} catch (_) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,7 +362,7 @@ class _ConnectionPageState extends State<ConnectionPage>
|
||||
);
|
||||
}
|
||||
String textToFind = textEditingValue.text.toLowerCase();
|
||||
_autocompleteOpts = peers
|
||||
_autocompleteOpts = peers
|
||||
.where((peer) =>
|
||||
peer.id.toLowerCase().contains(textToFind) ||
|
||||
peer.username
|
||||
@@ -421,7 +424,7 @@ class _ConnectionPageState extends State<ConnectionPage>
|
||||
onSubmitted: (_) {
|
||||
onConnect();
|
||||
},
|
||||
));
|
||||
).workaroundFreezeLinuxMint());
|
||||
},
|
||||
onSelected: (option) {
|
||||
setState(() {
|
||||
|
||||
@@ -12,9 +12,9 @@ import 'package:flutter_hbb/consts.dart';
|
||||
import 'package:flutter_hbb/desktop/pages/connection_page.dart';
|
||||
import 'package:flutter_hbb/desktop/pages/desktop_setting_page.dart';
|
||||
import 'package:flutter_hbb/desktop/pages/desktop_tab_page.dart';
|
||||
import 'package:flutter_hbb/desktop/widgets/scroll_wrapper.dart';
|
||||
import 'package:flutter_hbb/models/platform_model.dart';
|
||||
import 'package:flutter_hbb/models/server_model.dart';
|
||||
import 'package:flutter_hbb/models/state_model.dart';
|
||||
import 'package:flutter_hbb/plugin/ui_manager.dart';
|
||||
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -35,12 +35,11 @@ class DesktopHomePage extends StatefulWidget {
|
||||
const borderColor = Color(0xFF2F65BA);
|
||||
|
||||
class _DesktopHomePageState extends State<DesktopHomePage>
|
||||
with AutomaticKeepAliveClientMixin {
|
||||
with AutomaticKeepAliveClientMixin, WidgetsBindingObserver {
|
||||
final _leftPaneScrollController = ScrollController();
|
||||
|
||||
@override
|
||||
bool get wantKeepAlive => true;
|
||||
var updateUrl = '';
|
||||
var systemError = '';
|
||||
StreamSubscription? _uniLinksSubscription;
|
||||
var svcStopped = false.obs;
|
||||
@@ -52,6 +51,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||
bool isCardClosed = false;
|
||||
|
||||
final RxBool _editHover = false.obs;
|
||||
final RxBool _block = false.obs;
|
||||
|
||||
final GlobalKey _childKey = GlobalKey();
|
||||
|
||||
@@ -59,14 +59,20 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
final isIncomingOnly = bind.isIncomingOnly();
|
||||
return Row(
|
||||
return _buildBlock(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
buildLeftPane(context),
|
||||
if (!isIncomingOnly) const VerticalDivider(width: 1),
|
||||
if (!isIncomingOnly) Expanded(child: buildRightPane(context)),
|
||||
],
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
Widget _buildBlock({required Widget child}) {
|
||||
return buildRemoteBlock(
|
||||
block: _block, mask: true, use: canBeBlocked, child: child);
|
||||
}
|
||||
|
||||
Widget buildLeftPane(BuildContext context) {
|
||||
@@ -87,7 +93,8 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||
if (!isOutgoingOnly) buildIDBoard(context),
|
||||
if (!isOutgoingOnly) buildPasswordBoard(context),
|
||||
FutureBuilder<Widget>(
|
||||
future: buildHelpCards(),
|
||||
future: Future.value(
|
||||
Obx(() => buildHelpCards(stateGlobal.updateUrl.value))),
|
||||
builder: (_, data) {
|
||||
if (data.hasData) {
|
||||
if (isIncomingOnly) {
|
||||
@@ -125,47 +132,43 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||
child: Container(
|
||||
width: isIncomingOnly ? 280.0 : 200.0,
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
child: DesktopScrollWrapper(
|
||||
scrollController: _leftPaneScrollController,
|
||||
child: Stack(
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
controller: _leftPaneScrollController,
|
||||
physics: DraggableNeverScrollableScrollPhysics(),
|
||||
child: Column(
|
||||
key: _childKey,
|
||||
children: children,
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
controller: _leftPaneScrollController,
|
||||
child: Column(
|
||||
key: _childKey,
|
||||
children: children,
|
||||
),
|
||||
if (isOutgoingOnly)
|
||||
Positioned(
|
||||
bottom: 6,
|
||||
left: 12,
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: InkWell(
|
||||
child: Obx(
|
||||
() => Icon(
|
||||
Icons.settings,
|
||||
color: _editHover.value
|
||||
? textColor
|
||||
: Colors.grey.withOpacity(0.5),
|
||||
size: 22,
|
||||
),
|
||||
),
|
||||
if (isOutgoingOnly)
|
||||
Positioned(
|
||||
bottom: 6,
|
||||
left: 12,
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: InkWell(
|
||||
child: Obx(
|
||||
() => Icon(
|
||||
Icons.settings,
|
||||
color: _editHover.value
|
||||
? textColor
|
||||
: Colors.grey.withOpacity(0.5),
|
||||
size: 22,
|
||||
),
|
||||
onTap: () => {
|
||||
if (DesktopSettingPage.tabKeys.isNotEmpty)
|
||||
{
|
||||
DesktopSettingPage.switch2page(
|
||||
DesktopSettingPage.tabKeys[0])
|
||||
}
|
||||
},
|
||||
onHover: (value) => _editHover.value = value,
|
||||
),
|
||||
onTap: () => {
|
||||
if (DesktopSettingPage.tabKeys.isNotEmpty)
|
||||
{
|
||||
DesktopSettingPage.switch2page(
|
||||
DesktopSettingPage.tabKeys[0])
|
||||
}
|
||||
},
|
||||
onHover: (value) => _editHover.value = value,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -234,7 +237,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||
style: TextStyle(
|
||||
fontSize: 22,
|
||||
),
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
)
|
||||
],
|
||||
@@ -330,7 +333,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||
EdgeInsets.only(top: 14, bottom: 10),
|
||||
),
|
||||
style: TextStyle(fontSize: 15),
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
),
|
||||
if (showOneTime)
|
||||
@@ -420,14 +423,14 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||
);
|
||||
}
|
||||
|
||||
Future<Widget> buildHelpCards() async {
|
||||
Widget buildHelpCards(String updateUrl) {
|
||||
if (!bind.isCustomClient() &&
|
||||
updateUrl.isNotEmpty &&
|
||||
!isCardClosed &&
|
||||
bind.mainUriPrefixSync().contains('rustdesk')) {
|
||||
return buildInstallCard(
|
||||
"Status",
|
||||
"There is a newer version of ${bind.mainGetAppNameSync()} ${bind.mainGetNewVersion()} available.",
|
||||
"${translate("new-version-of-{${bind.mainGetAppNameSync()}}-tip")} (${bind.mainGetNewVersion()}).",
|
||||
"Click to download", () async {
|
||||
final Uri url = Uri.parse('https://rustdesk.com/download');
|
||||
await launchUrl(url);
|
||||
@@ -674,20 +677,6 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
if (!bind.isCustomClient()) {
|
||||
platformFFI.registerEventHandler(
|
||||
kCheckSoftwareUpdateFinish, kCheckSoftwareUpdateFinish,
|
||||
(Map<String, dynamic> evt) async {
|
||||
if (evt['url'] is String) {
|
||||
setState(() {
|
||||
updateUrl = evt['url'];
|
||||
});
|
||||
}
|
||||
});
|
||||
Timer(const Duration(seconds: 1), () async {
|
||||
bind.mainGetSoftwareUpdateUrl();
|
||||
});
|
||||
}
|
||||
_updateTimer = periodic_immediate(const Duration(seconds: 1), () async {
|
||||
await gFFI.serverModel.fetchID();
|
||||
final error = await bind.mainGetError();
|
||||
@@ -823,6 +812,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||
_updateWindowSize();
|
||||
});
|
||||
}
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
}
|
||||
|
||||
_updateWindowSize() {
|
||||
@@ -848,9 +838,18 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||
platformFFI.unregisterEventHandler(
|
||||
kCheckSoftwareUpdateFinish, kCheckSoftwareUpdateFinish);
|
||||
}
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
super.didChangeAppLifecycleState(state);
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
shouldBeBlocked(_block, canBeBlocked);
|
||||
}
|
||||
}
|
||||
|
||||
Widget buildPluginEntry() {
|
||||
final entries = PluginUiManager.instance.entries.entries;
|
||||
return Offstage(
|
||||
@@ -941,7 +940,7 @@ void setPasswordDialog({VoidCallback? notEmptyCallback}) async {
|
||||
});
|
||||
},
|
||||
maxLength: maxLength,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -968,7 +967,7 @@ void setPasswordDialog({VoidCallback? notEmptyCallback}) async {
|
||||
});
|
||||
},
|
||||
maxLength: maxLength,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -11,15 +11,16 @@ import 'package:flutter_hbb/common/widgets/setting_widgets.dart';
|
||||
import 'package:flutter_hbb/consts.dart';
|
||||
import 'package:flutter_hbb/desktop/pages/desktop_home_page.dart';
|
||||
import 'package:flutter_hbb/desktop/pages/desktop_tab_page.dart';
|
||||
import 'package:flutter_hbb/mobile/widgets/dialog.dart';
|
||||
import 'package:flutter_hbb/models/platform_model.dart';
|
||||
import 'package:flutter_hbb/models/server_model.dart';
|
||||
import 'package:flutter_hbb/models/state_model.dart';
|
||||
import 'package:flutter_hbb/plugin/manager.dart';
|
||||
import 'package:flutter_hbb/plugin/widgets/desktop_settings.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
import 'package:flutter_hbb/desktop/widgets/scroll_wrapper.dart';
|
||||
|
||||
import '../../common/widgets/dialog.dart';
|
||||
import '../../common/widgets/login.dart';
|
||||
@@ -106,13 +107,20 @@ class DesktopSettingPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _DesktopSettingPageState extends State<DesktopSettingPage>
|
||||
with TickerProviderStateMixin, AutomaticKeepAliveClientMixin {
|
||||
with
|
||||
TickerProviderStateMixin,
|
||||
AutomaticKeepAliveClientMixin,
|
||||
WidgetsBindingObserver {
|
||||
late PageController controller;
|
||||
late Rx<SettingsTabKey> selectedTab;
|
||||
|
||||
@override
|
||||
bool get wantKeepAlive => true;
|
||||
|
||||
final RxBool _block = false.obs;
|
||||
final RxBool _canBeBlocked = false.obs;
|
||||
Timer? _videoConnTimer;
|
||||
|
||||
_DesktopSettingPageState(SettingsTabKey initialTabkey) {
|
||||
var initialIndex = DesktopSettingPage.tabKeys.indexOf(initialTabkey);
|
||||
if (initialIndex == -1) {
|
||||
@@ -132,11 +140,34 @@ class _DesktopSettingPageState extends State<DesktopSettingPage>
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
super.didChangeAppLifecycleState(state);
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
shouldBeBlocked(_block, canBeBlocked);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
_videoConnTimer =
|
||||
periodic_immediate(Duration(milliseconds: 1000), () async {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
_canBeBlocked.value = await canBeBlocked();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
Get.delete<PageController>(tag: _kSettingPageControllerTag);
|
||||
Get.delete<RxInt>(tag: _kSettingPageTabKeyTag);
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
_videoConnTimer?.cancel();
|
||||
}
|
||||
|
||||
List<_TabInfo> _settingTabs() {
|
||||
@@ -206,12 +237,35 @@ class _DesktopSettingPageState extends State<DesktopSettingPage>
|
||||
return children;
|
||||
}
|
||||
|
||||
Widget _buildBlock({required List<Widget> children}) {
|
||||
// check both mouseMoveTime and videoConnCount
|
||||
return Obx(() {
|
||||
final videoConnBlock =
|
||||
_canBeBlocked.value && stateGlobal.videoConnCount > 0;
|
||||
return Stack(children: [
|
||||
buildRemoteBlock(
|
||||
block: _block,
|
||||
mask: false,
|
||||
use: canBeBlocked,
|
||||
child: preventMouseKeyBuilder(
|
||||
child: Row(children: children),
|
||||
block: videoConnBlock,
|
||||
),
|
||||
),
|
||||
if (videoConnBlock)
|
||||
Container(
|
||||
color: Colors.black.withOpacity(0.5),
|
||||
)
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
return Scaffold(
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
body: Row(
|
||||
body: _buildBlock(
|
||||
children: <Widget>[
|
||||
SizedBox(
|
||||
width: _kTabWidth,
|
||||
@@ -226,13 +280,11 @@ class _DesktopSettingPageState extends State<DesktopSettingPage>
|
||||
Expanded(
|
||||
child: Container(
|
||||
color: Theme.of(context).scaffoldBackgroundColor,
|
||||
child: DesktopScrollWrapper(
|
||||
scrollController: controller,
|
||||
child: PageView(
|
||||
controller: controller,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
children: _children(),
|
||||
)),
|
||||
child: PageView(
|
||||
controller: controller,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
children: _children(),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
@@ -281,13 +333,10 @@ class _DesktopSettingPageState extends State<DesktopSettingPage>
|
||||
|
||||
Widget _listView({required List<_TabInfo> tabs}) {
|
||||
final scrollController = ScrollController();
|
||||
return DesktopScrollWrapper(
|
||||
scrollController: scrollController,
|
||||
child: ListView(
|
||||
physics: DraggableNeverScrollableScrollPhysics(),
|
||||
controller: scrollController,
|
||||
children: tabs.map((tab) => _listItem(tab: tab)).toList(),
|
||||
));
|
||||
return ListView(
|
||||
controller: scrollController,
|
||||
children: tabs.map((tab) => _listItem(tab: tab)).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _listItem({required _TabInfo tab}) {
|
||||
@@ -349,22 +398,19 @@ class _GeneralState extends State<_General> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scrollController = ScrollController();
|
||||
return DesktopScrollWrapper(
|
||||
scrollController: scrollController,
|
||||
child: ListView(
|
||||
physics: DraggableNeverScrollableScrollPhysics(),
|
||||
controller: scrollController,
|
||||
children: [
|
||||
if (!isWeb) service(),
|
||||
theme(),
|
||||
_Card(title: 'Language', children: [language()]),
|
||||
if (!isWeb) hwcodec(),
|
||||
if (!isWeb) audio(context),
|
||||
if (!isWeb) record(context),
|
||||
if (!isWeb) WaylandCard(),
|
||||
other()
|
||||
],
|
||||
).marginOnly(bottom: _kListViewBottomMargin));
|
||||
return ListView(
|
||||
controller: scrollController,
|
||||
children: [
|
||||
if (!isWeb) service(),
|
||||
theme(),
|
||||
_Card(title: 'Language', children: [language()]),
|
||||
if (!isWeb) hwcodec(),
|
||||
if (!isWeb) audio(context),
|
||||
if (!isWeb) record(context),
|
||||
if (!isWeb) WaylandCard(),
|
||||
other()
|
||||
],
|
||||
).marginOnly(bottom: _kListViewBottomMargin);
|
||||
}
|
||||
|
||||
Widget theme() {
|
||||
@@ -705,29 +751,26 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
return DesktopScrollWrapper(
|
||||
scrollController: scrollController,
|
||||
child: SingleChildScrollView(
|
||||
physics: DraggableNeverScrollableScrollPhysics(),
|
||||
controller: scrollController,
|
||||
child: Column(
|
||||
children: [
|
||||
_lock(locked, 'Unlock Security Settings', () {
|
||||
locked = false;
|
||||
setState(() => {});
|
||||
}),
|
||||
AbsorbPointer(
|
||||
absorbing: locked,
|
||||
child: Column(children: [
|
||||
permissions(context),
|
||||
password(context),
|
||||
_Card(title: '2FA', children: [tfa()]),
|
||||
_Card(title: 'ID', children: [changeId()]),
|
||||
more(context),
|
||||
]),
|
||||
),
|
||||
],
|
||||
)).marginOnly(bottom: _kListViewBottomMargin));
|
||||
return SingleChildScrollView(
|
||||
controller: scrollController,
|
||||
child: Column(
|
||||
children: [
|
||||
_lock(locked, 'Unlock Security Settings', () {
|
||||
locked = false;
|
||||
setState(() => {});
|
||||
}),
|
||||
preventMouseKeyBuilder(
|
||||
block: locked,
|
||||
child: Column(children: [
|
||||
permissions(context),
|
||||
password(context),
|
||||
_Card(title: '2FA', children: [tfa()]),
|
||||
_Card(title: 'ID', children: [changeId()]),
|
||||
more(context),
|
||||
]),
|
||||
),
|
||||
],
|
||||
)).marginOnly(bottom: _kListViewBottomMargin);
|
||||
}
|
||||
|
||||
Widget tfa() {
|
||||
@@ -1146,7 +1189,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
contentPadding:
|
||||
EdgeInsets.symmetric(vertical: 12, horizontal: 12),
|
||||
),
|
||||
).marginOnly(right: 15),
|
||||
).workaroundFreezeLinuxMint().marginOnly(right: 15),
|
||||
),
|
||||
Obx(() => ElevatedButton(
|
||||
onPressed: applyEnabled.value &&
|
||||
@@ -1303,7 +1346,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
contentPadding:
|
||||
EdgeInsets.symmetric(vertical: 12, horizontal: 12),
|
||||
),
|
||||
).marginOnly(right: 15),
|
||||
).workaroundFreezeLinuxMint().marginOnly(right: 15),
|
||||
),
|
||||
Obx(() => ElevatedButton(
|
||||
onPressed:
|
||||
@@ -1374,112 +1417,82 @@ class _NetworkState extends State<_Network> with AutomaticKeepAliveClientMixin {
|
||||
bool get wantKeepAlive => true;
|
||||
bool locked = !isWeb && bind.mainIsInstalled();
|
||||
|
||||
final scrollController = ScrollController();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
bool enabled = !locked;
|
||||
final scrollController = ScrollController();
|
||||
final hideServer =
|
||||
bind.mainGetBuildinOption(key: kOptionHideServerSetting) == 'Y';
|
||||
// TODO: support web proxy
|
||||
final hideProxy =
|
||||
isWeb || bind.mainGetBuildinOption(key: kOptionHideProxySetting) == 'Y';
|
||||
return DesktopScrollWrapper(
|
||||
scrollController: scrollController,
|
||||
child: ListView(
|
||||
controller: scrollController,
|
||||
physics: DraggableNeverScrollableScrollPhysics(),
|
||||
children: [
|
||||
_lock(locked, 'Unlock Network Settings', () {
|
||||
locked = false;
|
||||
setState(() => {});
|
||||
}),
|
||||
AbsorbPointer(
|
||||
absorbing: locked,
|
||||
child: Column(children: [
|
||||
if (!hideServer) server(enabled),
|
||||
if (!hideProxy)
|
||||
_Card(title: 'Proxy', children: [
|
||||
_Button('Socks5/Http(s) Proxy', changeSocks5Proxy,
|
||||
enabled: enabled),
|
||||
]),
|
||||
]),
|
||||
),
|
||||
]).marginOnly(bottom: _kListViewBottomMargin));
|
||||
return ListView(controller: scrollController, children: [
|
||||
_lock(locked, 'Unlock Network Settings', () {
|
||||
locked = false;
|
||||
setState(() => {});
|
||||
}),
|
||||
preventMouseKeyBuilder(
|
||||
block: locked,
|
||||
child: Column(children: [
|
||||
network(context),
|
||||
]),
|
||||
),
|
||||
]).marginOnly(bottom: _kListViewBottomMargin);
|
||||
}
|
||||
|
||||
server(bool enabled) {
|
||||
// Simple temp wrapper for PR check
|
||||
tmpWrapper() {
|
||||
// Setting page is not modal, oldOptions should only be used when getting options, never when setting.
|
||||
Map<String, dynamic> oldOptions = jsonDecode(bind.mainGetOptionsSync());
|
||||
old(String key) {
|
||||
return (oldOptions[key] ?? '').trim();
|
||||
}
|
||||
Widget network(BuildContext context) {
|
||||
final hideServer =
|
||||
bind.mainGetBuildinOption(key: kOptionHideServerSetting) == 'Y';
|
||||
final hideProxy =
|
||||
isWeb || bind.mainGetBuildinOption(key: kOptionHideProxySetting) == 'Y';
|
||||
|
||||
RxString idErrMsg = ''.obs;
|
||||
RxString relayErrMsg = ''.obs;
|
||||
RxString apiErrMsg = ''.obs;
|
||||
var idController =
|
||||
TextEditingController(text: old('custom-rendezvous-server'));
|
||||
var relayController = TextEditingController(text: old('relay-server'));
|
||||
var apiController = TextEditingController(text: old('api-server'));
|
||||
var keyController = TextEditingController(text: old('key'));
|
||||
final controllers = [
|
||||
idController,
|
||||
relayController,
|
||||
apiController,
|
||||
keyController,
|
||||
];
|
||||
final errMsgs = [
|
||||
idErrMsg,
|
||||
relayErrMsg,
|
||||
apiErrMsg,
|
||||
];
|
||||
|
||||
submit() async {
|
||||
bool result = await setServerConfig(
|
||||
null,
|
||||
errMsgs,
|
||||
ServerConfig(
|
||||
idServer: idController.text,
|
||||
relayServer: relayController.text,
|
||||
apiServer: apiController.text,
|
||||
key: keyController.text));
|
||||
if (result) {
|
||||
setState(() {});
|
||||
showToast(translate('Successful'));
|
||||
} else {
|
||||
showToast(translate('Failed'));
|
||||
}
|
||||
}
|
||||
|
||||
bool secure = !enabled;
|
||||
return _Card(
|
||||
title: 'ID/Relay Server',
|
||||
title_suffix: ServerConfigImportExportWidgets(controllers, errMsgs),
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
Obx(() => _LabeledTextField(context, 'ID Server', idController,
|
||||
idErrMsg.value, enabled, secure)),
|
||||
if (!isWeb)
|
||||
Obx(() => _LabeledTextField(context, 'Relay Server',
|
||||
relayController, relayErrMsg.value, enabled, secure)),
|
||||
Obx(() => _LabeledTextField(context, 'API Server',
|
||||
apiController, apiErrMsg.value, enabled, secure)),
|
||||
_LabeledTextField(
|
||||
context, 'Key', keyController, '', enabled, secure),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [_Button('Apply', submit, enabled: enabled)],
|
||||
).marginOnly(top: 10),
|
||||
],
|
||||
)
|
||||
]);
|
||||
if (hideServer && hideProxy) {
|
||||
return Offstage();
|
||||
}
|
||||
|
||||
return tmpWrapper();
|
||||
return _Card(
|
||||
title: 'Network',
|
||||
children: [
|
||||
Container(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (!hideServer)
|
||||
ListTile(
|
||||
leading: Icon(Icons.dns_outlined, color: _accentColor),
|
||||
title: Text(
|
||||
translate('ID/Relay Server'),
|
||||
style: TextStyle(fontSize: _kContentFontSize),
|
||||
),
|
||||
enabled: !locked,
|
||||
onTap: () => showServerSettings(gFFI.dialogManager),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 16),
|
||||
minLeadingWidth: 0,
|
||||
horizontalTitleGap: 10,
|
||||
),
|
||||
if (!hideServer && !hideProxy)
|
||||
Divider(height: 1, indent: 16, endIndent: 16),
|
||||
if (!hideProxy)
|
||||
ListTile(
|
||||
leading:
|
||||
Icon(Icons.network_ping_outlined, color: _accentColor),
|
||||
title: Text(
|
||||
translate('Socks5/Http(s) Proxy'),
|
||||
style: TextStyle(fontSize: _kContentFontSize),
|
||||
),
|
||||
enabled: !locked,
|
||||
onTap: changeSocks5Proxy,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 16),
|
||||
minLeadingWidth: 0,
|
||||
horizontalTitleGap: 10,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1494,19 +1507,14 @@ class _DisplayState extends State<_Display> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scrollController = ScrollController();
|
||||
return DesktopScrollWrapper(
|
||||
scrollController: scrollController,
|
||||
child: ListView(
|
||||
controller: scrollController,
|
||||
physics: DraggableNeverScrollableScrollPhysics(),
|
||||
children: [
|
||||
viewStyle(context),
|
||||
scrollStyle(context),
|
||||
imageQuality(context),
|
||||
codec(context),
|
||||
if (!isWeb) privacyModeImpl(context),
|
||||
other(context),
|
||||
]).marginOnly(bottom: _kListViewBottomMargin));
|
||||
return ListView(controller: scrollController, children: [
|
||||
viewStyle(context),
|
||||
scrollStyle(context),
|
||||
imageQuality(context),
|
||||
codec(context),
|
||||
if (!isWeb) privacyModeImpl(context),
|
||||
other(context),
|
||||
]).marginOnly(bottom: _kListViewBottomMargin);
|
||||
}
|
||||
|
||||
Widget viewStyle(BuildContext context) {
|
||||
@@ -1729,15 +1737,12 @@ class _AccountState extends State<_Account> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scrollController = ScrollController();
|
||||
return DesktopScrollWrapper(
|
||||
scrollController: scrollController,
|
||||
child: ListView(
|
||||
physics: DraggableNeverScrollableScrollPhysics(),
|
||||
controller: scrollController,
|
||||
children: [
|
||||
_Card(title: 'Account', children: [accountAction(), useInfo()]),
|
||||
],
|
||||
).marginOnly(bottom: _kListViewBottomMargin));
|
||||
return ListView(
|
||||
controller: scrollController,
|
||||
children: [
|
||||
_Card(title: 'Account', children: [accountAction(), useInfo()]),
|
||||
],
|
||||
).marginOnly(bottom: _kListViewBottomMargin);
|
||||
}
|
||||
|
||||
Widget accountAction() {
|
||||
@@ -1834,18 +1839,14 @@ class _PluginState extends State<_Plugin> {
|
||||
Widget build(BuildContext context) {
|
||||
bind.pluginListReload();
|
||||
final scrollController = ScrollController();
|
||||
return DesktopScrollWrapper(
|
||||
scrollController: scrollController,
|
||||
child: ChangeNotifierProvider.value(
|
||||
value: pluginManager,
|
||||
child: Consumer<PluginManager>(builder: (context, model, child) {
|
||||
return ListView(
|
||||
physics: DraggableNeverScrollableScrollPhysics(),
|
||||
controller: scrollController,
|
||||
children: model.plugins.map((entry) => pluginCard(entry)).toList(),
|
||||
).marginOnly(bottom: _kListViewBottomMargin);
|
||||
}),
|
||||
),
|
||||
return ChangeNotifierProvider.value(
|
||||
value: pluginManager,
|
||||
child: Consumer<PluginManager>(builder: (context, model, child) {
|
||||
return ListView(
|
||||
controller: scrollController,
|
||||
children: model.plugins.map((entry) => pluginCard(entry)).toList(),
|
||||
).marginOnly(bottom: _kListViewBottomMargin);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1897,75 +1898,72 @@ class _AboutState extends State<_About> {
|
||||
final fingerprint = data['fingerprint'].toString();
|
||||
const linkStyle = TextStyle(decoration: TextDecoration.underline);
|
||||
final scrollController = ScrollController();
|
||||
return DesktopScrollWrapper(
|
||||
scrollController: scrollController,
|
||||
child: SingleChildScrollView(
|
||||
controller: scrollController,
|
||||
physics: DraggableNeverScrollableScrollPhysics(),
|
||||
child: _Card(title: translate('About RustDesk'), children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 8.0,
|
||||
),
|
||||
SelectionArea(
|
||||
child: Text('${translate('Version')}: $version')
|
||||
.marginSymmetric(vertical: 4.0)),
|
||||
SelectionArea(
|
||||
child: Text('${translate('Build Date')}: $buildDate')
|
||||
.marginSymmetric(vertical: 4.0)),
|
||||
if (!isWeb)
|
||||
SelectionArea(
|
||||
child: Text('${translate('Fingerprint')}: $fingerprint')
|
||||
.marginSymmetric(vertical: 4.0)),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
launchUrlString('https://rustdesk.com/privacy.html');
|
||||
},
|
||||
child: Text(
|
||||
translate('Privacy Statement'),
|
||||
style: linkStyle,
|
||||
).marginSymmetric(vertical: 4.0)),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
launchUrlString('https://rustdesk.com');
|
||||
},
|
||||
child: Text(
|
||||
translate('Website'),
|
||||
style: linkStyle,
|
||||
).marginSymmetric(vertical: 4.0)),
|
||||
Container(
|
||||
decoration: const BoxDecoration(color: Color(0xFF2c8cff)),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 24, horizontal: 8),
|
||||
child: SelectionArea(
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Copyright © ${DateTime.now().toString().substring(0, 4)} Purslane Ltd.\n$license',
|
||||
style: const TextStyle(color: Colors.white),
|
||||
),
|
||||
Text(
|
||||
translate('Slogan_tip'),
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w800,
|
||||
color: Colors.white),
|
||||
)
|
||||
],
|
||||
return SingleChildScrollView(
|
||||
controller: scrollController,
|
||||
child: _Card(title: translate('About RustDesk'), children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 8.0,
|
||||
),
|
||||
SelectionArea(
|
||||
child: Text('${translate('Version')}: $version')
|
||||
.marginSymmetric(vertical: 4.0)),
|
||||
SelectionArea(
|
||||
child: Text('${translate('Build Date')}: $buildDate')
|
||||
.marginSymmetric(vertical: 4.0)),
|
||||
if (!isWeb)
|
||||
SelectionArea(
|
||||
child: Text('${translate('Fingerprint')}: $fingerprint')
|
||||
.marginSymmetric(vertical: 4.0)),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
launchUrlString('https://rustdesk.com/privacy.html');
|
||||
},
|
||||
child: Text(
|
||||
translate('Privacy Statement'),
|
||||
style: linkStyle,
|
||||
).marginSymmetric(vertical: 4.0)),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
launchUrlString('https://rustdesk.com');
|
||||
},
|
||||
child: Text(
|
||||
translate('Website'),
|
||||
style: linkStyle,
|
||||
).marginSymmetric(vertical: 4.0)),
|
||||
Container(
|
||||
decoration: const BoxDecoration(color: Color(0xFF2c8cff)),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 24, horizontal: 8),
|
||||
child: SelectionArea(
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Copyright © ${DateTime.now().toString().substring(0, 4)} Purslane Ltd.\n$license',
|
||||
style: const TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
],
|
||||
)),
|
||||
).marginSymmetric(vertical: 4.0)
|
||||
],
|
||||
).marginOnly(left: _kContentHMargin)
|
||||
]),
|
||||
));
|
||||
Text(
|
||||
translate('Slogan_tip'),
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w800,
|
||||
color: Colors.white),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
)),
|
||||
).marginSymmetric(vertical: 4.0)
|
||||
],
|
||||
).marginOnly(left: _kContentHMargin)
|
||||
]),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -2283,26 +2281,39 @@ _LabeledTextField(
|
||||
String errorText,
|
||||
bool enabled,
|
||||
bool secure) {
|
||||
return Row(
|
||||
return Table(
|
||||
columnWidths: const {
|
||||
0: FixedColumnWidth(150),
|
||||
1: FlexColumnWidth(),
|
||||
},
|
||||
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(minWidth: 140),
|
||||
child: Text(
|
||||
'${translate(label)}:',
|
||||
textAlign: TextAlign.right,
|
||||
style: TextStyle(
|
||||
fontSize: 16, color: disabledTextColor(context, enabled)),
|
||||
).marginOnly(right: 10)),
|
||||
Expanded(
|
||||
child: TextField(
|
||||
TableRow(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 10),
|
||||
child: Text(
|
||||
'${translate(label)}:',
|
||||
textAlign: TextAlign.right,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: disabledTextColor(context, enabled),
|
||||
),
|
||||
),
|
||||
),
|
||||
TextField(
|
||||
controller: controller,
|
||||
enabled: enabled,
|
||||
obscureText: secure,
|
||||
autocorrect: false,
|
||||
decoration: InputDecoration(
|
||||
errorText: errorText.isNotEmpty ? errorText : null),
|
||||
errorText: errorText.isNotEmpty ? errorText : null,
|
||||
),
|
||||
style: TextStyle(
|
||||
color: disabledTextColor(context, enabled),
|
||||
)),
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
],
|
||||
),
|
||||
],
|
||||
).marginOnly(bottom: 8);
|
||||
@@ -2480,7 +2491,7 @@ void changeSocks5Proxy() async {
|
||||
controller: proxyController,
|
||||
autofocus: true,
|
||||
enabled: !isOptFixed,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
).marginOnly(bottom: 8),
|
||||
@@ -2500,7 +2511,7 @@ void changeSocks5Proxy() async {
|
||||
labelText: isMobile ? translate('Username') : null,
|
||||
),
|
||||
enabled: !isOptFixed,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
).marginOnly(bottom: 8),
|
||||
@@ -2526,7 +2537,7 @@ void changeSocks5Proxy() async {
|
||||
controller: pwdController,
|
||||
enabled: !isOptFixed,
|
||||
maxLength: bind.mainMaxEncryptLen(),
|
||||
)),
|
||||
).workaroundFreezeLinuxMint()),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -37,13 +37,9 @@ class DesktopTabPage extends StatefulWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class _DesktopTabPageState extends State<DesktopTabPage>
|
||||
with WidgetsBindingObserver {
|
||||
class _DesktopTabPageState extends State<DesktopTabPage> {
|
||||
final tabController = DesktopTabController(tabType: DesktopTabType.main);
|
||||
|
||||
final RxBool _block = false.obs;
|
||||
// bool mouseIn = false;
|
||||
|
||||
_DesktopTabPageState() {
|
||||
RemoteCountState.init();
|
||||
Get.put<DesktopTabController>(tabController);
|
||||
@@ -69,19 +65,10 @@ class _DesktopTabPageState extends State<DesktopTabPage>
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
super.didChangeAppLifecycleState(state);
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
shouldBeBlocked(_block, canBeBlocked);
|
||||
} else if (state == AppLifecycleState.inactive) {}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// HardwareKeyboard.instance.addHandler(_handleKeyEvent);
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -97,7 +84,6 @@ class _DesktopTabPageState extends State<DesktopTabPage>
|
||||
@override
|
||||
void dispose() {
|
||||
// HardwareKeyboard.instance.removeHandler(_handleKeyEvent);
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
Get.delete<DesktopTabController>();
|
||||
|
||||
super.dispose();
|
||||
@@ -119,7 +105,6 @@ class _DesktopTabPageState extends State<DesktopTabPage>
|
||||
isClose: false,
|
||||
),
|
||||
),
|
||||
blockTab: _block,
|
||||
)));
|
||||
return isMacOS || kUseCompatibleUiMode
|
||||
? tabWidget
|
||||
|
||||
@@ -768,7 +768,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
||||
),
|
||||
controller: name,
|
||||
autofocus: true,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
@@ -1657,7 +1657,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
||||
onChanged: _locationStatus.value == LocationStatus.fileSearchBar
|
||||
? (searchText) => onSearchText(searchText, isLocal)
|
||||
: null,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
)
|
||||
],
|
||||
);
|
||||
|
||||
@@ -147,7 +147,7 @@ class _InstallPageBodyState extends State<_InstallPageBody>
|
||||
decoration: InputDecoration(
|
||||
contentPadding: EdgeInsets.all(0.75 * em),
|
||||
),
|
||||
).marginOnly(right: 10),
|
||||
).workaroundFreezeLinuxMint().marginOnly(right: 10),
|
||||
),
|
||||
Obx(
|
||||
() => OutlinedButton.icon(
|
||||
|
||||
@@ -238,7 +238,7 @@ class _PortForwardPageState extends State<PortForwardPage>
|
||||
inputFormatters: inputFormatters,
|
||||
decoration: InputDecoration(
|
||||
hintText: hint,
|
||||
))),
|
||||
)).workaroundFreezeLinuxMint()),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wakelock_plus/wakelock_plus.dart';
|
||||
import 'package:flutter_improved_scrolling/flutter_improved_scrolling.dart';
|
||||
import 'package:flutter_hbb/models/state_model.dart';
|
||||
|
||||
import '../../consts.dart';
|
||||
@@ -742,12 +741,6 @@ class _ImagePaintState extends State<ImagePaint> {
|
||||
ScrollController horizontal,
|
||||
ScrollController vertical,
|
||||
) {
|
||||
final scrollConfig = CustomMouseWheelScrollConfig(
|
||||
scrollDuration: kDefaultScrollDuration,
|
||||
scrollCurve: Curves.linearToEaseOut,
|
||||
mouseWheelTurnsThrottleTimeMs:
|
||||
kDefaultMouseWheelThrottleDuration.inMilliseconds,
|
||||
scrollAmountMultiplier: kDefaultScrollAmountMultiplier);
|
||||
var widget = child;
|
||||
if (layoutSize.width < size.width) {
|
||||
widget = ScrollConfiguration(
|
||||
@@ -793,36 +786,26 @@ class _ImagePaintState extends State<ImagePaint> {
|
||||
);
|
||||
}
|
||||
if (layoutSize.width < size.width) {
|
||||
widget = ImprovedScrolling(
|
||||
scrollController: horizontal,
|
||||
enableCustomMouseWheelScrolling: cursorOverImage.isFalse,
|
||||
customMouseWheelScrollConfig: scrollConfig,
|
||||
child: RawScrollbar(
|
||||
thickness: kScrollbarThickness,
|
||||
thumbColor: Colors.grey,
|
||||
controller: horizontal,
|
||||
thumbVisibility: false,
|
||||
trackVisibility: false,
|
||||
notificationPredicate: layoutSize.height < size.height
|
||||
? (notification) => notification.depth == 1
|
||||
: defaultScrollNotificationPredicate,
|
||||
child: widget,
|
||||
),
|
||||
widget = RawScrollbar(
|
||||
thickness: kScrollbarThickness,
|
||||
thumbColor: Colors.grey,
|
||||
controller: horizontal,
|
||||
thumbVisibility: false,
|
||||
trackVisibility: false,
|
||||
notificationPredicate: layoutSize.height < size.height
|
||||
? (notification) => notification.depth == 1
|
||||
: defaultScrollNotificationPredicate,
|
||||
child: widget,
|
||||
);
|
||||
}
|
||||
if (layoutSize.height < size.height) {
|
||||
widget = ImprovedScrolling(
|
||||
scrollController: vertical,
|
||||
enableCustomMouseWheelScrolling: cursorOverImage.isFalse,
|
||||
customMouseWheelScrollConfig: scrollConfig,
|
||||
child: RawScrollbar(
|
||||
thickness: kScrollbarThickness,
|
||||
thumbColor: Colors.grey,
|
||||
controller: vertical,
|
||||
thumbVisibility: false,
|
||||
trackVisibility: false,
|
||||
child: widget,
|
||||
),
|
||||
widget = RawScrollbar(
|
||||
thickness: kScrollbarThickness,
|
||||
thumbColor: Colors.grey,
|
||||
controller: vertical,
|
||||
thumbVisibility: false,
|
||||
trackVisibility: false,
|
||||
child: widget,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +110,8 @@ class ConnectionManager extends StatefulWidget {
|
||||
|
||||
class ConnectionManagerState extends State<ConnectionManager>
|
||||
with WidgetsBindingObserver {
|
||||
final RxBool _block = false.obs;
|
||||
final RxBool _controlPageBlock = false.obs;
|
||||
final RxBool _sidePageBlock = false.obs;
|
||||
|
||||
ConnectionManagerState() {
|
||||
gFFI.serverModel.tabController.onSelected = (client_id_str) {
|
||||
@@ -139,7 +140,8 @@ class ConnectionManagerState extends State<ConnectionManager>
|
||||
super.didChangeAppLifecycleState(state);
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
if (!allowRemoteCMModification()) {
|
||||
shouldBeBlocked(_block, null);
|
||||
shouldBeBlocked(_controlPageBlock, null);
|
||||
shouldBeBlocked(_sidePageBlock, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -192,7 +194,6 @@ class ConnectionManagerState extends State<ConnectionManager>
|
||||
selectedBorderColor: MyTheme.accent,
|
||||
maxLabelWidth: 100,
|
||||
tail: null, //buildScrollJumper(),
|
||||
blockTab: allowRemoteCMModification() ? null : _block,
|
||||
tabBuilder: (key, icon, label, themeConf) {
|
||||
final client = serverModel.clients
|
||||
.firstWhereOrNull((client) => client.id.toString() == key);
|
||||
@@ -237,13 +238,20 @@ class ConnectionManagerState extends State<ConnectionManager>
|
||||
? buildSidePage()
|
||||
: buildRemoteBlock(
|
||||
child: buildSidePage(),
|
||||
block: _block,
|
||||
block: _sidePageBlock,
|
||||
mask: true),
|
||||
)),
|
||||
SizedBox(
|
||||
width: realClosedWidth,
|
||||
child:
|
||||
SizedBox(width: realClosedWidth, child: pageView)),
|
||||
child: SizedBox(
|
||||
width: realClosedWidth,
|
||||
child: allowRemoteCMModification()
|
||||
? pageView
|
||||
: buildRemoteBlock(
|
||||
child: _buildKeyEventBlock(pageView),
|
||||
block: _controlPageBlock,
|
||||
mask: false,
|
||||
))),
|
||||
]);
|
||||
return Container(
|
||||
color: Theme.of(context).scaffoldBackgroundColor,
|
||||
@@ -268,6 +276,10 @@ class ConnectionManagerState extends State<ConnectionManager>
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildKeyEventBlock(Widget child) {
|
||||
return ExcludeFocus(child: child, excluding: true);
|
||||
}
|
||||
|
||||
Widget buildTitleBar() {
|
||||
return SizedBox(
|
||||
height: kDesktopRemoteTabBarHeight,
|
||||
|
||||
@@ -1495,7 +1495,7 @@ class _ResolutionsMenuState extends State<_ResolutionsMenu> {
|
||||
);
|
||||
}
|
||||
|
||||
TextField _resolutionInput(TextEditingController controller) {
|
||||
Widget _resolutionInput(TextEditingController controller) {
|
||||
return TextField(
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
@@ -1509,7 +1509,7 @@ class _ResolutionsMenuState extends State<_ResolutionsMenu> {
|
||||
FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
|
||||
],
|
||||
controller: controller,
|
||||
);
|
||||
).workaroundFreezeLinuxMint();
|
||||
}
|
||||
|
||||
List<Widget> _supportedResolutionMenuButtons() => resolutions
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_hbb/consts.dart';
|
||||
import 'package:flutter_improved_scrolling/flutter_improved_scrolling.dart';
|
||||
|
||||
class DesktopScrollWrapper extends StatelessWidget {
|
||||
final ScrollController scrollController;
|
||||
final Widget child;
|
||||
const DesktopScrollWrapper(
|
||||
{Key? key, required this.scrollController, required this.child})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ImprovedScrolling(
|
||||
scrollController: scrollController,
|
||||
enableCustomMouseWheelScrolling: true,
|
||||
// enableKeyboardScrolling: true, // strange behavior on mac
|
||||
customMouseWheelScrollConfig: CustomMouseWheelScrollConfig(
|
||||
scrollDuration: kDefaultScrollDuration,
|
||||
scrollCurve: Curves.linearToEaseOut,
|
||||
mouseWheelTurnsThrottleTimeMs:
|
||||
kDefaultMouseWheelThrottleDuration.inMilliseconds,
|
||||
scrollAmountMultiplier: kDefaultScrollAmountMultiplier),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -246,7 +246,6 @@ class DesktopTab extends StatefulWidget {
|
||||
final Color? selectedTabBackgroundColor;
|
||||
final Color? unSelectedTabBackgroundColor;
|
||||
final Color? selectedBorderColor;
|
||||
final RxBool? blockTab;
|
||||
|
||||
final DesktopTabController controller;
|
||||
|
||||
@@ -272,7 +271,6 @@ class DesktopTab extends StatefulWidget {
|
||||
this.selectedTabBackgroundColor,
|
||||
this.unSelectedTabBackgroundColor,
|
||||
this.selectedBorderColor,
|
||||
this.blockTab,
|
||||
}) : super(key: key);
|
||||
|
||||
static RxString tablabelGetter(String peerId) {
|
||||
@@ -311,7 +309,6 @@ class _DesktopTabState extends State<DesktopTab>
|
||||
Color? get unSelectedTabBackgroundColor =>
|
||||
widget.unSelectedTabBackgroundColor;
|
||||
Color? get selectedBorderColor => widget.selectedBorderColor;
|
||||
RxBool? get blockTab => widget.blockTab;
|
||||
DesktopTabController get controller => widget.controller;
|
||||
RxList<String> get invisibleTabKeys => widget.invisibleTabKeys;
|
||||
Debouncer get _scrollDebounce => widget._scrollDebounce;
|
||||
@@ -533,21 +530,9 @@ class _DesktopTabState extends State<DesktopTab>
|
||||
]);
|
||||
}
|
||||
|
||||
Widget _buildBlock({required Widget child}) {
|
||||
if (blockTab != null) {
|
||||
return buildRemoteBlock(
|
||||
child: child,
|
||||
block: blockTab!,
|
||||
use: canBeBlocked,
|
||||
mask: tabType == DesktopTabType.main);
|
||||
} else {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
List<Widget> _tabWidgets = [];
|
||||
Widget _buildPageView() {
|
||||
final child = _buildBlock(
|
||||
final child = Container(
|
||||
child: Obx(() => PageView(
|
||||
controller: state.value.pageController,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
|
||||
@@ -120,6 +120,7 @@ Future<void> initEnv(String appType) async {
|
||||
void runMainApp(bool startService) async {
|
||||
// register uni links
|
||||
await initEnv(kAppTypeMain);
|
||||
checkUpdate();
|
||||
// trigger connection status updater
|
||||
await bind.mainCheckConnectStatus();
|
||||
if (startService) {
|
||||
@@ -156,6 +157,7 @@ void runMainApp(bool startService) async {
|
||||
|
||||
void runMobileApp() async {
|
||||
await initEnv(kAppTypeMain);
|
||||
checkUpdate();
|
||||
if (isAndroid) androidChannelInit();
|
||||
if (isAndroid) platformFFI.syncAndroidServiceAppDirConfigPath();
|
||||
draggablePositions.load();
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:auto_size_text_field/auto_size_text_field.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hbb/common/formatter/id_formatter.dart';
|
||||
import 'package:flutter_hbb/common/widgets/connection_page_title.dart';
|
||||
import 'package:flutter_hbb/models/state_model.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
@@ -40,8 +41,6 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
||||
final _idController = IDTextEditingController();
|
||||
final RxBool _idEmpty = true.obs;
|
||||
|
||||
/// Update url. If it's not null, means an update is available.
|
||||
var _updateUrl = '';
|
||||
List<Peer> peers = [];
|
||||
|
||||
bool isPeersLoading = false;
|
||||
@@ -72,22 +71,6 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
||||
}
|
||||
});
|
||||
}
|
||||
if (isAndroid) {
|
||||
if (!bind.isCustomClient()) {
|
||||
platformFFI.registerEventHandler(
|
||||
kCheckSoftwareUpdateFinish, kCheckSoftwareUpdateFinish,
|
||||
(Map<String, dynamic> evt) async {
|
||||
if (evt['url'] is String) {
|
||||
setState(() {
|
||||
_updateUrl = evt['url'];
|
||||
});
|
||||
}
|
||||
});
|
||||
Timer(const Duration(seconds: 1), () async {
|
||||
bind.mainGetSoftwareUpdateUrl();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -97,7 +80,8 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
||||
slivers: [
|
||||
SliverList(
|
||||
delegate: SliverChildListDelegate([
|
||||
if (!bind.isCustomClient()) _buildUpdateUI(),
|
||||
if (!bind.isCustomClient())
|
||||
Obx(() => _buildUpdateUI(stateGlobal.updateUrl.value)),
|
||||
_buildRemoteIDTextField(),
|
||||
])),
|
||||
SliverFillRemaining(
|
||||
@@ -116,13 +100,21 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
||||
}
|
||||
|
||||
/// UI for software update.
|
||||
/// If [_updateUrl] is not empty, shows a button to update the software.
|
||||
Widget _buildUpdateUI() {
|
||||
return _updateUrl.isEmpty
|
||||
/// If _updateUrl] is not empty, shows a button to update the software.
|
||||
Widget _buildUpdateUI(String updateUrl) {
|
||||
return updateUrl.isEmpty
|
||||
? const SizedBox(height: 0)
|
||||
: InkWell(
|
||||
onTap: () async {
|
||||
final url = 'https://rustdesk.com/download';
|
||||
// https://pub.dev/packages/url_launcher#configuration
|
||||
// https://developer.android.com/training/package-visibility/use-cases#open-urls-custom-tabs
|
||||
//
|
||||
// `await launchUrl(Uri.parse(url))` can also run if skip
|
||||
// 1. The following check
|
||||
// 2. `<action android:name="android.support.customtabs.action.CustomTabsService" />` in AndroidManifest.xml
|
||||
//
|
||||
// But it is better to add the check.
|
||||
if (await canLaunchUrl(Uri.parse(url))) {
|
||||
await launchUrl(Uri.parse(url));
|
||||
}
|
||||
|
||||
@@ -225,7 +225,7 @@ class _FileManagerPageState extends State<FileManagerPage> {
|
||||
errorText: errorText,
|
||||
),
|
||||
controller: name,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
|
||||
@@ -147,6 +147,19 @@ class _RemotePageState extends State<RemotePage> with WidgetsBindingObserver {
|
||||
gFFI.chatModel.onVoiceCallClosed("End connetion");
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
trySyncClipboard();
|
||||
}
|
||||
}
|
||||
|
||||
// For client side
|
||||
// When swithing from other app to this app, try to sync clipboard.
|
||||
void trySyncClipboard() {
|
||||
gFFI.invokeMethod("try_sync_clipboard");
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeMetrics() {
|
||||
// If the soft keyboard is visible and the canvas has been changed(panned or scaled)
|
||||
@@ -591,7 +604,7 @@ class _RemotePageState extends State<RemotePage> with WidgetsBindingObserver {
|
||||
// ko/zh/ja input method: the button will trigger `onKeyEvent`
|
||||
// and the event will not popup if `KeyEventResult.handled` is returned.
|
||||
onChanged: handleSoftKeyboardInput,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
];
|
||||
if (showCursorPaint) {
|
||||
@@ -872,6 +885,8 @@ class _KeyHelpToolsState extends State<KeyHelpTools> {
|
||||
|
||||
final pi = gFFI.ffiModel.pi;
|
||||
final isMac = pi.platform == kPeerPlatformMacOS;
|
||||
final isWin = pi.platform == kPeerPlatformWindows;
|
||||
final isLinux = pi.platform == kPeerPlatformLinux;
|
||||
final modifiers = <Widget>[
|
||||
wrap('Ctrl ', () {
|
||||
setState(() => inputModel.ctrl = !inputModel.ctrl);
|
||||
@@ -952,6 +967,28 @@ class _KeyHelpToolsState extends State<KeyHelpTools> {
|
||||
wrap('PgDn', () {
|
||||
inputModel.inputKey('VK_NEXT');
|
||||
}),
|
||||
// to-do: support PrtScr on Mac
|
||||
if (isWin || isLinux)
|
||||
wrap('PrtScr', () {
|
||||
inputModel.inputKey('VK_SNAPSHOT');
|
||||
}),
|
||||
if (isWin || isLinux)
|
||||
wrap('ScrollLock', () {
|
||||
inputModel.inputKey('VK_SCROLL');
|
||||
}),
|
||||
if (isWin || isLinux)
|
||||
wrap('Pause', () {
|
||||
inputModel.inputKey('VK_PAUSE');
|
||||
}),
|
||||
if (isWin || isLinux)
|
||||
// Maybe it's better to call it "Menu"
|
||||
// https://en.wikipedia.org/wiki/Menu_key
|
||||
wrap('Menu', () {
|
||||
inputModel.inputKey('Apps');
|
||||
}),
|
||||
wrap('Enter', () {
|
||||
inputModel.inputKey('VK_ENTER');
|
||||
}),
|
||||
SizedBox(width: 9999),
|
||||
wrap('', () {
|
||||
inputModel.inputKey('VK_LEFT');
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'dart:typed_data';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hbb/common/widgets/setting_widgets.dart';
|
||||
import 'package:flutter_hbb/desktop/pages/desktop_setting_page.dart';
|
||||
import 'package:flutter_hbb/models/state_model.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:settings_ui/settings_ui.dart';
|
||||
@@ -70,6 +71,7 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
|
||||
false; //androidVersion >= 26; // remove because not work on every device
|
||||
var _ignoreBatteryOpt = false;
|
||||
var _enableStartOnBoot = false;
|
||||
var _checkUpdateOnStartup = false;
|
||||
var _floatingWindowDisabled = false;
|
||||
var _keepScreenOn = KeepScreenOn.duringControlled; // relay on floating window
|
||||
var _enableAbr = false;
|
||||
@@ -154,6 +156,13 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
|
||||
_enableStartOnBoot = enableStartOnBoot;
|
||||
}
|
||||
|
||||
var checkUpdateOnStartup =
|
||||
mainGetLocalBoolOptionSync(kOptionEnableCheckUpdate);
|
||||
if (checkUpdateOnStartup != _checkUpdateOnStartup) {
|
||||
update = true;
|
||||
_checkUpdateOnStartup = checkUpdateOnStartup;
|
||||
}
|
||||
|
||||
var floatingWindowDisabled =
|
||||
bind.mainGetLocalOption(key: kOptionDisableFloatingWindow) == "Y" ||
|
||||
!await AndroidPermissionManager.check(kSystemAlertWindow);
|
||||
@@ -552,6 +561,22 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
|
||||
gFFI.invokeMethod(AndroidChannel.kSetStartOnBootOpt, toValue);
|
||||
}));
|
||||
|
||||
if (!bind.isCustomClient()) {
|
||||
enhancementsTiles.add(
|
||||
SettingsTile.switchTile(
|
||||
initialValue: _checkUpdateOnStartup,
|
||||
title:
|
||||
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
Text(translate('Check for software update on startup')),
|
||||
]),
|
||||
onToggle: (bool toValue) async {
|
||||
await mainSetLocalBoolOption(kOptionEnableCheckUpdate, toValue);
|
||||
setState(() => _checkUpdateOnStartup = toValue);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
onFloatingWindowChanged(bool toValue) async {
|
||||
if (toValue) {
|
||||
if (!await AndroidPermissionManager.check(kSystemAlertWindow)) {
|
||||
@@ -828,11 +853,6 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
|
||||
}
|
||||
}
|
||||
|
||||
void showServerSettings(OverlayDialogManager dialogManager) async {
|
||||
Map<String, dynamic> options = jsonDecode(await bind.mainGetOptions());
|
||||
showServerSettingsWithValue(ServerConfig.fromOptions(options), dialogManager);
|
||||
}
|
||||
|
||||
void showLanguageSettings(OverlayDialogManager dialogManager) async {
|
||||
try {
|
||||
final langs = json.decode(await bind.mainGetLangs()) as List<dynamic>;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hbb/common/widgets/setting_widgets.dart';
|
||||
import 'package:flutter_hbb/common/widgets/toolbar.dart';
|
||||
@@ -65,7 +66,7 @@ void setPermanentPasswordDialog(OverlayDialogManager dialogManager) async {
|
||||
? null
|
||||
: translate('Too short, at least 6 characters.');
|
||||
},
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
TextFormField(
|
||||
obscureText: true,
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
@@ -84,7 +85,7 @@ void setPermanentPasswordDialog(OverlayDialogManager dialogManager) async {
|
||||
? null
|
||||
: translate('The confirmation is not identical.');
|
||||
},
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
])),
|
||||
onCancel: close,
|
||||
onSubmit: (validateLength && validateSame) ? submit : null,
|
||||
@@ -146,6 +147,16 @@ void setTemporaryPasswordLengthDialog(
|
||||
}, backDismiss: true, clickMaskDismiss: true);
|
||||
}
|
||||
|
||||
void showServerSettings(OverlayDialogManager dialogManager) async {
|
||||
Map<String, dynamic> options = {};
|
||||
try {
|
||||
options = jsonDecode(await bind.mainGetOptions());
|
||||
} catch (e) {
|
||||
print("Invalid server config: $e");
|
||||
}
|
||||
showServerSettingsWithValue(ServerConfig.fromOptions(options), dialogManager);
|
||||
}
|
||||
|
||||
void showServerSettingsWithValue(
|
||||
ServerConfig serverConfig, OverlayDialogManager dialogManager) async {
|
||||
var isInProgress = false;
|
||||
@@ -184,6 +195,43 @@ void showServerSettingsWithValue(
|
||||
return ret;
|
||||
}
|
||||
|
||||
Widget buildField(
|
||||
String label, TextEditingController controller, String errorMsg,
|
||||
{String? Function(String?)? validator, bool autofocus = false}) {
|
||||
if (isDesktop || isWeb) {
|
||||
return Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 120,
|
||||
child: Text(label),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
controller: controller,
|
||||
decoration: InputDecoration(
|
||||
errorText: errorMsg.isEmpty ? null : errorMsg,
|
||||
contentPadding:
|
||||
EdgeInsets.symmetric(horizontal: 8, vertical: 12),
|
||||
),
|
||||
validator: validator,
|
||||
autofocus: autofocus,
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
return TextFormField(
|
||||
controller: controller,
|
||||
decoration: InputDecoration(
|
||||
labelText: label,
|
||||
errorText: errorMsg.isEmpty ? null : errorMsg,
|
||||
),
|
||||
validator: validator,
|
||||
).workaroundFreezeLinuxMint();
|
||||
}
|
||||
|
||||
return CustomAlertDialog(
|
||||
title: Row(
|
||||
children: [
|
||||
@@ -191,56 +239,45 @@ void showServerSettingsWithValue(
|
||||
...ServerConfigImportExportWidgets(controllers, errMsgs),
|
||||
],
|
||||
),
|
||||
content: Form(
|
||||
content: ConstrainedBox(
|
||||
constraints: const BoxConstraints(minWidth: 500),
|
||||
child: Form(
|
||||
child: Obx(() => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
TextFormField(
|
||||
controller: idCtrl,
|
||||
decoration: InputDecoration(
|
||||
labelText: translate('ID Server'),
|
||||
errorText: idServerMsg.value.isEmpty
|
||||
? null
|
||||
: idServerMsg.value),
|
||||
)
|
||||
] +
|
||||
[
|
||||
if (isAndroid)
|
||||
TextFormField(
|
||||
controller: relayCtrl,
|
||||
decoration: InputDecoration(
|
||||
labelText: translate('Relay Server'),
|
||||
errorText: relayServerMsg.value.isEmpty
|
||||
? null
|
||||
: relayServerMsg.value),
|
||||
)
|
||||
] +
|
||||
[
|
||||
TextFormField(
|
||||
controller: apiCtrl,
|
||||
decoration: InputDecoration(
|
||||
labelText: translate('API Server'),
|
||||
),
|
||||
autovalidateMode: AutovalidateMode.onUserInteraction,
|
||||
validator: (v) {
|
||||
if (v != null && v.isNotEmpty) {
|
||||
if (!(v.startsWith('http://') ||
|
||||
v.startsWith("https://"))) {
|
||||
return translate("invalid_http");
|
||||
}
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
buildField(translate('ID Server'), idCtrl, idServerMsg.value,
|
||||
autofocus: true),
|
||||
SizedBox(height: 8),
|
||||
if (!isIOS && !isWeb) ...[
|
||||
buildField(translate('Relay Server'), relayCtrl,
|
||||
relayServerMsg.value),
|
||||
SizedBox(height: 8),
|
||||
],
|
||||
buildField(
|
||||
translate('API Server'),
|
||||
apiCtrl,
|
||||
apiServerMsg.value,
|
||||
validator: (v) {
|
||||
if (v != null && v.isNotEmpty) {
|
||||
if (!(v.startsWith('http://') ||
|
||||
v.startsWith("https://"))) {
|
||||
return translate("invalid_http");
|
||||
}
|
||||
return null;
|
||||
},
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
buildField('Key', keyCtrl, ''),
|
||||
if (isInProgress)
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 8),
|
||||
child: LinearProgressIndicator(),
|
||||
),
|
||||
TextFormField(
|
||||
controller: keyCtrl,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Key',
|
||||
),
|
||||
),
|
||||
// NOT use Offstage to wrap LinearProgressIndicator
|
||||
if (isInProgress) const LinearProgressIndicator(),
|
||||
]))),
|
||||
],
|
||||
)),
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
dialogButton('Cancel', onPressed: () {
|
||||
close();
|
||||
|
||||
@@ -648,6 +648,9 @@ class AbModel {
|
||||
}
|
||||
|
||||
Color getCurrentAbTagColor(String tag) {
|
||||
if (tag == kUntagged) {
|
||||
return MyTheme.accent;
|
||||
}
|
||||
int? colorValue = current.tagColors[tag];
|
||||
if (colorValue != null) {
|
||||
return Color(colorValue);
|
||||
|
||||
@@ -261,6 +261,27 @@ class FileModel {
|
||||
debugPrint("Failed to decode onSelectedFiles: $e");
|
||||
}
|
||||
}
|
||||
|
||||
void sendEmptyDirs(dynamic obj) {
|
||||
late final List<dynamic> emptyDirs;
|
||||
try {
|
||||
emptyDirs = jsonDecode(obj['dirs'] as String);
|
||||
} catch (e) {
|
||||
debugPrint("Failed to decode sendEmptyDirs: $e");
|
||||
}
|
||||
final otherSideData = remoteController.directoryData();
|
||||
final toPath = otherSideData.directory.path;
|
||||
final isPeerWindows = otherSideData.options.isWindows;
|
||||
|
||||
final isLocalWindows = isWindows || isWebOnWindows;
|
||||
for (var dir in emptyDirs) {
|
||||
if (isLocalWindows != isPeerWindows) {
|
||||
dir = PathUtil.convert(dir, isLocalWindows, isPeerWindows);
|
||||
}
|
||||
var peerPath = PathUtil.join(toPath, dir, isPeerWindows);
|
||||
remoteController.createDirWithRemote(peerPath, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DirectoryData {
|
||||
@@ -502,8 +523,9 @@ class FileController {
|
||||
"path: ${from.path}, toPath: $toPath, to: ${PathUtil.join(toPath, from.name, isWindows)}");
|
||||
}
|
||||
|
||||
if (!isLocal &&
|
||||
versionCmp(rootState.target!.ffiModel.pi.version, '1.3.3') < 0) {
|
||||
if (isWeb ||
|
||||
(!isLocal &&
|
||||
versionCmp(rootState.target!.ffiModel.pi.version, '1.3.3') < 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1506,6 +1528,12 @@ class PathUtil {
|
||||
return pathUtil.split(path);
|
||||
}
|
||||
|
||||
static String convert(String path, bool isMainWindows, bool isOtherWindows) {
|
||||
final mainPathUtil = isMainWindows ? windowsContext : posixContext;
|
||||
final otherPathUtil = isOtherWindows ? windowsContext : posixContext;
|
||||
return otherPathUtil.joinAll(mainPathUtil.split(path));
|
||||
}
|
||||
|
||||
static String dirname(String path, bool isWindows) {
|
||||
final pathUtil = isWindows ? windowsContext : posixContext;
|
||||
return pathUtil.dirname(path);
|
||||
|
||||
@@ -1080,7 +1080,7 @@ class InputModel {
|
||||
onExit: true,
|
||||
);
|
||||
|
||||
static int tryGetNearestRange(int v, int min, int max, int n) {
|
||||
static double tryGetNearestRange(double v, double min, double max, double n) {
|
||||
if (v < min && v >= min - n) {
|
||||
v = min;
|
||||
}
|
||||
@@ -1138,8 +1138,8 @@ class InputModel {
|
||||
return;
|
||||
}
|
||||
evtValue = {
|
||||
'x': pos.x,
|
||||
'y': pos.y,
|
||||
'x': pos.x.toInt(),
|
||||
'y': pos.y.toInt(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1221,8 +1221,8 @@ class InputModel {
|
||||
evt['x'] = '0';
|
||||
evt['y'] = '0';
|
||||
} else {
|
||||
evt['x'] = '${pos.x}';
|
||||
evt['y'] = '${pos.y}';
|
||||
evt['x'] = '${pos.x.toInt()}';
|
||||
evt['y'] = '${pos.y.toInt()}';
|
||||
}
|
||||
|
||||
Map<int, String> mapButtons = {
|
||||
@@ -1362,31 +1362,27 @@ class InputModel {
|
||||
y = pos.dy;
|
||||
}
|
||||
|
||||
var evtX = 0;
|
||||
var evtY = 0;
|
||||
try {
|
||||
evtX = x.round();
|
||||
evtY = y.round();
|
||||
} catch (e) {
|
||||
debugPrintStack(label: 'canvas.scale value ${canvas.scale}, $e');
|
||||
return null;
|
||||
}
|
||||
|
||||
return InputModel.getPointInRemoteRect(
|
||||
true, peerPlatform, kind, evtType, evtX, evtY, rect,
|
||||
true, peerPlatform, kind, evtType, x, y, rect,
|
||||
buttons: buttons);
|
||||
}
|
||||
|
||||
static Point? getPointInRemoteRect(bool isLocalDesktop, String? peerPlatform,
|
||||
String kind, String evtType, int evtX, int evtY, Rect rect,
|
||||
static Point<double>? getPointInRemoteRect(
|
||||
bool isLocalDesktop,
|
||||
String? peerPlatform,
|
||||
String kind,
|
||||
String evtType,
|
||||
double evtX,
|
||||
double evtY,
|
||||
Rect rect,
|
||||
{int buttons = kPrimaryMouseButton}) {
|
||||
int minX = rect.left.toInt();
|
||||
double minX = rect.left;
|
||||
// https://github.com/rustdesk/rustdesk/issues/6678
|
||||
// For Windows, [0,maxX], [0,maxY] should be set to enable window snapping.
|
||||
int maxX = (rect.left + rect.width).toInt() -
|
||||
double maxX = (rect.left + rect.width) -
|
||||
(peerPlatform == kPeerPlatformWindows ? 0 : 1);
|
||||
int minY = rect.top.toInt();
|
||||
int maxY = (rect.top + rect.height).toInt() -
|
||||
double minY = rect.top;
|
||||
double maxY = (rect.top + rect.height) -
|
||||
(peerPlatform == kPeerPlatformWindows ? 0 : 1);
|
||||
evtX = InputModel.tryGetNearestRange(evtX, minX, maxX, 5);
|
||||
evtY = InputModel.tryGetNearestRange(evtY, minY, maxY, 5);
|
||||
|
||||
@@ -402,6 +402,10 @@ class FfiModel with ChangeNotifier {
|
||||
if (isWeb) {
|
||||
parent.target?.fileModel.onSelectedFiles(evt);
|
||||
}
|
||||
} else if (name == "send_emptry_dirs") {
|
||||
if (isWeb) {
|
||||
parent.target?.fileModel.sendEmptyDirs(evt);
|
||||
}
|
||||
} else if (name == "record_status") {
|
||||
if (desktopType == DesktopType.remote || isMobile) {
|
||||
parent.target?.recordingModel.updateStatus(evt['start'] == 'true');
|
||||
@@ -1268,7 +1272,9 @@ class ImageModel with ChangeNotifier {
|
||||
rgba,
|
||||
rect?.width.toInt() ?? 0,
|
||||
rect?.height.toInt() ?? 0,
|
||||
isWeb ? ui.PixelFormat.rgba8888 : ui.PixelFormat.bgra8888,
|
||||
isWeb | isWindows | isLinux
|
||||
? ui.PixelFormat.rgba8888
|
||||
: ui.PixelFormat.bgra8888,
|
||||
);
|
||||
if (parent.target?.id != pid) return;
|
||||
await update(image);
|
||||
@@ -2184,7 +2190,7 @@ class CursorModel with ChangeNotifier {
|
||||
|
||||
if (dx == 0 && dy == 0) return;
|
||||
|
||||
Point? newPos;
|
||||
Point<double>? newPos;
|
||||
final rect = parent.target?.ffiModel.rect;
|
||||
if (rect == null) {
|
||||
// unreachable
|
||||
@@ -2195,8 +2201,8 @@ class CursorModel with ChangeNotifier {
|
||||
parent.target?.ffiModel.pi.platform,
|
||||
kPointerEventKindMouse,
|
||||
kMouseEventTypeDefault,
|
||||
(_x + dx).toInt(),
|
||||
(_y + dy).toInt(),
|
||||
_x + dx,
|
||||
_y + dy,
|
||||
rect,
|
||||
buttons: kPrimaryButton);
|
||||
if (newPos == null) {
|
||||
@@ -2204,8 +2210,8 @@ class CursorModel with ChangeNotifier {
|
||||
}
|
||||
dx = newPos.x - _x;
|
||||
dy = newPos.y - _y;
|
||||
_x = newPos.x.toDouble();
|
||||
_y = newPos.y.toDouble();
|
||||
_x = newPos.x;
|
||||
_y = newPos.y;
|
||||
if (tryMoveCanvasX && dx != 0) {
|
||||
parent.target?.canvasModel.panX(-dx * scale);
|
||||
}
|
||||
|
||||
@@ -323,10 +323,10 @@ class ServerModel with ChangeNotifier {
|
||||
}
|
||||
|
||||
toggleClipboard() async {
|
||||
_clipboardOk = !_clipboardOk;
|
||||
_clipboardOk = !clipboardOk;
|
||||
bind.mainSetOption(
|
||||
key: kOptionEnableClipboard,
|
||||
value: _clipboardOk ? defaultOptionYes : 'N');
|
||||
value: clipboardOk ? defaultOptionYes : 'N');
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ class StateGlobal {
|
||||
final RxDouble _windowBorderWidth = RxDouble(kWindowBorderWidth);
|
||||
final RxBool showRemoteToolBar = false.obs;
|
||||
final svcStatus = SvcStatus.notReady.obs;
|
||||
final RxInt videoConnCount = 0.obs;
|
||||
final RxBool isFocused = false.obs;
|
||||
// for mobile and web
|
||||
bool isInMainPage = true;
|
||||
@@ -25,6 +26,8 @@ class StateGlobal {
|
||||
|
||||
final isPortrait = false.obs;
|
||||
|
||||
final updateUrl = ''.obs;
|
||||
|
||||
String _inputSource = '';
|
||||
|
||||
// Use for desktop -> remote toolbar -> resolution
|
||||
|
||||
@@ -1801,6 +1801,26 @@ class RustdeskImpl {
|
||||
throw UnimplementedError("mainMaxEncryptLen");
|
||||
}
|
||||
|
||||
bool mainAudioSupportLoopback({dynamic hint}) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<String> sessionReadLocalEmptyDirsRecursiveSync(
|
||||
{required UuidValue sessionId,
|
||||
required String path,
|
||||
required bool includeHidden,
|
||||
dynamic hint}) {
|
||||
throw UnimplementedError("sessionReadLocalEmptyDirsRecursiveSync");
|
||||
}
|
||||
|
||||
Future<void> sessionReadRemoteEmptyDirsRecursiveSync(
|
||||
{required UuidValue sessionId,
|
||||
required String path,
|
||||
required bool includeHidden,
|
||||
dynamic hint}) {
|
||||
throw UnimplementedError("sessionReadRemoteEmptyDirsRecursiveSync");
|
||||
}
|
||||
|
||||
Future<void> sessionRenameFile(
|
||||
{required UuidValue sessionId,
|
||||
required int actId,
|
||||
|
||||
@@ -14,8 +14,13 @@ struct _MyApplication {
|
||||
|
||||
G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
|
||||
|
||||
GtkWidget *find_gl_area(GtkWidget *widget);
|
||||
void try_set_transparent(GtkWindow* window, GdkScreen* screen, FlView* view);
|
||||
|
||||
extern bool gIsConnectionManager;
|
||||
|
||||
GtkWidget *find_gl_area(GtkWidget *widget);
|
||||
|
||||
// Implements GApplication::activate.
|
||||
static void my_application_activate(GApplication* application) {
|
||||
MyApplication* self = MY_APPLICATION(application);
|
||||
@@ -39,9 +44,10 @@ static void my_application_activate(GApplication* application) {
|
||||
// If running on Wayland assume the header bar will work (may need changing
|
||||
// if future cases occur).
|
||||
gboolean use_header_bar = TRUE;
|
||||
GdkScreen* screen = NULL;
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
GdkScreen* screen = gtk_window_get_screen(window);
|
||||
if (GDK_IS_X11_SCREEN(screen)) {
|
||||
screen = gtk_window_get_screen(window);
|
||||
if (screen != NULL && GDK_IS_X11_SCREEN(screen)) {
|
||||
const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
|
||||
if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
|
||||
use_header_bar = FALSE;
|
||||
@@ -66,16 +72,19 @@ static void my_application_activate(GApplication* application) {
|
||||
height = 490;
|
||||
}
|
||||
gtk_window_set_default_size(window, width, height); // <-- comment this line
|
||||
gtk_widget_show(GTK_WIDGET(window));
|
||||
// gtk_widget_show(GTK_WIDGET(window));
|
||||
gtk_widget_set_opacity(GTK_WIDGET(window), 0);
|
||||
|
||||
g_autoptr(FlDartProject) project = fl_dart_project_new();
|
||||
fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
|
||||
|
||||
FlView* view = fl_view_new(project);
|
||||
gtk_widget_show(GTK_WIDGET(view));
|
||||
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
|
||||
|
||||
try_set_transparent(window, gtk_window_get_screen(window), view);
|
||||
gtk_widget_show(GTK_WIDGET(window));
|
||||
gtk_widget_show(GTK_WIDGET(view));
|
||||
|
||||
fl_register_plugins(FL_PLUGIN_REGISTRY(view));
|
||||
|
||||
gtk_widget_grab_focus(GTK_WIDGET(view));
|
||||
@@ -121,3 +130,48 @@ MyApplication* my_application_new() {
|
||||
"flags", G_APPLICATION_NON_UNIQUE,
|
||||
nullptr));
|
||||
}
|
||||
|
||||
GtkWidget *find_gl_area(GtkWidget *widget)
|
||||
{
|
||||
if (GTK_IS_GL_AREA(widget)) {
|
||||
return widget;
|
||||
}
|
||||
|
||||
if (GTK_IS_CONTAINER(widget)) {
|
||||
GList *children = gtk_container_get_children(GTK_CONTAINER(widget));
|
||||
for (GList *iter = children; iter != NULL; iter = g_list_next(iter)) {
|
||||
GtkWidget *child = GTK_WIDGET(iter->data);
|
||||
GtkWidget *gl_area = find_gl_area(child);
|
||||
if (gl_area != NULL) {
|
||||
g_list_free(children);
|
||||
return gl_area;
|
||||
}
|
||||
}
|
||||
g_list_free(children);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// https://github.com/flutter/flutter/issues/152154
|
||||
// Remove this workaround when flutter version is updated.
|
||||
void try_set_transparent(GtkWindow* window, GdkScreen* screen, FlView* view)
|
||||
{
|
||||
GtkWidget *gl_area = NULL;
|
||||
|
||||
printf("Try setting transparent\n");
|
||||
|
||||
gl_area = find_gl_area(GTK_WIDGET(view));
|
||||
if (gl_area != NULL) {
|
||||
gtk_gl_area_set_has_alpha(GTK_GL_AREA(gl_area), TRUE);
|
||||
}
|
||||
|
||||
if (screen != NULL) {
|
||||
GdkVisual *visual = NULL;
|
||||
gtk_widget_set_app_paintable(GTK_WIDGET(window), TRUE);
|
||||
visual = gdk_screen_get_rgba_visual(screen);
|
||||
if (visual != NULL && gdk_screen_is_composited(screen)) {
|
||||
gtk_widget_set_visual(GTK_WIDGET(window), visual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,7 +335,7 @@ packages:
|
||||
description:
|
||||
path: "."
|
||||
ref: HEAD
|
||||
resolved-ref: "519350f1f40746798299e94786197d058353bac9"
|
||||
resolved-ref: "4f562ab49d289cfa36bfda7cff12746ec0200033"
|
||||
url: "https://github.com/rustdesk-org/rustdesk_desktop_multi_window"
|
||||
source: git
|
||||
version: "0.1.0"
|
||||
@@ -530,15 +530,6 @@ packages:
|
||||
url: "https://github.com/rustdesk-org/flutter_gpu_texture_renderer"
|
||||
source: git
|
||||
version: "0.0.1"
|
||||
flutter_improved_scrolling:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "."
|
||||
ref: HEAD
|
||||
resolved-ref: "62f09545149f320616467c306c8c5f71714a18e6"
|
||||
url: "https://github.com/rustdesk-org/flutter_improved_scrolling"
|
||||
source: git
|
||||
version: "0.0.3"
|
||||
flutter_keyboard_visibility:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -1277,10 +1268,11 @@ packages:
|
||||
texture_rgba_renderer:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: texture_rgba_renderer
|
||||
sha256: cb048abdd800468ca40749ca10d1db9d1e6a055d1cde6234c05191293f0c7d61
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
path: "."
|
||||
ref: "42797e0f03141dc2b585f76c64a13974508058b4"
|
||||
resolved-ref: "42797e0f03141dc2b585f76c64a13974508058b4"
|
||||
url: "https://github.com/rustdesk-org/flutter_texture_rgba_renderer"
|
||||
source: git
|
||||
version: "0.0.16"
|
||||
timing:
|
||||
dependency: transitive
|
||||
@@ -1372,13 +1364,13 @@ packages:
|
||||
source: hosted
|
||||
version: "6.2.2"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: url_launcher_ios
|
||||
sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03"
|
||||
sha256: "16a513b6c12bb419304e72ea0ae2ab4fed569920d1c7cb850263fe3acc824626"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.4"
|
||||
version: "6.3.2"
|
||||
url_launcher_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
# 1.1.9-1 works for android, but for ios it becomes 1.1.91, need to set it to 1.1.9-a.1 for iOS, will get 1.1.9.1, but iOS store not allow 4 numbers
|
||||
version: 1.3.3+52
|
||||
version: 1.3.6+55
|
||||
|
||||
environment:
|
||||
sdk: '^3.1.0'
|
||||
@@ -36,6 +36,7 @@ dependencies:
|
||||
#firebase_analytics: ^9.1.5
|
||||
package_info_plus: ^4.2.0
|
||||
url_launcher: ^6.2.1
|
||||
url_launcher_ios: ^6.3.2
|
||||
toggle_switch: ^2.1.0
|
||||
dash_chat_2:
|
||||
git:
|
||||
@@ -71,13 +72,6 @@ dependencies:
|
||||
debounce_throttle: ^2.0.0
|
||||
file_picker: ^5.1.0
|
||||
flutter_svg: ^2.0.5
|
||||
flutter_improved_scrolling:
|
||||
# currently, we use flutter 3.10.0+.
|
||||
#
|
||||
# for flutter 3.0.5, please use official version(just comment code below).
|
||||
# if build rustdesk by flutter >=3.3, please use our custom pub below (uncomment code below).
|
||||
git:
|
||||
url: https://github.com/rustdesk-org/flutter_improved_scrolling
|
||||
uni_links:
|
||||
git:
|
||||
url: https://github.com/rustdesk-org/uni_links
|
||||
@@ -91,7 +85,10 @@ dependencies:
|
||||
password_strength: ^0.2.0
|
||||
flutter_launcher_icons: ^0.13.1
|
||||
flutter_keyboard_visibility: ^5.4.0
|
||||
texture_rgba_renderer: ^0.0.16
|
||||
texture_rgba_renderer:
|
||||
git:
|
||||
url: https://github.com/rustdesk-org/flutter_texture_rgba_renderer
|
||||
ref: 42797e0f03141dc2b585f76c64a13974508058b4
|
||||
percent_indicator: ^4.2.2
|
||||
dropdown_button2: ^2.0.0
|
||||
flutter_gpu_texture_renderer:
|
||||
|
||||
@@ -211,6 +211,11 @@ struct wf_clipboard
|
||||
BOOL sync;
|
||||
UINT32 capabilities;
|
||||
|
||||
// This flag is not really needed,
|
||||
// but we can use it to double confirm that files can only be pasted after `Ctrl+C`.
|
||||
// Not sure `is_file_descriptor_from_remote()` is engough to check all cases on all Windows.
|
||||
BOOL copied;
|
||||
|
||||
size_t map_size;
|
||||
size_t map_capacity;
|
||||
formatMapping *format_mappings;
|
||||
@@ -263,6 +268,8 @@ static UINT cliprdr_send_request_filecontents(wfClipboard *clipboard, UINT32 con
|
||||
ULONG index, UINT32 flag, DWORD positionhigh,
|
||||
DWORD positionlow, ULONG request);
|
||||
|
||||
static BOOL is_file_descriptor_from_remote();
|
||||
|
||||
static void CliprdrDataObject_Delete(CliprdrDataObject *instance);
|
||||
|
||||
static CliprdrEnumFORMATETC *CliprdrEnumFORMATETC_New(ULONG nFormats, FORMATETC *pFormatEtc);
|
||||
@@ -712,6 +719,15 @@ static HRESULT STDMETHODCALLTYPE CliprdrDataObject_GetData(IDataObject *This, FO
|
||||
if (!clipboard)
|
||||
return E_INVALIDARG;
|
||||
|
||||
// If `Ctrl+C` is not pressed yet, do not handle the file paste, and empty the clipboard.
|
||||
if (!clipboard->copied) {
|
||||
if (try_open_clipboard(clipboard->hwnd)) {
|
||||
EmptyClipboard();
|
||||
CloseClipboard();
|
||||
}
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if ((idx = cliprdr_lookup_format(instance, pFormatEtc)) == -1)
|
||||
{
|
||||
// empty clipboard here?
|
||||
@@ -1479,6 +1495,8 @@ static UINT cliprdr_send_format_list(wfClipboard *clipboard, UINT32 connID)
|
||||
|
||||
// send
|
||||
rc = clipboard->context->ClientFormatList(clipboard->context, &formatList);
|
||||
// No need to check `rc`, `copied` is only used to indicate `Ctrl+C` is pressed.
|
||||
clipboard->copied = TRUE;
|
||||
|
||||
for (index = 0; index < numFormats; index++)
|
||||
{
|
||||
@@ -2274,7 +2292,9 @@ static UINT wf_cliprdr_monitor_ready(CliprdrClientContext *context,
|
||||
if (rc != CHANNEL_RC_OK)
|
||||
return rc;
|
||||
|
||||
return cliprdr_send_format_list(clipboard, monitorReady->connID);
|
||||
return rc;
|
||||
// Don't send format list here, because we don't want to paste files copied before the connection.
|
||||
// return cliprdr_send_format_list(clipboard, monitorReady->connID);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2321,11 +2341,20 @@ static UINT wf_cliprdr_server_format_list(CliprdrClientContext *context,
|
||||
UINT32 i;
|
||||
formatMapping *mapping;
|
||||
CLIPRDR_FORMAT *format;
|
||||
wfClipboard *clipboard = (wfClipboard *)context->Custom;
|
||||
wfClipboard *clipboard = NULL;
|
||||
|
||||
if (!context || !formatList)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
clipboard = (wfClipboard *)context->Custom;
|
||||
if (!clipboard)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
if (!clear_format_map(clipboard))
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
clipboard->copied = TRUE;
|
||||
|
||||
for (i = 0; i < formatList->numFormats; i++)
|
||||
{
|
||||
format = &(formatList->formats[i]);
|
||||
@@ -3060,6 +3089,19 @@ wf_cliprdr_server_file_contents_response(CliprdrClientContext *context,
|
||||
return rc;
|
||||
}
|
||||
|
||||
BOOL is_file_descriptor_from_remote()
|
||||
{
|
||||
UINT fsid = 0;
|
||||
if (IsClipboardFormatAvailable(CF_HDROP)) {
|
||||
return FALSE;
|
||||
}
|
||||
fsid = RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW);
|
||||
if (IsClipboardFormatAvailable(fsid)) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL wf_cliprdr_init(wfClipboard *clipboard, CliprdrClientContext *cliprdr)
|
||||
{
|
||||
if (!clipboard || !cliprdr)
|
||||
@@ -3071,6 +3113,7 @@ BOOL wf_cliprdr_init(wfClipboard *clipboard, CliprdrClientContext *cliprdr)
|
||||
clipboard->map_size = 0;
|
||||
clipboard->hUser32 = LoadLibraryA("user32.dll");
|
||||
clipboard->data_obj = NULL;
|
||||
clipboard->copied = FALSE;
|
||||
|
||||
if (clipboard->hUser32)
|
||||
{
|
||||
@@ -3126,14 +3169,18 @@ BOOL wf_cliprdr_uninit(wfClipboard *clipboard, CliprdrClientContext *cliprdr)
|
||||
if (!clipboard || !cliprdr)
|
||||
return FALSE;
|
||||
|
||||
clipboard->copied = FALSE;
|
||||
cliprdr->Custom = NULL;
|
||||
|
||||
/* discard all contexts in clipboard */
|
||||
if (try_open_clipboard(clipboard->hwnd))
|
||||
{
|
||||
if (!EmptyClipboard())
|
||||
if (is_file_descriptor_from_remote())
|
||||
{
|
||||
DEBUG_CLIPRDR("EmptyClipboard failed with 0x%x", GetLastError());
|
||||
if (!EmptyClipboard())
|
||||
{
|
||||
DEBUG_CLIPRDR("EmptyClipboard failed with 0x%x", GetLastError());
|
||||
}
|
||||
}
|
||||
if (!CloseClipboard())
|
||||
{
|
||||
@@ -3227,6 +3274,8 @@ BOOL wf_do_empty_cliprdr(wfClipboard *clipboard)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
clipboard->copied = FALSE;
|
||||
|
||||
if (WaitForSingleObject(clipboard->data_obj_mutex, INFINITE) != WAIT_OBJECT_0)
|
||||
{
|
||||
return FALSE;
|
||||
@@ -3248,10 +3297,14 @@ BOOL wf_do_empty_cliprdr(wfClipboard *clipboard)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!EmptyClipboard())
|
||||
if (is_file_descriptor_from_remote())
|
||||
{
|
||||
rc = FALSE;
|
||||
if (!EmptyClipboard())
|
||||
{
|
||||
rc = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!CloseClipboard())
|
||||
{
|
||||
// critical error!!!
|
||||
|
||||
@@ -345,7 +345,7 @@ fn convert_to_tfc_key(key: Key) -> Option<TFC_Key> {
|
||||
Key::Numpad9 => TFC_Key::N9,
|
||||
Key::Decimal => TFC_Key::NumpadDecimal,
|
||||
Key::Clear => TFC_Key::NumpadClear,
|
||||
Key::Pause => TFC_Key::PlayPause,
|
||||
Key::Pause => TFC_Key::Pause,
|
||||
Key::Print => TFC_Key::Print,
|
||||
Key::Snapshot => TFC_Key::PrintScreen,
|
||||
Key::Insert => TFC_Key::Insert,
|
||||
|
||||
@@ -284,7 +284,9 @@ enum ControlKey {
|
||||
}
|
||||
|
||||
message KeyEvent {
|
||||
// `down` indicates the key's state(down or up).
|
||||
bool down = 1;
|
||||
// `press` indicates a click event(down and up).
|
||||
bool press = 2;
|
||||
oneof union {
|
||||
ControlKey control_key = 3;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rustdesk-portable-packer"
|
||||
version = "1.3.3"
|
||||
version = "1.3.6"
|
||||
edition = "2021"
|
||||
description = "RustDesk Remote Desktop"
|
||||
|
||||
|
||||
@@ -371,14 +371,6 @@ pub fn call_clipboard_manager_update_clipboard(data: &[u8]) -> JniResult<()> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn call_clipboard_manager_enable_service_clipboard(enable: bool) -> JniResult<()> {
|
||||
_call_clipboard_manager(
|
||||
"rustEnableServiceClipboard",
|
||||
"(Z)V",
|
||||
&[JValue::Bool(jboolean::from(enable))],
|
||||
)
|
||||
}
|
||||
|
||||
pub fn call_clipboard_manager_enable_client_clipboard(enable: bool) -> JniResult<()> {
|
||||
_call_clipboard_manager(
|
||||
"rustEnableClientClipboard",
|
||||
|
||||
@@ -193,15 +193,11 @@ impl EncoderApi for HwRamEncoder {
|
||||
}
|
||||
|
||||
fn support_abr(&self) -> bool {
|
||||
["qsv", "vaapi", "mediacodec", "videotoolbox"]
|
||||
.iter()
|
||||
.all(|&x| !self.config.name.contains(x))
|
||||
["qsv", "vaapi"].iter().all(|&x| !self.config.name.contains(x))
|
||||
}
|
||||
|
||||
fn support_changing_quality(&self) -> bool {
|
||||
["vaapi", "mediacodec", "videotoolbox"]
|
||||
.iter()
|
||||
.all(|&x| !self.config.name.contains(x))
|
||||
["vaapi"].iter().all(|&x| !self.config.name.contains(x))
|
||||
}
|
||||
|
||||
fn latency_free(&self) -> bool {
|
||||
@@ -696,8 +692,8 @@ pub fn check_available_hwcodec() -> String {
|
||||
#[cfg(not(feature = "vram"))]
|
||||
let vram_string = "".to_owned();
|
||||
let c = HwCodecConfig {
|
||||
ram_encode: Encoder::available_encoders(ctx, Some(vram_string.clone())),
|
||||
ram_decode: Decoder::available_decoders(Some(vram_string)),
|
||||
ram_encode: Encoder::available_encoders(ctx, Some(vram_string)),
|
||||
ram_decode: Decoder::available_decoders(),
|
||||
#[cfg(feature = "vram")]
|
||||
vram_encode: vram.0,
|
||||
#[cfg(feature = "vram")]
|
||||
|
||||
@@ -5,7 +5,7 @@ set -e
|
||||
if [ "$1" = configure ]; then
|
||||
|
||||
INITSYS=$(ls -al /proc/1/exe | awk -F' ' '{print $NF}' | awk -F'/' '{print $NF}')
|
||||
ln -s /usr/lib/rustdesk/rustdesk /usr/bin/rustdesk
|
||||
ln -s /usr/share/rustdesk/rustdesk /usr/bin/rustdesk
|
||||
|
||||
if [ "systemd" == "$INITSYS" ]; then
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
pkgname=rustdesk
|
||||
pkgver=1.3.3
|
||||
pkgver=1.3.6
|
||||
pkgrel=0
|
||||
epoch=
|
||||
pkgdesc=""
|
||||
@@ -7,7 +7,7 @@ arch=('x86_64')
|
||||
url=""
|
||||
license=('AGPL-3.0')
|
||||
groups=()
|
||||
depends=('gtk3' 'xdotool' 'libxcb' 'libxfixes' 'alsa-lib' 'libva' 'libvdpau' 'libappindicator-gtk3' 'pam' 'gst-plugins-base' 'gst-plugin-pipewire')
|
||||
depends=('gtk3' 'xdotool' 'libxcb' 'libxfixes' 'alsa-lib' 'libva' 'libappindicator-gtk3' 'pam' 'gst-plugins-base' 'gst-plugin-pipewire')
|
||||
makedepends=()
|
||||
checkdepends=()
|
||||
optdepends=()
|
||||
@@ -23,10 +23,10 @@ md5sums=() #generate with 'makepkg -g'
|
||||
|
||||
package() {
|
||||
if [[ ${FLUTTER} ]]; then
|
||||
mkdir -p "${pkgdir}/usr/lib/rustdesk" && cp -r ${HBB}/flutter/build/linux/x64/release/bundle/* -t "${pkgdir}/usr/lib/rustdesk"
|
||||
mkdir -p "${pkgdir}/usr/share/rustdesk" && cp -r ${HBB}/flutter/build/linux/x64/release/bundle/* -t "${pkgdir}/usr/share/rustdesk"
|
||||
fi
|
||||
mkdir -p "${pkgdir}/usr/bin"
|
||||
pushd ${pkgdir} && ln -s /usr/lib/rustdesk/rustdesk usr/bin/rustdesk && popd
|
||||
pushd ${pkgdir} && ln -s /usr/share/rustdesk/rustdesk usr/bin/rustdesk && popd
|
||||
install -Dm 644 $HBB/res/rustdesk.service -t "${pkgdir}/usr/share/rustdesk/files"
|
||||
install -Dm 644 $HBB/res/rustdesk.desktop -t "${pkgdir}/usr/share/rustdesk/files"
|
||||
install -Dm 644 $HBB/res/rustdesk-link.desktop -t "${pkgdir}/usr/share/rustdesk/files"
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
Name: rustdesk
|
||||
Version: 1.3.3
|
||||
Version: 1.3.6
|
||||
Release: 0
|
||||
Summary: RPM package
|
||||
License: GPL-3.0
|
||||
URL: https://rustdesk.com
|
||||
Vendor: rustdesk <info@rustdesk.com>
|
||||
Requires: gtk3 libxcb1 xdotool libXfixes3 alsa-utils libXtst6 libvdpau1 libva2 pam gstreamer-plugins-base gstreamer-plugin-pipewire
|
||||
Requires: gtk3 libxcb1 xdotool libXfixes3 alsa-utils libXtst6 libva2 pam gstreamer-plugins-base gstreamer-plugin-pipewire
|
||||
Recommends: libayatana-appindicator3-1
|
||||
Provides: libdesktop_drop_plugin.so()(64bit), libdesktop_multi_window_plugin.so()(64bit), libfile_selector_linux_plugin.so()(64bit), libflutter_custom_cursor_plugin.so()(64bit), libflutter_linux_gtk.so()(64bit), libscreen_retriever_plugin.so()(64bit), libtray_manager_plugin.so()(64bit), liburl_launcher_linux_plugin.so()(64bit), libwindow_manager_plugin.so()(64bit), libwindow_size_plugin.so()(64bit), libtexture_rgba_renderer_plugin.so()(64bit)
|
||||
|
||||
# https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/
|
||||
|
||||
%description
|
||||
The best open-source remote desktop client software, written in Rust.
|
||||
|
||||
@@ -22,7 +24,7 @@ The best open-source remote desktop client software, written in Rust.
|
||||
|
||||
%install
|
||||
|
||||
mkdir -p "%{buildroot}/usr/lib/rustdesk" && cp -r ${HBB}/flutter/build/linux/x64/release/bundle/* -t "%{buildroot}/usr/lib/rustdesk"
|
||||
mkdir -p "%{buildroot}/usr/share/rustdesk" && cp -r ${HBB}/flutter/build/linux/x64/release/bundle/* -t "%{buildroot}/usr/share/rustdesk"
|
||||
mkdir -p "%{buildroot}/usr/bin"
|
||||
install -Dm 644 $HBB/res/rustdesk.service -t "%{buildroot}/usr/share/rustdesk/files"
|
||||
install -Dm 644 $HBB/res/rustdesk.desktop -t "%{buildroot}/usr/share/rustdesk/files"
|
||||
@@ -31,7 +33,7 @@ install -Dm 644 $HBB/res/128x128@2x.png "%{buildroot}/usr/share/icons/hicolor/25
|
||||
install -Dm 644 $HBB/res/scalable.svg "%{buildroot}/usr/share/icons/hicolor/scalable/apps/rustdesk.svg"
|
||||
|
||||
%files
|
||||
/usr/lib/rustdesk/*
|
||||
/usr/share/rustdesk/*
|
||||
/usr/share/rustdesk/files/rustdesk.service
|
||||
/usr/share/icons/hicolor/256x256/apps/rustdesk.png
|
||||
/usr/share/icons/hicolor/scalable/apps/rustdesk.svg
|
||||
@@ -41,7 +43,6 @@ install -Dm 644 $HBB/res/scalable.svg "%{buildroot}/usr/share/icons/hicolor/scal
|
||||
%changelog
|
||||
# let's skip this for now
|
||||
|
||||
# https://www.cnblogs.com/xingmuxin/p/8990255.html
|
||||
%pre
|
||||
# can do something for centos7
|
||||
case "$1" in
|
||||
@@ -58,7 +59,7 @@ esac
|
||||
cp /usr/share/rustdesk/files/rustdesk.service /etc/systemd/system/rustdesk.service
|
||||
cp /usr/share/rustdesk/files/rustdesk.desktop /usr/share/applications/
|
||||
cp /usr/share/rustdesk/files/rustdesk-link.desktop /usr/share/applications/
|
||||
ln -s /usr/lib/rustdesk/rustdesk /usr/bin/rustdesk
|
||||
ln -sf /usr/share/rustdesk/rustdesk /usr/bin/rustdesk
|
||||
systemctl daemon-reload
|
||||
systemctl enable rustdesk
|
||||
systemctl start rustdesk
|
||||
@@ -81,12 +82,17 @@ esac
|
||||
case "$1" in
|
||||
0)
|
||||
# for uninstall
|
||||
rm /usr/bin/rustdesk || true
|
||||
rmdir /usr/lib/rustdesk || true
|
||||
rmdir /usr/local/rustdesk || true
|
||||
rmdir /usr/share/rustdesk || true
|
||||
rm /usr/share/applications/rustdesk.desktop || true
|
||||
rm /usr/share/applications/rustdesk-link.desktop || true
|
||||
rm /usr/bin/rustdesk || true
|
||||
update-desktop-database
|
||||
;;
|
||||
1)
|
||||
# for upgrade
|
||||
rmdir /usr/lib/rustdesk || true
|
||||
rmdir /usr/local/rustdesk || true
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
Name: rustdesk
|
||||
Version: 1.3.3
|
||||
Version: 1.3.6
|
||||
Release: 0
|
||||
Summary: RPM package
|
||||
License: GPL-3.0
|
||||
URL: https://rustdesk.com
|
||||
Vendor: rustdesk <info@rustdesk.com>
|
||||
Requires: gtk3 libxcb libxdo libXfixes alsa-lib libvdpau libva pam gstreamer1-plugins-base
|
||||
Requires: gtk3 libxcb libxdo libXfixes alsa-lib libva pam gstreamer1-plugins-base
|
||||
Recommends: libayatana-appindicator-gtk3
|
||||
Provides: libdesktop_drop_plugin.so()(64bit), libdesktop_multi_window_plugin.so()(64bit), libfile_selector_linux_plugin.so()(64bit), libflutter_custom_cursor_plugin.so()(64bit), libflutter_linux_gtk.so()(64bit), libscreen_retriever_plugin.so()(64bit), libtray_manager_plugin.so()(64bit), liburl_launcher_linux_plugin.so()(64bit), libwindow_manager_plugin.so()(64bit), libwindow_size_plugin.so()(64bit), libtexture_rgba_renderer_plugin.so()(64bit)
|
||||
|
||||
# https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/
|
||||
|
||||
%description
|
||||
The best open-source remote desktop client software, written in Rust.
|
||||
|
||||
@@ -22,7 +24,7 @@ The best open-source remote desktop client software, written in Rust.
|
||||
|
||||
%install
|
||||
|
||||
mkdir -p "%{buildroot}/usr/lib/rustdesk" && cp -r ${HBB}/flutter/build/linux/x64/release/bundle/* -t "%{buildroot}/usr/lib/rustdesk"
|
||||
mkdir -p "%{buildroot}/usr/share/rustdesk" && cp -r ${HBB}/flutter/build/linux/x64/release/bundle/* -t "%{buildroot}/usr/share/rustdesk"
|
||||
mkdir -p "%{buildroot}/usr/bin"
|
||||
install -Dm 644 $HBB/res/rustdesk.service -t "%{buildroot}/usr/share/rustdesk/files"
|
||||
install -Dm 644 $HBB/res/rustdesk.desktop -t "%{buildroot}/usr/share/rustdesk/files"
|
||||
@@ -31,7 +33,7 @@ install -Dm 644 $HBB/res/128x128@2x.png "%{buildroot}/usr/share/icons/hicolor/25
|
||||
install -Dm 644 $HBB/res/scalable.svg "%{buildroot}/usr/share/icons/hicolor/scalable/apps/rustdesk.svg"
|
||||
|
||||
%files
|
||||
/usr/lib/rustdesk/*
|
||||
/usr/share/rustdesk/*
|
||||
/usr/share/rustdesk/files/rustdesk.service
|
||||
/usr/share/icons/hicolor/256x256/apps/rustdesk.png
|
||||
/usr/share/icons/hicolor/scalable/apps/rustdesk.svg
|
||||
@@ -41,7 +43,6 @@ install -Dm 644 $HBB/res/scalable.svg "%{buildroot}/usr/share/icons/hicolor/scal
|
||||
%changelog
|
||||
# let's skip this for now
|
||||
|
||||
# https://www.cnblogs.com/xingmuxin/p/8990255.html
|
||||
%pre
|
||||
# can do something for centos7
|
||||
case "$1" in
|
||||
@@ -58,7 +59,7 @@ esac
|
||||
cp /usr/share/rustdesk/files/rustdesk.service /etc/systemd/system/rustdesk.service
|
||||
cp /usr/share/rustdesk/files/rustdesk.desktop /usr/share/applications/
|
||||
cp /usr/share/rustdesk/files/rustdesk-link.desktop /usr/share/applications/
|
||||
ln -s /usr/lib/rustdesk/rustdesk /usr/bin/rustdesk
|
||||
ln -sf /usr/share/rustdesk/rustdesk /usr/bin/rustdesk
|
||||
systemctl daemon-reload
|
||||
systemctl enable rustdesk
|
||||
systemctl start rustdesk
|
||||
@@ -81,12 +82,17 @@ esac
|
||||
case "$1" in
|
||||
0)
|
||||
# for uninstall
|
||||
rm /usr/bin/rustdesk || true
|
||||
rmdir /usr/lib/rustdesk || true
|
||||
rmdir /usr/local/rustdesk || true
|
||||
rmdir /usr/share/rustdesk || true
|
||||
rm /usr/share/applications/rustdesk.desktop || true
|
||||
rm /usr/share/applications/rustdesk-link.desktop || true
|
||||
rm /usr/bin/rustdesk || true
|
||||
update-desktop-database
|
||||
;;
|
||||
1)
|
||||
# for upgrade
|
||||
rmdir /usr/lib/rustdesk || true
|
||||
rmdir /usr/local/rustdesk || true
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -3,9 +3,11 @@ Version: 1.1.9
|
||||
Release: 0
|
||||
Summary: RPM package
|
||||
License: GPL-3.0
|
||||
Requires: gtk3 libxcb1 xdotool libXfixes3 alsa-utils libXtst6 libvdpau1 libva2 pam gstreamer-plugins-base gstreamer-plugin-pipewire
|
||||
Requires: gtk3 libxcb1 xdotool libXfixes3 alsa-utils libXtst6 libva2 pam gstreamer-plugins-base gstreamer-plugin-pipewire
|
||||
Recommends: libayatana-appindicator3-1
|
||||
|
||||
# https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/
|
||||
|
||||
%description
|
||||
The best open-source remote desktop client software, written in Rust.
|
||||
|
||||
@@ -19,12 +21,12 @@ The best open-source remote desktop client software, written in Rust.
|
||||
|
||||
%install
|
||||
mkdir -p %{buildroot}/usr/bin/
|
||||
mkdir -p %{buildroot}/usr/lib/rustdesk/
|
||||
mkdir -p %{buildroot}/usr/share/rustdesk/
|
||||
mkdir -p %{buildroot}/usr/share/rustdesk/files/
|
||||
mkdir -p %{buildroot}/usr/share/icons/hicolor/256x256/apps/
|
||||
mkdir -p %{buildroot}/usr/share/icons/hicolor/scalable/apps/
|
||||
install -m 755 $HBB/target/release/rustdesk %{buildroot}/usr/bin/rustdesk
|
||||
install $HBB/libsciter-gtk.so %{buildroot}/usr/lib/rustdesk/libsciter-gtk.so
|
||||
install $HBB/libsciter-gtk.so %{buildroot}/usr/share/rustdesk/libsciter-gtk.so
|
||||
install $HBB/res/rustdesk.service %{buildroot}/usr/share/rustdesk/files/
|
||||
install $HBB/res/128x128@2x.png %{buildroot}/usr/share/icons/hicolor/256x256/apps/rustdesk.png
|
||||
install $HBB/res/scalable.svg %{buildroot}/usr/share/icons/hicolor/scalable/apps/rustdesk.svg
|
||||
@@ -33,7 +35,7 @@ install $HBB/res/rustdesk-link.desktop %{buildroot}/usr/share/rustdesk/files/
|
||||
|
||||
%files
|
||||
/usr/bin/rustdesk
|
||||
/usr/lib/rustdesk/libsciter-gtk.so
|
||||
/usr/share/rustdesk/libsciter-gtk.so
|
||||
/usr/share/rustdesk/files/rustdesk.service
|
||||
/usr/share/icons/hicolor/256x256/apps/rustdesk.png
|
||||
/usr/share/icons/hicolor/scalable/apps/rustdesk.svg
|
||||
@@ -43,7 +45,6 @@ install $HBB/res/rustdesk-link.desktop %{buildroot}/usr/share/rustdesk/files/
|
||||
%changelog
|
||||
# let's skip this for now
|
||||
|
||||
# https://www.cnblogs.com/xingmuxin/p/8990255.html
|
||||
%pre
|
||||
# can do something for centos7
|
||||
case "$1" in
|
||||
|
||||
13
res/rpm.spec
13
res/rpm.spec
@@ -1,13 +1,15 @@
|
||||
Name: rustdesk
|
||||
Version: 1.3.3
|
||||
Version: 1.3.6
|
||||
Release: 0
|
||||
Summary: RPM package
|
||||
License: GPL-3.0
|
||||
URL: https://rustdesk.com
|
||||
Vendor: rustdesk <info@rustdesk.com>
|
||||
Requires: gtk3 libxcb libxdo libXfixes alsa-lib libvdpau1 libva2 pam gstreamer1-plugins-base
|
||||
Requires: gtk3 libxcb libxdo libXfixes alsa-lib libva2 pam gstreamer1-plugins-base
|
||||
Recommends: libayatana-appindicator-gtk3
|
||||
|
||||
# https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/
|
||||
|
||||
%description
|
||||
The best open-source remote desktop client software, written in Rust.
|
||||
|
||||
@@ -21,12 +23,12 @@ The best open-source remote desktop client software, written in Rust.
|
||||
|
||||
%install
|
||||
mkdir -p %{buildroot}/usr/bin/
|
||||
mkdir -p %{buildroot}/usr/lib/rustdesk/
|
||||
mkdir -p %{buildroot}/usr/share/rustdesk/
|
||||
mkdir -p %{buildroot}/usr/share/rustdesk/files/
|
||||
mkdir -p %{buildroot}/usr/share/icons/hicolor/256x256/apps/
|
||||
mkdir -p %{buildroot}/usr/share/icons/hicolor/scalable/apps/
|
||||
install -m 755 $HBB/target/release/rustdesk %{buildroot}/usr/bin/rustdesk
|
||||
install $HBB/libsciter-gtk.so %{buildroot}/usr/lib/rustdesk/libsciter-gtk.so
|
||||
install $HBB/libsciter-gtk.so %{buildroot}/usr/share/rustdesk/libsciter-gtk.so
|
||||
install $HBB/res/rustdesk.service %{buildroot}/usr/share/rustdesk/files/
|
||||
install $HBB/res/128x128@2x.png %{buildroot}/usr/share/icons/hicolor/256x256/apps/rustdesk.png
|
||||
install $HBB/res/scalable.svg %{buildroot}/usr/share/icons/hicolor/scalable/apps/rustdesk.svg
|
||||
@@ -35,7 +37,7 @@ install $HBB/res/rustdesk-link.desktop %{buildroot}/usr/share/rustdesk/files/
|
||||
|
||||
%files
|
||||
/usr/bin/rustdesk
|
||||
/usr/lib/rustdesk/libsciter-gtk.so
|
||||
/usr/share/rustdesk/libsciter-gtk.so
|
||||
/usr/share/rustdesk/files/rustdesk.service
|
||||
/usr/share/icons/hicolor/256x256/apps/rustdesk.png
|
||||
/usr/share/icons/hicolor/scalable/apps/rustdesk.svg
|
||||
@@ -46,7 +48,6 @@ install $HBB/res/rustdesk-link.desktop %{buildroot}/usr/share/rustdesk/files/
|
||||
%changelog
|
||||
# let's skip this for now
|
||||
|
||||
# https://www.cnblogs.com/xingmuxin/p/8990255.html
|
||||
%pre
|
||||
# can do something for centos7
|
||||
case "$1" in
|
||||
|
||||
@@ -8,16 +8,28 @@ vcpkg_find_acquire_program(PERL)
|
||||
get_filename_component(PERL_PATH ${PERL} DIRECTORY)
|
||||
vcpkg_add_to_path(${PERL_PATH})
|
||||
|
||||
vcpkg_from_git(
|
||||
OUT_SOURCE_PATH SOURCE_PATH
|
||||
URL "https://aomedia.googlesource.com/aom"
|
||||
REF 8ad484f8a18ed1853c094e7d3a4e023b2a92df28 # 3.9.1
|
||||
PATCHES
|
||||
aom-uninitialized-pointer.diff
|
||||
aom-avx2.diff
|
||||
# Can be dropped when https://bugs.chromium.org/p/aomedia/issues/detail?id=3029 is merged into the upstream
|
||||
aom-install.diff
|
||||
)
|
||||
if(DEFINED ENV{USE_AOM_391})
|
||||
vcpkg_from_git(
|
||||
OUT_SOURCE_PATH SOURCE_PATH
|
||||
URL "https://aomedia.googlesource.com/aom"
|
||||
REF 8ad484f8a18ed1853c094e7d3a4e023b2a92df28 # 3.9.1
|
||||
PATCHES
|
||||
aom-uninitialized-pointer.diff
|
||||
aom-avx2.diff
|
||||
aom-install.diff
|
||||
)
|
||||
else()
|
||||
vcpkg_from_git(
|
||||
OUT_SOURCE_PATH SOURCE_PATH
|
||||
URL "https://aomedia.googlesource.com/aom"
|
||||
REF d6f30ae474dd6c358f26de0a0fc26a0d7340a84c # 3.11.0
|
||||
PATCHES
|
||||
aom-uninitialized-pointer.diff
|
||||
# aom-avx2.diff
|
||||
# Can be dropped when https://bugs.chromium.org/p/aomedia/issues/detail?id=3029 is merged into the upstream
|
||||
aom-install.diff
|
||||
)
|
||||
endif()
|
||||
|
||||
set(aom_target_cpu "")
|
||||
if(VCPKG_TARGET_IS_UWP OR (VCPKG_TARGET_IS_WINDOWS AND VCPKG_TARGET_ARCHITECTURE MATCHES "^arm"))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "aom",
|
||||
"version-semver": "3.9.1",
|
||||
"version-semver": "3.11.0",
|
||||
"port-version": 0,
|
||||
"description": "AV1 codec library",
|
||||
"homepage": "https://aomedia.googlesource.com/aom",
|
||||
|
||||
27
res/vcpkg/ffmpeg/0001-create-lib-libraries.patch
Normal file
27
res/vcpkg/ffmpeg/0001-create-lib-libraries.patch
Normal file
@@ -0,0 +1,27 @@
|
||||
diff --git a/configure b/configure
|
||||
index 1f0b9497cb..3243e23021 100644
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -5697,17 +5697,19 @@ case $target_os in
|
||||
;;
|
||||
win32|win64)
|
||||
disable symver
|
||||
- if enabled shared; then
|
||||
+# if enabled shared; then
|
||||
# Link to the import library instead of the normal static library
|
||||
# for shared libs.
|
||||
LD_LIB='%.lib'
|
||||
# Cannot build both shared and static libs with MSVC or icl.
|
||||
- disable static
|
||||
- fi
|
||||
+# disable static
|
||||
+# fi
|
||||
! enabled small && test_cmd $windres --version && enable gnu_windres
|
||||
enabled x86_32 && check_ldflags -LARGEADDRESSAWARE
|
||||
add_cppflags -DWIN32_LEAN_AND_MEAN
|
||||
shlibdir_default="$bindir_default"
|
||||
+ LIBPREF=""
|
||||
+ LIBSUF=".lib"
|
||||
SLIBPREF=""
|
||||
SLIBSUF=".dll"
|
||||
SLIBNAME_WITH_VERSION='$(SLIBPREF)$(FULLNAME)-$(LIBVERSION)$(SLIBSUF)'
|
||||
65
res/vcpkg/ffmpeg/0004-dependencies.patch
Normal file
65
res/vcpkg/ffmpeg/0004-dependencies.patch
Normal file
@@ -0,0 +1,65 @@
|
||||
diff --git a/configure b/configure
|
||||
index a8b74e0..c99f41c 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -6633,7 +6633,7 @@ fi
|
||||
|
||||
enabled zlib && { check_pkg_config zlib zlib "zlib.h" zlibVersion ||
|
||||
check_lib zlib zlib.h zlibVersion -lz; }
|
||||
-enabled bzlib && check_lib bzlib bzlib.h BZ2_bzlibVersion -lbz2
|
||||
+enabled bzlib && require_pkg_config bzlib bzip2 bzlib.h BZ2_bzlibVersion
|
||||
enabled lzma && check_lib lzma lzma.h lzma_version_number -llzma
|
||||
|
||||
enabled zlib && test_exec $zlib_extralibs <<EOF && enable zlib_gzip
|
||||
@@ -6757,7 +6757,8 @@ if enabled libmfx; then
|
||||
fi
|
||||
|
||||
enabled libmodplug && require_pkg_config libmodplug libmodplug libmodplug/modplug.h ModPlug_Load
|
||||
-enabled libmp3lame && require "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame $libm_extralibs
|
||||
+enabled libmp3lame && { check_lib libmp3lame lame/lame.h lame_set_VBR_quality -lmp3lame $libm_extralibs ||
|
||||
+ require libmp3lame lame/lame.h lame_set_VBR_quality -llibmp3lame-static -llibmpghip-static $libm_extralibs; }
|
||||
enabled libmysofa && { check_pkg_config libmysofa libmysofa mysofa.h mysofa_neighborhood_init_withstepdefine ||
|
||||
require libmysofa mysofa.h mysofa_neighborhood_init_withstepdefine -lmysofa $zlib_extralibs; }
|
||||
enabled libnpp && { check_lib libnpp npp.h nppGetLibVersion -lnppig -lnppicc -lnppc -lnppidei -lnppif ||
|
||||
@@ -6772,7 +6773,7 @@ require_pkg_config libopencv opencv opencv/cxcore.h cvCreateImageHeader; }
|
||||
enabled libopenh264 && require_pkg_config libopenh264 "openh264 >= 1.3.0" wels/codec_api.h WelsGetCodecVersion
|
||||
enabled libopenjpeg && { check_pkg_config libopenjpeg "libopenjp2 >= 2.1.0" openjpeg.h opj_version ||
|
||||
{ require_pkg_config libopenjpeg "libopenjp2 >= 2.1.0" openjpeg.h opj_version -DOPJ_STATIC && add_cppflags -DOPJ_STATIC; } }
|
||||
-enabled libopenmpt && require_pkg_config libopenmpt "libopenmpt >= 0.2.6557" libopenmpt/libopenmpt.h openmpt_module_create -lstdc++ && append libopenmpt_extralibs "-lstdc++"
|
||||
+enabled libopenmpt && require_pkg_config libopenmpt "libopenmpt >= 0.2.6557" libopenmpt/libopenmpt.h openmpt_module_create
|
||||
enabled libopenvino && { { check_pkg_config libopenvino openvino openvino/c/openvino.h ov_core_create && enable openvino2; } ||
|
||||
{ check_pkg_config libopenvino openvino c_api/ie_c_api.h ie_c_api_version ||
|
||||
require libopenvino c_api/ie_c_api.h ie_c_api_version -linference_engine_c_api; } }
|
||||
@@ -6796,8 +6797,8 @@ enabled libshaderc && require_pkg_config spirv_compiler "shaderc >= 2019.
|
||||
enabled libshine && require_pkg_config libshine shine shine/layer3.h shine_encode_buffer
|
||||
enabled libsmbclient && { check_pkg_config libsmbclient smbclient libsmbclient.h smbc_init ||
|
||||
require libsmbclient libsmbclient.h smbc_init -lsmbclient; }
|
||||
-enabled libsnappy && require libsnappy snappy-c.h snappy_compress -lsnappy -lstdc++
|
||||
-enabled libsoxr && require libsoxr soxr.h soxr_create -lsoxr
|
||||
+enabled libsnappy && require_pkg_config libsnappy snappy snappy-c.h snappy_compress
|
||||
+enabled libsoxr && require libsoxr soxr.h soxr_create -lsoxr $libm_extralibs
|
||||
enabled libssh && require_pkg_config libssh "libssh >= 0.6.0" libssh/sftp.h sftp_init
|
||||
enabled libspeex && require_pkg_config libspeex speex speex/speex.h speex_decoder_init
|
||||
enabled libsrt && require_pkg_config libsrt "srt >= 1.3.0" srt/srt.h srt_socket
|
||||
@@ -6880,6 +6881,8 @@ enabled openal && { check_pkg_config openal "openal >= 1.1" "AL/al.h"
|
||||
enabled opencl && { check_pkg_config opencl OpenCL CL/cl.h clEnqueueNDRangeKernel ||
|
||||
check_lib opencl OpenCL/cl.h clEnqueueNDRangeKernel "-framework OpenCL" ||
|
||||
check_lib opencl CL/cl.h clEnqueueNDRangeKernel -lOpenCL ||
|
||||
+ check_lib opencl CL/cl.h clEnqueueNDRangeKernel -lOpenCL -lAdvapi32 -lOle32 -lCfgmgr32||
|
||||
+ check_lib opencl CL/cl.h clEnqueueNDRangeKernel -lOpenCL -pthread -ldl ||
|
||||
die "ERROR: opencl not found"; } &&
|
||||
{ test_cpp_condition "OpenCL/cl.h" "defined(CL_VERSION_1_2)" ||
|
||||
test_cpp_condition "CL/cl.h" "defined(CL_VERSION_1_2)" ||
|
||||
@@ -7204,10 +7207,10 @@ enabled amf &&
|
||||
"(AMF_VERSION_MAJOR << 48 | AMF_VERSION_MINOR << 32 | AMF_VERSION_RELEASE << 16 | AMF_VERSION_BUILD_NUM) >= 0x0001000400210000"
|
||||
|
||||
# Funny iconv installations are not unusual, so check it after all flags have been set
|
||||
-if enabled libc_iconv; then
|
||||
+if enabled libc_iconv && disabled iconv; then
|
||||
check_func_headers iconv.h iconv
|
||||
elif enabled iconv; then
|
||||
- check_func_headers iconv.h iconv || check_lib iconv iconv.h iconv -liconv
|
||||
+ check_func_headers iconv.h iconv || check_lib iconv iconv.h iconv -liconv || check_lib iconv iconv.h iconv -liconv -lcharset
|
||||
fi
|
||||
|
||||
enabled debug && add_cflags -g"$debuglevel" && add_asflags -g"$debuglevel"
|
||||
@@ -1,55 +1,78 @@
|
||||
diff --git a/libavcodec/x86/Makefile b/libavcodec/x86/Makefile
|
||||
--- a/libavcodec/x86/Makefile
|
||||
+++ b/libavcodec/x86/Makefile
|
||||
@@ -158,6 +158,8 @@ X86ASM-OBJS-$(CONFIG_ALAC_DECODER) += x86/alacdsp.o
|
||||
X86ASM-OBJS-$(CONFIG_APNG_DECODER) += x86/pngdsp.o
|
||||
X86ASM-OBJS-$(CONFIG_CAVS_DECODER) += x86/cavsidct.o
|
||||
+ifdef ARCH_X86_64
|
||||
X86ASM-OBJS-$(CONFIG_CFHD_ENCODER) += x86/cfhdencdsp.o
|
||||
+endif
|
||||
X86ASM-OBJS-$(CONFIG_CFHD_DECODER) += x86/cfhddsp.o
|
||||
X86ASM-OBJS-$(CONFIG_DCA_DECODER) += x86/dcadsp.o x86/synth_filter.o
|
||||
X86ASM-OBJS-$(CONFIG_DIRAC_DECODER) += x86/diracdsp.o \
|
||||
@@ -175,15 +177,21 @@ x86/hevc_sao_10bit.o
|
||||
X86ASM-OBJS-$(CONFIG_JPEG2000_DECODER) += x86/jpeg2000dsp.o
|
||||
X86ASM-OBJS-$(CONFIG_LSCR_DECODER) += x86/pngdsp.o
|
||||
+ifdef ARCH_X86_64
|
||||
X86ASM-OBJS-$(CONFIG_MLP_DECODER) += x86/mlpdsp.o
|
||||
+endif
|
||||
X86ASM-OBJS-$(CONFIG_MPEG4_DECODER) += x86/xvididct.o
|
||||
X86ASM-OBJS-$(CONFIG_PNG_DECODER) += x86/pngdsp.o
|
||||
+ifdef ARCH_X86_64
|
||||
X86ASM-OBJS-$(CONFIG_PRORES_DECODER) += x86/proresdsp.o
|
||||
X86ASM-OBJS-$(CONFIG_PRORES_LGPL_DECODER) += x86/proresdsp.o
|
||||
+endif
|
||||
X86ASM-OBJS-$(CONFIG_RV40_DECODER) += x86/rv40dsp.o
|
||||
X86ASM-OBJS-$(CONFIG_SBC_ENCODER) += x86/sbcdsp.o
|
||||
X86ASM-OBJS-$(CONFIG_SVQ1_ENCODER) += x86/svq1enc.o
|
||||
X86ASM-OBJS-$(CONFIG_TAK_DECODER) += x86/takdsp.o
|
||||
+ifdef ARCH_X86_64
|
||||
X86ASM-OBJS-$(CONFIG_TRUEHD_DECODER) += x86/mlpdsp.o
|
||||
+endif
|
||||
X86ASM-OBJS-$(CONFIG_TTA_DECODER) += x86/ttadsp.o
|
||||
X86ASM-OBJS-$(CONFIG_TTA_ENCODER) += x86/ttaencdsp.o
|
||||
X86ASM-OBJS-$(CONFIG_UTVIDEO_DECODER) += x86/utvideodsp.o
|
||||
diff --git a/libavfilter/x86/Makefile b/libavfilter/x86/Makefile
|
||||
--- a/libavfilter/x86/Makefile
|
||||
+++ b/libavfilter/x86/Makefile
|
||||
@@ -44,6 +44,8 @@
|
||||
X86ASM-OBJS-$(CONFIG_AFIR_FILTER) += x86/af_afir.o
|
||||
X86ASM-OBJS-$(CONFIG_ANLMDN_FILTER) += x86/af_anlmdn.o
|
||||
+ifdef ARCH_X86_64
|
||||
X86ASM-OBJS-$(CONFIG_ATADENOISE_FILTER) += x86/vf_atadenoise.o
|
||||
+endif
|
||||
X86ASM-OBJS-$(CONFIG_BLEND_FILTER) += x86/vf_blend.o
|
||||
X86ASM-OBJS-$(CONFIG_BWDIF_FILTER) += x86/vf_bwdif.o
|
||||
X86ASM-OBJS-$(CONFIG_COLORSPACE_FILTER) += x86/colorspacedsp.o
|
||||
@@ -62,6 +62,8 @@ X86ASM-OBJS-$(CONFIG_LUT3D_FILTER) += x86/vf_lut3d.o
|
||||
X86ASM-OBJS-$(CONFIG_MASKEDCLAMP_FILTER) += x86/vf_maskedclamp.o
|
||||
X86ASM-OBJS-$(CONFIG_MASKEDMERGE_FILTER) += x86/vf_maskedmerge.o
|
||||
+ifdef ARCH_X86_64
|
||||
X86ASM-OBJS-$(CONFIG_NLMEANS_FILTER) += x86/vf_nlmeans.o
|
||||
+endif
|
||||
X86ASM-OBJS-$(CONFIG_OVERLAY_FILTER) += x86/vf_overlay.o
|
||||
X86ASM-OBJS-$(CONFIG_PP7_FILTER) += x86/vf_pp7.o
|
||||
X86ASM-OBJS-$(CONFIG_PSNR_FILTER) += x86/vf_psnr.o
|
||||
diff --git a/libavcodec/x86/mlpdsp.asm b/libavcodec/x86/mlpdsp.asm
|
||||
index 3dc641e..609b834 100644
|
||||
--- a/libavcodec/x86/mlpdsp.asm
|
||||
+++ b/libavcodec/x86/mlpdsp.asm
|
||||
@@ -23,7 +23,9 @@
|
||||
|
||||
SECTION .text
|
||||
|
||||
-%if ARCH_X86_64
|
||||
+%ifn ARCH_X86_64
|
||||
+mlpdsp_placeholder: times 4 db 0
|
||||
+%else
|
||||
|
||||
%macro SHLX 2
|
||||
%if cpuflag(bmi2)
|
||||
diff --git a/libavcodec/x86/proresdsp.asm b/libavcodec/x86/proresdsp.asm
|
||||
index 65c9fad..5ad73f3 100644
|
||||
--- a/libavcodec/x86/proresdsp.asm
|
||||
+++ b/libavcodec/x86/proresdsp.asm
|
||||
@@ -24,7 +24,10 @@
|
||||
|
||||
%include "libavutil/x86/x86util.asm"
|
||||
|
||||
-%if ARCH_X86_64
|
||||
+%ifn ARCH_X86_64
|
||||
+SECTION .rdata
|
||||
+proresdsp_placeholder: times 4 db 0
|
||||
+%else
|
||||
|
||||
SECTION_RODATA
|
||||
|
||||
diff --git a/libavcodec/x86/vvc/vvc_mc.asm b/libavcodec/x86/vvc/vvc_mc.asm
|
||||
index 30aa97c..3975f98 100644
|
||||
--- a/libavcodec/x86/vvc/vvc_mc.asm
|
||||
+++ b/libavcodec/x86/vvc/vvc_mc.asm
|
||||
@@ -31,7 +31,9 @@
|
||||
|
||||
SECTION_RODATA 32
|
||||
|
||||
-%if ARCH_X86_64
|
||||
+%ifn ARCH_X86_64
|
||||
+vvc_mc_placeholder: times 4 db 0
|
||||
+%else
|
||||
|
||||
%if HAVE_AVX2_EXTERNAL
|
||||
|
||||
diff --git a/libavfilter/x86/vf_atadenoise.asm b/libavfilter/x86/vf_atadenoise.asm
|
||||
index 4945ad3..748b65a 100644
|
||||
--- a/libavfilter/x86/vf_atadenoise.asm
|
||||
+++ b/libavfilter/x86/vf_atadenoise.asm
|
||||
@@ -20,7 +20,10 @@
|
||||
;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
;******************************************************************************
|
||||
|
||||
-%if ARCH_X86_64
|
||||
+%ifn ARCH_X86_64
|
||||
+SECTION .rdata
|
||||
+vf_atadenoise_placeholder: times 4 db 0
|
||||
+%else
|
||||
|
||||
%include "libavutil/x86/x86util.asm"
|
||||
|
||||
diff --git a/libavfilter/x86/vf_nlmeans.asm b/libavfilter/x86/vf_nlmeans.asm
|
||||
index 8f57801..9aef3a4 100644
|
||||
--- a/libavfilter/x86/vf_nlmeans.asm
|
||||
+++ b/libavfilter/x86/vf_nlmeans.asm
|
||||
@@ -21,7 +21,10 @@
|
||||
|
||||
%include "libavutil/x86/x86util.asm"
|
||||
|
||||
-%if HAVE_AVX2_EXTERNAL && ARCH_X86_64
|
||||
+%ifn HAVE_AVX2_EXTERNAL && ARCH_X86_64
|
||||
+SECTION .rdata
|
||||
+vf_nlmeans_placeholder: times 4 db 0
|
||||
+%else
|
||||
|
||||
SECTION_RODATA 32
|
||||
|
||||
|
||||
12
res/vcpkg/ffmpeg/0007-fix-lib-naming.patch
Normal file
12
res/vcpkg/ffmpeg/0007-fix-lib-naming.patch
Normal file
@@ -0,0 +1,12 @@
|
||||
diff --git a/configure b/configure
|
||||
index d6c4388..75b96c3 100644
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -4781,6 +4781,7 @@ msvc_common_flags(){
|
||||
-mfp16-format=*) ;;
|
||||
-lz) echo zlib.lib ;;
|
||||
-lx264) echo libx264.lib ;;
|
||||
+ -lmp3lame) echo libmp3lame.lib ;;
|
||||
-lstdc++) ;;
|
||||
-l*) echo ${flag#-l}.lib ;;
|
||||
-LARGEADDRESSAWARE) echo $flag ;;
|
||||
@@ -1,14 +0,0 @@
|
||||
diff --git a/configure b/configure
|
||||
index 2be953f7e7..e075949ffc 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -6497,6 +6497,7 @@ enabled openssl && { { check_pkg_config openssl "openssl >= 3.0.0
|
||||
{ enabled gplv3 || ! enabled gpl || enabled nonfree || die "ERROR: OpenSSL >=3.0.0 requires --enable-version3"; }; } ||
|
||||
{ enabled gpl && ! enabled nonfree && die "ERROR: OpenSSL <3.0.0 is incompatible with the gpl"; } ||
|
||||
check_pkg_config openssl openssl openssl/ssl.h OPENSSL_init_ssl ||
|
||||
check_pkg_config openssl openssl openssl/ssl.h SSL_library_init ||
|
||||
+ check_lib openssl openssl/ssl.h OPENSSL_init_ssl -lssl -lcrypto $pthreads_extralibs -ldl ||
|
||||
check_lib openssl openssl/ssl.h OPENSSL_init_ssl -lssl -lcrypto ||
|
||||
check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto ||
|
||||
check_lib openssl openssl/ssl.h SSL_library_init -lssl32 -leay32 ||
|
||||
|
||||
28
res/vcpkg/ffmpeg/0020-fix-aarch64-libswscale.patch
Normal file
28
res/vcpkg/ffmpeg/0020-fix-aarch64-libswscale.patch
Normal file
@@ -0,0 +1,28 @@
|
||||
diff --git a/libswscale/aarch64/yuv2rgb_neon.S b/libswscale/aarch64/yuv2rgb_neon.S
|
||||
index 89d69e7f6c..4bc1607a7a 100644
|
||||
--- a/libswscale/aarch64/yuv2rgb_neon.S
|
||||
+++ b/libswscale/aarch64/yuv2rgb_neon.S
|
||||
@@ -169,19 +169,19 @@ function ff_\ifmt\()_to_\ofmt\()_neon, export=1
|
||||
sqdmulh v26.8h, v26.8h, v0.8h // ((Y1*(1<<3) - y_offset) * y_coeff) >> 15
|
||||
sqdmulh v27.8h, v27.8h, v0.8h // ((Y2*(1<<3) - y_offset) * y_coeff) >> 15
|
||||
|
||||
-.ifc \ofmt,argb // 1 2 3 0
|
||||
+.ifc \ofmt,argb
|
||||
compute_rgba v5.8b,v6.8b,v7.8b,v4.8b, v17.8b,v18.8b,v19.8b,v16.8b
|
||||
.endif
|
||||
|
||||
-.ifc \ofmt,rgba // 0 1 2 3
|
||||
+.ifc \ofmt,rgba
|
||||
compute_rgba v4.8b,v5.8b,v6.8b,v7.8b, v16.8b,v17.8b,v18.8b,v19.8b
|
||||
.endif
|
||||
|
||||
-.ifc \ofmt,abgr // 3 2 1 0
|
||||
+.ifc \ofmt,abgr
|
||||
compute_rgba v7.8b,v6.8b,v5.8b,v4.8b, v19.8b,v18.8b,v17.8b,v16.8b
|
||||
.endif
|
||||
|
||||
-.ifc \ofmt,bgra // 2 1 0 3
|
||||
+.ifc \ofmt,bgra
|
||||
compute_rgba v6.8b,v5.8b,v4.8b,v7.8b, v18.8b,v17.8b,v16.8b,v19.8b
|
||||
.endif
|
||||
|
||||
15
res/vcpkg/ffmpeg/0024-fix-osx-host-c11.patch
Normal file
15
res/vcpkg/ffmpeg/0024-fix-osx-host-c11.patch
Normal file
@@ -0,0 +1,15 @@
|
||||
diff --git a/configure b/configure
|
||||
index 4f5353f84b..dd9147c677 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -5607,8 +5607,8 @@ check_cppflags -D_FILE_OFFSET_BITS=64
|
||||
check_cppflags -D_LARGEFILE_SOURCE
|
||||
|
||||
add_host_cppflags -D_ISOC11_SOURCE
|
||||
check_host_cflags_cc -std=$stdc ctype.h "__STDC_VERSION__ >= 201112L" ||
|
||||
- check_host_cflags_cc -std=c11 ctype.h "__STDC_VERSION__ >= 201112L" || die "Host compiler lacks C11 support"
|
||||
+ check_host_cflags_cc -std=c11 ctype.h "__STDC_VERSION__ >= 201112L"
|
||||
|
||||
check_host_cflags -Wall
|
||||
check_host_cflags $host_cflags_speed
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
|
||||
index cd7b0d941c..b4a6dce885 100644
|
||||
--- a/libavformat/avformat.h
|
||||
+++ b/libavformat/avformat.h
|
||||
@@ -1169,7 +1169,11 @@ typedef struct AVStreamGroup {
|
||||
} AVStreamGroup;
|
||||
|
||||
struct AVCodecParserContext *av_stream_get_parser(const AVStream *s);
|
||||
|
||||
+// Chromium: We use the internal field first_dts vvv
|
||||
+int64_t av_stream_get_first_dts(const AVStream *st);
|
||||
+// Chromium: We use the internal field first_dts ^^^
|
||||
+
|
||||
#define AV_PROGRAM_RUNNING 1
|
||||
|
||||
/**
|
||||
diff --git a/libavformat/mux_utils.c b/libavformat/mux_utils.c
|
||||
index de7580c32d..0ef0fe530e 100644
|
||||
--- a/libavformat/mux_utils.c
|
||||
+++ b/libavformat/mux_utils.c
|
||||
@@ -29,7 +29,14 @@ #include "avformat.h"
|
||||
#include "avio.h"
|
||||
#include "internal.h"
|
||||
#include "mux.h"
|
||||
|
||||
+// Chromium: We use the internal field first_dts vvv
|
||||
+int64_t av_stream_get_first_dts(const AVStream *st)
|
||||
+{
|
||||
+ return cffstream(st)->first_dts;
|
||||
+}
|
||||
+// Chromium: We use the internal field first_dts ^^^
|
||||
+
|
||||
int avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID codec_id,
|
||||
int std_compliance)
|
||||
{
|
||||
13
res/vcpkg/ffmpeg/0041-add-const-for-opengl-definition.patch
Normal file
13
res/vcpkg/ffmpeg/0041-add-const-for-opengl-definition.patch
Normal file
@@ -0,0 +1,13 @@
|
||||
diff --git a/libavdevice/opengl_enc.c b/libavdevice/opengl_enc.c
|
||||
index b2ac6eb..6351614 100644
|
||||
--- a/libavdevice/opengl_enc.c
|
||||
+++ b/libavdevice/opengl_enc.c
|
||||
@@ -116,7 +116,7 @@ typedef void (APIENTRY *FF_PFNGLATTACHSHADERPROC) (GLuint program, GLuint shad
|
||||
typedef GLuint (APIENTRY *FF_PFNGLCREATESHADERPROC) (GLenum type);
|
||||
typedef void (APIENTRY *FF_PFNGLDELETESHADERPROC) (GLuint shader);
|
||||
typedef void (APIENTRY *FF_PFNGLCOMPILESHADERPROC) (GLuint shader);
|
||||
-typedef void (APIENTRY *FF_PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const char* *string, const GLint *length);
|
||||
+typedef void (APIENTRY *FF_PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const char* const *string, const GLint *length);
|
||||
typedef void (APIENTRY *FF_PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
|
||||
typedef void (APIENTRY *FF_PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, char *infoLog);
|
||||
|
||||
9
res/vcpkg/ffmpeg/0042-fix-arm64-linux.patch
Normal file
9
res/vcpkg/ffmpeg/0042-fix-arm64-linux.patch
Normal file
@@ -0,0 +1,9 @@
|
||||
diff --git a/ffbuild/libversion.sh b/ffbuild/libversion.sh
|
||||
index a94ab58..ecaa90c 100644
|
||||
--- a/ffbuild/libversion.sh
|
||||
+++ b/ffbuild/libversion.sh
|
||||
@@ -1,3 +1,4 @@
|
||||
+#!/bin/sh
|
||||
toupper(){
|
||||
echo "$@" | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||
}
|
||||
12
res/vcpkg/ffmpeg/0043-fix-miss-head.patch
Normal file
12
res/vcpkg/ffmpeg/0043-fix-miss-head.patch
Normal file
@@ -0,0 +1,12 @@
|
||||
diff --git a/libavfilter/textutils.c b/libavfilter/textutils.c
|
||||
index ef658d0..c61b0ad 100644
|
||||
--- a/libavfilter/textutils.c
|
||||
+++ b/libavfilter/textutils.c
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "libavutil/file.h"
|
||||
#include "libavutil/mem.h"
|
||||
#include "libavutil/time.h"
|
||||
+#include "libavutil/time_internal.h"
|
||||
|
||||
static int ff_expand_text_function_internal(FFExpandTextContext *expand_text, AVBPrint *bp,
|
||||
char *name, unsigned argc, char **argv)
|
||||
@@ -1,7 +1,7 @@
|
||||
From f6988e5424e041ff6f6e241f4d8fa69a04c05e64 Mon Sep 17 00:00:00 2001
|
||||
From da6921d5bcb50961193526f47aa2dbe71ee5fe81 Mon Sep 17 00:00:00 2001
|
||||
From: 21pages <sunboeasy@gmail.com>
|
||||
Date: Thu, 5 Sep 2024 16:26:20 +0800
|
||||
Subject: [PATCH 1/3] avcodec/amfenc: add query_timeout option for h264/hevc
|
||||
Date: Tue, 10 Dec 2024 13:40:46 +0800
|
||||
Subject: [PATCH 1/5] avcodec/amfenc: add query_timeout option for h264/hevc
|
||||
|
||||
Signed-off-by: 21pages <sunboeasy@gmail.com>
|
||||
---
|
||||
@@ -11,10 +11,10 @@ Signed-off-by: 21pages <sunboeasy@gmail.com>
|
||||
3 files changed, 9 insertions(+)
|
||||
|
||||
diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h
|
||||
index 2dbd378ef8..d636673a9d 100644
|
||||
index d985d01bb1..320c66919e 100644
|
||||
--- a/libavcodec/amfenc.h
|
||||
+++ b/libavcodec/amfenc.h
|
||||
@@ -89,6 +89,7 @@ typedef struct AmfContext {
|
||||
@@ -91,6 +91,7 @@ typedef struct AmfContext {
|
||||
int quality;
|
||||
int b_frame_delta_qp;
|
||||
int ref_b_frame_delta_qp;
|
||||
@@ -23,40 +23,40 @@ index 2dbd378ef8..d636673a9d 100644
|
||||
// Dynamic options, can be set after Init() call
|
||||
|
||||
diff --git a/libavcodec/amfenc_h264.c b/libavcodec/amfenc_h264.c
|
||||
index c1d5f4054e..415828f005 100644
|
||||
index 8edd39c633..6ad4961b2f 100644
|
||||
--- a/libavcodec/amfenc_h264.c
|
||||
+++ b/libavcodec/amfenc_h264.c
|
||||
@@ -135,6 +135,7 @@ static const AVOption options[] = {
|
||||
{ "aud", "Inserts AU Delimiter NAL unit", OFFSET(aud) ,AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
|
||||
@@ -137,6 +137,7 @@ static const AVOption options[] = {
|
||||
|
||||
|
||||
{ "log_to_dbg", "Enable AMF logging to debug output", OFFSET(log_to_dbg) , AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
|
||||
+ { "query_timeout", "Timeout for QueryOutput call in ms", OFFSET(query_timeout), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, 1000, VE },
|
||||
|
||||
//Pre Analysis options
|
||||
{ "preanalysis", "Enable preanalysis", OFFSET(preanalysis), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE },
|
||||
@@ -222,6 +223,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
@@ -228,6 +229,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
|
||||
AMF_ASSIGN_PROPERTY_RATE(res, ctx->encoder, AMF_VIDEO_ENCODER_FRAMERATE, framerate);
|
||||
|
||||
+ if (ctx->query_timeout >= 0)
|
||||
+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QUERY_TIMEOUT, ctx->query_timeout);
|
||||
+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QUERY_TIMEOUT, ctx->query_timeout);
|
||||
+
|
||||
switch (avctx->profile) {
|
||||
case AV_PROFILE_H264_BASELINE:
|
||||
profile = AMF_VIDEO_ENCODER_PROFILE_BASELINE;
|
||||
diff --git a/libavcodec/amfenc_hevc.c b/libavcodec/amfenc_hevc.c
|
||||
index 33a167aa52..65259d7153 100644
|
||||
index 4898824f3a..22cb95c7ce 100644
|
||||
--- a/libavcodec/amfenc_hevc.c
|
||||
+++ b/libavcodec/amfenc_hevc.c
|
||||
@@ -98,6 +98,7 @@ static const AVOption options[] = {
|
||||
{ "aud", "Inserts AU Delimiter NAL unit", OFFSET(aud) ,AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE },
|
||||
@@ -104,6 +104,7 @@ static const AVOption options[] = {
|
||||
|
||||
|
||||
{ "log_to_dbg", "Enable AMF logging to debug output", OFFSET(log_to_dbg), AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE },
|
||||
+ { "query_timeout", "Timeout for QueryOutput call in ms", OFFSET(query_timeout), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, 1000, VE },
|
||||
|
||||
//Pre Analysis options
|
||||
{ "preanalysis", "Enable preanalysis", OFFSET(preanalysis), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE },
|
||||
@@ -183,6 +184,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
@@ -194,6 +195,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
|
||||
AMF_ASSIGN_PROPERTY_RATE(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_FRAMERATE, framerate);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 6e76c57cf2c0e790228f19c88089eef110fd74aa Mon Sep 17 00:00:00 2001
|
||||
From 8d061adb7b00fc765b8001307c025437ef1cad88 Mon Sep 17 00:00:00 2001
|
||||
From: 21pages <sunboeasy@gmail.com>
|
||||
Date: Thu, 5 Sep 2024 16:32:16 +0800
|
||||
Subject: [PATCH 2/3] libavcodec/amfenc: reconfig when bitrate change
|
||||
Subject: [PATCH 2/5] libavcodec/amfenc: reconfig when bitrate change
|
||||
|
||||
Signed-off-by: 21pages <sunboeasy@gmail.com>
|
||||
---
|
||||
@@ -10,10 +10,10 @@ Signed-off-by: 21pages <sunboeasy@gmail.com>
|
||||
2 files changed, 21 insertions(+)
|
||||
|
||||
diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c
|
||||
index 061859f85c..97587fe66b 100644
|
||||
index a47aea6108..f70f0109f6 100644
|
||||
--- a/libavcodec/amfenc.c
|
||||
+++ b/libavcodec/amfenc.c
|
||||
@@ -222,6 +222,7 @@ static int amf_init_context(AVCodecContext *avctx)
|
||||
@@ -275,6 +275,7 @@ static int amf_init_context(AVCodecContext *avctx)
|
||||
|
||||
ctx->hwsurfaces_in_queue = 0;
|
||||
ctx->hwsurfaces_in_queue_max = 16;
|
||||
@@ -21,7 +21,7 @@ index 061859f85c..97587fe66b 100644
|
||||
|
||||
// configure AMF logger
|
||||
// the return of these functions indicates old state and do not affect behaviour
|
||||
@@ -583,6 +584,23 @@ static void amf_release_buffer_with_frame_ref(AMFBuffer *frame_ref_storage_buffe
|
||||
@@ -640,6 +641,23 @@ static void amf_release_buffer_with_frame_ref(AMFBuffer *frame_ref_storage_buffe
|
||||
frame_ref_storage_buffer->pVtbl->Release(frame_ref_storage_buffer);
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ index 061859f85c..97587fe66b 100644
|
||||
int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
|
||||
{
|
||||
AmfContext *ctx = avctx->priv_data;
|
||||
@@ -596,6 +614,8 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
|
||||
@@ -653,6 +671,8 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
|
||||
int query_output_data_flag = 0;
|
||||
AMF_RESULT res_resubmit;
|
||||
|
||||
@@ -55,10 +55,10 @@ index 061859f85c..97587fe66b 100644
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h
|
||||
index d636673a9d..09506ee2e0 100644
|
||||
index 320c66919e..481e0fb75d 100644
|
||||
--- a/libavcodec/amfenc.h
|
||||
+++ b/libavcodec/amfenc.h
|
||||
@@ -113,6 +113,7 @@ typedef struct AmfContext {
|
||||
@@ -115,6 +115,7 @@ typedef struct AmfContext {
|
||||
int max_b_frames;
|
||||
int qvbr_quality_level;
|
||||
int hw_high_motion_quality_boost;
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
From 14b77216106eaaff9cf701528039ae4264eaf420 Mon Sep 17 00:00:00 2001
|
||||
From: 21pages <sunboeasy@gmail.com>
|
||||
Date: Thu, 5 Sep 2024 16:41:59 +0800
|
||||
Subject: [PATCH 3/3] amf colorspace
|
||||
|
||||
Signed-off-by: 21pages <sunboeasy@gmail.com>
|
||||
---
|
||||
libavcodec/amfenc.h | 1 +
|
||||
libavcodec/amfenc_h264.c | 40 ++++++++++++++++++++++++++++++++++
|
||||
libavcodec/amfenc_hevc.c | 47 ++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 88 insertions(+)
|
||||
|
||||
diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h
|
||||
index 09506ee2e0..7f458b14f7 100644
|
||||
--- a/libavcodec/amfenc.h
|
||||
+++ b/libavcodec/amfenc.h
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <AMF/components/VideoEncoderVCE.h>
|
||||
#include <AMF/components/VideoEncoderHEVC.h>
|
||||
#include <AMF/components/VideoEncoderAV1.h>
|
||||
+#include <AMF/components/ColorSpace.h>
|
||||
|
||||
#include "libavutil/fifo.h"
|
||||
|
||||
diff --git a/libavcodec/amfenc_h264.c b/libavcodec/amfenc_h264.c
|
||||
index 415828f005..7da5a96c71 100644
|
||||
--- a/libavcodec/amfenc_h264.c
|
||||
+++ b/libavcodec/amfenc_h264.c
|
||||
@@ -200,6 +200,9 @@ static av_cold int amf_encode_init_h264(AVCodecContext *avctx)
|
||||
AMFRate framerate;
|
||||
AMFSize framesize = AMFConstructSize(avctx->width, avctx->height);
|
||||
int deblocking_filter = (avctx->flags & AV_CODEC_FLAG_LOOP_FILTER) ? 1 : 0;
|
||||
+ amf_int64 color_depth;
|
||||
+ amf_int64 color_profile;
|
||||
+ enum AVPixelFormat pix_fmt;
|
||||
|
||||
if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
|
||||
framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den);
|
||||
@@ -266,10 +269,47 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder, AMF_VIDEO_ENCODER_ASPECT_RATIO, ratio);
|
||||
}
|
||||
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN;
|
||||
/// Color Range (Partial/TV/MPEG or Full/PC/JPEG)
|
||||
if (avctx->color_range == AVCOL_RANGE_JPEG) {
|
||||
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_FULL_RANGE_COLOR, 1);
|
||||
+ switch (avctx->colorspace) {
|
||||
+ case AVCOL_SPC_SMPTE170M:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_601;
|
||||
+ break;
|
||||
+ case AVCOL_SPC_BT709:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_709;
|
||||
+ break;
|
||||
+ case AVCOL_SPC_BT2020_NCL:
|
||||
+ case AVCOL_SPC_BT2020_CL:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_2020;
|
||||
+ break;
|
||||
+ }
|
||||
+ } else {
|
||||
+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_FULL_RANGE_COLOR, 0);
|
||||
+ switch (avctx->colorspace) {
|
||||
+ case AVCOL_SPC_SMPTE170M:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_601;
|
||||
+ break;
|
||||
+ case AVCOL_SPC_BT709:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_709;
|
||||
+ break;
|
||||
+ case AVCOL_SPC_BT2020_NCL:
|
||||
+ case AVCOL_SPC_BT2020_CL:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_2020;
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
+ pix_fmt = avctx->hw_frames_ctx ? ((AVHWFramesContext*)avctx->hw_frames_ctx->data)->sw_format : avctx->pix_fmt;
|
||||
+ color_depth = AMF_COLOR_BIT_DEPTH_8;
|
||||
+ if (pix_fmt == AV_PIX_FMT_P010) {
|
||||
+ color_depth = AMF_COLOR_BIT_DEPTH_10;
|
||||
+ }
|
||||
+
|
||||
+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_COLOR_BIT_DEPTH, color_depth);
|
||||
+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_OUTPUT_COLOR_PROFILE, color_profile);
|
||||
+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_OUTPUT_TRANSFER_CHARACTERISTIC, (amf_int64)avctx->color_trc);
|
||||
+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_OUTPUT_COLOR_PRIMARIES, (amf_int64)avctx->color_primaries);
|
||||
|
||||
// autodetect rate control method
|
||||
if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN) {
|
||||
diff --git a/libavcodec/amfenc_hevc.c b/libavcodec/amfenc_hevc.c
|
||||
index 65259d7153..7c930d3ccc 100644
|
||||
--- a/libavcodec/amfenc_hevc.c
|
||||
+++ b/libavcodec/amfenc_hevc.c
|
||||
@@ -161,6 +161,9 @@ static av_cold int amf_encode_init_hevc(AVCodecContext *avctx)
|
||||
AMFRate framerate;
|
||||
AMFSize framesize = AMFConstructSize(avctx->width, avctx->height);
|
||||
int deblocking_filter = (avctx->flags & AV_CODEC_FLAG_LOOP_FILTER) ? 1 : 0;
|
||||
+ amf_int64 color_depth;
|
||||
+ amf_int64 color_profile;
|
||||
+ enum AVPixelFormat pix_fmt;
|
||||
|
||||
if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
|
||||
framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den);
|
||||
@@ -191,6 +194,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
case AV_PROFILE_HEVC_MAIN:
|
||||
profile = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN;
|
||||
break;
|
||||
+ case AV_PROFILE_HEVC_MAIN_10:
|
||||
+ profile = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN_10;
|
||||
+ break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -219,6 +225,47 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ASPECT_RATIO, ratio);
|
||||
}
|
||||
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN;
|
||||
+ if (avctx->color_range == AVCOL_RANGE_JPEG) {
|
||||
+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_NOMINAL_RANGE, 1);
|
||||
+ switch (avctx->colorspace) {
|
||||
+ case AVCOL_SPC_SMPTE170M:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_601;
|
||||
+ break;
|
||||
+ case AVCOL_SPC_BT709:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_709;
|
||||
+ break;
|
||||
+ case AVCOL_SPC_BT2020_NCL:
|
||||
+ case AVCOL_SPC_BT2020_CL:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_2020;
|
||||
+ break;
|
||||
+ }
|
||||
+ } else {
|
||||
+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_NOMINAL_RANGE, 0);
|
||||
+ switch (avctx->colorspace) {
|
||||
+ case AVCOL_SPC_SMPTE170M:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_601;
|
||||
+ break;
|
||||
+ case AVCOL_SPC_BT709:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_709;
|
||||
+ break;
|
||||
+ case AVCOL_SPC_BT2020_NCL:
|
||||
+ case AVCOL_SPC_BT2020_CL:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_2020;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ pix_fmt = avctx->hw_frames_ctx ? ((AVHWFramesContext*)avctx->hw_frames_ctx->data)->sw_format : avctx->pix_fmt;
|
||||
+ color_depth = AMF_COLOR_BIT_DEPTH_8;
|
||||
+ if (pix_fmt == AV_PIX_FMT_P010) {
|
||||
+ color_depth = AMF_COLOR_BIT_DEPTH_10;
|
||||
+ }
|
||||
+
|
||||
+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_COLOR_BIT_DEPTH, color_depth);
|
||||
+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_COLOR_PROFILE, color_profile);
|
||||
+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_TRANSFER_CHARACTERISTIC, (amf_int64)avctx->color_trc);
|
||||
+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_COLOR_PRIMARIES, (amf_int64)avctx->color_primaries);
|
||||
+
|
||||
// Picture control properties
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_NUM_GOPS_PER_IDR, ctx->gops_per_idr);
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_GOP_SIZE, avctx->gop_size);
|
||||
--
|
||||
2.43.0.windows.1
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
From d74de94b49efcf7a0b25673ace6016938d1b9272 Mon Sep 17 00:00:00 2001
|
||||
From: 21pages <sunboeasy@gmail.com>
|
||||
Date: Tue, 10 Dec 2024 14:12:01 +0800
|
||||
Subject: [PATCH 3/5] videotoolbox changing bitrate
|
||||
|
||||
Signed-off-by: 21pages <sunboeasy@gmail.com>
|
||||
---
|
||||
libavcodec/videotoolboxenc.c | 40 ++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 40 insertions(+)
|
||||
|
||||
diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c
|
||||
index da7b291b03..3c866177f5 100644
|
||||
--- a/libavcodec/videotoolboxenc.c
|
||||
+++ b/libavcodec/videotoolboxenc.c
|
||||
@@ -279,6 +279,8 @@ typedef struct VTEncContext {
|
||||
int max_slice_bytes;
|
||||
int power_efficient;
|
||||
int max_ref_frames;
|
||||
+
|
||||
+ int last_bit_rate;
|
||||
} VTEncContext;
|
||||
|
||||
static void vtenc_free_buf_node(BufNode *info)
|
||||
@@ -1180,6 +1182,7 @@ static int vtenc_create_encoder(AVCodecContext *avctx,
|
||||
int64_t one_second_value = 0;
|
||||
void *nums[2];
|
||||
|
||||
+ vtctx->last_bit_rate = bit_rate;
|
||||
int status = VTCompressionSessionCreate(kCFAllocatorDefault,
|
||||
avctx->width,
|
||||
avctx->height,
|
||||
@@ -2638,6 +2641,42 @@ out:
|
||||
return status;
|
||||
}
|
||||
|
||||
+static void update_config(AVCodecContext *avctx)
|
||||
+{
|
||||
+ VTEncContext *vtctx = avctx->priv_data;
|
||||
+
|
||||
+ if (avctx->codec_id != AV_CODEC_ID_PRORES) {
|
||||
+ if (avctx->bit_rate != vtctx->last_bit_rate) {
|
||||
+ av_log(avctx, AV_LOG_INFO, "Setting bit rate to %d\n", avctx->bit_rate);
|
||||
+ vtctx->last_bit_rate = avctx->bit_rate;
|
||||
+ SInt32 bit_rate = avctx->bit_rate;
|
||||
+ CFNumberRef bit_rate_num = CFNumberCreate(kCFAllocatorDefault,
|
||||
+ kCFNumberSInt32Type,
|
||||
+ &bit_rate);
|
||||
+ if (!bit_rate_num) return;
|
||||
+
|
||||
+ if (vtctx->constant_bit_rate) {
|
||||
+ int status = VTSessionSetProperty(vtctx->session,
|
||||
+ compat_keys.kVTCompressionPropertyKey_ConstantBitRate,
|
||||
+ bit_rate_num);
|
||||
+ if (status == kVTPropertyNotSupportedErr) {
|
||||
+ av_log(avctx, AV_LOG_ERROR, "Error: -constant_bit_rate true is not supported by the encoder.\n");
|
||||
+ }
|
||||
+ } else {
|
||||
+ int status = VTSessionSetProperty(vtctx->session,
|
||||
+ kVTCompressionPropertyKey_AverageBitRate,
|
||||
+ bit_rate_num);
|
||||
+ if (!status) {
|
||||
+ av_log(avctx, AV_LOG_ERROR, "Error: cannot set average bit rate: %d\n", status);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ CFRelease(bit_rate_num);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
static av_cold int vtenc_frame(
|
||||
AVCodecContext *avctx,
|
||||
AVPacket *pkt,
|
||||
@@ -2650,6 +2689,7 @@ static av_cold int vtenc_frame(
|
||||
CMSampleBufferRef buf = NULL;
|
||||
ExtraSEI sei = {0};
|
||||
|
||||
+ update_config(avctx);
|
||||
if (frame) {
|
||||
status = vtenc_send_frame(avctx, vtctx, frame);
|
||||
|
||||
--
|
||||
2.43.0.windows.1
|
||||
|
||||
246
res/vcpkg/ffmpeg/patch/0005-mediacodec-changing-bitrate.patch
Normal file
246
res/vcpkg/ffmpeg/patch/0005-mediacodec-changing-bitrate.patch
Normal file
@@ -0,0 +1,246 @@
|
||||
From 7323bd68c1b34e9298ea557ff7a3e1883b653957 Mon Sep 17 00:00:00 2001
|
||||
From: 21pages <sunboeasy@gmail.com>
|
||||
Date: Tue, 10 Dec 2024 14:28:16 +0800
|
||||
Subject: [PATCH 4/5] mediacodec changing bitrate
|
||||
|
||||
Signed-off-by: 21pages <sunboeasy@gmail.com>
|
||||
---
|
||||
libavcodec/mediacodec_wrapper.c | 98 +++++++++++++++++++++++++++++++++
|
||||
libavcodec/mediacodec_wrapper.h | 7 +++
|
||||
libavcodec/mediacodecenc.c | 18 ++++++
|
||||
3 files changed, 123 insertions(+)
|
||||
|
||||
diff --git a/libavcodec/mediacodec_wrapper.c b/libavcodec/mediacodec_wrapper.c
|
||||
index 96c886666a..06b8504304 100644
|
||||
--- a/libavcodec/mediacodec_wrapper.c
|
||||
+++ b/libavcodec/mediacodec_wrapper.c
|
||||
@@ -35,6 +35,8 @@
|
||||
#include "ffjni.h"
|
||||
#include "mediacodec_wrapper.h"
|
||||
|
||||
+#define PARAMETER_KEY_VIDEO_BITRATE "video-bitrate"
|
||||
+
|
||||
struct JNIAMediaCodecListFields {
|
||||
|
||||
jclass mediacodec_list_class;
|
||||
@@ -195,6 +197,8 @@ struct JNIAMediaCodecFields {
|
||||
jmethodID set_input_surface_id;
|
||||
jmethodID signal_end_of_input_stream_id;
|
||||
|
||||
+ jmethodID set_parameters_id;
|
||||
+
|
||||
jclass mediainfo_class;
|
||||
|
||||
jmethodID init_id;
|
||||
@@ -248,6 +252,8 @@ static const struct FFJniField jni_amediacodec_mapping[] = {
|
||||
{ "android/media/MediaCodec", "setInputSurface", "(Landroid/view/Surface;)V", FF_JNI_METHOD, OFFSET(set_input_surface_id), 0 },
|
||||
{ "android/media/MediaCodec", "signalEndOfInputStream", "()V", FF_JNI_METHOD, OFFSET(signal_end_of_input_stream_id), 0 },
|
||||
|
||||
+ { "android/media/MediaCodec", "setParameters", "(Landroid/os/Bundle;)V", FF_JNI_METHOD, OFFSET(set_parameters_id), 0 },
|
||||
+
|
||||
{ "android/media/MediaCodec$BufferInfo", NULL, NULL, FF_JNI_CLASS, OFFSET(mediainfo_class), 1 },
|
||||
|
||||
{ "android/media/MediaCodec.BufferInfo", "<init>", "()V", FF_JNI_METHOD, OFFSET(init_id), 1 },
|
||||
@@ -292,6 +298,24 @@ typedef struct FFAMediaCodecJni {
|
||||
|
||||
static const FFAMediaCodec media_codec_jni;
|
||||
|
||||
+struct JNIABundleFields
|
||||
+{
|
||||
+ jclass bundle_class;
|
||||
+ jmethodID init_id;
|
||||
+ jmethodID put_int_id;
|
||||
+};
|
||||
+
|
||||
+#define OFFSET(x) offsetof(struct JNIABundleFields, x)
|
||||
+static const struct FFJniField jni_abundle_mapping[] = {
|
||||
+ { "android/os/Bundle", NULL, NULL, FF_JNI_CLASS, OFFSET(bundle_class), 1 },
|
||||
+
|
||||
+ { "android/os/Bundle", "<init>", "()V", FF_JNI_METHOD, OFFSET(init_id), 1 },
|
||||
+ { "android/os/Bundle", "putInt", "(Ljava/lang/String;I)V", FF_JNI_METHOD, OFFSET(put_int_id), 1 },
|
||||
+
|
||||
+ { NULL }
|
||||
+};
|
||||
+#undef OFFSET
|
||||
+
|
||||
#define JNI_GET_ENV_OR_RETURN(env, log_ctx, ret) do { \
|
||||
(env) = ff_jni_get_env(log_ctx); \
|
||||
if (!(env)) { \
|
||||
@@ -1762,6 +1786,70 @@ static int mediacodec_jni_signalEndOfInputStream(FFAMediaCodec *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+
|
||||
+static int mediacodec_jni_setParameter(FFAMediaCodec *ctx, const char* name, int value)
|
||||
+{
|
||||
+ JNIEnv *env = NULL;
|
||||
+ struct JNIABundleFields jfields = { 0 };
|
||||
+ jobject object = NULL;
|
||||
+ jstring key = NULL;
|
||||
+ FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
|
||||
+ void *log_ctx = codec;
|
||||
+ int ret = -1;
|
||||
+
|
||||
+ JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
|
||||
+
|
||||
+ if (ff_jni_init_jfields(env, &jfields, jni_abundle_mapping, 0, log_ctx) < 0) {
|
||||
+ av_log(log_ctx, AV_LOG_ERROR, "Failed to init jfields\n");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ object = (*env)->NewObject(env, jfields.bundle_class, jfields.init_id);
|
||||
+ if (!object) {
|
||||
+ av_log(log_ctx, AV_LOG_ERROR, "Failed to create bundle object\n");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ key = ff_jni_utf_chars_to_jstring(env, name, log_ctx);
|
||||
+ if (!key) {
|
||||
+ av_log(log_ctx, AV_LOG_ERROR, "Failed to convert key to jstring\n");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ (*env)->CallVoidMethod(env, object, jfields.put_int_id, key, value);
|
||||
+ if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ if (!codec->jfields.set_parameters_id) {
|
||||
+ av_log(log_ctx, AV_LOG_ERROR, "System doesn't support setParameters\n");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ (*env)->CallVoidMethod(env, codec->object, codec->jfields.set_parameters_id, object);
|
||||
+ if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ ret = 0;
|
||||
+
|
||||
+fail:
|
||||
+ if (key) {
|
||||
+ (*env)->DeleteLocalRef(env, key);
|
||||
+ }
|
||||
+ if (object) {
|
||||
+ (*env)->DeleteLocalRef(env, object);
|
||||
+ }
|
||||
+ ff_jni_reset_jfields(env, &jfields, jni_abundle_mapping, 0, log_ctx);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mediacodec_jni_setDynamicBitrate(FFAMediaCodec *ctx, int bitrate)
|
||||
+{
|
||||
+ return mediacodec_jni_setParameter(ctx, PARAMETER_KEY_VIDEO_BITRATE, bitrate);
|
||||
+}
|
||||
+
|
||||
static const FFAMediaFormat media_format_jni = {
|
||||
.class = &amediaformat_class,
|
||||
|
||||
@@ -1821,6 +1909,8 @@ static const FFAMediaCodec media_codec_jni = {
|
||||
.getConfigureFlagEncode = mediacodec_jni_getConfigureFlagEncode,
|
||||
.cleanOutputBuffers = mediacodec_jni_cleanOutputBuffers,
|
||||
.signalEndOfInputStream = mediacodec_jni_signalEndOfInputStream,
|
||||
+
|
||||
+ .setDynamicBitrate = mediacodec_jni_setDynamicBitrate,
|
||||
};
|
||||
|
||||
typedef struct FFAMediaFormatNdk {
|
||||
@@ -2335,6 +2425,12 @@ static int mediacodec_ndk_signalEndOfInputStream(FFAMediaCodec *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int mediacodec_ndk_setDynamicBitrate(FFAMediaCodec *ctx, int bitrate)
|
||||
+{
|
||||
+ av_log(ctx, AV_LOG_ERROR, "ndk setDynamicBitrate unavailable\n");
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
static const FFAMediaFormat media_format_ndk = {
|
||||
.class = &amediaformat_ndk_class,
|
||||
|
||||
@@ -2396,6 +2492,8 @@ static const FFAMediaCodec media_codec_ndk = {
|
||||
.getConfigureFlagEncode = mediacodec_ndk_getConfigureFlagEncode,
|
||||
.cleanOutputBuffers = mediacodec_ndk_cleanOutputBuffers,
|
||||
.signalEndOfInputStream = mediacodec_ndk_signalEndOfInputStream,
|
||||
+
|
||||
+ .setDynamicBitrate = mediacodec_ndk_setDynamicBitrate,
|
||||
};
|
||||
|
||||
FFAMediaFormat *ff_AMediaFormat_new(int ndk)
|
||||
diff --git a/libavcodec/mediacodec_wrapper.h b/libavcodec/mediacodec_wrapper.h
|
||||
index 11a4260497..86c64556ad 100644
|
||||
--- a/libavcodec/mediacodec_wrapper.h
|
||||
+++ b/libavcodec/mediacodec_wrapper.h
|
||||
@@ -219,6 +219,8 @@ struct FFAMediaCodec {
|
||||
|
||||
// For encoder with FFANativeWindow as input.
|
||||
int (*signalEndOfInputStream)(FFAMediaCodec *);
|
||||
+
|
||||
+ int (*setDynamicBitrate)(FFAMediaCodec *codec, int bitrate);
|
||||
};
|
||||
|
||||
static inline char *ff_AMediaCodec_getName(FFAMediaCodec *codec)
|
||||
@@ -343,6 +345,11 @@ static inline int ff_AMediaCodec_signalEndOfInputStream(FFAMediaCodec *codec)
|
||||
return codec->signalEndOfInputStream(codec);
|
||||
}
|
||||
|
||||
+static inline int ff_AMediaCodec_setDynamicBitrate(FFAMediaCodec *codec, int bitrate)
|
||||
+{
|
||||
+ return codec->setDynamicBitrate(codec, bitrate);
|
||||
+}
|
||||
+
|
||||
int ff_Build_SDK_INT(AVCodecContext *avctx);
|
||||
|
||||
enum FFAMediaFormatColorRange {
|
||||
diff --git a/libavcodec/mediacodecenc.c b/libavcodec/mediacodecenc.c
|
||||
index 6ca3968a24..221f7360f4 100644
|
||||
--- a/libavcodec/mediacodecenc.c
|
||||
+++ b/libavcodec/mediacodecenc.c
|
||||
@@ -76,6 +76,8 @@ typedef struct MediaCodecEncContext {
|
||||
int level;
|
||||
int pts_as_dts;
|
||||
int extract_extradata;
|
||||
+
|
||||
+ int last_bit_rate;
|
||||
} MediaCodecEncContext;
|
||||
|
||||
enum {
|
||||
@@ -193,6 +195,8 @@ static av_cold int mediacodec_init(AVCodecContext *avctx)
|
||||
int ret;
|
||||
int gop;
|
||||
|
||||
+ s->last_bit_rate = avctx->bit_rate;
|
||||
+
|
||||
if (s->use_ndk_codec < 0)
|
||||
s->use_ndk_codec = !av_jni_get_java_vm(avctx);
|
||||
|
||||
@@ -542,11 +546,25 @@ static int mediacodec_send(AVCodecContext *avctx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void update_config(AVCodecContext *avctx)
|
||||
+{
|
||||
+ MediaCodecEncContext *s = avctx->priv_data;
|
||||
+ if (avctx->bit_rate != s->last_bit_rate) {
|
||||
+ s->last_bit_rate = avctx->bit_rate;
|
||||
+ if (0 != ff_AMediaCodec_setDynamicBitrate(s->codec, avctx->bit_rate)) {
|
||||
+ av_log(avctx, AV_LOG_ERROR, "Failed to set bitrate to %d\n", avctx->bit_rate);
|
||||
+ } else {
|
||||
+ av_log(avctx, AV_LOG_INFO, "Set bitrate to %d\n", avctx->bit_rate);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int mediacodec_encode(AVCodecContext *avctx, AVPacket *pkt)
|
||||
{
|
||||
MediaCodecEncContext *s = avctx->priv_data;
|
||||
int ret;
|
||||
|
||||
+ update_config(avctx);
|
||||
// Return on three case:
|
||||
// 1. Serious error
|
||||
// 2. Got a packet success
|
||||
--
|
||||
2.43.0.windows.1
|
||||
|
||||
1883
res/vcpkg/ffmpeg/patch/0006-dlopen-libva.patch
Normal file
1883
res/vcpkg/ffmpeg/patch/0006-dlopen-libva.patch
Normal file
File diff suppressed because it is too large
Load Diff
30
res/vcpkg/ffmpeg/patch/0007-fix-linux-configure.patch
Normal file
30
res/vcpkg/ffmpeg/patch/0007-fix-linux-configure.patch
Normal file
@@ -0,0 +1,30 @@
|
||||
From 595f0468e127f204741b6c37a479d71daaf571eb Mon Sep 17 00:00:00 2001
|
||||
From: 21pages <sunboeasy@gmail.com>
|
||||
Date: Tue, 10 Dec 2024 21:17:14 +0800
|
||||
Subject: [PATCH] fix linux configure
|
||||
|
||||
Signed-off-by: 21pages <sunboeasy@gmail.com>
|
||||
---
|
||||
configure | 6 ------
|
||||
1 file changed, 6 deletions(-)
|
||||
|
||||
diff --git a/configure b/configure
|
||||
index d77a55b653..48ca90ac5e 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -7071,12 +7071,6 @@ enabled mmal && { check_lib mmal interface/mmal/mmal.h mmal_port_co
|
||||
check_lib mmal interface/mmal/mmal.h mmal_port_connect -lmmal_core -lmmal_util -lmmal_vc_client -lbcm_host; } ||
|
||||
die "ERROR: mmal not found" &&
|
||||
check_func_headers interface/mmal/mmal.h "MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS"; }
|
||||
-enabled openal && { check_pkg_config openal "openal >= 1.1" "AL/al.h" alGetError ||
|
||||
- { for al_extralibs in "${OPENAL_LIBS}" "-lopenal" "-lOpenAL32"; do
|
||||
- check_lib openal 'AL/al.h' alGetError "${al_extralibs}" && break; done } ||
|
||||
- die "ERROR: openal not found"; } &&
|
||||
- { test_cpp_condition "AL/al.h" "defined(AL_VERSION_1_1)" ||
|
||||
- die "ERROR: openal must be installed and version must be 1.1 or compatible"; }
|
||||
enabled opencl && { check_pkg_config opencl OpenCL CL/cl.h clEnqueueNDRangeKernel ||
|
||||
check_lib opencl OpenCL/cl.h clEnqueueNDRangeKernel "-framework OpenCL" ||
|
||||
check_lib opencl CL/cl.h clEnqueueNDRangeKernel -lOpenCL ||
|
||||
--
|
||||
2.34.1
|
||||
|
||||
26
res/vcpkg/ffmpeg/patch/0008-remove-amf-loop-query.patch
Normal file
26
res/vcpkg/ffmpeg/patch/0008-remove-amf-loop-query.patch
Normal file
@@ -0,0 +1,26 @@
|
||||
From 1440f556234d135ce58a2ef38916c6a63b05870e Mon Sep 17 00:00:00 2001
|
||||
From: 21pages <sunboeasy@gmail.com>
|
||||
Date: Sat, 14 Dec 2024 21:39:44 +0800
|
||||
Subject: [PATCH] remove amf loop query
|
||||
|
||||
Signed-off-by: 21pages <sunboeasy@gmail.com>
|
||||
---
|
||||
libavcodec/amfenc.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c
|
||||
index f70f0109f6..a53a05b16b 100644
|
||||
--- a/libavcodec/amfenc.c
|
||||
+++ b/libavcodec/amfenc.c
|
||||
@@ -886,7 +886,7 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
|
||||
av_usleep(1000);
|
||||
}
|
||||
}
|
||||
- } while (block_and_wait);
|
||||
+ } while (false); // already set query timeout
|
||||
|
||||
if (res_query == AMF_EOF) {
|
||||
ret = AVERROR_EOF;
|
||||
--
|
||||
2.43.0.windows.1
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user