mirror of
https://github.com/TermoraDev/termora.git
synced 2026-01-16 02:12:58 +08:00
Compare commits
187 Commits
2.0.0-beta
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
524ddd7eb2 | ||
|
|
68bd883305 | ||
|
|
3fa2659d59 | ||
|
|
3ece32e427 | ||
|
|
dad4d26fd8 | ||
|
|
9b387c71fc | ||
|
|
7ac833b53b | ||
|
|
2327c5fd48 | ||
|
|
bfc63a3983 | ||
|
|
c727925791 | ||
|
|
cae1173180 | ||
|
|
10d2736232 | ||
|
|
97f01b7e3f | ||
|
|
21c7dd7a42 | ||
|
|
bbc64043ed | ||
|
|
79842f4625 | ||
|
|
626b344088 | ||
|
|
5b165ed587 | ||
|
|
d73b3b706e | ||
|
|
2928b35585 | ||
|
|
04bece21ff | ||
|
|
9e2e104baa | ||
|
|
0615378a17 | ||
|
|
013b03f9ef | ||
|
|
026b13ba05 | ||
|
|
6ec526eeeb | ||
|
|
e064bb9bb5 | ||
|
|
1f3fb5e2c0 | ||
|
|
5984f3e856 | ||
|
|
572c381e90 | ||
|
|
7a8ecb06bf | ||
|
|
4c928ac826 | ||
|
|
d07f9ede8c | ||
|
|
21a015bf8c | ||
|
|
71a1f5db4b | ||
|
|
96fd07a6ff | ||
|
|
733e062a7b | ||
|
|
e87a779adc | ||
|
|
9c6aa4dcb6 | ||
|
|
566b087eb1 | ||
|
|
2235e4c2a4 | ||
|
|
3b9d1f277b | ||
|
|
5110595404 | ||
|
|
034e0939be | ||
|
|
4ccfa82c8a | ||
|
|
d21ae5499a | ||
|
|
d80a9d48ab | ||
|
|
b305d6fd34 | ||
|
|
756fd305d1 | ||
|
|
f9549fbb7d | ||
|
|
e18b454fcc | ||
|
|
4f4ccfa7d4 | ||
|
|
5dfd5fefb2 | ||
|
|
a7ea4c70d2 | ||
|
|
b7796f58f0 | ||
|
|
c7bedc57e0 | ||
|
|
935f305ada | ||
|
|
8cf47a7ca1 | ||
|
|
c6c5ad711d | ||
|
|
5fc76d955a | ||
|
|
0aabe1b0dc | ||
|
|
820c4274e7 | ||
|
|
fcec30d70a | ||
|
|
f6dc0098f7 | ||
|
|
ca7b30bdb0 | ||
|
|
f73e7f4214 | ||
|
|
613a1ca78a | ||
|
|
bf9e3ea2e2 | ||
|
|
a4390c4c6d | ||
|
|
9cf317e245 | ||
|
|
d000d73122 | ||
|
|
88613ed2f6 | ||
|
|
2fc381caa5 | ||
|
|
30e245f7a3 | ||
|
|
35cf92e685 | ||
|
|
522ee44ca2 | ||
|
|
5cf03e1f1f | ||
|
|
afca4ddf0e | ||
|
|
ca757f975a | ||
|
|
79c304ae3d | ||
|
|
1848c869e7 | ||
|
|
029e570551 | ||
|
|
905c570e4c | ||
|
|
a3069229b8 | ||
|
|
1e930d61c9 | ||
|
|
0015c3a7fb | ||
|
|
4bfb87e5c7 | ||
|
|
4fbb626c42 | ||
|
|
35b175d944 | ||
|
|
5939297550 | ||
|
|
e6e5867742 | ||
|
|
bd9b73ad6a | ||
|
|
dbea769994 | ||
|
|
9cd83c4025 | ||
|
|
d4cc080e7b | ||
|
|
a324bc3d96 | ||
|
|
36929e9ea3 | ||
|
|
dd73b933d9 | ||
|
|
117a9ea692 | ||
|
|
2f932de295 | ||
|
|
679b24a74d | ||
|
|
c6b33ea828 | ||
|
|
a4ea8f2491 | ||
|
|
1c2315b5e9 | ||
|
|
d48e412580 | ||
|
|
3b3fb41384 | ||
|
|
190ac697fb | ||
|
|
8cdbf24cdc | ||
|
|
6e182b6813 | ||
|
|
3fa4064655 | ||
|
|
a77a03d8b3 | ||
|
|
5f8b9d36e2 | ||
|
|
1ed5e164de | ||
|
|
c67d5b0276 | ||
|
|
9646a98f6d | ||
|
|
aee34415a7 | ||
|
|
e4e70cc72c | ||
|
|
49779fe8f2 | ||
|
|
969ddc3662 | ||
|
|
de9b418c75 | ||
|
|
f8588745cd | ||
|
|
7c0cbab187 | ||
|
|
176fa64de0 | ||
|
|
495ab69195 | ||
|
|
93c28242fb | ||
|
|
57662f717b | ||
|
|
3669bd1f88 | ||
|
|
00e695b7d5 | ||
|
|
02c92e6019 | ||
|
|
8ba74f0846 | ||
|
|
79ed6d3858 | ||
|
|
8a66606275 | ||
|
|
3ebdf73fbf | ||
|
|
d249e5da5a | ||
|
|
7243e933e6 | ||
|
|
f92e43ee41 | ||
|
|
f6243e33da | ||
|
|
72f334d572 | ||
|
|
68cbb10dec | ||
|
|
45f5c4ee91 | ||
|
|
48c511613e | ||
|
|
c94063d459 | ||
|
|
c26aafd831 | ||
|
|
a5638329e7 | ||
|
|
8323f8eb5d | ||
|
|
35199ed094 | ||
|
|
b5d53cf416 | ||
|
|
39e26a6e3d | ||
|
|
15cb06af0f | ||
|
|
1e0bbb5a00 | ||
|
|
fb6fdbc14c | ||
|
|
96df53ce40 | ||
|
|
42f86dc3a3 | ||
|
|
32b11c6063 | ||
|
|
b2f43ba439 | ||
|
|
7d9cfc79cf | ||
|
|
5624a44104 | ||
|
|
2aaa6371ab | ||
|
|
fdc1b0c07d | ||
|
|
8ec7e416ea | ||
|
|
ae7730fb35 | ||
|
|
f99e3e9147 | ||
|
|
5fcda04544 | ||
|
|
aca0fbb1e3 | ||
|
|
4f8ffbf225 | ||
|
|
8b08edf38f | ||
|
|
e3d43111e8 | ||
|
|
6bb9a33a04 | ||
|
|
ca64880a01 | ||
|
|
c8d70e2a5a | ||
|
|
cee7eb8928 | ||
|
|
abc5f203d0 | ||
|
|
c3fc8f8e12 | ||
|
|
afd4f8baa9 | ||
|
|
b5ca8b988c | ||
|
|
89b22ba984 | ||
|
|
f329ef60df | ||
|
|
8acfdb8bca | ||
|
|
a7aec52f2a | ||
|
|
7f1317a9a7 | ||
|
|
a8a1fea91b | ||
|
|
675ad4608a | ||
|
|
72ba3757e2 | ||
|
|
c58e84d2ae | ||
|
|
18a7a5059b | ||
|
|
f0102b6f13 | ||
|
|
0cf8eb3c17 |
25
.github/workflows/linux.yml
vendored
25
.github/workflows/linux.yml
vendored
@@ -3,7 +3,8 @@ name: Linux
|
||||
on: [ push, pull_request ]
|
||||
|
||||
env:
|
||||
DOCKER_NAME: hstyi/jbr:21.0.7b1038.58
|
||||
JBR_MAJOR: 21.0.8
|
||||
JBR_PATCH: b1163.69
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -14,7 +15,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
fetch-depth: 1
|
||||
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
@@ -25,6 +26,10 @@ jobs:
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ runner.arch }}-gradlexyz-
|
||||
|
||||
- name: Set dynamic DOCKER_NAME
|
||||
run: |
|
||||
echo "DOCKER_NAME=hstyi/jbr:${{ env.JBR_MAJOR }}${{ env.JBR_PATCH }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Create docker-run.sh helper script
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -54,11 +59,23 @@ jobs:
|
||||
shell: bash
|
||||
run: sudo chmod -R 777 ~/.gradle
|
||||
|
||||
- name: Upload artifact
|
||||
- name: Upload targz artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: termora-linux-${{ runner.arch }}
|
||||
name: termora-linux-targz-${{ runner.arch }}
|
||||
path: |
|
||||
build/distributions/*.tar.gz
|
||||
|
||||
- name: Upload AppImage artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: termora-linux-AppImage-${{ runner.arch }}
|
||||
path: |
|
||||
build/distributions/*.AppImage
|
||||
|
||||
- name: Upload deb artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: termora-linux-deb-${{ runner.arch }}
|
||||
path: |
|
||||
build/distributions/*.deb
|
||||
|
||||
23
.github/workflows/osx.yml
vendored
23
.github/workflows/osx.yml
vendored
@@ -3,25 +3,27 @@ name: macOS
|
||||
on: [ push, pull_request ]
|
||||
|
||||
env:
|
||||
TERMORA_MAC_SIGN: "${{ startsWith(github.event.head_commit.message, 'release: ') && github.repository == 'TermoraDev/termora' }}"
|
||||
TERMORA_MAC_SIGN: "${{ github.repository == 'TermoraDev/termora' }}"
|
||||
TERMORA_MAC_SIGN_USER_NAME: ${{ secrets.TERMORA_MAC_SIGN_USER_NAME }}
|
||||
# 只有发布版本时才需要公证
|
||||
TERMORA_MAC_NOTARY: "${{ startsWith(github.event.head_commit.message, 'release: ') && github.repository == 'TermoraDev/termora' }}"
|
||||
TERMORA_MAC_NOTARY_KEYCHAIN_PROFILE: ${{ secrets.TERMORA_MAC_NOTARY_KEYCHAIN_PROFILE }}
|
||||
JBR_MAJOR: 21.0.8
|
||||
JBR_PATCH: b1163.69
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ macos-15, macos-13 ]
|
||||
os: [ macos-15-intel, macos-latest ]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Install the Apple certificate
|
||||
if: "startsWith(github.event.head_commit.message, 'release: ') && github.repository == 'TermoraDev/termora' && env.BUILD_CERTIFICATE_BASE64 != ''"
|
||||
if: ${{ fromJSON(env.TERMORA_MAC_SIGN) && env.BUILD_CERTIFICATE_BASE64 != '' }}
|
||||
env:
|
||||
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
|
||||
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
|
||||
@@ -44,7 +46,7 @@ jobs:
|
||||
security list-keychain -d user -s $KEYCHAIN_PATH
|
||||
|
||||
- name: Setup the Notary information
|
||||
if: "startsWith(github.event.head_commit.message, 'release: ') && github.repository == 'TermoraDev/termora' && env.APPLE_ID != ''"
|
||||
if: ${{ fromJSON(env.TERMORA_MAC_NOTARY) && env.APPLE_ID != '' }}
|
||||
env:
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
@@ -60,7 +62,7 @@ jobs:
|
||||
else
|
||||
ARCH="x64"
|
||||
fi
|
||||
wget -q -O $RUNNER_TEMP/java_package.tar.gz https://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-21.0.7-osx-$ARCH-b1034.51.tar.gz
|
||||
wget -q -O $RUNNER_TEMP/java_package.tar.gz https://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-${{ env.JBR_MAJOR }}-osx-$ARCH-${{ env.JBR_PATCH }}.tar.gz
|
||||
|
||||
# install jdk
|
||||
- name: Installing Java
|
||||
@@ -79,6 +81,10 @@ jobs:
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ runner.arch }}-gradle-
|
||||
|
||||
- name: Install create-dmg
|
||||
shell: bash
|
||||
run: brew install create-dmg
|
||||
|
||||
- name: Compile
|
||||
shell: bash
|
||||
run: ./gradlew :check-license && ./gradlew classes -x test
|
||||
@@ -91,10 +97,9 @@ jobs:
|
||||
shell: bash
|
||||
run: ./gradlew :jpackage && ./gradlew :dist
|
||||
|
||||
- name: Upload artifact
|
||||
- name: Upload dmg artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: termora-osx-${{ runner.arch }}
|
||||
name: termora-osx-dmg-${{ runner.arch }}
|
||||
path: |
|
||||
build/distributions/*.zip
|
||||
build/distributions/*.dmg
|
||||
|
||||
55
.github/workflows/windows-x86-64.yml
vendored
55
.github/workflows/windows-x86-64.yml
vendored
@@ -1,55 +0,0 @@
|
||||
name: Windows x86-64
|
||||
|
||||
on: [ push, pull_request ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install zip
|
||||
run: |
|
||||
$system32 = [System.Environment]::GetEnvironmentVariable("WINDIR") + "\System32"
|
||||
Invoke-WebRequest -Uri "http://stahlworks.com/dev/zip.exe" -OutFile "$system32\zip.exe"
|
||||
Invoke-WebRequest -Uri "http://stahlworks.com/dev/unzip.exe" -OutFile "$system32\unzip.exe"
|
||||
|
||||
- name: Install 7z
|
||||
uses: milliewalky/setup-7-zip@v2
|
||||
|
||||
- name: Installing Java
|
||||
run: |
|
||||
curl -s --output ${{ runner.temp }}\java_package.zip -L https://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-21.0.7-windows-x64-b1034.51.zip
|
||||
unzip -q ${{ runner.temp }}\java_package.zip -d ${{ runner.temp }}\jbr
|
||||
echo "JAVA_HOME=${{ runner.temp }}\jbr\jbrsdk-21.0.7-windows-x64-b1034.51" >> $env:GITHUB_ENV
|
||||
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-${{ runner.arch }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ runner.arch }}-gradle-
|
||||
|
||||
- name: Compile
|
||||
run: .\gradlew :check-license && .\gradlew classes -x test
|
||||
|
||||
- name: JLink
|
||||
run: .\gradlew :jar :copy-dependencies :plugins:migration:build :jlink
|
||||
|
||||
- name: Package
|
||||
run: .\gradlew :jpackage && .\gradlew :dist
|
||||
|
||||
- name: Stop Gradle
|
||||
run: .\gradlew.bat --stop
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: termora-windows-x86-64
|
||||
path: |
|
||||
build/distributions/*.zip
|
||||
build/distributions/*.exe
|
||||
116
.github/workflows/windows.yml
vendored
Normal file
116
.github/workflows/windows.yml
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
name: Windows
|
||||
|
||||
on: [ push, pull_request ]
|
||||
|
||||
env:
|
||||
JBR_MAJOR: 21.0.8
|
||||
JBR_PATCH: b1163.69
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ windows-11-arm, windows-2022 ]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Setup MSbuild
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
|
||||
- name: Set architecture
|
||||
id: set-arch
|
||||
run: |
|
||||
if ($env:PROCESSOR_ARCHITECTURE -eq "ARM64") {
|
||||
echo "ARCH=aarch64" >> $env:GITHUB_ENV
|
||||
} else {
|
||||
echo "ARCH=x64" >> $env:GITHUB_ENV
|
||||
}
|
||||
|
||||
- name: Find MakeAppx
|
||||
shell: pwsh
|
||||
run: |
|
||||
$installedRootsKey = "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots"
|
||||
$kitsRoot = (Get-ItemProperty $installedRootsKey).KitsRoot10
|
||||
$versions = Get-ChildItem -Path $installedRootsKey | Select-Object -ExpandProperty PSChildName
|
||||
$maxVersion = $versions | ForEach-Object { [version]$_ } | Sort-Object -Descending | Select-Object -First 1
|
||||
$arch = if ($env:ARCH -eq "aarch64") { "arm64" } else { "x64" }
|
||||
$makeAppXPath = Join-Path -Path $kitsRoot -ChildPath "bin\$maxVersion\$arch\makeappx.exe"
|
||||
Write-Output "MakeAppx.exe path: $makeAppXPath"
|
||||
|
||||
if (Test-Path $makeAppXPath) {
|
||||
"MAKEAPPX_PATH=$makeAppXPath" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
|
||||
} else {
|
||||
Write-Output "MakeAppx.exe not found!"
|
||||
exit 1
|
||||
}
|
||||
|
||||
- name: Install zip
|
||||
run: |
|
||||
$system32 = [System.Environment]::GetEnvironmentVariable("WINDIR") + "\System32"
|
||||
Invoke-WebRequest -Uri "http://stahlworks.com/dev/zip.exe" -OutFile "$system32\zip.exe"
|
||||
Invoke-WebRequest -Uri "http://stahlworks.com/dev/unzip.exe" -OutFile "$system32\unzip.exe"
|
||||
|
||||
- name: Install 7z
|
||||
uses: milliewalky/setup-7-zip@v2
|
||||
|
||||
- name: Installing Java
|
||||
run: |
|
||||
$zipPath = "${{ runner.temp }}\java_package.zip"
|
||||
$extractDir = "${{ runner.temp }}\jbr"
|
||||
$url = "https://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-${{ env.JBR_MAJOR }}-windows-${{ env.ARCH }}-${{ env.JBR_PATCH }}.zip"
|
||||
curl -s --output $zipPath -L $url
|
||||
unzip -q $zipPath -d $extractDir
|
||||
$jbrDir = Get-ChildItem $extractDir | Select-Object -First 1
|
||||
echo "JAVA_HOME=$($jbrDir.FullName)" >> $env:GITHUB_ENV
|
||||
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-${{ runner.arch }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ runner.arch }}-gradle-
|
||||
|
||||
- name: Compile
|
||||
run: .\gradlew :check-license && .\gradlew classes -x test
|
||||
|
||||
- name: JLink
|
||||
run: .\gradlew :jar :copy-dependencies :plugins:migration:build :jlink
|
||||
|
||||
- name: Package
|
||||
run: .\gradlew :jpackage && .\gradlew :dist
|
||||
|
||||
- name: MSIX
|
||||
env:
|
||||
TERMORA_TYPE: appx
|
||||
run: |
|
||||
.\gradlew --stop
|
||||
.\gradlew :dist
|
||||
|
||||
- name: Stop Gradle
|
||||
run: .\gradlew.bat --stop
|
||||
|
||||
- name: Upload zip artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: termora-windows-zip-${{ runner.arch }}
|
||||
path: |
|
||||
build/distributions/*.zip
|
||||
|
||||
- name: Upload exe artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: termora-windows-exe-${{ runner.arch }}
|
||||
path: |
|
||||
build/distributions/*.exe
|
||||
|
||||
- name: Upload msix artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: termora-windows-msix-${{ runner.arch }}
|
||||
path: |
|
||||
build/distributions/*.msix
|
||||
@@ -82,6 +82,7 @@ Termora is developed using [**Kotlin/JVM**](https://kotlinlang.org/) and partial
|
||||
- 🧾 [Latest Release](https://github.com/TermoraDev/termora/releases/latest)
|
||||
- 🍺 **Homebrew**: `brew install --cask termora`
|
||||
- 🔨 **WinGet**: `winget install termora`
|
||||
- <img src="https://apps.microsoft.com/assets/icons/logo-16x16.png" alt="microsoft logo"/> <b>Microsoft Store</b>: <a href="https://apps.microsoft.com/store/detail/9NRZBHG43SB9?cid=DevShareMCLPCS">Visit Termora in the Microsoft Store</a>
|
||||
|
||||
|
||||
|
||||
@@ -90,8 +91,6 @@ Termora is developed using [**Kotlin/JVM**](https://kotlinlang.org/) and partial
|
||||
We recommend using the [JetBrainsRuntime](https://github.com/JetBrains/JetBrainsRuntime) JDK for development.
|
||||
|
||||
- Run locally: `./gradlew :run`
|
||||
- Build for current OS: `./gradlew :dist`
|
||||
|
||||
|
||||
|
||||
## 📄 License
|
||||
|
||||
@@ -80,6 +80,7 @@ Termora 使用 [**Kotlin/JVM**](https://kotlinlang.org/) 开发,支持(正
|
||||
- 🧾 [Latest release](https://github.com/TermoraDev/termora/releases/latest)
|
||||
- 🍺 **Homebrew**:`brew install --cask termora`
|
||||
- 🪟 **WinGet**:`winget install termora`
|
||||
- <img src="https://apps.microsoft.com/assets/icons/logo-16x16.png" alt="microsoft logo"/> <b>Microsoft Store</b>: <a href="https://apps.microsoft.com/store/detail/9NRZBHG43SB9?cid=DevShareMCLPCS">Termora</a>
|
||||
|
||||
|
||||
|
||||
@@ -88,8 +89,6 @@ Termora 使用 [**Kotlin/JVM**](https://kotlinlang.org/) 开发,支持(正
|
||||
建议使用 [JetBrainsRuntime](https://github.com/JetBrains/JetBrainsRuntime) JDK 运行环境。
|
||||
|
||||
- 本地运行:`./gradlew :run`
|
||||
- 构建当前系统安装包:`./gradlew :dist`
|
||||
|
||||
|
||||
|
||||
## 📄 授权协议
|
||||
|
||||
306
build.gradle.kts
306
build.gradle.kts
@@ -1,3 +1,4 @@
|
||||
import org.apache.tools.ant.filters.ReplaceTokens
|
||||
import org.gradle.internal.jvm.Jvm
|
||||
import org.gradle.kotlin.dsl.support.uppercaseFirstChar
|
||||
import org.gradle.nativeplatform.platform.internal.ArchitectureInternal
|
||||
@@ -28,7 +29,10 @@ version = rootProject.projectDir.resolve("VERSION").readText().trim()
|
||||
val os: OperatingSystem = DefaultNativePlatform.getCurrentOperatingSystem()
|
||||
val arch: ArchitectureInternal = DefaultNativePlatform.getCurrentArchitecture()
|
||||
val appVersion = project.version.toString().split("-")[0]
|
||||
val makeAppx = if (os.isWindows) StringUtils.defaultString(System.getenv("MAKEAPPX_PATH")) else StringUtils.EMPTY
|
||||
val isDeb = os.isLinux && System.getenv("TERMORA_TYPE") == "deb"
|
||||
val isAppx = os.isWindows && makeAppx.isNotBlank() && System.getenv("TERMORA_TYPE") == "appx"
|
||||
val isBeta = project.version.toString().contains("beta", ignoreCase = true)
|
||||
|
||||
// macOS 签名信息
|
||||
val macOSSignUsername = System.getenv("TERMORA_MAC_SIGN_USER_NAME") ?: StringUtils.EMPTY
|
||||
@@ -169,102 +173,149 @@ publishing {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.processResources {
|
||||
val betaVersion = project.version.toString().substringAfterLast('.')
|
||||
filesMatching("**/AppxManifest.xml") {
|
||||
filter<ReplaceTokens>(
|
||||
"tokens" to mapOf(
|
||||
"version" to appVersion,
|
||||
"betaVersion" to if (isBeta) betaVersion else "0",
|
||||
"architecture" to if (arch.isArm64) "arm64" else "x64",
|
||||
"projectDir" to project.projectDir.absolutePath,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
tasks.test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
@Suppress("CascadeIf")
|
||||
tasks.register<Copy>("copy-dependencies") {
|
||||
val dir = layout.buildDirectory.dir("libs")
|
||||
from(configurations.runtimeClasspath).into(dir)
|
||||
val jna = libs.jna.asProvider().get()
|
||||
val pty4j = libs.pty4j.get()
|
||||
val flatlaf = libs.flatlaf.get()
|
||||
val jSerialComm = libs.jSerialComm.get()
|
||||
val restart4j = libs.restart4j.get()
|
||||
val sqlite = libs.sqlite.get()
|
||||
|
||||
// 对 JNA 和 PTY4J 的本地库提取
|
||||
// 提取出来是为了单独签名,不然无法通过公证
|
||||
if (os.isMacOsX) {
|
||||
doLast {
|
||||
val archName = if (arch.isArm) "aarch64" else "x86_64"
|
||||
val dylib = dir.get().dir("dylib").asFile
|
||||
|
||||
doLast {
|
||||
for (file in dir.get().asFile.listFiles() ?: emptyArray()) {
|
||||
if ("${jna.name}-${jna.version}" == file.nameWithoutExtension) {
|
||||
val targetDir = File(dylib, jna.name)
|
||||
FileUtils.forceMkdir(targetDir)
|
||||
if (os.isWindows) {
|
||||
// @formatter:off
|
||||
exec { commandLine("unzip","-j","-o", file.absolutePath, "com/sun/jna/win32-${arch.name}/*", "-d", targetDir.absolutePath) }
|
||||
// @formatter:on
|
||||
} else if (os.isLinux) {
|
||||
// @formatter:off
|
||||
exec { commandLine("unzip","-j","-o", file.absolutePath, "com/sun/jna/linux-${arch.name}/*", "-d", targetDir.absolutePath) }
|
||||
// @formatter:on
|
||||
} else if (os.isMacOsX) {
|
||||
// @formatter:off
|
||||
exec { commandLine("unzip","-j","-o", file.absolutePath, "com/sun/jna/darwin-${arch.name}/*", "-d", targetDir.absolutePath) }
|
||||
// @formatter:on
|
||||
// 删除所有二进制类库
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/darwin-*") }
|
||||
}
|
||||
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/win32-*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/linux-*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/darwin-*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/sunos-*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/openbsd-*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/linux-*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/freebsd-*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/dragonflybsd-*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/aix-*") }
|
||||
} else if ("${pty4j.name}-${pty4j.version}" == file.nameWithoutExtension) {
|
||||
val targetDir = FileUtils.getFile(dylib, pty4j.name, "darwin")
|
||||
val osName = if (os.isWindows) "win32" else if (os.isMacOsX) "darwin" else "linux"
|
||||
val myArchName = if (arch.isArm) "aarch64" else "x86-64"
|
||||
val targetDir = if (os.isMacOsX) FileUtils.getFile(dylib, pty4j.name, osName)
|
||||
else FileUtils.getFile(dylib, pty4j.name, osName, myArchName)
|
||||
FileUtils.forceMkdir(targetDir)
|
||||
if (os.isWindows) {
|
||||
// @formatter:off
|
||||
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "resources/*win/${myArchName}/*", "-d", targetDir.absolutePath) }
|
||||
// @formatter:on
|
||||
} else if (os.isLinux) {
|
||||
// @formatter:off
|
||||
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "resources/*linux/${myArchName}/*", "-d", targetDir.absolutePath) }
|
||||
// @formatter:on
|
||||
} else if (os.isMacOsX) {
|
||||
// @formatter:off
|
||||
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "resources/com/pty4j/native/darwin*", "-d", targetDir.absolutePath) }
|
||||
// @formatter:on
|
||||
// 删除所有二进制类库
|
||||
}
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "resources/*") }
|
||||
} else if ("${jSerialComm.name}-${jSerialComm.version}" == file.nameWithoutExtension) {
|
||||
val targetDir = FileUtils.getFile(dylib, jSerialComm.name, "OSX", archName)
|
||||
FileUtils.forceMkdir(targetDir)
|
||||
// @formatter:off
|
||||
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "OSX/${archName}/*", "-d", targetDir.absolutePath) }
|
||||
// @formatter:on
|
||||
// 删除所有二进制类库
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "Android/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "FreeBSD/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "Linux/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "OpenBSD/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "OSX/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "Solaris/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "Windows/*") }
|
||||
} else if ("${restart4j.name}-${restart4j.version}" == file.nameWithoutExtension) {
|
||||
val targetDir = FileUtils.getFile(dylib, restart4j.name)
|
||||
FileUtils.forceMkdir(targetDir)
|
||||
if (os.isWindows) {
|
||||
// @formatter:off
|
||||
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "win32/${archName}/*", "-d", targetDir.absolutePath) }
|
||||
// @formatter:on
|
||||
} else if (os.isLinux) {
|
||||
// @formatter:off
|
||||
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "linux/${archName}/*", "-d", targetDir.absolutePath) }
|
||||
// @formatter:on
|
||||
} else if (os.isMacOsX) {
|
||||
// @formatter:off
|
||||
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "darwin/${archName}/*", "-d", targetDir.absolutePath) }
|
||||
// @formatter:on
|
||||
// 删除所有二进制类库
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "win32/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "darwin/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "linux/*") }
|
||||
}
|
||||
// 设置可执行权限
|
||||
for (e in FileUtils.listFiles(
|
||||
targetDir,
|
||||
FileFilterUtils.trueFileFilter(),
|
||||
FileFilterUtils.falseFileFilter()
|
||||
)) {
|
||||
e.setExecutable(true)
|
||||
}
|
||||
)) e.setExecutable(true)
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "win32/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "darwin/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "linux/*") }
|
||||
} else if ("${sqlite.name}-${sqlite.version}" == file.nameWithoutExtension) {
|
||||
val targetDir = FileUtils.getFile(dylib, sqlite.name)
|
||||
FileUtils.forceMkdir(targetDir)
|
||||
if (os.isWindows) {
|
||||
// @formatter:off
|
||||
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "org/sqlite/native/Windows/${archName}/*", "-d", targetDir.absolutePath) }
|
||||
// @formatter:on
|
||||
} else if (os.isLinux) {
|
||||
// @formatter:off
|
||||
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "org/sqlite/native/Linux/${archName}/*", "-d", targetDir.absolutePath) }
|
||||
// @formatter:on
|
||||
} else if (os.isMacOsX) {
|
||||
// @formatter:off
|
||||
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "org/sqlite/native/Mac/${archName}/*", "-d", targetDir.absolutePath) }
|
||||
// @formatter:on
|
||||
// 删除所有二进制类库
|
||||
}
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/*") }
|
||||
} else if ("${flatlaf.name}-${flatlaf.version}" == file.nameWithoutExtension) {
|
||||
val targetDir = FileUtils.getFile(dylib, flatlaf.name)
|
||||
FileUtils.forceMkdir(targetDir)
|
||||
val isArm = arch.isArm
|
||||
if (os.isWindows) {
|
||||
// @formatter:off
|
||||
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "com/formdev/flatlaf/natives/*windows*${if (isArm) "arm64" else "x86_64"}*", "-d", targetDir.absolutePath) }
|
||||
// @formatter:on
|
||||
} else if (os.isLinux) {
|
||||
// @formatter:off
|
||||
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "com/formdev/flatlaf/natives/*linux*${if (isArm) "arm64" else "x86_64"}*", "-d", targetDir.absolutePath) }
|
||||
// @formatter:on
|
||||
} else if (os.isMacOsX) {
|
||||
// @formatter:off
|
||||
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "com/formdev/flatlaf/natives/*macos*${if (isArm) "arm" else "x86"}*", "-d", targetDir.absolutePath) }
|
||||
// @formatter:on
|
||||
}
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/formdev/flatlaf/natives/*") }
|
||||
}
|
||||
}
|
||||
|
||||
// 对二进制签名
|
||||
if (os.isMacOsX) {
|
||||
Files.walk(dylib.toPath()).use { paths ->
|
||||
for (path in paths) {
|
||||
if (Files.isRegularFile(path)) {
|
||||
@@ -273,116 +324,8 @@ tasks.register<Copy>("copy-dependencies") {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (os.isLinux || os.isWindows) { // 缩减安装包
|
||||
doLast {
|
||||
for (file in dir.get().asFile.listFiles() ?: emptyArray()) {
|
||||
if ("${jna.name}-${jna.version}" == file.nameWithoutExtension) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/darwin-*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/sunos-*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/openbsd-*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/freebsd-*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/dragonflybsd-*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/aix-*") }
|
||||
if (os.isWindows) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/linux-*") }
|
||||
if (arch.isArm) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/win32-x86*") }
|
||||
} else {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/win32-aarch64/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/win32-x86/*") }
|
||||
}
|
||||
} else if (os.isLinux) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/win32-*") }
|
||||
}
|
||||
} else if ("${pty4j.name}-${pty4j.version}" == file.nameWithoutExtension) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "resources/*darwin*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "resources/*freebsd*") }
|
||||
if (os.isWindows) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "resources/*linux*") }
|
||||
if (arch.isArm) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "resources/*win/x86/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "resources/*win/x86-64*") }
|
||||
} else {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "resources/*win/x86/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "resources/*win/aarch64/*") }
|
||||
}
|
||||
} else if (os.isLinux) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "resources/*win*") }
|
||||
}
|
||||
} else if ("${jSerialComm.name}-${jSerialComm.version}" == file.nameWithoutExtension) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "Android/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "FreeBSD/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "OpenBSD/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "OSX/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "Solaris/*") }
|
||||
if (os.isWindows) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "Linux/*") }
|
||||
} else if (os.isLinux) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "Windows/*") }
|
||||
}
|
||||
} else if ("${restart4j.name}-${restart4j.version}" == file.nameWithoutExtension) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "darwin/*") }
|
||||
if (os.isWindows) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "linux/*") }
|
||||
if (arch.isArm) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "win32/x86_64/*") }
|
||||
} else {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "win32/aarch64/*") }
|
||||
}
|
||||
} else if (os.isLinux) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "win32/*") }
|
||||
if (arch.isArm) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "linux/x86_64/*") }
|
||||
} else {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "linux/aarch64/*") }
|
||||
}
|
||||
}
|
||||
} else if ("${sqlite.name}-${sqlite.version}" == file.nameWithoutExtension) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Linux-*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/FreeBSD/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Mac/*") }
|
||||
if (os.isWindows) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Linux/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Windows/armv7/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Windows/x86/*") }
|
||||
if (arch.isArm) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Windows/x86_64/*") }
|
||||
} else {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Windows/aarch64/*") }
|
||||
}
|
||||
} else if (os.isLinux) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Windows/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Linux/arm*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Linux/ppc64/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Linux/riscv64/*") }
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Linux/x86/*") }
|
||||
if (arch.isArm) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Linux/x86_64/*") }
|
||||
} else {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Linux/aarch64/*") }
|
||||
}
|
||||
}
|
||||
} else if ("${flatlaf.name}-${flatlaf.version}" == file.nameWithoutExtension) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/formdev/flatlaf/natives/*macos*") }
|
||||
if (os.isWindows) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/formdev/flatlaf/natives/*linux*") }
|
||||
if (arch.isArm) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/formdev/flatlaf/natives/*x86*") }
|
||||
} else {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/formdev/flatlaf/natives/*x86.dll") }
|
||||
}
|
||||
} else if (os.isLinux) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/formdev/flatlaf/natives/*windows*") }
|
||||
if (arch.isArm) {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/formdev/flatlaf/natives/*x86*") }
|
||||
} else {
|
||||
exec { commandLine("zip", "-d", file.absolutePath, "com/formdev/flatlaf/natives/*arm*") }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tasks.register<Exec>("jlink") {
|
||||
@@ -396,6 +339,7 @@ tasks.register<Exec>("jlink") {
|
||||
"java.security.jgss",
|
||||
"jdk.crypto.ec",
|
||||
"jdk.unsupported",
|
||||
"jdk.httpserver",
|
||||
)
|
||||
|
||||
commandLine(
|
||||
@@ -441,6 +385,7 @@ tasks.register<Exec>("jpackage") {
|
||||
}
|
||||
|
||||
if (os.isLinux) {
|
||||
options.add("--add-opens=java.desktop/sun.awt.X11=ALL-UNNAMED")
|
||||
if (isDeb) {
|
||||
options.add("-Djpackage.app-layout=deb")
|
||||
}
|
||||
@@ -460,18 +405,6 @@ tasks.register<Exec>("jpackage") {
|
||||
arguments.addAll(listOf("--copyright", "TermoraDev"))
|
||||
arguments.addAll(listOf("--app-content", "$buildDir/plugins"))
|
||||
|
||||
if (os.isWindows) {
|
||||
arguments.addAll(
|
||||
listOf(
|
||||
"--description",
|
||||
"${project.name.uppercaseFirstChar()}: A terminal emulator and SSH client"
|
||||
)
|
||||
)
|
||||
} else {
|
||||
arguments.addAll(listOf("--description", "A terminal emulator and SSH client."))
|
||||
}
|
||||
|
||||
|
||||
if (os.isMacOsX) {
|
||||
arguments.addAll(listOf("--mac-package-name", project.name.uppercaseFirstChar()))
|
||||
arguments.addAll(listOf("--mac-app-category", "developer-tools"))
|
||||
@@ -480,10 +413,6 @@ tasks.register<Exec>("jpackage") {
|
||||
}
|
||||
|
||||
if (os.isWindows) {
|
||||
arguments.add("--win-dir-chooser")
|
||||
arguments.add("--win-shortcut")
|
||||
arguments.add("--win-shortcut-prompt")
|
||||
arguments.addAll(listOf("--win-upgrade-uuid", "E1D93CAD-5BF8-442E-93BA-6E90DE601E4C"))
|
||||
arguments.addAll(listOf("--icon", "${projectDir.absolutePath}/src/main/resources/icons/termora.ico"))
|
||||
}
|
||||
|
||||
@@ -496,7 +425,7 @@ tasks.register<Exec>("jpackage") {
|
||||
if (os.isMacOsX) {
|
||||
arguments.add("dmg")
|
||||
} else if (os.isWindows) {
|
||||
arguments.add("msi")
|
||||
arguments.add("app-image")
|
||||
} else if (os.isLinux) {
|
||||
arguments.add(if (isDeb) "deb" else "app-image")
|
||||
if (isDeb) {
|
||||
@@ -507,7 +436,7 @@ tasks.register<Exec>("jpackage") {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
if (os.isMacOsX && macOSSign) {
|
||||
if (macOSSign) {
|
||||
arguments.add("--mac-sign")
|
||||
arguments.add("--mac-signing-key-user-name")
|
||||
arguments.add(macOSSignUsername)
|
||||
@@ -568,10 +497,31 @@ tasks.register("check-license") {
|
||||
* 创建 zip、msi
|
||||
*/
|
||||
fun packOnWindows(distributionDir: Directory, finalFilenameWithoutExtension: String, projectName: String) {
|
||||
val dir = layout.buildDirectory.dir("jpackage/images/win-msi.image/").get().asFile
|
||||
val dir = layout.buildDirectory.dir("distributions").get().asFile
|
||||
val cfg = FileUtils.getFile(dir, projectName, "app", "${projectName}.cfg")
|
||||
val configText = cfg.readText()
|
||||
|
||||
// appx
|
||||
if (isAppx) {
|
||||
cfg.writeText(StringBuilder(configText).appendLine("java-options=-Djpackage.app-layout=appx").toString())
|
||||
val appxManifest = FileUtils.getFile(dir, projectName, "AppxManifest.xml")
|
||||
layout.buildDirectory.file("resources/main/AppxManifest.xml").get().asFile
|
||||
.renameTo(appxManifest)
|
||||
val icons = setOf("termora.png", "termora_44x44.png", "termora_150x150.png")
|
||||
for (file in projectDir.resolve("src/main/resources/icons/").listFiles()) {
|
||||
if (icons.contains(file.name)) {
|
||||
val p = appxManifest.parentFile.resolve("icons/${file.name}")
|
||||
FileUtils.forceMkdirParent(p)
|
||||
file.copyTo(p, true)
|
||||
}
|
||||
}
|
||||
exec {
|
||||
commandLine(makeAppx, "pack", "/d", projectName, "/p", "${finalFilenameWithoutExtension}.msix")
|
||||
workingDir = dir
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// zip
|
||||
cfg.writeText(StringBuilder(configText).appendLine("java-options=-Djpackage.app-layout=zip").toString())
|
||||
exec {
|
||||
@@ -593,21 +543,22 @@ fun packOnWindows(distributionDir: Directory, finalFilenameWithoutExtension: Str
|
||||
"/DMyAppVersion=${appVersion}",
|
||||
"/DMyOutputDir=${distributionDir.asFile.absolutePath}",
|
||||
"/DMySetupIconFile=${FileUtils.getFile(projectDir, "src", "main", "resources", "icons", "termora.ico")}",
|
||||
"/DMySourceDir=${layout.buildDirectory.dir("jpackage/images/win-msi.image/${projectName}").get().asFile}",
|
||||
"/DMyWizardSmallImageFile=${
|
||||
FileUtils.getFile(
|
||||
projectDir,
|
||||
"src",
|
||||
"main",
|
||||
"resources",
|
||||
"icons",
|
||||
"termora_128x128.bmp"
|
||||
)
|
||||
}",
|
||||
"/DMySourceDir=${FileUtils.getFile(dir, projectName).absolutePath}",
|
||||
"/F${finalFilenameWithoutExtension}",
|
||||
FileUtils.getFile(projectDir, "src", "main", "resources", "termora.iss")
|
||||
)
|
||||
}
|
||||
|
||||
// msi
|
||||
exec {
|
||||
commandLine(
|
||||
"cmd", "/c", "move",
|
||||
"${projectName}-${appVersion}.msi",
|
||||
"${finalFilenameWithoutExtension}.msi"
|
||||
)
|
||||
workingDir = distributionDir.asFile
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -711,7 +662,7 @@ fun packOnLinux(distributionDir: Directory, finalFilenameWithoutExtension: Strin
|
||||
commandLine(
|
||||
"wget",
|
||||
"-O", appimagetool.absolutePath,
|
||||
"https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-${if (arch.isArm) "aarch64" else "x86_64"}.AppImage"
|
||||
"https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-${if (arch.isArm) "aarch64" else "x86_64"}.AppImage"
|
||||
)
|
||||
workingDir = distributionDir.asFile
|
||||
}
|
||||
@@ -720,17 +671,24 @@ fun packOnLinux(distributionDir: Directory, finalFilenameWithoutExtension: Strin
|
||||
exec { commandLine("chmod", "+x", appimagetool.absolutePath) }
|
||||
}
|
||||
|
||||
|
||||
// Desktop file
|
||||
val termoraName = project.name.uppercaseFirstChar()
|
||||
|
||||
// copy icon
|
||||
FileUtils.copyFile(
|
||||
File("${projectDir.absolutePath}/src/main/resources/icons/termora_256x256.png"),
|
||||
distributionDir.file(termoraName + File.separator + termoraName + ".png").asFile
|
||||
)
|
||||
|
||||
val desktopFile = distributionDir.file(termoraName + File.separator + termoraName + ".desktop").asFile
|
||||
desktopFile.writeText(
|
||||
"""[Desktop Entry]
|
||||
Type=Application
|
||||
Name=${termoraName}
|
||||
Comment=Terminal emulator and SSH client
|
||||
Icon=/lib/${termoraName}
|
||||
Icon=${termoraName}
|
||||
Categories=Development;
|
||||
StartupWMClass=${termoraName}
|
||||
Terminal=false
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
@@ -1,50 +1,50 @@
|
||||
[versions]
|
||||
kotlin = "2.2.0"
|
||||
kotlin = "2.3.0"
|
||||
slf4j = "2.0.17"
|
||||
pty4j = "0.13.6"
|
||||
pty4j = "0.13.10"
|
||||
tinylog = "2.7.0"
|
||||
kotlinx-coroutines = "1.10.2"
|
||||
flatlaf = "3.6.1-SNAPSHOT"
|
||||
flatlaf = "3.7"
|
||||
kotlinx-serialization-json = "1.9.0"
|
||||
commons-codec = "1.18.0"
|
||||
commons-lang3 = "3.18.0"
|
||||
commons-csv = "1.14.0"
|
||||
commons-net = "3.11.1"
|
||||
commons-text = "1.13.1"
|
||||
commons-compress = "1.27.1"
|
||||
commons-codec = "1.20.0"
|
||||
commons-lang3 = "3.20.0"
|
||||
commons-csv = "1.14.1"
|
||||
commons-net = "3.12.0"
|
||||
commons-text = "1.15.0"
|
||||
commons-compress = "1.28.0"
|
||||
commons-vfs2 = "2.10.0"
|
||||
swingx = "1.6.5-1"
|
||||
jgoodies-forms = "1.9.0"
|
||||
jfa = "1.2.0"
|
||||
oshi = "6.8.1"
|
||||
oshi = "6.9.1"
|
||||
versioncompare = "1.4.1"
|
||||
jna = "5.17.0"
|
||||
jna = "5.18.1"
|
||||
jSystemThemeDetector = "3.9.1"
|
||||
commons-io = "2.19.0"
|
||||
commons-io = "2.21.0"
|
||||
jbr-api = "17.1.10.1"
|
||||
hutool = "5.8.39"
|
||||
jsch = "2.27.2"
|
||||
okhttp = "5.1.0"
|
||||
hutool = "5.8.43"
|
||||
jsch = "2.27.3"
|
||||
okhttp = "5.3.0"
|
||||
sshj = "0.39.0"
|
||||
sshd-core = "2.15.0"
|
||||
jgit = "7.2.0.202503040940-r"
|
||||
commonmark = "0.25.0"
|
||||
jgit = "7.4.0.202509020913-r"
|
||||
commonmark = "0.27.0"
|
||||
jnafilechooser = "1.1.2"
|
||||
xodus = "2.0.1"
|
||||
bip39 = "1.0.9"
|
||||
colorpicker = "2.0.1"
|
||||
rhino = "1.8.0"
|
||||
delight-rhino-sandbox = "0.0.17"
|
||||
testcontainers = "1.21.3"
|
||||
mixpanel = "1.5.3"
|
||||
jSerialComm = "2.11.2"
|
||||
rhino = "1.9.0"
|
||||
delight-rhino-sandbox = "0.2.1"
|
||||
testcontainers = "2.0.3"
|
||||
mixpanel = "1.5.4"
|
||||
jSerialComm = "2.11.4"
|
||||
ini4j = "0.5.5-2"
|
||||
restart4j = "0.0.1"
|
||||
eddsa = "0.3.0"
|
||||
exposed = "1.0.0-beta-4"
|
||||
exposed = "1.0.0-rc-4"
|
||||
h2 = "2.3.232"
|
||||
sqlite = "3.50.2.0"
|
||||
jug = "5.1.0"
|
||||
sqlite = "3.50.3.0"
|
||||
jug = "5.2.0"
|
||||
semver4j = "6.0.0"
|
||||
jsvg = "2.0.0"
|
||||
dom4j = "2.2.0"
|
||||
@@ -70,7 +70,7 @@ flatlafextras = { group = "com.formdev", name = "flatlaf-extras", version.ref =
|
||||
flatlafswingx = { module = "com.formdev:flatlaf-swingx", version.ref = "flatlaf" }
|
||||
testcontainers-bom = { module = "org.testcontainers:testcontainers-bom", version.ref = "testcontainers" }
|
||||
testcontainers = { module = "org.testcontainers:testcontainers" }
|
||||
testcontainers-junit-jupiter = { module = "org.testcontainers:junit-jupiter" }
|
||||
testcontainers-junit-jupiter = { module = "org.testcontainers:testcontainers-junit-jupiter" }
|
||||
swingx = { module = "org.swinglabs.swingx:swingx-all", version.ref = "swingx" }
|
||||
jgoodies-forms = { module = "com.jgoodies:jgoodies-forms", version.ref = "jgoodies-forms" }
|
||||
jna = { module = "net.java.dev.jna:jna", version.ref = "jna" }
|
||||
@@ -106,7 +106,7 @@ eddsa = { module = "net.i2p.crypto:eddsa", version.ref = "eddsa" }
|
||||
exposed-core = { module = "org.jetbrains.exposed:exposed-core", version.ref = "exposed" }
|
||||
exposed-crypt = { module = "org.jetbrains.exposed:exposed-crypt", version.ref = "exposed" }
|
||||
exposed-jdbc = { module = "org.jetbrains.exposed:exposed-jdbc", version.ref = "exposed" }
|
||||
exposed-migration = { module = "org.jetbrains.exposed:exposed-migration", version.ref = "exposed" }
|
||||
exposed-migration = { module = "org.jetbrains.exposed:exposed-migration-core", version.ref = "exposed" }
|
||||
h2 = { module = "com.h2database:h2", version.ref = "h2" }
|
||||
sqlite = { module = "org.xerial:sqlite-jdbc", version.ref = "sqlite" }
|
||||
jug = { module = "com.fasterxml.uuid:java-uuid-generator", version.ref = "jug" }
|
||||
|
||||
@@ -5,6 +5,7 @@ The files in this catalogue are for public access only. Specific descriptions ar
|
||||
- You may view and study the contents of these files;
|
||||
- You may NOT use them for any commercial purpose;
|
||||
- You may NOT modify, copy, distribute, republish, or use them to create derivative works;
|
||||
- Written permission must be obtained from the author for any use beyond personal viewing.
|
||||
- Written permission must be obtained from the author for any use beyond personal viewing;
|
||||
- If you submit a Pull Request that modifies, supplements, or adds to the files in this directory or its subdirectories, unless otherwise agreed in writing, you agree that the copyright of your contribution is owned by hstyi and may be used and managed under the current license terms.
|
||||
|
||||
All rights reserved.
|
||||
@@ -3,7 +3,7 @@ plugins {
|
||||
}
|
||||
|
||||
|
||||
project.version = "0.0.5"
|
||||
project.version = "0.0.6"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -18,4 +18,8 @@ object Appearance {
|
||||
set(value) {
|
||||
enableManager.setFlag("Plugins.bg.interval", value)
|
||||
}
|
||||
|
||||
var fillMode: String
|
||||
get() = enableManager.getFlag("Plugins.bg.fillMode", FillMode.STRETCH.name)
|
||||
set(value) = enableManager.setFlag("Plugins.bg.fillMode", value)
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package app.termora.plugins.bg
|
||||
|
||||
import app.termora.GlassPaneExtension
|
||||
import app.termora.WindowScope
|
||||
import app.termora.restore
|
||||
import app.termora.save
|
||||
import com.formdev.flatlaf.FlatLaf
|
||||
import java.awt.AlphaComposite
|
||||
import java.awt.Graphics2D
|
||||
@@ -12,15 +14,52 @@ class BGGlassPaneExtension private constructor() : GlassPaneExtension {
|
||||
val instance = BGGlassPaneExtension()
|
||||
}
|
||||
|
||||
|
||||
override fun paint(scope: WindowScope, c: JComponent, g2d: Graphics2D) {
|
||||
|
||||
val img = BackgroundManager.getInstance().getBackgroundImage() ?: return
|
||||
g2d.save()
|
||||
g2d.composite = AlphaComposite.getInstance(
|
||||
AlphaComposite.SRC_OVER,
|
||||
if (FlatLaf.isLafDark()) 0.2f else 0.1f
|
||||
)
|
||||
|
||||
when (Appearance.fillMode) {
|
||||
FillMode.STRETCH.name -> {
|
||||
g2d.drawImage(img, 0, 0, c.width, c.height, null)
|
||||
g2d.composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER)
|
||||
}
|
||||
|
||||
FillMode.CENTER.name -> {
|
||||
val x = (c.width - img.width) / 2
|
||||
val y = (c.height - img.height) / 2
|
||||
g2d.drawImage(img, x, y, null)
|
||||
}
|
||||
|
||||
FillMode.TILE.name -> {
|
||||
val iw = img.width
|
||||
val ih = img.height
|
||||
var y = 0
|
||||
while (y < c.height) {
|
||||
var x = 0
|
||||
while (x < c.width) {
|
||||
g2d.drawImage(img, x, y, null)
|
||||
x += iw
|
||||
}
|
||||
y += ih
|
||||
}
|
||||
}
|
||||
|
||||
FillMode.FIT.name -> {
|
||||
val scale = maxOf(c.width.toDouble() / img.width, c.height.toDouble() / img.height)
|
||||
val newW = (img.width * scale).toInt()
|
||||
val newH = (img.height * scale).toInt()
|
||||
val x = (c.width - newW) / 2
|
||||
val y = (c.height - newH) / 2
|
||||
g2d.drawImage(img, x, y, newW, newH, null)
|
||||
}
|
||||
}
|
||||
|
||||
g2d.restore()
|
||||
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,8 @@ import org.apache.commons.lang3.StringUtils
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Component
|
||||
import java.awt.event.ItemEvent
|
||||
import java.io.File
|
||||
import java.nio.file.StandardCopyOption
|
||||
import javax.swing.*
|
||||
@@ -23,6 +25,7 @@ class BackgroundOption : JPanel(BorderLayout()), OptionsPane.PluginOption {
|
||||
private val owner get() = SwingUtilities.getWindowAncestor(this)
|
||||
|
||||
val backgroundImageTextField = OutlineTextField()
|
||||
val fillModeComboBox = OutlineComboBox<FillMode>()
|
||||
val intervalSpinner = NumberSpinner(360, minimum = 30, maximum = 86400)
|
||||
|
||||
private val backgroundButton = JButton(Icons.folder)
|
||||
@@ -36,6 +39,38 @@ class BackgroundOption : JPanel(BorderLayout()), OptionsPane.PluginOption {
|
||||
|
||||
private fun initView() {
|
||||
|
||||
fillModeComboBox.addItem(FillMode.STRETCH)
|
||||
fillModeComboBox.addItem(FillMode.FIT)
|
||||
fillModeComboBox.addItem(FillMode.CENTER)
|
||||
fillModeComboBox.addItem(FillMode.TILE)
|
||||
|
||||
fillModeComboBox.selectedItem = runCatching { FillMode.valueOf(Appearance.fillMode) }
|
||||
.getOrNull() ?: FillMode.STRETCH
|
||||
|
||||
fillModeComboBox.renderer = object : DefaultListCellRenderer() {
|
||||
override fun getListCellRendererComponent(
|
||||
list: JList<*>?,
|
||||
value: Any?,
|
||||
index: Int,
|
||||
isSelected: Boolean,
|
||||
cellHasFocus: Boolean
|
||||
): Component? {
|
||||
var text = value?.toString()
|
||||
|
||||
if (value == FillMode.STRETCH) {
|
||||
text = BGI18n.getString("termora.plugins.bg.fill-mode.stretch")
|
||||
} else if (value == FillMode.FIT) {
|
||||
text = BGI18n.getString("termora.plugins.bg.fill-mode.fit")
|
||||
} else if (value == FillMode.CENTER) {
|
||||
text = BGI18n.getString("termora.plugins.bg.fill-mode.center")
|
||||
} else if (value == FillMode.TILE) {
|
||||
text = BGI18n.getString("termora.plugins.bg.fill-mode.tile")
|
||||
}
|
||||
|
||||
return super.getListCellRendererComponent(list, text, index, isSelected, cellHasFocus)
|
||||
}
|
||||
}
|
||||
|
||||
backgroundImageTextField.isEditable = false
|
||||
backgroundImageTextField.trailingComponent = backgroundButton
|
||||
backgroundImageTextField.text = Appearance.backgroundImage
|
||||
@@ -80,6 +115,15 @@ class BackgroundOption : JPanel(BorderLayout()), OptionsPane.PluginOption {
|
||||
Appearance.interval = value
|
||||
}
|
||||
}
|
||||
|
||||
fillModeComboBox.addItemListener {
|
||||
if (it.stateChange == ItemEvent.SELECTED) {
|
||||
Appearance.fillMode = fillModeComboBox.selectedItem?.toString() ?: FillMode.STRETCH.name
|
||||
for (frame in TermoraFrameManager.getInstance().getWindows()) {
|
||||
SwingUtilities.invokeLater { SwingUtilities.updateComponentTreeUI(frame) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onSelectedBackgroundImage(file: File) {
|
||||
@@ -124,7 +168,7 @@ class BackgroundOption : JPanel(BorderLayout()), OptionsPane.PluginOption {
|
||||
private fun getFormPanel(): JPanel {
|
||||
val layout = FormLayout(
|
||||
"left:pref, $FORM_MARGIN, default:grow, $FORM_MARGIN, default",
|
||||
"pref, $FORM_MARGIN, pref"
|
||||
"pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref"
|
||||
)
|
||||
|
||||
var rows = 1
|
||||
@@ -138,6 +182,10 @@ class BackgroundOption : JPanel(BorderLayout()), OptionsPane.PluginOption {
|
||||
.add(bgClearBox).xy(5, rows)
|
||||
.apply { rows += step }
|
||||
|
||||
builder.add("${BGI18n.getString("termora.plugins.bg.fill-mode")}:").xy(1, rows)
|
||||
.add(fillModeComboBox).xy(3, rows)
|
||||
.apply { rows += step }
|
||||
|
||||
builder.add("${BGI18n.getString("termora.plugins.bg.interval")}:").xy(1, rows)
|
||||
.add(intervalSpinner).xy(3, rows)
|
||||
.apply { rows += step }
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package app.termora.plugins.bg
|
||||
|
||||
enum class FillMode {
|
||||
STRETCH, // 拉伸
|
||||
FIT, // 等比例铺满
|
||||
CENTER, // 居中
|
||||
TILE, // 平铺
|
||||
}
|
||||
@@ -1,2 +1,7 @@
|
||||
termora.plugins.bg.interval=Interval
|
||||
termora.plugins.bg.fill-mode=Fill Mode
|
||||
termora.plugins.bg.fill-mode.stretch=Stretch
|
||||
termora.plugins.bg.fill-mode.fit=Fit
|
||||
termora.plugins.bg.fill-mode.center=Center
|
||||
termora.plugins.bg.fill-mode.tile=Tile
|
||||
termora.plugins.bg.background-image=Background Image
|
||||
|
||||
@@ -1,2 +1,8 @@
|
||||
termora.plugins.bg.background-image=背景图
|
||||
termora.plugins.bg.interval=切换间隔
|
||||
|
||||
termora.plugins.bg.fill-mode=填充模式
|
||||
termora.plugins.bg.fill-mode.stretch=拉伸
|
||||
termora.plugins.bg.fill-mode.fit=适合
|
||||
termora.plugins.bg.fill-mode.center=居中
|
||||
termora.plugins.bg.fill-mode.tile=平铺
|
||||
|
||||
@@ -1,2 +1,8 @@
|
||||
termora.plugins.bg.background-image=背景圖
|
||||
termora.plugins.bg.interval=切換間隔
|
||||
|
||||
termora.plugins.bg.fill-mode=填充模式
|
||||
termora.plugins.bg.fill-mode.stretch=拉伸
|
||||
termora.plugins.bg.fill-mode.fit=適合
|
||||
termora.plugins.bg.fill-mode.center=居中
|
||||
termora.plugins.bg.fill-mode.tile=平鋪
|
||||
|
||||
@@ -2,13 +2,13 @@ plugins {
|
||||
alias(libs.plugins.kotlin.jvm)
|
||||
}
|
||||
|
||||
project.version = "0.0.3"
|
||||
project.version = "0.0.4"
|
||||
|
||||
|
||||
|
||||
dependencies {
|
||||
testImplementation(kotlin("test"))
|
||||
implementation("com.qcloud:cos_api:5.6.247")
|
||||
implementation("com.qcloud:cos_api:5.6.259")
|
||||
compileOnly(project(":"))
|
||||
}
|
||||
|
||||
|
||||
@@ -4,13 +4,13 @@ plugins {
|
||||
|
||||
|
||||
|
||||
project.version = "0.0.6"
|
||||
project.version = "0.0.8"
|
||||
|
||||
|
||||
dependencies {
|
||||
testImplementation(kotlin("test"))
|
||||
compileOnly(project(":"))
|
||||
implementation("com.fifesoft:rsyntaxtextarea:3.6.0")
|
||||
implementation("com.fifesoft:rsyntaxtextarea:3.6.1")
|
||||
implementation("com.fifesoft:languagesupport:3.4.0")
|
||||
implementation("com.fifesoft:autocomplete:3.3.2")
|
||||
}
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
package app.termora.plugins.editor
|
||||
|
||||
import app.termora.DialogWrapper
|
||||
import app.termora.Disposable
|
||||
import app.termora.Disposer
|
||||
import app.termora.OptionPane
|
||||
import java.awt.Dimension
|
||||
import java.awt.Window
|
||||
import java.awt.event.WindowAdapter
|
||||
import java.awt.event.WindowEvent
|
||||
import java.io.File
|
||||
import java.nio.file.Path
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JOptionPane
|
||||
import javax.swing.UIManager
|
||||
import kotlin.io.path.absolutePathString
|
||||
import kotlin.io.path.name
|
||||
|
||||
|
||||
class EditorDialog(file: Path, owner: Window, private val myDisposable: Disposable) : DialogWrapper(null) {
|
||||
|
||||
private val filename = file.name
|
||||
private val filepath = File(file.absolutePathString())
|
||||
private val editorPanel = EditorPanel(this, filepath)
|
||||
private val disposed = AtomicBoolean()
|
||||
|
||||
init {
|
||||
size = Dimension(UIManager.getInt("Dialog.width"), UIManager.getInt("Dialog.height"))
|
||||
isModal = false
|
||||
controlsVisible = true
|
||||
isResizable = true
|
||||
title = filename
|
||||
iconImages = owner.iconImages
|
||||
escapeDispose = false
|
||||
defaultCloseOperation = DO_NOTHING_ON_CLOSE
|
||||
|
||||
initEvents()
|
||||
|
||||
setLocationRelativeTo(owner)
|
||||
|
||||
init()
|
||||
}
|
||||
|
||||
|
||||
private fun initEvents() {
|
||||
|
||||
addWindowListener(object : WindowAdapter() {
|
||||
override fun windowClosing(e: WindowEvent?) {
|
||||
if (disposed.compareAndSet(false, true)) {
|
||||
doCancelAction()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Disposer.register(myDisposable, object : Disposable {
|
||||
override fun dispose() {
|
||||
if (disposed.compareAndSet(false, true)) {
|
||||
doCancelAction()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Disposer.register(disposable, object : Disposable {
|
||||
override fun dispose() {
|
||||
if (disposed.compareAndSet(false, true)) {
|
||||
Disposer.dispose(myDisposable)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun doCancelAction() {
|
||||
if (editorPanel.changes()) {
|
||||
if (OptionPane.showConfirmDialog(
|
||||
this,
|
||||
"文件尚未保存,你确定要退出吗?",
|
||||
optionType = JOptionPane.OK_CANCEL_OPTION,
|
||||
) != JOptionPane.OK_OPTION
|
||||
) {
|
||||
return
|
||||
}
|
||||
}
|
||||
super.doCancelAction()
|
||||
}
|
||||
|
||||
override fun createCenterPanel(): JComponent {
|
||||
return editorPanel
|
||||
}
|
||||
|
||||
override fun createSouthPanel(): JComponent? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package app.termora.plugins.editor
|
||||
|
||||
import app.termora.Disposable
|
||||
import app.termora.Disposer
|
||||
import app.termora.EnableManager
|
||||
import app.termora.OptionPane
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Dimension
|
||||
import java.awt.Window
|
||||
import java.awt.event.WindowAdapter
|
||||
import java.awt.event.WindowEvent
|
||||
import java.io.File
|
||||
import java.nio.file.Path
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import javax.swing.JFrame
|
||||
import javax.swing.JOptionPane
|
||||
import javax.swing.UIManager
|
||||
import kotlin.io.path.absolutePathString
|
||||
import kotlin.io.path.name
|
||||
import kotlin.math.max
|
||||
|
||||
class EditorFrame(private val file: Path, private val owner: Window, private val disposable: Disposable) : JFrame() {
|
||||
private val enableManager get() = EnableManager.getInstance()
|
||||
private val disposed = AtomicBoolean()
|
||||
private val filepath = File(file.absolutePathString())
|
||||
private val frame get() = this
|
||||
private val editorPanel = EditorPanel(this, filepath)
|
||||
|
||||
init {
|
||||
initView()
|
||||
initEvent()
|
||||
}
|
||||
|
||||
private fun initEvent() {
|
||||
|
||||
Disposer.register(disposable, object : Disposable {
|
||||
override fun dispose() {
|
||||
if (disposed.compareAndSet(false, true)) frame.dispose()
|
||||
}
|
||||
})
|
||||
|
||||
addWindowListener(object : WindowAdapter() {
|
||||
override fun windowClosed(e: WindowEvent) {
|
||||
if (disposed.compareAndSet(false, true)) Disposer.dispose(disposable)
|
||||
enableManager.setFlag("Plugins.editor.dialog.width", width)
|
||||
enableManager.setFlag("Plugins.editor.dialog.height", height)
|
||||
enableManager.setFlag("Plugins.editor.dialog.extendedState", extendedState)
|
||||
}
|
||||
|
||||
override fun windowClosing(e: WindowEvent?) {
|
||||
if (editorPanel.changes()) {
|
||||
if (OptionPane.showConfirmDialog(
|
||||
frame,
|
||||
EditorI18n.getString("termora.plugins.editor.not-save"),
|
||||
optionType = JOptionPane.OK_CANCEL_OPTION,
|
||||
) == JOptionPane.OK_OPTION
|
||||
) {
|
||||
frame.dispose()
|
||||
}
|
||||
} else {
|
||||
frame.dispose()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
size = Dimension(UIManager.getInt("Dialog.width"), UIManager.getInt("Dialog.height"))
|
||||
val state = enableManager.getFlag("Plugins.editor.dialog.extendedState", 0)
|
||||
|
||||
if ((state and MAXIMIZED_BOTH) == MAXIMIZED_BOTH) {
|
||||
frame.setLocationRelativeTo(null)
|
||||
frame.extendedState = state
|
||||
} else {
|
||||
val mySize = size
|
||||
mySize.width = max(enableManager.getFlag("Plugins.editor.dialog.width", mySize.width), mySize.width)
|
||||
mySize.height = max(enableManager.getFlag("Plugins.editor.dialog.height", mySize.height), mySize.height)
|
||||
size = mySize
|
||||
setLocationRelativeTo(owner)
|
||||
}
|
||||
|
||||
title = file.name
|
||||
iconImages = owner.iconImages
|
||||
defaultCloseOperation = DO_NOTHING_ON_CLOSE
|
||||
|
||||
rootPane.contentPane.layout = BorderLayout()
|
||||
rootPane.contentPane.add(editorPanel, BorderLayout.CENTER)
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.termora.plugins.editor
|
||||
|
||||
import app.termora.NamedI18n
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
object EditorI18n : NamedI18n("i18n/messages") {
|
||||
private val log = LoggerFactory.getLogger(EditorI18n::class.java)
|
||||
|
||||
override fun getLogger(): Logger {
|
||||
return log
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,6 @@
|
||||
package app.termora.plugins.editor
|
||||
|
||||
import app.termora.DocumentAdaptor
|
||||
import app.termora.DynamicColor
|
||||
import app.termora.EnableManager
|
||||
import app.termora.Icons
|
||||
import app.termora.*
|
||||
import app.termora.database.DatabaseManager
|
||||
import com.formdev.flatlaf.FlatLaf
|
||||
import com.formdev.flatlaf.extras.components.FlatTextField
|
||||
@@ -35,10 +32,14 @@ import javax.swing.event.DocumentEvent
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
class EditorPanel(private val window: JDialog, private val file: File) : JPanel(BorderLayout()) {
|
||||
class EditorPanel(private val window: JFrame, private val file: File) : JPanel(BorderLayout()) {
|
||||
|
||||
companion object {
|
||||
private val log = LoggerFactory.getLogger(EditorPanel::class.java)
|
||||
private val saveIcon = DynamicIcon(
|
||||
"icons/save.svg", "icons/save_dark.svg",
|
||||
loader = EditorPlugin::class.java.classLoader
|
||||
)
|
||||
}
|
||||
|
||||
private var text = file.readText(Charsets.UTF_8)
|
||||
@@ -54,6 +55,7 @@ class EditorPanel(private val window: JDialog, private val file: File) : JPanel(
|
||||
private val prevBtn = JButton(Icons.up)
|
||||
private val context = SearchContext()
|
||||
private val softWrapBtn = JToggleButton(Icons.softWrap)
|
||||
private val saveBtn = JButton(saveIcon)
|
||||
private val scrollUpBtn = JButton(Icons.scrollUp)
|
||||
private val scrollEndBtn = JButton(Icons.scrollDown)
|
||||
private val prettyBtn = JButton(Icons.reformatCode)
|
||||
@@ -141,11 +143,18 @@ class EditorPanel(private val window: JDialog, private val file: File) : JPanel(
|
||||
)
|
||||
|
||||
toolbar.orientation = VERTICAL
|
||||
toolbar.add(saveBtn)
|
||||
toolbar.add(scrollUpBtn)
|
||||
toolbar.add(prettyBtn)
|
||||
toolbar.add(softWrapBtn)
|
||||
toolbar.add(scrollEndBtn)
|
||||
|
||||
saveBtn.toolTipText = EditorI18n.getString("termora.plugins.editor.save")
|
||||
scrollUpBtn.toolTipText = EditorI18n.getString("termora.plugins.editor.first-line")
|
||||
scrollEndBtn.toolTipText = EditorI18n.getString("termora.plugins.editor.last-line")
|
||||
softWrapBtn.toolTipText = EditorI18n.getString("termora.plugins.editor.soft-wrap")
|
||||
prettyBtn.toolTipText = EditorI18n.getString("termora.plugins.editor.format")
|
||||
|
||||
val viewPanel = JPanel(BorderLayout())
|
||||
viewPanel.add(scrollPane, BorderLayout.CENTER)
|
||||
viewPanel.add(toolbar, BorderLayout.EAST)
|
||||
@@ -211,6 +220,8 @@ class EditorPanel(private val window: JDialog, private val file: File) : JPanel(
|
||||
}
|
||||
})
|
||||
|
||||
saveBtn.addActionListener(textArea.actionMap.get("Save"))
|
||||
|
||||
textArea.actionMap.put("Format", object : AbstractAction() {
|
||||
override fun actionPerformed(e: ActionEvent) {
|
||||
format()
|
||||
|
||||
@@ -14,7 +14,7 @@ class MyTransportEditFileExtension private constructor() : TransportEditFileExte
|
||||
|
||||
override fun edit(owner: Window, path: Path): Disposable {
|
||||
val disposable = Disposer.newDisposable()
|
||||
SwingUtilities.invokeLater { EditorDialog(path, owner, disposable).isVisible = true }
|
||||
SwingUtilities.invokeLater { EditorFrame(path, owner, disposable).isVisible = true }
|
||||
return disposable
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
termora.plugins.editor.not-save=The file has not been saved. Are you sure you want to exit?
|
||||
termora.plugins.editor.save=Save
|
||||
termora.plugins.editor.first-line=Jump to first line
|
||||
termora.plugins.editor.last-line=Jump to last line
|
||||
termora.plugins.editor.soft-wrap=Soft-wrap
|
||||
termora.plugins.editor.format=Format
|
||||
@@ -0,0 +1,6 @@
|
||||
termora.plugins.editor.not-save=Файл не сохранён. Вы уверены, что хотите выйти?
|
||||
termora.plugins.editor.save=Сохранить
|
||||
termora.plugins.editor.first-line=Перейти на первую строку
|
||||
termora.plugins.editor.last-line=Перейти на последнюю строку
|
||||
termora.plugins.editor.soft-wrap=Мягкий перенос
|
||||
termora.plugins.editor.format=Формат
|
||||
@@ -0,0 +1,6 @@
|
||||
termora.plugins.editor.not-save=文件尚未保存,你确定要退出吗?
|
||||
termora.plugins.editor.save=保存
|
||||
termora.plugins.editor.first-line=跳转到第一行
|
||||
termora.plugins.editor.last-line=跳转到最后一行
|
||||
termora.plugins.editor.soft-wrap=自动换行
|
||||
termora.plugins.editor.format=格式化
|
||||
@@ -0,0 +1,6 @@
|
||||
termora.plugins.editor.not-save=檔案尚未儲存,你確定要退出嗎?
|
||||
termora.plugins.editor.save=儲存
|
||||
termora.plugins.editor.first-line=跳到第一行
|
||||
termora.plugins.editor.last-line=跳到最後一行
|
||||
termora.plugins.editor.soft-wrap=自動換行
|
||||
termora.plugins.editor.format=格式化
|
||||
4
plugins/editor/src/main/resources/icons/save.svg
Normal file
4
plugins/editor/src/main/resources/icons/save.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<!-- Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.5 3V5.5H10.5V3M4.5 13V9.5H11.5V13M2.5 13.5V2.5H11.5L13.5 4.5V13.5H2.5Z" stroke="#6C707E" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 357 B |
4
plugins/editor/src/main/resources/icons/save_dark.svg
Normal file
4
plugins/editor/src/main/resources/icons/save_dark.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<!-- Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.5 3V5.5H10.5V3M4.5 13V9.5H11.5V13M2.5 13.5V2.5H11.5L13.5 4.5V13.5H2.5Z" stroke="#CED0D6" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 357 B |
@@ -2,12 +2,12 @@ plugins {
|
||||
alias(libs.plugins.kotlin.jvm)
|
||||
}
|
||||
|
||||
project.version = "0.0.1"
|
||||
project.version = "0.0.2"
|
||||
|
||||
dependencies {
|
||||
testImplementation(kotlin("test"))
|
||||
compileOnly(project(":"))
|
||||
implementation("org.apache.commons:commons-pool2:2.12.1")
|
||||
implementation("org.apache.commons:commons-pool2:2.13.0")
|
||||
testImplementation(project(":"))
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import java.awt.Component
|
||||
import java.awt.KeyboardFocusManager
|
||||
import java.awt.event.ComponentAdapter
|
||||
import java.awt.event.ComponentEvent
|
||||
import java.awt.event.ItemEvent
|
||||
import java.nio.charset.Charset
|
||||
import javax.swing.*
|
||||
|
||||
@@ -246,6 +247,12 @@ class FTPHostOptionsPane : OptionsPane() {
|
||||
removeComponentListener(this)
|
||||
}
|
||||
})
|
||||
|
||||
authenticationTypeComboBox.addItemListener {
|
||||
if (it.stateChange == ItemEvent.SELECTED) {
|
||||
passwordTextField.isEnabled = authenticationTypeComboBox.selectedItem == AuthenticationType.Password
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getIcon(isSelected: Boolean): Icon {
|
||||
|
||||
@@ -2,14 +2,14 @@ plugins {
|
||||
alias(libs.plugins.kotlin.jvm)
|
||||
}
|
||||
|
||||
project.version = "0.0.7"
|
||||
project.version = "0.0.8"
|
||||
|
||||
dependencies {
|
||||
testImplementation(kotlin("test"))
|
||||
compileOnly(project(":"))
|
||||
implementation("com.maxmind.geoip2:geoip2:4.3.1")
|
||||
implementation("com.maxmind.geoip2:geoip2:5.0.0")
|
||||
// https://github.com/hstyi/geolite2
|
||||
implementation("com.github.hstyi:geolite2:v1.0-202507070058")
|
||||
implementation("com.github.hstyi:geolite2:v1.0-202510270056")
|
||||
}
|
||||
|
||||
apply(from = "$rootDir/plugins/common.gradle.kts")
|
||||
|
||||
@@ -3,7 +3,7 @@ plugins {
|
||||
}
|
||||
|
||||
|
||||
project.version = "0.0.3"
|
||||
project.version = "0.0.4"
|
||||
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -187,8 +187,6 @@ class MigrationApplicationRunnerExtension private constructor() : ApplicationRun
|
||||
// 重启
|
||||
TermoraRestarter.getInstance().scheduleRestart(null, ask = false)
|
||||
|
||||
// 退出程序
|
||||
Disposer.dispose(TermoraFrameManager.getInstance())
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ project.version = "0.0.2"
|
||||
|
||||
dependencies {
|
||||
testImplementation(kotlin("test"))
|
||||
implementation("com.huaweicloud:esdk-obs-java-bundle:3.25.5")
|
||||
implementation("com.huaweicloud:esdk-obs-java-bundle:3.25.7")
|
||||
compileOnly(project(":"))
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ dependencies {
|
||||
testImplementation(libs.testcontainers.junit.jupiter)
|
||||
testImplementation(project(":"))
|
||||
|
||||
implementation("io.minio:minio:8.5.17")
|
||||
implementation("io.minio:minio:8.6.0")
|
||||
compileOnly(project(":"))
|
||||
}
|
||||
|
||||
|
||||
@@ -4,13 +4,13 @@ plugins {
|
||||
|
||||
|
||||
|
||||
project.version = "0.0.1"
|
||||
project.version = "0.0.5"
|
||||
|
||||
|
||||
dependencies {
|
||||
testImplementation(kotlin("test"))
|
||||
compileOnly(project(":"))
|
||||
implementation("com.fazecast:jSerialComm:2.11.2")
|
||||
implementation("com.fazecast:jSerialComm:2.11.4")
|
||||
}
|
||||
|
||||
apply(from = "$rootDir/plugins/common.gradle.kts")
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
package app.termora.plugins.serial
|
||||
|
||||
import app.termora.*
|
||||
import app.termora.account.AccountOwner
|
||||
import app.termora.highlight.KeywordHighlight
|
||||
import app.termora.plugin.internal.AltKeyModifier
|
||||
import app.termora.plugin.internal.BasicGeneralOption
|
||||
import app.termora.plugin.internal.BasicTerminalOption
|
||||
import com.fazecast.jSerialComm.SerialPort
|
||||
import com.formdev.flatlaf.FlatClientProperties
|
||||
import com.jgoodies.forms.builder.FormBuilder
|
||||
@@ -15,12 +19,16 @@ import java.awt.BorderLayout
|
||||
import java.awt.Component
|
||||
import java.awt.event.ComponentAdapter
|
||||
import java.awt.event.ComponentEvent
|
||||
import java.nio.charset.Charset
|
||||
import javax.swing.*
|
||||
|
||||
class SerialHostOptionsPane : OptionsPane() {
|
||||
class SerialHostOptionsPane(private val accountOwner: AccountOwner) : OptionsPane() {
|
||||
private val generalOption = BasicGeneralOption()
|
||||
private val terminalOption = TerminalOption()
|
||||
private val terminalOption = BasicTerminalOption().apply {
|
||||
showCharsetComboBox = true
|
||||
showStartupCommandTextField = true
|
||||
accountOwner = this@SerialHostOptionsPane.accountOwner
|
||||
init()
|
||||
}
|
||||
private val serialCommOption = SerialCommOption()
|
||||
|
||||
init {
|
||||
@@ -48,6 +56,12 @@ class SerialHostOptionsPane : OptionsPane() {
|
||||
encoding = terminalOption.charsetComboBox.selectedItem as String,
|
||||
startupCommand = terminalOption.startupCommandTextField.text,
|
||||
serialComm = serialComm,
|
||||
extras = mutableMapOf(
|
||||
"altModifier" to (terminalOption.altModifierComboBox.selectedItem?.toString()
|
||||
?: AltKeyModifier.EightBit.name),
|
||||
"keywordHighlightSetId" to ((terminalOption.highlightSetComboBox.selectedItem as? KeywordHighlight)?.id
|
||||
?: "-1"),
|
||||
)
|
||||
)
|
||||
|
||||
return Host(
|
||||
@@ -76,6 +90,20 @@ class SerialHostOptionsPane : OptionsPane() {
|
||||
serialCommOption.stopBitsComboBox.selectedItem = serialComm.stopBits
|
||||
serialCommOption.flowControlComboBox.selectedItem = serialComm.flowControl
|
||||
|
||||
val altModifier = host.options.extras["altModifier"] ?: AltKeyModifier.EightBit.name
|
||||
terminalOption.altModifierComboBox.selectedItem = runCatching { AltKeyModifier.valueOf(altModifier) }
|
||||
.getOrNull() ?: AltKeyModifier.EightBit
|
||||
|
||||
|
||||
val keywordHighlightSetId = host.options.extras["keywordHighlightSetId"]
|
||||
for (i in 0 until terminalOption.highlightSetComboBox.itemCount) {
|
||||
val item = terminalOption.highlightSetComboBox.getItemAt(i)
|
||||
if (item.id == keywordHighlightSetId) {
|
||||
terminalOption.highlightSetComboBox.selectedItem = item
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun validateFields(): Boolean {
|
||||
@@ -128,67 +156,6 @@ class SerialHostOptionsPane : OptionsPane() {
|
||||
}
|
||||
|
||||
|
||||
protected inner class TerminalOption : JPanel(BorderLayout()), Option {
|
||||
val charsetComboBox = JComboBox<String>()
|
||||
val startupCommandTextField = OutlineTextField()
|
||||
|
||||
|
||||
init {
|
||||
initView()
|
||||
initEvents()
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
add(getCenterComponent(), BorderLayout.CENTER)
|
||||
|
||||
|
||||
for (e in Charset.availableCharsets()) {
|
||||
charsetComboBox.addItem(e.key)
|
||||
}
|
||||
|
||||
charsetComboBox.selectedItem = "UTF-8"
|
||||
|
||||
}
|
||||
|
||||
private fun initEvents() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
override fun getIcon(isSelected: Boolean): Icon {
|
||||
return Icons.terminal
|
||||
}
|
||||
|
||||
override fun getTitle(): String {
|
||||
return I18n.getString("termora.new-host.terminal")
|
||||
}
|
||||
|
||||
override fun getJComponent(): JComponent {
|
||||
return this
|
||||
}
|
||||
|
||||
private fun getCenterComponent(): JComponent {
|
||||
val layout = FormLayout(
|
||||
"left:pref, $FORM_MARGIN, default:grow",
|
||||
"pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref"
|
||||
)
|
||||
|
||||
var rows = 1
|
||||
val step = 2
|
||||
val panel = FormBuilder.create().layout(layout)
|
||||
.add("${I18n.getString("termora.new-host.terminal.encoding")}:").xy(1, rows)
|
||||
.add(charsetComboBox).xy(3, rows).apply { rows += step }
|
||||
.add("${I18n.getString("termora.new-host.terminal.startup-commands")}:").xy(1, rows)
|
||||
.add(startupCommandTextField).xy(3, rows).apply { rows += step }
|
||||
.apply { rows += step }
|
||||
.build()
|
||||
|
||||
|
||||
return panel
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected inner class SerialCommOption : JPanel(BorderLayout()), Option {
|
||||
val serialPortComboBox = OutlineComboBox<String>()
|
||||
val baudRateComboBox = OutlineComboBox<Int>()
|
||||
|
||||
@@ -2,11 +2,12 @@ package app.termora.plugins.serial
|
||||
|
||||
import app.termora.Disposer
|
||||
import app.termora.Host
|
||||
import app.termora.account.AccountOwner
|
||||
import app.termora.protocol.ProtocolHostPanel
|
||||
import java.awt.BorderLayout
|
||||
|
||||
class SerialProtocolHostPanel : ProtocolHostPanel() {
|
||||
private val pane = SerialHostOptionsPane()
|
||||
class SerialProtocolHostPanel(accountOwner: AccountOwner) : ProtocolHostPanel() {
|
||||
private val pane = SerialHostOptionsPane(accountOwner)
|
||||
|
||||
init {
|
||||
initView()
|
||||
|
||||
@@ -16,7 +16,7 @@ internal class SerialProtocolHostPanelExtension private constructor() : Protocol
|
||||
}
|
||||
|
||||
override fun createProtocolHostPanel(accountOwner: AccountOwner): ProtocolHostPanel {
|
||||
return SerialProtocolHostPanel()
|
||||
return SerialProtocolHostPanel(accountOwner)
|
||||
}
|
||||
|
||||
override fun ordered(): Long {
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package app.termora.plugins.serial
|
||||
|
||||
import app.termora.Host
|
||||
import app.termora.Icons
|
||||
import app.termora.PtyHostTerminalTab
|
||||
import app.termora.WindowScope
|
||||
import app.termora.*
|
||||
import app.termora.terminal.PtyConnector
|
||||
import org.apache.commons.io.Charsets
|
||||
import java.nio.charset.StandardCharsets
|
||||
@@ -11,6 +8,8 @@ import javax.swing.Icon
|
||||
|
||||
class SerialTerminalTab(windowScope: WindowScope, host: Host) :
|
||||
PtyHostTerminalTab(windowScope, host) {
|
||||
|
||||
|
||||
override suspend fun openPtyConnector(): PtyConnector {
|
||||
val serialPort = Serials.openPort(host)
|
||||
return SerialPortPtyConnector(
|
||||
@@ -19,6 +18,10 @@ class SerialTerminalTab(windowScope: WindowScope, host: Host) :
|
||||
)
|
||||
}
|
||||
|
||||
override fun createReconnectTerminalTab(): TerminalTab {
|
||||
return SerialTerminalTab(windowScope, host)
|
||||
}
|
||||
|
||||
override fun getIcon(): Icon {
|
||||
return Icons.plugin
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ plugins {
|
||||
alias(libs.plugins.kotlin.jvm)
|
||||
}
|
||||
|
||||
project.version = "0.0.3"
|
||||
project.version = "0.0.4"
|
||||
|
||||
dependencies {
|
||||
testImplementation(kotlin("test"))
|
||||
|
||||
@@ -42,6 +42,7 @@ class SMBHostOptionsPane : OptionsPane() {
|
||||
sftpDefaultDirectory = sftpOption.defaultDirectoryField.text,
|
||||
extras = mutableMapOf(
|
||||
"smb.share" to generalOption.shareTextField.text,
|
||||
"smb.domain" to generalOption.domainTextField.text,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -66,6 +67,7 @@ class SMBHostOptionsPane : OptionsPane() {
|
||||
generalOption.remarkTextArea.text = host.remark
|
||||
generalOption.passwordTextField.text = host.authentication.password
|
||||
generalOption.shareTextField.text = host.options.extras["smb.share"] ?: StringUtils.EMPTY
|
||||
generalOption.domainTextField.text = host.options.extras["smb.domain"] ?: StringUtils.EMPTY
|
||||
|
||||
sftpOption.defaultDirectoryField.text = host.options.sftpDefaultDirectory
|
||||
}
|
||||
@@ -114,6 +116,7 @@ class SMBHostOptionsPane : OptionsPane() {
|
||||
val nameTextField = OutlineTextField(128)
|
||||
val shareTextField = OutlineTextField(256)
|
||||
val usernameTextField = OutlineComboBox<String>()
|
||||
val domainTextField = OutlineTextField(128)
|
||||
val hostTextField = OutlineTextField(255)
|
||||
val passwordTextField = OutlinePasswordField(255)
|
||||
val remarkTextArea = FixedLengthTextArea(512)
|
||||
@@ -188,7 +191,9 @@ class SMBHostOptionsPane : OptionsPane() {
|
||||
.add(portTextField).xy(7, rows).apply { rows += step }
|
||||
|
||||
.add("${I18n.getString("termora.new-host.general.username")}:").xy(1, rows)
|
||||
.add(usernameTextField).xyw(3, rows, 5).apply { rows += step }
|
||||
.add(usernameTextField).xy(3, rows)
|
||||
.add("${SMBI18n.getString("termora.plugins.smb.domain")}:").xy(5, rows)
|
||||
.add(domainTextField).xy(7, rows).apply { rows += step }
|
||||
|
||||
.add("${I18n.getString("termora.new-host.general.password")}:").xy(1, rows)
|
||||
.add(passwordTextField).xyw(3, rows, 5).apply { rows += step }
|
||||
|
||||
@@ -30,6 +30,7 @@ class SMBProtocolProvider private constructor() : TransferProtocolProvider {
|
||||
val client = SMBClient()
|
||||
val host = requester.host
|
||||
val connection = client.connect(host.host, host.port)
|
||||
val domain = host.options.extras["smb.domain"] ?: StringUtils.EMPTY
|
||||
val session = when (host.username) {
|
||||
"Guest" -> connection.authenticate(AuthenticationContext.guest())
|
||||
"Anonymous" -> connection.authenticate(AuthenticationContext.anonymous())
|
||||
@@ -37,7 +38,7 @@ class SMBProtocolProvider private constructor() : TransferProtocolProvider {
|
||||
AuthenticationContext(
|
||||
host.username,
|
||||
host.authentication.password.toCharArray(),
|
||||
null
|
||||
domain.ifBlank { null }
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
termora.plugins.smb.share=Share name
|
||||
termora.plugins.smb.domain=Domain
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
termora.plugins.smb.share=共享名称
|
||||
termora.plugins.smb.domain=域名
|
||||
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
termora.plugins.smb.share=共享名稱
|
||||
termora.plugins.smb.domain=網域
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ plugins {
|
||||
}
|
||||
|
||||
|
||||
project.version = "0.0.3"
|
||||
project.version = "0.0.4"
|
||||
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -2,13 +2,6 @@ termora.plugins.sync.disabled-sync=You are already logged in and cannot use this
|
||||
|
||||
termora.settings.sync=Sync
|
||||
termora.settings.sync.done=Synchronized data successfully
|
||||
termora.settings.sync.export=${termora.keymgr.export}
|
||||
termora.settings.sync.import=${termora.keymgr.import}
|
||||
termora.settings.sync.import.file-too-large=The file is too large
|
||||
termora.settings.sync.import.successful=Import data successfully
|
||||
termora.settings.sync.export-done=The export was successful
|
||||
termora.settings.sync.export-encrypt=Enter password to encrypt file (optional)
|
||||
termora.settings.sync.export-done-open-folder=The export was successful. Do you want to open the folder?
|
||||
termora.settings.sync.range=Range
|
||||
termora.settings.sync.range.keys=My keys
|
||||
termora.settings.sync.range.keyword-highlights=${termora.highlight}
|
||||
|
||||
@@ -2,15 +2,10 @@ termora.plugins.sync.disabled-sync=你已登录,无法使用此功能
|
||||
|
||||
|
||||
termora.settings.sync=同步
|
||||
termora.settings.sync.export-done=导出成功
|
||||
termora.settings.sync.export-encrypt=输入密码加密文件 (可选)
|
||||
termora.settings.sync.export-done-open-folder=导出成功,是否需要打开所在文件夹?
|
||||
termora.settings.sync.range=范围
|
||||
termora.settings.sync.range.keys=我的密钥
|
||||
termora.settings.sync.last-sync-time=最后同步时间
|
||||
termora.settings.sync.done=同步数据成功
|
||||
termora.settings.sync.import.file-too-large=文件太大
|
||||
termora.settings.sync.import.successful=导入数据成功
|
||||
termora.settings.sync.gist=片段
|
||||
termora.settings.sync.token=令牌
|
||||
termora.settings.sync.type=类型
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
termora.plugins.sync.disabled-sync=你已登錄,無法使用此功能
|
||||
|
||||
termora.settings.sync=同步
|
||||
termora.settings.sync.export-done=匯出成功
|
||||
termora.settings.sync.export-encrypt=輸入密碼加密檔案 (可選)
|
||||
termora.settings.sync.export-done-open-folder=匯出成功,是否需要打開所在資料夾?
|
||||
termora.settings.sync.range=範圍
|
||||
termora.settings.sync.range.keys=我的密鑰
|
||||
termora.settings.sync.last-sync-time=最後同步時間
|
||||
|
||||
17
plugins/vnc/build.gradle.kts
Normal file
17
plugins/vnc/build.gradle.kts
Normal file
@@ -0,0 +1,17 @@
|
||||
plugins {
|
||||
alias(libs.plugins.kotlin.jvm)
|
||||
}
|
||||
|
||||
|
||||
project.version = "0.0.1"
|
||||
|
||||
|
||||
dependencies {
|
||||
testImplementation(kotlin("test"))
|
||||
testImplementation(project(":"))
|
||||
implementation(files("${project.projectDir}/libs/trilead-ssh2-build217-jenkins-8.jar"))
|
||||
compileOnly(project(":"))
|
||||
}
|
||||
|
||||
|
||||
apply(from = "$rootDir/plugins/common.gradle.kts")
|
||||
BIN
plugins/vnc/libs/trilead-ssh2-build217-jenkins-8.jar
Normal file
BIN
plugins/vnc/libs/trilead-ssh2-build217-jenkins-8.jar
Normal file
Binary file not shown.
@@ -0,0 +1,40 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.core;
|
||||
|
||||
/**
|
||||
* @author dime at tightvnc.com
|
||||
*/
|
||||
public class SettingsChangedEvent {
|
||||
private final Object source;
|
||||
|
||||
public SettingsChangedEvent(Object source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public Object getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
}
|
||||
144
plugins/vnc/src/main/java/com/glavsoft/drawing/ColorDecoder.java
Normal file
144
plugins/vnc/src/main/java/com/glavsoft/drawing/ColorDecoder.java
Normal file
@@ -0,0 +1,144 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.drawing;
|
||||
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.rfb.encoding.PixelFormat;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
public class ColorDecoder {
|
||||
protected byte redShift;
|
||||
protected byte greenShift;
|
||||
protected byte blueShift;
|
||||
public short redMax;
|
||||
public short greenMax;
|
||||
public short blueMax;
|
||||
public final int bytesPerPixel;
|
||||
public final int bytesPerCPixel;
|
||||
public final int bytesPerPixelTight;
|
||||
private final byte[] buff;
|
||||
|
||||
private int startShift;
|
||||
private int startShiftCompact;
|
||||
private int addShiftItem;
|
||||
private final boolean isTightSpecific;
|
||||
|
||||
public ColorDecoder(PixelFormat pf) {
|
||||
redShift = pf.redShift;
|
||||
greenShift = pf.greenShift;
|
||||
blueShift = pf.blueShift;
|
||||
redMax = pf.redMax;
|
||||
greenMax = pf.greenMax;
|
||||
blueMax = pf.blueMax;
|
||||
bytesPerPixel = pf.bitsPerPixel / 8;
|
||||
final long significant = redMax << redShift | greenMax << greenShift | blueMax << blueShift;
|
||||
bytesPerCPixel = pf.depth <= 24 // as in RFB
|
||||
// || 32 == pf.depth) // UltraVNC use this... :(
|
||||
&& 32 == pf.bitsPerPixel
|
||||
&& ((significant & 0x00ff000000L) == 0 || (significant & 0x000000ffL) == 0)
|
||||
? 3
|
||||
: bytesPerPixel;
|
||||
bytesPerPixelTight = 24 == pf.depth && 32 == pf.bitsPerPixel ? 3 : bytesPerPixel;
|
||||
buff = new byte[bytesPerPixel];
|
||||
if (0 == pf.bigEndianFlag) {
|
||||
startShift = 0;
|
||||
startShiftCompact = 0;
|
||||
addShiftItem = 8;
|
||||
} else {
|
||||
startShift = pf.bitsPerPixel - 8;
|
||||
startShiftCompact = Math.max(0, pf.depth - 8);
|
||||
addShiftItem = -8;
|
||||
}
|
||||
isTightSpecific = 4==bytesPerPixel && 3==bytesPerPixelTight &&
|
||||
255 == redMax && 255 == greenMax && 255 == blueMax;
|
||||
}
|
||||
|
||||
protected int readColor(Transport transport) throws TransportException {
|
||||
return getColor(transport.readBytes(buff, 0, bytesPerPixel), 0);
|
||||
}
|
||||
|
||||
protected int readCompactColor(Transport transport) throws TransportException {
|
||||
return getCompactColor(transport.readBytes(buff, 0, bytesPerCPixel), 0);
|
||||
}
|
||||
|
||||
protected int readTightColor(Transport transport) throws TransportException {
|
||||
return getTightColor(transport.readBytes(buff, 0, bytesPerPixelTight), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert rfb encoded pixel color into 0x00rrggbb int value.
|
||||
* @param rawColor - bytes are ordered in right sequence (little/big endian transformations already done
|
||||
* @return 0x00rrggbb
|
||||
*/
|
||||
protected int convertColor(int rawColor) {
|
||||
return 255 * (rawColor >> redShift & redMax) / redMax << 16 |
|
||||
255 * (rawColor >> greenShift & greenMax) / greenMax << 8 |
|
||||
255 * (rawColor >> blueShift & blueMax) / blueMax;
|
||||
}
|
||||
|
||||
public void fillRawComponents(byte[] comp, byte[] bytes, int offset) {
|
||||
int rawColor = getRawTightColor(bytes, offset);
|
||||
comp[0] = (byte) (rawColor >> redShift & redMax);
|
||||
comp[1] = (byte) (rawColor >> greenShift & greenMax);
|
||||
comp[2] = (byte) (rawColor >> blueShift & blueMax);
|
||||
}
|
||||
|
||||
public int getTightColor(byte[] bytes, int offset) {
|
||||
return convertColor(getRawTightColor(bytes, offset));
|
||||
}
|
||||
|
||||
private int getRawTightColor(byte[] bytes, int offset) {
|
||||
if (isTightSpecific)
|
||||
return (bytes[offset++] & 0xff)<<16 |
|
||||
(bytes[offset++] & 0xff)<<8 |
|
||||
bytes[offset] & 0xff;
|
||||
else
|
||||
return getRawColor(bytes, offset);
|
||||
}
|
||||
|
||||
protected int getColor(byte[] bytes, int offset) {
|
||||
return convertColor(getRawColor(bytes, offset));
|
||||
}
|
||||
|
||||
private int getRawColor(byte[] bytes, int offset) {
|
||||
int shift = startShift;
|
||||
int item = addShiftItem;
|
||||
int rawColor = (bytes[offset++] & 0xff)<<shift;
|
||||
for (int i=1; i<bytesPerPixel; ++i) {
|
||||
rawColor |= (bytes[offset++] & 0xff)<<(shift+=item);
|
||||
}
|
||||
return rawColor;
|
||||
}
|
||||
|
||||
protected int getCompactColor(byte[] bytes, int offset) {
|
||||
int shift = startShiftCompact;
|
||||
int item = addShiftItem;
|
||||
int rawColor = (bytes[offset++] & 0xff)<<shift;
|
||||
for (int i=1; i< bytesPerCPixel; ++i) {
|
||||
rawColor |= (bytes[offset++] & 0xff)<<(shift+=item);
|
||||
}
|
||||
return convertColor(rawColor);
|
||||
}
|
||||
|
||||
}
|
||||
340
plugins/vnc/src/main/java/com/glavsoft/drawing/Renderer.java
Normal file
340
plugins/vnc/src/main/java/com/glavsoft/drawing/Renderer.java
Normal file
@@ -0,0 +1,340 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.drawing;
|
||||
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.rfb.encoding.PixelFormat;
|
||||
import com.glavsoft.rfb.encoding.decoder.FramebufferUpdateRectangle;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Render bitmap data
|
||||
*
|
||||
* @author dime @ tightvnc.com
|
||||
*/
|
||||
public abstract class Renderer {
|
||||
protected final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
public abstract void drawJpegImage(byte[] bytes, int offset,
|
||||
int jpegBufferLength, FramebufferUpdateRectangle rect);
|
||||
|
||||
protected int width;
|
||||
protected int height;
|
||||
protected int[] pixels;
|
||||
protected SoftCursor cursor;
|
||||
protected ColorDecoder colorDecoder;
|
||||
|
||||
protected void init(int width, int height, PixelFormat pixelFormat) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
initColorDecoder(pixelFormat);
|
||||
pixels = new int[width * height];
|
||||
Arrays.fill(pixels, 0);
|
||||
}
|
||||
|
||||
public void initColorDecoder(PixelFormat pixelFormat) {
|
||||
lock.lock();
|
||||
colorDecoder = new ColorDecoder(pixelFormat);
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw byte array bitmap data
|
||||
*
|
||||
* @param bytes bitmap data
|
||||
* @param x bitmap x position
|
||||
* @param y bitmap y position
|
||||
* @param width bitmap width
|
||||
* @param height bitmap height
|
||||
*/
|
||||
public void drawBytes(byte[] bytes, int x, int y, int width, int height) {
|
||||
int i = 0;
|
||||
lock.lock();
|
||||
for (int ly = y; ly < y + height; ++ly) {
|
||||
int end = ly * this.width + x + width;
|
||||
for (int pixelsOffset = ly * this.width + x; pixelsOffset < end; ++pixelsOffset) {
|
||||
pixels[pixelsOffset] = getPixelColor(bytes, i);
|
||||
i += colorDecoder.bytesPerPixel;
|
||||
}
|
||||
}
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw byte array bitmap data (for ZRLE)
|
||||
*/
|
||||
public int drawCompactBytes(byte[] bytes, int offset, int x, int y, int width, int height) {
|
||||
int i = offset;
|
||||
lock.lock();
|
||||
for (int ly = y; ly < y + height; ++ly) {
|
||||
int end = ly * this.width + x + width;
|
||||
for (int pixelsOffset = ly * this.width + x; pixelsOffset < end; ++pixelsOffset) {
|
||||
pixels[pixelsOffset] = getCompactPixelColor(bytes, i);
|
||||
i += colorDecoder.bytesPerCPixel;
|
||||
}
|
||||
}
|
||||
lock.unlock();
|
||||
return i - offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw int (colors) array bitmap data (for ZRLE)
|
||||
*/
|
||||
public void drawColoredBitmap(int[] colors, int x, int y, int width, int height) {
|
||||
int i = 0;
|
||||
lock.lock();
|
||||
for (int ly = y; ly < y + height; ++ly) {
|
||||
int end = ly * this.width + x + width;
|
||||
for (int pixelsOffset = ly * this.width + x; pixelsOffset < end; ++pixelsOffset) {
|
||||
pixels[pixelsOffset] = colors[i++];
|
||||
}
|
||||
}
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw byte array bitmap data (for Tight)
|
||||
*/
|
||||
public int drawTightBytes(byte[] bytes, int offset, int x, int y, int width, int height) {
|
||||
int i = offset;
|
||||
lock.lock();
|
||||
for (int ly = y; ly < y + height; ++ly) {
|
||||
int end = ly * this.width + x + width;
|
||||
for (int pixelsOffset = ly * this.width + x; pixelsOffset < end; ++pixelsOffset) {
|
||||
pixels[pixelsOffset] = colorDecoder.getTightColor(bytes, i);
|
||||
i += colorDecoder.bytesPerPixelTight;
|
||||
}
|
||||
}
|
||||
lock.unlock();
|
||||
return i - offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw byte array bitmap data (from array with plain RGB color components. Assumed: rrrrrrrr gggggggg bbbbbbbb)
|
||||
*/
|
||||
public void drawUncaliberedRGBLine(byte[] bytes, int x, int y, int width) {
|
||||
int end = y * this.width + x + width;
|
||||
lock.lock();
|
||||
for (int i = 3, pixelsOffset = y * this.width + x; pixelsOffset < end; ++pixelsOffset) {
|
||||
pixels[pixelsOffset] =
|
||||
// (0xff & bytes[i++]) << 16 |
|
||||
// (0xff & bytes[i++]) << 8 |
|
||||
// 0xff & bytes[i++];
|
||||
(0xff & 255 * (colorDecoder.redMax & bytes[i++]) / colorDecoder.redMax) << 16 |
|
||||
(0xff & 255 * (colorDecoder.greenMax & bytes[i++]) / colorDecoder.greenMax) << 8 |
|
||||
0xff & 255 * (colorDecoder.blueMax & bytes[i++]) / colorDecoder.blueMax;
|
||||
}
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw paletted byte array bitmap data
|
||||
*
|
||||
* @param buffer bitmap data
|
||||
* @param rect bitmap location and dimensions
|
||||
* @param palette colour palette
|
||||
* @param paletteSize number of colors in palette
|
||||
*/
|
||||
public void drawBytesWithPalette(byte[] buffer, FramebufferUpdateRectangle rect, int[] palette, int paletteSize) {
|
||||
lock.lock();
|
||||
// 2 colors
|
||||
if (2 == paletteSize) {
|
||||
int dx, dy, n;
|
||||
int i = rect.y * this.width + rect.x;
|
||||
int rowBytes = (rect.width + 7) / 8;
|
||||
byte b;
|
||||
|
||||
for (dy = 0; dy < rect.height; dy++) {
|
||||
for (dx = 0; dx < rect.width / 8; dx++) {
|
||||
b = buffer[dy * rowBytes + dx];
|
||||
for (n = 7; n >= 0; n--) {
|
||||
pixels[i++] = palette[b >> n & 1];
|
||||
}
|
||||
}
|
||||
for (n = 7; n >= 8 - rect.width % 8; n--) {
|
||||
pixels[i++] = palette[buffer[dy * rowBytes + dx] >> n & 1];
|
||||
}
|
||||
i += this.width - rect.width;
|
||||
}
|
||||
} else {
|
||||
// 3..255 colors (assuming bytesPixel == 4).
|
||||
int i = 0;
|
||||
for (int ly = rect.y; ly < rect.y + rect.height; ++ly) {
|
||||
for (int lx = rect.x; lx < rect.x + rect.width; ++lx) {
|
||||
int pixelsOffset = ly * this.width + lx;
|
||||
pixels[pixelsOffset] = palette[buffer[i++] & 0xFF];
|
||||
}
|
||||
}
|
||||
}
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy rectangle region from one position to another. Regions may be overlapped.
|
||||
*
|
||||
* @param srcX source rectangle x position
|
||||
* @param srcY source rectangle y position
|
||||
* @param dstRect destination rectangle
|
||||
*/
|
||||
public void copyRect(int srcX, int srcY, FramebufferUpdateRectangle dstRect) {
|
||||
int startSrcY, endSrcY, dstY, deltaY;
|
||||
if (srcY > dstRect.y) {
|
||||
startSrcY = srcY;
|
||||
endSrcY = srcY + dstRect.height;
|
||||
dstY = dstRect.y;
|
||||
deltaY = +1;
|
||||
} else {
|
||||
startSrcY = srcY + dstRect.height - 1;
|
||||
endSrcY = srcY - 1;
|
||||
dstY = dstRect.y + dstRect.height - 1;
|
||||
deltaY = -1;
|
||||
}
|
||||
lock.lock();
|
||||
for (int y = startSrcY; y != endSrcY; y += deltaY) {
|
||||
System.arraycopy(pixels, y * width + srcX,
|
||||
pixels, dstY * width + dstRect.x, dstRect.width);
|
||||
dstY += deltaY;
|
||||
}
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill rectangle region with specified colour
|
||||
*
|
||||
* @param color colour to fill with
|
||||
* @param rect rectangle region positions and dimensions
|
||||
*/
|
||||
public void fillRect(int color, FramebufferUpdateRectangle rect) {
|
||||
fillRect(color, rect.x, rect.y, rect.width, rect.height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill rectangle region with specified colour
|
||||
*
|
||||
* @param color colour to fill with
|
||||
* @param x rectangle x position
|
||||
* @param y rectangle y position
|
||||
* @param width rectangle width
|
||||
* @param height rectangle height
|
||||
*/
|
||||
public void fillRect(int color, int x, int y, int width, int height) {
|
||||
lock.lock();
|
||||
int sy = y * this.width + x;
|
||||
int ey = sy + height * this.width;
|
||||
for (int i = sy; i < ey; i += this.width) {
|
||||
Arrays.fill(pixels, i, i + width, color);
|
||||
}
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads color bytes (PIXEL) from transport, returns int combined RGB
|
||||
* value consisting of the red component in bits 16-23, the green component
|
||||
* in bits 8-15, and the blue component in bits 0-7. May be used directly for
|
||||
* creation awt.Color object
|
||||
*/
|
||||
public int readPixelColor(Transport transport) throws TransportException {
|
||||
return colorDecoder.readColor(transport);
|
||||
}
|
||||
|
||||
public int readTightPixelColor(Transport transport) throws TransportException {
|
||||
return colorDecoder.readTightColor(transport);
|
||||
}
|
||||
|
||||
public ColorDecoder getColorDecoder() {
|
||||
return colorDecoder;
|
||||
}
|
||||
|
||||
public int getCompactPixelColor(byte[] bytes, int offset) {
|
||||
return colorDecoder.getCompactColor(bytes, offset);
|
||||
}
|
||||
|
||||
public int getPixelColor(byte[] bytes, int offset) {
|
||||
return colorDecoder.getColor(bytes, offset);
|
||||
}
|
||||
|
||||
public int getBytesPerPixel() {
|
||||
return colorDecoder.bytesPerPixel;
|
||||
}
|
||||
|
||||
public int getBytesPerCPixel() {
|
||||
return colorDecoder.bytesPerCPixel;
|
||||
}
|
||||
|
||||
public int getBytesPerPixelTight() {
|
||||
return colorDecoder.bytesPerPixelTight;
|
||||
}
|
||||
|
||||
public void fillColorBitmapWithColor(int[] bitmapData, int decodedOffset, int rlength, int color) {
|
||||
while (rlength-- > 0) {
|
||||
bitmapData[decodedOffset++] = color;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Width of rendered image
|
||||
*
|
||||
* @return width
|
||||
*/
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Height of rendered image
|
||||
*
|
||||
* @return height
|
||||
*/
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and decode cursor image
|
||||
*
|
||||
* @param rect new cursor hot point position and cursor dimensions
|
||||
* @throws TransportException
|
||||
*/
|
||||
public void createCursor(int[] cursorPixels, FramebufferUpdateRectangle rect)
|
||||
throws TransportException {
|
||||
synchronized (cursor.getLock()) {
|
||||
cursor.createCursor(cursorPixels, rect.x, rect.y, rect.width, rect.height);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and decode new cursor position
|
||||
*
|
||||
* @param rect cursor position
|
||||
*/
|
||||
public void decodeCursorPosition(FramebufferUpdateRectangle rect) {
|
||||
synchronized (cursor.getLock()) {
|
||||
cursor.updatePosition(rect.x, rect.y);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.drawing;
|
||||
|
||||
/**
|
||||
* Abstract class for operations with soft cursor positions, dimensions and
|
||||
* hot point position.
|
||||
*/
|
||||
public abstract class SoftCursor {
|
||||
|
||||
protected int hotX, hotY;
|
||||
protected int x, y;
|
||||
public int width, height;
|
||||
public int rX, rY;
|
||||
public int oldRX, oldRY;
|
||||
public int oldWidth, oldHeight;
|
||||
private final Object lock = new Object();
|
||||
|
||||
public SoftCursor(int hotX, int hotY, int width, int height) {
|
||||
this.hotX = hotX;
|
||||
this.hotY = hotY;
|
||||
oldWidth = this.width = width;
|
||||
oldHeight = this.height = height;
|
||||
oldRX = rX = 0;
|
||||
oldRY = rY = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update cursor position
|
||||
*
|
||||
* @param newX
|
||||
* @param newY
|
||||
*/
|
||||
public void updatePosition(int newX, int newY) {
|
||||
oldRX = rX; oldRY = rY;
|
||||
oldWidth = width; oldHeight = height;
|
||||
x = newX; y = newY;
|
||||
rX = x - hotX; rY = y - hotY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set new cursor dimensions and hot point position
|
||||
*
|
||||
* @param hotX
|
||||
* @param hotY
|
||||
* @param width
|
||||
* @param height
|
||||
*/
|
||||
public void setNewDimensions(int hotX, int hotY, int width, int height) {
|
||||
this.hotX = hotX;
|
||||
this.hotY = hotY;
|
||||
oldWidth = this.width;
|
||||
oldHeight = this.height;
|
||||
oldRX = rX; oldRY = rY;
|
||||
rX = x - hotX; rY = y - hotY;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public void createCursor(int[] cursorPixels, int hotX, int hotY, int width, int height) {
|
||||
createNewCursorImage(cursorPixels, hotX, hotY, width, height);
|
||||
setNewDimensions(hotX, hotY, width, height);
|
||||
}
|
||||
|
||||
protected abstract void createNewCursorImage(int[] cursorPixels, int hotX, int hotY, int width, int height);
|
||||
|
||||
public Object getLock() {
|
||||
return lock;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.exceptions;
|
||||
|
||||
/**
|
||||
* Throws when authentication was wrong
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AuthenticationFailedException extends ProtocolException {
|
||||
|
||||
private String reason;
|
||||
|
||||
public AuthenticationFailedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
public AuthenticationFailedException(String message, String reason) {
|
||||
super(message);
|
||||
this.reason = reason;
|
||||
}
|
||||
public String getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.exceptions;
|
||||
|
||||
/**
|
||||
* Throwed when connection closed (EOF)
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ClosedConnectionException extends TransportException {
|
||||
|
||||
public ClosedConnectionException(Throwable exception) {
|
||||
super(exception);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.exceptions;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class CommonException extends Exception {
|
||||
|
||||
public CommonException(Throwable exception) {
|
||||
super(exception);
|
||||
}
|
||||
public CommonException(String message, Throwable exception) {
|
||||
super(message, exception);
|
||||
}
|
||||
public CommonException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.exceptions;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class CouldNotConnectException extends TransportException {
|
||||
|
||||
public CouldNotConnectException(Throwable exception) {
|
||||
super(exception);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.exceptions;
|
||||
|
||||
/**
|
||||
* Throws when problem with DES (or smth else) cryptosystem occured
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class CryptoException extends FatalException {
|
||||
public CryptoException(String message, Throwable exception) {
|
||||
super(message, exception);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.exceptions;
|
||||
|
||||
/**
|
||||
* Trhows when further normal program execution unavailable
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class FatalException extends CommonException {
|
||||
public FatalException(String message, Throwable e) {
|
||||
super(message, e);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.exceptions;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class ProtocolException extends CommonException {
|
||||
public ProtocolException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.exceptions;
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class TransportException extends CommonException {
|
||||
public TransportException(String message, Throwable exception) {
|
||||
super(message, exception);
|
||||
}
|
||||
public TransportException(Throwable exception) {
|
||||
super(exception);
|
||||
}
|
||||
public TransportException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.exceptions;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class UnsupportedProtocolVersionException extends ProtocolException {
|
||||
public UnsupportedProtocolVersionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.exceptions;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class UnsupportedSecurityTypeException extends ProtocolException {
|
||||
public UnsupportedSecurityTypeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb;
|
||||
|
||||
/**
|
||||
* Interface for handling clipboard texts
|
||||
*/
|
||||
public interface ClipboardController extends IChangeSettingsListener {
|
||||
void updateSystemClipboard(byte[] bytes);
|
||||
|
||||
/**
|
||||
* Get text clipboard contens when needed send to remote, or null vise versa
|
||||
* Implement this method such a way in swing context, because swing's clipboard
|
||||
* update listener invoked only on DataFlavor changes not content changes.
|
||||
* Implement as returned null on systems where clipboard listeners work correctly.
|
||||
*
|
||||
* @return clipboad string contents if it is changed from last method call
|
||||
* or null when clipboard contains non text object or clipboard contents didn't changed
|
||||
*/
|
||||
String getRenewedClipboardText();
|
||||
|
||||
/**
|
||||
* Returns clipboard text content previously retrieved frim system clipboard by
|
||||
* updateSavedClippoardContent()
|
||||
*
|
||||
* @return clipboard text content
|
||||
*/
|
||||
String getClipboardText();
|
||||
|
||||
/**
|
||||
* Enable/disable clipboard transfer
|
||||
*
|
||||
* @param enable
|
||||
*/
|
||||
void setEnabled(boolean enable);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb;
|
||||
|
||||
import com.glavsoft.core.SettingsChangedEvent;
|
||||
|
||||
/**
|
||||
* @author dime at tightvnc.com
|
||||
*/
|
||||
public interface IChangeSettingsListener {
|
||||
void settingsChanged(SettingsChangedEvent event);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb;
|
||||
|
||||
import com.glavsoft.drawing.Renderer;
|
||||
import com.glavsoft.rfb.encoding.PixelFormat;
|
||||
import com.glavsoft.rfb.encoding.decoder.FramebufferUpdateRectangle;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
/**
|
||||
* Interface for sending repaint event from worker thread to GUI thread
|
||||
*/
|
||||
public interface IRepaintController extends IChangeSettingsListener {
|
||||
void repaintBitmap(FramebufferUpdateRectangle rect);
|
||||
void repaintBitmap(int x, int y, int width, int height);
|
||||
void repaintCursor();
|
||||
void updateCursorPosition(short x, short y);
|
||||
Renderer createRenderer(Transport transport, int width, int height, PixelFormat pixelFormat);
|
||||
void setPixelFormat(PixelFormat pixelFormat);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb;
|
||||
|
||||
public interface IRequestString {
|
||||
String getResult();
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb;
|
||||
|
||||
/**
|
||||
* Fires Rfb session [start]-stop events
|
||||
*/
|
||||
public interface IRfbSessionListener {
|
||||
|
||||
/**
|
||||
* Fired after rfb session closed (threads stopped, other resources fried).
|
||||
* Note: this event may be fired from unpredictable thread.
|
||||
* @param reason reason to show why session closed
|
||||
*/
|
||||
void rfbSessionStopped(String reason);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb;
|
||||
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
/**
|
||||
* Structure used to describe protocol options such as tunneling methods,
|
||||
* authentication schemes and message types (protocol versions 3.7t, 3.8t).
|
||||
* typedef struct _rfbCapabilityInfo {
|
||||
* CARD32 code; // numeric identifier
|
||||
* CARD8 vendorSignature[4]; // vendor identification
|
||||
* CARD8 nameSignature[8]; // abbreviated option name
|
||||
* } rfbCapabilityInfo;
|
||||
*/
|
||||
public class RfbCapabilityInfo {
|
||||
/*
|
||||
* Vendors known by TightVNC: standard VNC/RealVNC, TridiaVNC, and TightVNC.
|
||||
* #define rfbStandardVendor "STDV"
|
||||
* #define rfbTridiaVncVendor "TRDV"
|
||||
* #define rfbTightVncVendor "TGHT"
|
||||
*/
|
||||
public static final String VENDOR_STANDARD = "STDV";
|
||||
public static final String VENDOR_TRIADA = "TRDV";
|
||||
public static final String VENDOR_TIGHT = "TGHT";
|
||||
|
||||
public static final String TUNNELING_NO_TUNNEL = "NOTUNNEL";
|
||||
|
||||
public static final String AUTHENTICATION_NO_AUTH = "NOAUTH__";
|
||||
public static final String AUTHENTICATION_VNC_AUTH ="VNCAUTH_";
|
||||
|
||||
public static final String ENCODING_COPYRECT = "COPYRECT";
|
||||
public static final String ENCODING_HEXTILE = "HEXTILE_";
|
||||
public static final String ENCODING_ZLIB = "ZLIB____";
|
||||
public static final String ENCODING_ZRLE = "ZRLE____";
|
||||
public static final String ENCODING_RRE = "RRE_____";
|
||||
public static final String ENCODING_TIGHT = "TIGHT___";
|
||||
// "Pseudo" encoding types
|
||||
public static final String ENCODING_RICH_CURSOR = "RCHCURSR";
|
||||
public static final String ENCODING_CURSOR_POS = "POINTPOS";
|
||||
public static final String ENCODING_DESKTOP_SIZE = "NEWFBSIZ";
|
||||
|
||||
private int code;
|
||||
private String vendorSignature;
|
||||
private String nameSignature;
|
||||
private boolean enable;
|
||||
|
||||
public RfbCapabilityInfo(int code, String vendorSignature, String nameSignature) {
|
||||
this.code = code;
|
||||
this.vendorSignature = vendorSignature;
|
||||
this.nameSignature = nameSignature;
|
||||
enable = true;
|
||||
}
|
||||
|
||||
public RfbCapabilityInfo() {
|
||||
this(0, "", "");
|
||||
}
|
||||
|
||||
public RfbCapabilityInfo readFrom(Transport transport) throws TransportException {
|
||||
code = transport.readInt32();
|
||||
vendorSignature = transport.readString(4);
|
||||
nameSignature = transport.readString(8);
|
||||
enable = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
RfbCapabilityInfo that = (RfbCapabilityInfo) o;
|
||||
return code == that.code &&
|
||||
nameSignature.equals(that.nameSignature) &&
|
||||
vendorSignature.equals(that.vendorSignature);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = code;
|
||||
result = 31 * result + vendorSignature.hashCode();
|
||||
result = 31 * result + nameSignature.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setEnable(boolean enable) {
|
||||
this.enable = enable;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getVendorSignature() {
|
||||
return vendorSignature;
|
||||
}
|
||||
|
||||
public String getNameSignature() {
|
||||
return nameSignature;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RfbCapabilityInfo{" +
|
||||
"code=" + code +
|
||||
", vendorSignature='" + vendorSignature + '\'' +
|
||||
", nameSignature='" + nameSignature + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.client;
|
||||
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static com.glavsoft.utils.Strings.getBytesWithCharset;
|
||||
|
||||
/**
|
||||
* ClientCutText
|
||||
* The client has new ISO 8859-1 (Latin-1) text in its cut buffer. Ends of lines are repre-
|
||||
* sented by the linefeed / newline character (value 10) alone. No carriage-return (value
|
||||
* 13) is needed. There is currently no way to transfer text outside the Latin-1 character
|
||||
* set.
|
||||
* 1 - U8 - 6
|
||||
* 3 - - padding
|
||||
* 4 - U32 - length
|
||||
* length - U8 array - text
|
||||
*/
|
||||
public class ClientCutTextMessage implements ClientToServerMessage {
|
||||
private final byte [] bytes;
|
||||
|
||||
public ClientCutTextMessage(String str, Charset charset) {
|
||||
final byte[] b = charset != null? getBytesWithCharset(str, charset): str.getBytes();
|
||||
this.bytes = Arrays.copyOf(b, b.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Transport transport) throws TransportException {
|
||||
transport.writeByte(ClientMessageType.CLIENT_CUT_TEXT.id)
|
||||
.zero(3) // padding
|
||||
.writeInt32(bytes.length)
|
||||
.write(bytes)
|
||||
.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ClientCutTextMessage: [length: " + bytes.length +", text: ...]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.client;
|
||||
|
||||
/**
|
||||
* @author dime at glavsoft.com
|
||||
*/
|
||||
public enum ClientMessageType {
|
||||
SET_PIXEL_FORMAT(0),
|
||||
SET_ENCODINGS(2),
|
||||
FRAMEBUFFER_UPDATE_REQUEST(3),
|
||||
KEY_EVENT(4),
|
||||
POINTER_EVENT(5),
|
||||
CLIENT_CUT_TEXT(6),
|
||||
|
||||
VIDEO_RECTANGLE_SELECTION(151),
|
||||
VIDEO_FREEZE(152);
|
||||
|
||||
final public int id;
|
||||
|
||||
ClientMessageType(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
private static final ClientMessageType [] standardTypes =
|
||||
{SET_PIXEL_FORMAT, SET_ENCODINGS, FRAMEBUFFER_UPDATE_REQUEST, KEY_EVENT, POINTER_EVENT, CLIENT_CUT_TEXT};
|
||||
|
||||
public static boolean isStandardType(ClientMessageType type) {
|
||||
for (final ClientMessageType it : standardTypes) {
|
||||
if (it == type) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static ClientMessageType byId(int id) {
|
||||
for (ClientMessageType type : values()) {
|
||||
if (type.id == id)
|
||||
return type;
|
||||
}
|
||||
throw new IllegalArgumentException("Unsupported client message type: " + id);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.client;
|
||||
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
public interface ClientToServerMessage {
|
||||
void send(Transport transport) throws TransportException;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.client;
|
||||
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
|
||||
public class FramebufferUpdateRequestMessage implements ClientToServerMessage {
|
||||
private final boolean incremental;
|
||||
private final int height;
|
||||
private final int width;
|
||||
private final int y;
|
||||
private final int x;
|
||||
|
||||
public FramebufferUpdateRequestMessage(int x, int y, int width,
|
||||
int height, boolean incremental) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.incremental = incremental;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Transport transport) throws TransportException {
|
||||
transport.writeByte(ClientMessageType.FRAMEBUFFER_UPDATE_REQUEST.id)
|
||||
.writeByte(incremental ? 1 : 0)
|
||||
.writeInt16(x)
|
||||
.writeInt16(y)
|
||||
.writeInt16(width)
|
||||
.writeInt16(height)
|
||||
.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FramebufferUpdateRequestMessage: [x: " + x + " y: " + y
|
||||
+ " width: " + width + " height: " + height +
|
||||
" incremental: " + incremental + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.client;
|
||||
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
/**
|
||||
* A key press or release. Down-flag is non-zero (true) if the key is now pressed, zero
|
||||
* (false) if it is now released. The key itself is specified using the "keysym" values
|
||||
* defined by the X Window System.
|
||||
* 1 - U8 - message-type
|
||||
* 1 - U8 - down-flag
|
||||
* 2 - - - padding
|
||||
* 4 - U32 - key
|
||||
* For most ordinary keys, the "keysym" is the same as the corresponding ASCII value.
|
||||
* For full details, see The Xlib Reference Manual, published by O'Reilly & Associates,
|
||||
* or see the header file <X11/keysymdef.h> from any X Window System installation.
|
||||
*/
|
||||
public class KeyEventMessage implements ClientToServerMessage {
|
||||
|
||||
private final int key;
|
||||
private final boolean downFlag;
|
||||
|
||||
public KeyEventMessage(int key, boolean downFlag) {
|
||||
this.downFlag = downFlag;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Transport transport) throws TransportException {
|
||||
transport.writeByte(ClientMessageType.KEY_EVENT.id)
|
||||
.writeByte(downFlag ? 1 : 0)
|
||||
.zero(2) // padding
|
||||
.write(key)
|
||||
.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[KeyEventMessage: [down-flag: "+downFlag + ", key: " + key +"("+Integer.toHexString(key)+")]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.client;
|
||||
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
public class PointerEventMessage implements ClientToServerMessage {
|
||||
private final byte buttonMask;
|
||||
private final short x;
|
||||
private final short y;
|
||||
|
||||
public PointerEventMessage(byte buttonMask, short x, short y) {
|
||||
this.buttonMask = buttonMask;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Transport transport) throws TransportException {
|
||||
transport.writeByte(ClientMessageType.POINTER_EVENT.id)
|
||||
.writeByte(buttonMask)
|
||||
.writeInt16(x)
|
||||
.writeInt16(y)
|
||||
.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PointerEventMessage: [x: "+ x +", y: "+ y + ", button-mask: " +
|
||||
buttonMask +"]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.client;
|
||||
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.rfb.encoding.EncodingType;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class SetEncodingsMessage implements ClientToServerMessage {
|
||||
private final Set<EncodingType> encodings;
|
||||
|
||||
public SetEncodingsMessage(Set<EncodingType> set) {
|
||||
this.encodings = set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Transport transport) throws TransportException {
|
||||
transport.writeByte(ClientMessageType.SET_ENCODINGS.id)
|
||||
.zero(1) // padding byte
|
||||
.writeInt16(encodings.size());
|
||||
for (EncodingType enc : encodings) {
|
||||
transport.writeInt32(enc.getId());
|
||||
}
|
||||
transport.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("SetEncodingsMessage: [encodings: ");
|
||||
for (EncodingType enc : encodings) {
|
||||
sb.append(enc.name()).append(',');
|
||||
}
|
||||
sb.setLength(sb.length()-1);
|
||||
return sb.append(']').toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.client;
|
||||
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.rfb.encoding.PixelFormat;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
public class SetPixelFormatMessage implements ClientToServerMessage {
|
||||
private final PixelFormat pixelFormat;
|
||||
|
||||
public SetPixelFormatMessage(PixelFormat pixelFormat) {
|
||||
this.pixelFormat = pixelFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Transport transport) throws TransportException {
|
||||
transport.writeByte(ClientMessageType.SET_PIXEL_FORMAT.id)
|
||||
.zero(3);
|
||||
pixelFormat.send(transport);
|
||||
transport.flush();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.client;
|
||||
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
/**
|
||||
* @author dime at glavsoft.com
|
||||
*/
|
||||
public class VideoFreezeMessage implements ClientToServerMessage {
|
||||
|
||||
private boolean freeze;
|
||||
|
||||
public VideoFreezeMessage(boolean freeze) {
|
||||
this.freeze = freeze;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Transport transport) throws TransportException {
|
||||
transport.writeByte(ClientMessageType.VIDEO_FREEZE.id)
|
||||
.writeByte(freeze ? 1 : 0)
|
||||
.flush();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.client;
|
||||
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
/**
|
||||
* @author dime at glavsoft.com
|
||||
*/
|
||||
public class VideoRectangleSelectionMessage implements ClientToServerMessage {
|
||||
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int width;
|
||||
private final int height;
|
||||
|
||||
public VideoRectangleSelectionMessage(int x, int y, int width, int height) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Transport transport) throws TransportException {
|
||||
transport.writeByte(ClientMessageType.VIDEO_RECTANGLE_SELECTION.id)
|
||||
.zero(1) // padding
|
||||
.writeInt16(x)
|
||||
.writeInt16(y)
|
||||
.writeInt16(width)
|
||||
.writeInt16(height)
|
||||
.flush();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.encoding;
|
||||
|
||||
import com.glavsoft.rfb.encoding.decoder.CopyRectDecoder;
|
||||
import com.glavsoft.rfb.encoding.decoder.CursorPosDecoder;
|
||||
import com.glavsoft.rfb.encoding.decoder.Decoder;
|
||||
import com.glavsoft.rfb.encoding.decoder.DesctopSizeDecoder;
|
||||
import com.glavsoft.rfb.encoding.decoder.FakeDecoder;
|
||||
import com.glavsoft.rfb.encoding.decoder.HextileDecoder;
|
||||
import com.glavsoft.rfb.encoding.decoder.RREDecoder;
|
||||
import com.glavsoft.rfb.encoding.decoder.RawDecoder;
|
||||
import com.glavsoft.rfb.encoding.decoder.RichCursorDecoder;
|
||||
import com.glavsoft.rfb.encoding.decoder.TightDecoder;
|
||||
import com.glavsoft.rfb.encoding.decoder.ZRLEDecoder;
|
||||
import com.glavsoft.rfb.encoding.decoder.ZlibDecoder;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
/**
|
||||
* Encoding types
|
||||
*/
|
||||
public enum EncodingType {
|
||||
/**
|
||||
* Desktop data representes as raw bytes stream
|
||||
*/
|
||||
RAW_ENCODING(0, "Raw", RawDecoder.class),
|
||||
/**
|
||||
* Specfies encodings which allow to copy part of image in client's
|
||||
* framebuffer from one place to another.
|
||||
*/
|
||||
COPY_RECT(1, "CopyRect", CopyRectDecoder.class),
|
||||
RRE(2, "RRE", RREDecoder.class),
|
||||
/**
|
||||
* Hextile encoding, uses palettes, filling and raw subencoding
|
||||
*/
|
||||
HEXTILE(5, "Hextile", HextileDecoder.class),
|
||||
/**
|
||||
* This encoding is like raw but previously all data compressed with zlib.
|
||||
*/
|
||||
ZLIB(6, "ZLib", ZlibDecoder.class),
|
||||
/**
|
||||
* Tight Encoding for slow connection. It is uses raw data, palettes, filling
|
||||
* and jpeg subencodings
|
||||
*/
|
||||
TIGHT(7, "Tight", TightDecoder.class),
|
||||
//ZlibHex(8),
|
||||
/**
|
||||
* ZRLE Encoding is like Hextile but previously all data compressed with zlib.
|
||||
*/
|
||||
ZRLE(16, "ZRLE", ZRLEDecoder.class),
|
||||
|
||||
/**
|
||||
* Rich Cursor pseudo encoding which allows to transfer cursor shape
|
||||
* with transparency
|
||||
*/
|
||||
RICH_CURSOR(0xFFFFFF11, "RichCursor", RichCursorDecoder.class),
|
||||
/**
|
||||
* Desktop Size Pseudo encoding allows to notificate client about
|
||||
* remote screen resolution changed.
|
||||
*/
|
||||
DESKTOP_SIZE(0xFFFFFF21, "DesctopSize", DesctopSizeDecoder.class),
|
||||
/**
|
||||
* Cusros position encoding allows to transfer remote cursor position to
|
||||
* client side.
|
||||
*/
|
||||
CURSOR_POS(0xFFFFFF18, "CursorPos", CursorPosDecoder.class),
|
||||
|
||||
COMPRESS_LEVEL_0(0xFFFFFF00 + 0, "CompressionLevel0", FakeDecoder.class),
|
||||
COMPRESS_LEVEL_1(0xFFFFFF00 + 1, "CompressionLevel1", null),
|
||||
COMPRESS_LEVEL_2(0xFFFFFF00 + 2, "CompressionLevel2", null),
|
||||
COMPRESS_LEVEL_3(0xFFFFFF00 + 3, "CompressionLevel3", null),
|
||||
COMPRESS_LEVEL_4(0xFFFFFF00 + 4, "CompressionLevel4", null),
|
||||
COMPRESS_LEVEL_5(0xFFFFFF00 + 5, "CompressionLevel5", null),
|
||||
COMPRESS_LEVEL_6(0xFFFFFF00 + 6, "CompressionLevel6", null),
|
||||
COMPRESS_LEVEL_7(0xFFFFFF00 + 7, "CompressionLevel7", null),
|
||||
COMPRESS_LEVEL_8(0xFFFFFF00 + 8, "CompressionLevel8", null),
|
||||
COMPRESS_LEVEL_9(0xFFFFFF00 + 9, "CompressionLevel9", null),
|
||||
|
||||
JPEG_QUALITY_LEVEL_0(0xFFFFFFE0 + 0, "JpegQualityLevel0", FakeDecoder.class),
|
||||
JPEG_QUALITY_LEVEL_1(0xFFFFFFE0 + 1, "JpegQualityLevel1", null),
|
||||
JPEG_QUALITY_LEVEL_2(0xFFFFFFE0 + 2, "JpegQualityLevel2", null),
|
||||
JPEG_QUALITY_LEVEL_3(0xFFFFFFE0 + 3, "JpegQualityLevel3", null),
|
||||
JPEG_QUALITY_LEVEL_4(0xFFFFFFE0 + 4, "JpegQualityLevel4", null),
|
||||
JPEG_QUALITY_LEVEL_5(0xFFFFFFE0 + 5, "JpegQualityLevel5", null),
|
||||
JPEG_QUALITY_LEVEL_6(0xFFFFFFE0 + 6, "JpegQualityLevel6", null),
|
||||
JPEG_QUALITY_LEVEL_7(0xFFFFFFE0 + 7, "JpegQualityLevel7", null),
|
||||
JPEG_QUALITY_LEVEL_8(0xFFFFFFE0 + 8, "JpegQualityLevel8", null),
|
||||
JPEG_QUALITY_LEVEL_9(0xFFFFFFE0 + 9, "JpegQualityLevel9", null);
|
||||
|
||||
private final int id;
|
||||
private final String name;
|
||||
public final Class<? extends Decoder> klass;
|
||||
|
||||
private EncodingType(int id, String name, Class<? extends Decoder> klass) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.klass = klass;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public static final LinkedHashSet<EncodingType> ordinaryEncodings = new LinkedHashSet<EncodingType>();
|
||||
static {
|
||||
ordinaryEncodings.add(ZRLE);
|
||||
ordinaryEncodings.add(TIGHT);
|
||||
ordinaryEncodings.add(ZLIB);
|
||||
ordinaryEncodings.add(HEXTILE);
|
||||
ordinaryEncodings.add(RRE);
|
||||
ordinaryEncodings.add(COPY_RECT);
|
||||
ordinaryEncodings.add(RAW_ENCODING);
|
||||
}
|
||||
|
||||
public static final LinkedHashSet<EncodingType> pseudoEncodings = new LinkedHashSet<EncodingType>();
|
||||
static {
|
||||
pseudoEncodings.add(RICH_CURSOR);
|
||||
pseudoEncodings.add(CURSOR_POS);
|
||||
pseudoEncodings.add(DESKTOP_SIZE);
|
||||
}
|
||||
|
||||
public static EncodingType byId(int id) {
|
||||
// TODO needs to speedup with hash usage?
|
||||
for (EncodingType type : values()) {
|
||||
if (type.getId() == id)
|
||||
return type;
|
||||
}
|
||||
throw new IllegalArgumentException("Unsupported encoding code: " + id);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.encoding;
|
||||
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
/**
|
||||
* Pixel Format:
|
||||
* 1 - U8 - bits-per-pixel
|
||||
* 1 - U8 - depth
|
||||
* 1 - U8 - big-endian-flag
|
||||
* 1 - U8 - true-color-flag
|
||||
* 2 - U16 - red-max
|
||||
* 2 - U16 - green-max
|
||||
* 2 - U16 - blue-max
|
||||
* 1 - U8 - red-shift
|
||||
* 1 - U8 - green-shift
|
||||
* 1 - U8 - blue-shift
|
||||
* 3 - - padding
|
||||
*/
|
||||
public class PixelFormat {
|
||||
public byte bitsPerPixel;
|
||||
public byte depth;
|
||||
public byte bigEndianFlag;
|
||||
public byte trueColourFlag;
|
||||
public short redMax;
|
||||
public short greenMax;
|
||||
public short blueMax;
|
||||
public byte redShift;
|
||||
public byte greenShift;
|
||||
public byte blueShift;
|
||||
|
||||
public void fill(Transport transport) throws TransportException {
|
||||
bitsPerPixel = transport.readByte();
|
||||
depth = transport.readByte();
|
||||
bigEndianFlag = transport.readByte();
|
||||
trueColourFlag = transport.readByte();
|
||||
redMax = transport.readInt16();
|
||||
greenMax = transport.readInt16();
|
||||
blueMax = transport.readInt16();
|
||||
redShift = transport.readByte();
|
||||
greenShift = transport.readByte();
|
||||
blueShift = transport.readByte();
|
||||
transport.readBytes(3); // skip padding bytes
|
||||
}
|
||||
|
||||
public void send(Transport transport) throws TransportException {
|
||||
transport.write(bitsPerPixel)
|
||||
.write(depth)
|
||||
.write(bigEndianFlag)
|
||||
.write(trueColourFlag)
|
||||
.write(redMax)
|
||||
.write(greenMax)
|
||||
.write(blueMax)
|
||||
.write(redShift)
|
||||
.write(greenShift)
|
||||
.write(blueShift)
|
||||
.writeInt16(0) // padding bytes
|
||||
.writeByte(0); // padding bytes
|
||||
}
|
||||
|
||||
public static PixelFormat create24bitColorDepthPixelFormat(int bigEndianFlag) {
|
||||
final PixelFormat pixelFormat = new PixelFormat();
|
||||
pixelFormat.bigEndianFlag = (byte) bigEndianFlag;
|
||||
pixelFormat.bitsPerPixel = 32;
|
||||
pixelFormat.blueMax = 255;
|
||||
pixelFormat.blueShift = 0;
|
||||
pixelFormat.greenMax = 255;
|
||||
pixelFormat.greenShift = 8;
|
||||
pixelFormat.redMax = 255;
|
||||
pixelFormat.redShift = 16;
|
||||
pixelFormat.depth = 24;
|
||||
pixelFormat.trueColourFlag = 1;
|
||||
return pixelFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* specifies 65536 colors, 5bit per Red, 6bit per Green, 5bit per Blue
|
||||
*/
|
||||
public static PixelFormat create16bitColorDepthPixelFormat(int bigEndianFlag) {
|
||||
final PixelFormat pixelFormat = new PixelFormat();
|
||||
pixelFormat.bigEndianFlag = (byte) bigEndianFlag;
|
||||
pixelFormat.bitsPerPixel = 16;
|
||||
pixelFormat.blueMax = 31;
|
||||
pixelFormat.blueShift = 0;
|
||||
pixelFormat.greenMax = 63;
|
||||
pixelFormat.greenShift = 5;
|
||||
pixelFormat.redMax = 31;
|
||||
pixelFormat.redShift = 11;
|
||||
pixelFormat.depth = 16;
|
||||
pixelFormat.trueColourFlag = 1;
|
||||
return pixelFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* specifies 256 colors, 2bit per Blue, 3bit per Green & Red
|
||||
*/
|
||||
public static PixelFormat create8bitColorDepthBGRPixelFormat(int bigEndianFlag) {
|
||||
final PixelFormat pixelFormat = new PixelFormat();
|
||||
pixelFormat.bigEndianFlag = (byte) bigEndianFlag;
|
||||
pixelFormat.bitsPerPixel = 8;
|
||||
pixelFormat.redMax = 7;
|
||||
pixelFormat.redShift = 0;
|
||||
pixelFormat.greenMax = 7;
|
||||
pixelFormat.greenShift = 3;
|
||||
pixelFormat.blueMax = 3;
|
||||
pixelFormat.blueShift = 6;
|
||||
pixelFormat.depth = 8;
|
||||
pixelFormat.trueColourFlag = 1;
|
||||
return pixelFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* specifies 64 colors, 2bit per Red, Green & Blue
|
||||
*/
|
||||
public static PixelFormat create6bitColorDepthPixelFormat(int bigEndianFlag) {
|
||||
final PixelFormat pixelFormat = new PixelFormat();
|
||||
pixelFormat.bigEndianFlag = (byte) bigEndianFlag;
|
||||
pixelFormat.bitsPerPixel = 8;
|
||||
pixelFormat.blueMax = 3;
|
||||
pixelFormat.blueShift = 0;
|
||||
pixelFormat.greenMax = 3;
|
||||
pixelFormat.greenShift = 2;
|
||||
pixelFormat.redMax = 3;
|
||||
pixelFormat.redShift = 4;
|
||||
pixelFormat.depth = 6;
|
||||
pixelFormat.trueColourFlag = 1;
|
||||
return pixelFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* specifies 8 colors, 1bit per Red, Green & Blue
|
||||
*/
|
||||
public static PixelFormat create3bitColorDepthPixelFormat(int bigEndianFlag) {
|
||||
final PixelFormat pixelFormat = new PixelFormat();
|
||||
pixelFormat.bigEndianFlag = (byte) bigEndianFlag;
|
||||
pixelFormat.bitsPerPixel = 8;
|
||||
pixelFormat.blueMax = 1;
|
||||
pixelFormat.blueShift = 0;
|
||||
pixelFormat.greenMax = 1;
|
||||
pixelFormat.greenShift = 1;
|
||||
pixelFormat.redMax = 1;
|
||||
pixelFormat.redShift = 2;
|
||||
pixelFormat.depth = 3;
|
||||
pixelFormat.trueColourFlag = 1;
|
||||
return pixelFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PixelFormat: [bits-per-pixel: " + String.valueOf(0xff & bitsPerPixel) +
|
||||
", depth: " + String.valueOf(0xff & depth) +
|
||||
", big-endian-flag: " + String.valueOf(0xff & bigEndianFlag) +
|
||||
", true-color-flag: " + String.valueOf(0xff & trueColourFlag) +
|
||||
", red-max: " + String.valueOf(0xffff & redMax) +
|
||||
", green-max: " + String.valueOf(0xffff & greenMax) +
|
||||
", blue-max: " + String.valueOf(0xffff & blueMax) +
|
||||
", red-shift: " + String.valueOf(0xff & redShift) +
|
||||
", green-shift: " + String.valueOf(0xff & greenShift) +
|
||||
", blue-shift: " + String.valueOf(0xff & blueShift) +
|
||||
"]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.encoding;
|
||||
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
/**
|
||||
* Struct filled from the ServerInit message
|
||||
* 2 - U16 - framebuffer-width
|
||||
* 2 - U16 - framebuffer-height
|
||||
* 16 - PixelFormat - server-pixel-format
|
||||
* 4 - U32 - name-length
|
||||
* name-length - U8 array - name-string
|
||||
*/
|
||||
public class ServerInitMessage {
|
||||
protected String name;
|
||||
protected int framebufferWidth;
|
||||
protected int framebufferHeight;
|
||||
protected PixelFormat pixelFormat;
|
||||
|
||||
public ServerInitMessage readFrom(Transport transport) throws TransportException {
|
||||
framebufferWidth = transport.readUInt16();
|
||||
framebufferHeight = transport.readUInt16();
|
||||
pixelFormat = new PixelFormat();
|
||||
pixelFormat.fill(transport);
|
||||
name = transport.readString();
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getFramebufferWidth() {
|
||||
return framebufferWidth;
|
||||
}
|
||||
|
||||
public int getFramebufferHeight() {
|
||||
return framebufferHeight;
|
||||
}
|
||||
|
||||
public PixelFormat getPixelFormat() {
|
||||
return pixelFormat;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ServerInitMessage{" +
|
||||
"name='" + name + '\'' +
|
||||
", framebufferWidth=" + framebufferWidth +
|
||||
", framebufferHeight=" + framebufferHeight +
|
||||
", pixelFormat=" + pixelFormat +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.encoding.decoder;
|
||||
|
||||
/**
|
||||
* Resizeable to needed length byte buffer
|
||||
* Singleton for share among decoders.
|
||||
*/
|
||||
public class ByteBuffer {
|
||||
private static ThreadLocal<ByteBuffer> threadLocal = new ThreadLocal<ByteBuffer>() {
|
||||
@Override
|
||||
protected ByteBuffer initialValue() {
|
||||
return new ByteBuffer();
|
||||
}
|
||||
};
|
||||
private byte [] buffer = new byte[0];
|
||||
|
||||
private ByteBuffer() { /*empty*/ }
|
||||
|
||||
public static ByteBuffer getInstance() {
|
||||
return threadLocal.get();
|
||||
}
|
||||
|
||||
public static void removeInstance() {
|
||||
threadLocal.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for buffer capacity is enougth ( < length) and enlarge it if not
|
||||
*/
|
||||
public void correctBufferCapacity(int length) {
|
||||
// procondition: buffer != null
|
||||
assert (buffer != null);
|
||||
if (buffer.length < length) {
|
||||
buffer = new byte[length];
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getBuffer(int length) {
|
||||
correctBufferCapacity(length);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.encoding.decoder;
|
||||
|
||||
import com.glavsoft.drawing.Renderer;
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
public class CopyRectDecoder extends Decoder {
|
||||
|
||||
@Override
|
||||
public void decode(Transport transport, Renderer renderer,
|
||||
FramebufferUpdateRectangle rect) throws TransportException {
|
||||
int srcX = transport.readUInt16();
|
||||
int srcY = transport.readUInt16();
|
||||
if (rect.width == 0 || rect.height == 0) return;
|
||||
renderer.copyRect(srcX, srcY, rect);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.encoding.decoder;
|
||||
|
||||
import com.glavsoft.drawing.Renderer;
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
/**
|
||||
* @author dime at glavsoft.com
|
||||
*/
|
||||
public class CursorPosDecoder extends Decoder {
|
||||
|
||||
@Override
|
||||
public void decode(Transport transport, Renderer renderer, FramebufferUpdateRectangle rect) throws TransportException {
|
||||
renderer.decodeCursorPosition(rect);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.encoding.decoder;
|
||||
|
||||
import com.glavsoft.drawing.Renderer;
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
|
||||
public abstract class Decoder {
|
||||
/**
|
||||
* Decode rectangle data.
|
||||
*/
|
||||
abstract public void decode(Transport transport, Renderer renderer,
|
||||
FramebufferUpdateRectangle rect) throws TransportException;
|
||||
|
||||
/**
|
||||
* Reset decoder when needed. Ex. reset ZLib stream inflaters for Z* and Tight decoders.
|
||||
*/
|
||||
public void reset() { /*empty*/ }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.encoding.decoder;
|
||||
|
||||
import com.glavsoft.drawing.Renderer;
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
/**
|
||||
* @author dime at glavsoft.com
|
||||
*/
|
||||
public class DesctopSizeDecoder extends Decoder {
|
||||
|
||||
@Override
|
||||
public void decode(Transport transport, Renderer renderer, FramebufferUpdateRectangle rect) throws TransportException {
|
||||
// do nothing, all real job will be done in ReceiverTask.framebufferUpdateMessage()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.encoding.decoder;
|
||||
|
||||
import com.glavsoft.drawing.Renderer;
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
/**
|
||||
* @author dime at glavsoft.com
|
||||
*/
|
||||
public class FakeDecoder extends Decoder {
|
||||
|
||||
@Override
|
||||
public void decode(Transport transport, Renderer renderer, FramebufferUpdateRectangle rect) throws TransportException {
|
||||
throw new IllegalStateException("Improper use of fake decoder");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.encoding.decoder;
|
||||
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.rfb.encoding.EncodingType;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
/**
|
||||
* Header for framebuffer-update-rectangle header server message
|
||||
* 2 - U16 - x-position
|
||||
* 2 - U16 - y-position
|
||||
* 2 - U16 - width
|
||||
* 2 - U16 - height
|
||||
* 4 - S32 - encoding-type
|
||||
* and then follows the pixel data in the specified encoding
|
||||
*/
|
||||
public class FramebufferUpdateRectangle {
|
||||
public int x;
|
||||
public int y;
|
||||
public int width;
|
||||
public int height;
|
||||
private EncodingType encodingType;
|
||||
|
||||
public FramebufferUpdateRectangle() {
|
||||
// nop
|
||||
}
|
||||
|
||||
public FramebufferUpdateRectangle(int x, int y, int w, int h) {
|
||||
this.x = x; this.y = y;
|
||||
width = w; height = h;
|
||||
}
|
||||
|
||||
public void fill(Transport transport) throws TransportException {
|
||||
x = transport.readUInt16();
|
||||
y = transport.readUInt16();
|
||||
width = transport.readUInt16();
|
||||
height = transport.readUInt16();
|
||||
int encoding = transport.readInt32();
|
||||
encodingType = EncodingType.byId(encoding);
|
||||
}
|
||||
|
||||
public EncodingType getEncodingType() {
|
||||
return encodingType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FramebufferUpdateRect: [x: " + x + ", y: " + y +
|
||||
", width: " + width + ", height: " + height +
|
||||
", encodingType: " + encodingType +
|
||||
"]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.encoding.decoder;
|
||||
|
||||
import com.glavsoft.drawing.Renderer;
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
|
||||
public class HextileDecoder extends Decoder {
|
||||
private static final int DEFAULT_TILE_SIZE = 16;
|
||||
private static final int RAW_MASK = 1;
|
||||
private static final int BACKGROUND_SPECIFIED_MASK = 2;
|
||||
private static final int FOREGROUND_SPECIFIED_MASK = 4;
|
||||
private static final int ANY_SUBRECTS_MASK = 8;
|
||||
private static final int SUBRECTS_COLOURED_MASK = 16;
|
||||
private static final int FG_COLOR_INDEX = 0;
|
||||
private static final int BG_COLOR_INDEX = 1;
|
||||
|
||||
@Override
|
||||
public void decode(Transport transport, Renderer renderer,
|
||||
FramebufferUpdateRectangle rect) throws TransportException {
|
||||
if (rect.width == 0 || rect.height == 0) return;
|
||||
int[] colors = new int[] {-1, -1};
|
||||
int maxX = rect.x + rect.width;
|
||||
int maxY = rect.y + rect.height;
|
||||
for (int tileY = rect.y; tileY < maxY;
|
||||
tileY += DEFAULT_TILE_SIZE) {
|
||||
int tileHeight = Math.min(maxY - tileY, DEFAULT_TILE_SIZE);
|
||||
for (int tileX = rect.x; tileX < maxX;
|
||||
tileX += DEFAULT_TILE_SIZE) {
|
||||
int tileWidth = Math.min(maxX - tileX, DEFAULT_TILE_SIZE);
|
||||
decodeTile(transport, renderer, colors, tileX,
|
||||
tileY, tileWidth, tileHeight);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void decodeTile(Transport transport,
|
||||
Renderer renderer, int[] colors,
|
||||
int tileX, int tileY, int tileWidth, int tileHeight)
|
||||
throws TransportException {
|
||||
int subencoding = transport.readUInt8();
|
||||
if ((subencoding & RAW_MASK) != 0) {
|
||||
RawDecoder.getInstance().decode(transport, renderer,
|
||||
tileX, tileY, tileWidth, tileHeight);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((subencoding & BACKGROUND_SPECIFIED_MASK) != 0) {
|
||||
colors[BG_COLOR_INDEX] = renderer.readPixelColor(transport);
|
||||
}
|
||||
renderer.fillRect(colors[BG_COLOR_INDEX],
|
||||
tileX, tileY, tileWidth, tileHeight);
|
||||
|
||||
if ((subencoding & FOREGROUND_SPECIFIED_MASK) != 0) {
|
||||
colors[FG_COLOR_INDEX] = renderer.readPixelColor(transport);
|
||||
}
|
||||
|
||||
if ((subencoding & ANY_SUBRECTS_MASK) == 0)
|
||||
return;
|
||||
|
||||
int numberOfSubrectangles = transport.readUInt8();
|
||||
boolean colorSpecified = (subencoding & SUBRECTS_COLOURED_MASK) != 0;
|
||||
for (int i = 0; i < numberOfSubrectangles; ++i) {
|
||||
int color = colorSpecified ? renderer.readPixelColor(transport) : colors[FG_COLOR_INDEX];
|
||||
colors[FG_COLOR_INDEX] = color;
|
||||
byte dimensions = transport.readByte(); // bits 7-4 for x, bits 3-0 for y
|
||||
int subtileX = dimensions >> 4 & 0x0f;
|
||||
int subtileY = dimensions & 0x0f;
|
||||
dimensions = transport.readByte(); // bits 7-4 for w, bits 3-0 for h
|
||||
int subtileWidth = 1 + (dimensions >> 4 & 0x0f);
|
||||
int subtileHeight = 1 + (dimensions & 0x0f);
|
||||
renderer.fillRect(color,
|
||||
tileX + subtileX, tileY + subtileY,
|
||||
subtileWidth, subtileHeight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.encoding.decoder;
|
||||
|
||||
import com.glavsoft.drawing.Renderer;
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
public class RREDecoder extends Decoder {
|
||||
|
||||
@Override
|
||||
public void decode(Transport transport, Renderer renderer,
|
||||
FramebufferUpdateRectangle rect) throws TransportException {
|
||||
int numOfSubrectangles = transport.readInt32();
|
||||
int color = renderer.readPixelColor(transport);
|
||||
renderer.fillRect(color, rect);
|
||||
for (int i = 0; i < numOfSubrectangles; ++i) {
|
||||
color = renderer.readPixelColor(transport);
|
||||
int x = transport.readUInt16();
|
||||
int y = transport.readUInt16();
|
||||
int width = transport.readUInt16();
|
||||
int height = transport.readUInt16();
|
||||
renderer.fillRect(color, rect.x + x, rect.y + y, width, height);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.encoding.decoder;
|
||||
|
||||
import com.glavsoft.drawing.Renderer;
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
public class RawDecoder extends Decoder {
|
||||
private static RawDecoder instance = new RawDecoder();
|
||||
public static RawDecoder getInstance() {
|
||||
return instance;
|
||||
}
|
||||
private RawDecoder() { /*empty*/ }
|
||||
|
||||
@Override
|
||||
public void decode(Transport transport,
|
||||
Renderer renderer, FramebufferUpdateRectangle rect) throws TransportException {
|
||||
decode(transport, renderer, rect.x, rect.y, rect.width, rect.height);
|
||||
}
|
||||
|
||||
public void decode(Transport transport, Renderer renderer, int x, int y,
|
||||
int width, int height) throws TransportException {
|
||||
int length = width * height * renderer.getBytesPerPixel();
|
||||
byte [] bytes = ByteBuffer.getInstance().getBuffer(length);
|
||||
transport.readBytes(bytes, 0, length);
|
||||
renderer.drawBytes(bytes, x, y, width, height);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.encoding.decoder;
|
||||
|
||||
import com.glavsoft.drawing.Renderer;
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
/**
|
||||
* Decoder for RichCursor pseudo encoding
|
||||
*/
|
||||
public class RichCursorDecoder extends Decoder {
|
||||
|
||||
@Override
|
||||
public void decode(Transport transport, Renderer renderer,
|
||||
FramebufferUpdateRectangle rect) throws TransportException {
|
||||
int bytesPerPixel = renderer.getBytesPerPixel();
|
||||
int length = rect.width * rect.height * bytesPerPixel;
|
||||
if (0 == length)
|
||||
return;
|
||||
byte[] buffer = ByteBuffer.getInstance().getBuffer(length);
|
||||
transport.readBytes(buffer, 0, length);
|
||||
|
||||
StringBuilder sb = new StringBuilder(" ");
|
||||
for (int i=0; i<length; ++i) {
|
||||
sb.append(Integer.toHexString(buffer[i]&0xff)).append(" ");
|
||||
}
|
||||
int scanLine = (rect.width + 7) / 8;
|
||||
byte[] bitmask = new byte[scanLine * rect.height];
|
||||
transport.readBytes(bitmask, 0, bitmask.length);
|
||||
|
||||
sb = new StringBuilder(" ");
|
||||
for (byte aBitmask : bitmask) {
|
||||
sb.append(Integer.toHexString(aBitmask & 0xff)).append(" ");
|
||||
}
|
||||
int[] cursorPixels = new int[rect.width * rect.height];
|
||||
for (int y = 0; y < rect.height; ++y) {
|
||||
for (int x = 0; x < rect.width; ++x) {
|
||||
int offset = y * rect.width + x;
|
||||
cursorPixels[offset] = isBitSet(bitmask[y * scanLine + x / 8], x % 8) ?
|
||||
0xFF000000 | renderer.getPixelColor(buffer, offset * bytesPerPixel) :
|
||||
0; // transparent
|
||||
}
|
||||
}
|
||||
renderer.createCursor(cursorPixels, rect);
|
||||
}
|
||||
|
||||
private boolean isBitSet(byte aByte, int index) {
|
||||
return (aByte & 1 << 7 - index) > 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
// Copyright (C) 2010 - 2014 GlavSoft LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// This file is part of the TightVNC software. Please visit our Web site:
|
||||
//
|
||||
// http://www.tightvnc.com/
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
package com.glavsoft.rfb.encoding.decoder;
|
||||
|
||||
import com.glavsoft.drawing.ColorDecoder;
|
||||
import com.glavsoft.drawing.Renderer;
|
||||
import com.glavsoft.exceptions.TransportException;
|
||||
import com.glavsoft.transport.Transport;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
import java.util.zip.DataFormatException;
|
||||
import java.util.zip.Inflater;
|
||||
|
||||
/**
|
||||
* Tight protocol extention decoder
|
||||
*/
|
||||
public class TightDecoder extends Decoder {
|
||||
private static Logger logger = Logger.getLogger("com.glavsoft.rfb.encoding.decoder");
|
||||
|
||||
private static final int FILL_TYPE = 0x08;
|
||||
private static final int JPEG_TYPE = 0x09;
|
||||
|
||||
private static final int FILTER_ID_MASK = 0x40;
|
||||
private static final int STREAM_ID_MASK = 0x30;
|
||||
|
||||
private static final int BASIC_FILTER = 0x00;
|
||||
private static final int PALETTE_FILTER = 0x01;
|
||||
private static final int GRADIENT_FILTER = 0x02;
|
||||
private static final int MIN_SIZE_TO_COMPRESS = 12;
|
||||
|
||||
static final int DECODERS_NUM = 4;
|
||||
Inflater[] decoders;
|
||||
|
||||
private int decoderId;
|
||||
private int[] palette;
|
||||
|
||||
public TightDecoder() {
|
||||
reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode(Transport transport, Renderer renderer,
|
||||
FramebufferUpdateRectangle rect) throws TransportException {
|
||||
int bytesPerPixel = renderer.getBytesPerPixelTight();
|
||||
|
||||
/**
|
||||
* bits
|
||||
* 7 - FILL or JPEG type
|
||||
* 6 - filter presence flag
|
||||
* 5, 4 - decoder to use when Basic type (bit 7 not set)
|
||||
* or
|
||||
* 4 - JPEG type when set bit 7
|
||||
* 3 - reset decoder #3
|
||||
* 2 - reset decoder #2
|
||||
* 1 - reset decoder #1
|
||||
* 0 - reset decoder #0
|
||||
*/
|
||||
int compControl = transport.readUInt8();
|
||||
resetDecoders(compControl);
|
||||
|
||||
int compType = compControl >> 4 & 0x0F;
|
||||
switch (compType) {
|
||||
case FILL_TYPE:
|
||||
int color = renderer.readTightPixelColor(transport);
|
||||
renderer.fillRect(color, rect);
|
||||
break;
|
||||
case JPEG_TYPE:
|
||||
assert 3 == bytesPerPixel : "Tight doesn't support JPEG subencoding while depth not equal to 24bpp is used";
|
||||
processJpegType(transport, renderer, rect);
|
||||
break;
|
||||
default:
|
||||
assert compType <= JPEG_TYPE : "Compression control byte is incorrect!";
|
||||
processBasicType(compControl, transport, renderer, rect);
|
||||
}
|
||||
}
|
||||
|
||||
private void processBasicType(int compControl, Transport transport,
|
||||
Renderer renderer, FramebufferUpdateRectangle rect) throws TransportException {
|
||||
decoderId = (compControl & STREAM_ID_MASK) >> 4;
|
||||
|
||||
int filterId = 0;
|
||||
if ((compControl & FILTER_ID_MASK) > 0) { // filter byte presence
|
||||
filterId = transport.readUInt8();
|
||||
}
|
||||
int bytesPerCPixel = renderer.getBytesPerPixelTight();
|
||||
int lengthCurrentbpp = bytesPerCPixel * rect.width * rect.height;
|
||||
byte [] buffer;
|
||||
switch (filterId) {
|
||||
case BASIC_FILTER:
|
||||
buffer = readTightData(lengthCurrentbpp, transport);
|
||||
renderer.drawTightBytes(buffer, 0, rect.x, rect.y, rect.width, rect.height);
|
||||
break;
|
||||
case PALETTE_FILTER:
|
||||
int paletteSize = transport.readUInt8() + 1;
|
||||
completePalette(paletteSize, transport, renderer);
|
||||
int dataLength = paletteSize == 2 ?
|
||||
rect.height * ((rect.width + 7) / 8) :
|
||||
rect.width * rect.height;
|
||||
buffer = readTightData(dataLength, transport);
|
||||
renderer.drawBytesWithPalette(buffer, rect, palette, paletteSize);
|
||||
break;
|
||||
case GRADIENT_FILTER:
|
||||
/*
|
||||
* The "gradient" filter pre-processes pixel data with a simple algorithm
|
||||
* which converts each color component to a difference between a "predicted"
|
||||
* intensity and the actual intensity. Such a technique does not affect
|
||||
* uncompressed data size, but helps to compress photo-like images better.
|
||||
* Pseudo-code for converting intensities to differences is the following:
|
||||
*
|
||||
* P[i,j] := V[i-1,j] + V[i,j-1] - V[i-1,j-1];
|
||||
* if (P[i,j] < 0) then P[i,j] := 0;
|
||||
* if (P[i,j] > MAX) then P[i,j] := MAX;
|
||||
* D[i,j] := V[i,j] - P[i,j];
|
||||
*
|
||||
* Here V[i,j] is the intensity of a color component for a pixel at
|
||||
* coordinates (i,j). MAX is the maximum value of intensity for a color
|
||||
* component.*/
|
||||
buffer = readTightData(bytesPerCPixel * rect.width * rect.height, transport);
|
||||
byte [][] opRows = new byte[2][rect.width * 3 + 3];
|
||||
int opRowIndex = 0;
|
||||
byte [] components = new byte[3];
|
||||
int pixelOffset = 0;
|
||||
ColorDecoder colorDecoder = renderer.getColorDecoder();
|
||||
for (int i = 0; i < rect.height; ++i) {
|
||||
// exchange thisRow and prevRow:
|
||||
byte [] thisRow = opRows[opRowIndex];
|
||||
byte [] prevRow = opRows[opRowIndex = (opRowIndex + 1) % 2];
|
||||
for (int j = 3; j < rect.width * 3 + 3; j += 3) {
|
||||
colorDecoder.fillRawComponents(components, buffer, pixelOffset);
|
||||
pixelOffset += bytesPerCPixel;
|
||||
int
|
||||
d = (0xff & prevRow[j + 0]) + // "upper" pixel (from prev row)
|
||||
(0xff & thisRow[j + 0 - 3]) - // prev pixel
|
||||
(0xff & prevRow[j + 0 - 3]); // "diagonal" prev pixel
|
||||
thisRow[j + 0] = (byte) (components[0] + (d < 0 ? 0 : d > colorDecoder.redMax ? colorDecoder.redMax: d) & colorDecoder.redMax);
|
||||
d = (0xff & prevRow[j + 1]) +
|
||||
(0xff & thisRow[j + 1 - 3]) -
|
||||
(0xff & prevRow[j + 1 - 3]);
|
||||
thisRow[j + 1] = (byte) (components[1] + (d < 0 ? 0 : d > colorDecoder.greenMax ? colorDecoder.greenMax: d) & colorDecoder.greenMax);
|
||||
d = (0xff & prevRow[j + 2]) +
|
||||
(0xff & thisRow[j + 2 - 3]) -
|
||||
(0xff & prevRow[j + 2 - 3]);
|
||||
thisRow[j + 2] = (byte) (components[2] + (d < 0 ? 0 : d > colorDecoder.blueMax ? colorDecoder.blueMax: d) & colorDecoder.blueMax);
|
||||
}
|
||||
renderer.drawUncaliberedRGBLine(thisRow, rect.x, rect.y + i, rect.width);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete palette from transport
|
||||
*/
|
||||
private void completePalette(int paletteSize, Transport transport, Renderer renderer) throws TransportException {
|
||||
/**
|
||||
* When bytesPerPixel == 1 && paletteSize == 2 read 2 bytes of palette
|
||||
* When bytesPerPixel == 1 && paletteSize != 2 - error
|
||||
* When bytesPerPixel == 3 (4) read (paletteSize * 3) bytes of palette
|
||||
* so use renderer.readPixelColor
|
||||
*/
|
||||
if (null == palette) palette = new int[256];
|
||||
for (int i = 0; i < paletteSize; ++i) {
|
||||
palette[i] = renderer.readTightPixelColor(transport);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads compressed (expected length >= MIN_SIZE_TO_COMPRESS) or
|
||||
* uncompressed data. When compressed decompresses it.
|
||||
*
|
||||
* @param expectedLength expected data length in bytes
|
||||
* @param transport data source
|
||||
* @return result data
|
||||
* @throws TransportException
|
||||
*/
|
||||
private byte[] readTightData(int expectedLength, Transport transport) throws TransportException {
|
||||
if (expectedLength < MIN_SIZE_TO_COMPRESS) {
|
||||
byte [] buffer = ByteBuffer.getInstance().getBuffer(expectedLength);
|
||||
transport.readBytes(buffer, 0, expectedLength);
|
||||
return buffer;
|
||||
} else
|
||||
return readCompressedData(expectedLength, transport);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads compressed data length, then read compressed data into rawBuffer
|
||||
* and decompress data with expected length == length
|
||||
*
|
||||
* Note: returned data contains not only decompressed data but raw data at array tail
|
||||
* which need to be ignored. Use only first expectedLength bytes.
|
||||
*
|
||||
* @param expectedLength expected data length
|
||||
* @param transport data source
|
||||
* @return decompressed data (length == expectedLength) / + followed raw data (ignore, please)
|
||||
* @throws TransportException
|
||||
*/
|
||||
private byte[] readCompressedData(int expectedLength, Transport transport) throws TransportException {
|
||||
int rawDataLength = readCompactSize(transport);
|
||||
|
||||
byte [] buffer = ByteBuffer.getInstance().getBuffer(expectedLength + rawDataLength);
|
||||
// read compressed (raw) data behind space allocated for decompressed data
|
||||
transport.readBytes(buffer, expectedLength, rawDataLength);
|
||||
if (null == decoders[decoderId]) {
|
||||
decoders[decoderId] = new Inflater();
|
||||
}
|
||||
Inflater decoder = decoders[decoderId];
|
||||
decoder.setInput(buffer, expectedLength, rawDataLength);
|
||||
try {
|
||||
decoder.inflate(buffer, 0, expectedLength);
|
||||
} catch (DataFormatException e) {
|
||||
logger.throwing("TightDecoder", "readCompressedData", e);
|
||||
throw new TransportException("cannot inflate tight compressed data", e);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private void processJpegType(Transport transport, Renderer renderer,
|
||||
FramebufferUpdateRectangle rect) throws TransportException {
|
||||
int jpegBufferLength = readCompactSize(transport);
|
||||
byte [] bytes = ByteBuffer.getInstance().getBuffer(jpegBufferLength);
|
||||
transport.readBytes(bytes, 0, jpegBufferLength);
|
||||
renderer.drawJpegImage(bytes, 0, jpegBufferLength, rect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an integer from transport in compact representation (from 1 to 3 bytes).
|
||||
* Highest bit of read byte set to 1 means next byte contains data.
|
||||
* Lower 7 bit of each byte contains significant data. Max bytes = 3.
|
||||
* Less significant bytes first order.
|
||||
*
|
||||
* @param transport data source
|
||||
* @return int value
|
||||
* @throws TransportException
|
||||
*/
|
||||
private int readCompactSize(Transport transport) throws TransportException {
|
||||
int b = transport.readUInt8();
|
||||
int size = b & 0x7F;
|
||||
if ((b & 0x80) != 0) {
|
||||
b = transport.readUInt8();
|
||||
size += (b & 0x7F) << 7;
|
||||
if ((b & 0x80) != 0) {
|
||||
size += transport.readUInt8() << 14;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush (reset) zlib decoders when bits 3, 2, 1, 0 of compControl is set
|
||||
* @param compControl control flags
|
||||
*/
|
||||
private void resetDecoders(int compControl) {
|
||||
for (int i=0; i < DECODERS_NUM; ++i) {
|
||||
if ((compControl & 1) != 0 && decoders[i] != null) {
|
||||
decoders[i].reset();
|
||||
}
|
||||
compControl >>= 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
decoders = new Inflater[DECODERS_NUM];
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user