mirror of
				https://github.com/kunkundi/crossdesk.git
				synced 2025-10-29 12:32:58 +08:00 
			
		
		
		
	Compare commits
	
		
			28 Commits
		
	
	
		
			win-virtua
			...
			self-hoste
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 2c622bc76e | ||
|  | b790c7d08e | ||
|  | 0ca90d2516 | ||
|  | 401bfe4483 | ||
|  | 3b34c26555 | ||
|  | b668b3c936 | ||
|  | cc19ec125a | ||
|  | ffa77fdf44 | ||
|  | 47cf806532 | ||
|  | 911dce2e71 | ||
|  | 9f80d4f69d | ||
|  | cba644f055 | ||
|  | f733fe9e49 | ||
|  | 27263fe1db | ||
|  | 698bf72a6c | ||
|  | 0bd27d0b17 | ||
|  | ee5612da8b | ||
|  | c7a2023c88 | ||
|  | c031a8c145 | ||
|  | 0bf83f07ad | ||
|  | 3638b712bd | ||
|  | b2ab940f20 | ||
|  | 17f9536476 | ||
|  | 0ef51e3faf | ||
|  | cccf5dadb2 | ||
|  | 2f0b0ffc22 | ||
|  | c7411b59f1 | ||
|  | 8222782522 | 
							
								
								
									
										31
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										31
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							| @@ -34,10 +34,11 @@ jobs: | |||||||
|         shell: bash |         shell: bash | ||||||
|         id: set_deb_version |         id: set_deb_version | ||||||
|         run: | |         run: | | ||||||
|  |           SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7) | ||||||
|           if [[ ! "${VERSION_NUM}" =~ ^[0-9] ]]; then |           if [[ ! "${VERSION_NUM}" =~ ^[0-9] ]]; then | ||||||
|             LEGAL_VERSION="0.0.0-${VERSION_NUM}" |             LEGAL_VERSION="0.0.0-${VERSION_NUM}-${SHORT_SHA}" | ||||||
|           else |           else | ||||||
|             LEGAL_VERSION="${VERSION_NUM}" |             LEGAL_VERSION="${VERSION_NUM}-${SHORT_SHA}" | ||||||
|           fi |           fi | ||||||
|           echo "LEGAL_VERSION=${LEGAL_VERSION}" >> $GITHUB_ENV |           echo "LEGAL_VERSION=${LEGAL_VERSION}" >> $GITHUB_ENV | ||||||
|  |  | ||||||
| @@ -52,6 +53,7 @@ jobs: | |||||||
|           XMAKE_GLOBALDIR: /data |           XMAKE_GLOBALDIR: /data | ||||||
|         run: | |         run: | | ||||||
|           ls -la $XMAKE_GLOBALDIR |           ls -la $XMAKE_GLOBALDIR | ||||||
|  |           xmake f --CROSSDESK_VERSION=${LEGAL_VERSION} --root -y | ||||||
|           xmake b -vy --root crossdesk |           xmake b -vy --root crossdesk | ||||||
|  |  | ||||||
|       - name: Decode and save certificate |       - name: Decode and save certificate | ||||||
| @@ -96,10 +98,11 @@ jobs: | |||||||
|         shell: bash |         shell: bash | ||||||
|         id: set_deb_version |         id: set_deb_version | ||||||
|         run: | |         run: | | ||||||
|  |           SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7) | ||||||
|           if [[ ! "${VERSION_NUM}" =~ ^[0-9] ]]; then |           if [[ ! "${VERSION_NUM}" =~ ^[0-9] ]]; then | ||||||
|             LEGAL_VERSION="0.0.0-${VERSION_NUM}" |             LEGAL_VERSION="0.0.0-${VERSION_NUM}-${SHORT_SHA}" | ||||||
|           else |           else | ||||||
|             LEGAL_VERSION="${VERSION_NUM}" |             LEGAL_VERSION="${VERSION_NUM}-${SHORT_SHA}" | ||||||
|           fi |           fi | ||||||
|           echo "LEGAL_VERSION=${LEGAL_VERSION}" >> $GITHUB_ENV |           echo "LEGAL_VERSION=${LEGAL_VERSION}" >> $GITHUB_ENV | ||||||
|  |  | ||||||
| @@ -113,6 +116,7 @@ jobs: | |||||||
|           CUDA_PATH: /usr/local/cuda |           CUDA_PATH: /usr/local/cuda | ||||||
|           XMAKE_GLOBALDIR: /data |           XMAKE_GLOBALDIR: /data | ||||||
|         run: | |         run: | | ||||||
|  |           xmake f --CROSSDESK_VERSION=${LEGAL_VERSION} --root -y | ||||||
|           xmake b -vy --root crossdesk |           xmake b -vy --root crossdesk | ||||||
|  |  | ||||||
|       - name: Decode and save certificate |       - name: Decode and save certificate | ||||||
| @@ -140,7 +144,7 @@ jobs: | |||||||
|       matrix: |       matrix: | ||||||
|         include: |         include: | ||||||
|           - arch: x64 |           - arch: x64 | ||||||
|             runner: macos-15-intel |             runner: macos-13 | ||||||
|             cache-key: intel |             cache-key: intel | ||||||
|             out-dir: ./build/macosx/x86_64/release/crossdesk |             out-dir: ./build/macosx/x86_64/release/crossdesk | ||||||
|             package_script: ./scripts/macosx/pkg_x64.sh |             package_script: ./scripts/macosx/pkg_x64.sh | ||||||
| @@ -155,7 +159,8 @@ jobs: | |||||||
|         id: version |         id: version | ||||||
|         run: | |         run: | | ||||||
|           VERSION="${GITHUB_REF##*/}" |           VERSION="${GITHUB_REF##*/}" | ||||||
|           VERSION_NUM="${VERSION#v}" |           SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7) | ||||||
|  |           VERSION_NUM="${VERSION#v}-${SHORT_SHA}" | ||||||
|           echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_ENV |           echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_ENV | ||||||
|           echo "VERSION_NUM=${VERSION_NUM}" |           echo "VERSION_NUM=${VERSION_NUM}" | ||||||
|  |  | ||||||
| @@ -177,7 +182,9 @@ jobs: | |||||||
|         run: git submodule update --init --recursive |         run: git submodule update --init --recursive | ||||||
|  |  | ||||||
|       - name: Build CrossDesk |       - name: Build CrossDesk | ||||||
|         run: xmake b -vy crossdesk |         run: | | ||||||
|  |           xmake f --CROSSDESK_VERSION=${VERSION_NUM} -y | ||||||
|  |           xmake b -vy crossdesk | ||||||
|  |  | ||||||
|       - name: Decode and save certificate |       - name: Decode and save certificate | ||||||
|         shell: bash |         shell: bash | ||||||
| @@ -215,7 +222,8 @@ jobs: | |||||||
|           $version = $ref -replace '^refs/(tags|heads)/', '' |           $version = $ref -replace '^refs/(tags|heads)/', '' | ||||||
|           $version = $version -replace '^v', '' |           $version = $version -replace '^v', '' | ||||||
|           $version = $version -replace '/', '-' |           $version = $version -replace '/', '-' | ||||||
|           echo "VERSION_NUM=$version" >> $env:GITHUB_ENV |           $SHORT_SHA = $env:GITHUB_SHA.Substring(0,7) | ||||||
|  |           echo "VERSION_NUM=$version-$SHORT_SHA" >> $env:GITHUB_ENV | ||||||
|  |  | ||||||
|       - name: Cache xmake dependencies |       - name: Cache xmake dependencies | ||||||
|         uses: actions/cache@v4 |         uses: actions/cache@v4 | ||||||
| @@ -281,7 +289,9 @@ jobs: | |||||||
|           copy "${{ github.workspace }}\scripts\windows\nsProcess.dll" $nsisPluginDir |           copy "${{ github.workspace }}\scripts\windows\nsProcess.dll" $nsisPluginDir | ||||||
|  |  | ||||||
|       - name: Build CrossDesk |       - name: Build CrossDesk | ||||||
|         run: xmake b -vy crossdesk |         run: | | ||||||
|  |           xmake f --CROSSDESK_VERSION=${{ env.VERSION_NUM }} -y | ||||||
|  |           xmake b -vy crossdesk | ||||||
|   |   | ||||||
|       - name: Decode and save certificate |       - name: Decode and save certificate | ||||||
|         shell: powershell |         shell: powershell | ||||||
| @@ -321,7 +331,8 @@ jobs: | |||||||
|         id: version |         id: version | ||||||
|         run: | |         run: | | ||||||
|           VERSION="${GITHUB_REF##*/}" |           VERSION="${GITHUB_REF##*/}" | ||||||
|           VERSION_NUM="${VERSION#v}" |           SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7) | ||||||
|  |           VERSION_NUM="${VERSION#v}-${SHORT_SHA}" | ||||||
|           echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_OUTPUT |           echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_OUTPUT | ||||||
|  |  | ||||||
|       - name: Rename artifacts |       - name: Rename artifacts | ||||||
|   | |||||||
							
								
								
									
										52
									
								
								.github/workflows/close-issue.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										52
									
								
								.github/workflows/close-issue.yml
									
									
									
									
										vendored
									
									
								
							| @@ -5,6 +5,11 @@ on: | |||||||
|     # run every day at midnight |     # run every day at midnight | ||||||
|     - cron: "0 0 * * *" |     - cron: "0 0 * * *" | ||||||
|  |  | ||||||
|  | permissions: | ||||||
|  |   issues: write | ||||||
|  |   pull-requests: write | ||||||
|  |   contents: read | ||||||
|  |  | ||||||
| jobs: | jobs: | ||||||
|   close_inactive_issues: |   close_inactive_issues: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
| @@ -17,26 +22,59 @@ jobs: | |||||||
|               owner: context.repo.owner, |               owner: context.repo.owner, | ||||||
|               repo: context.repo.repo, |               repo: context.repo.repo, | ||||||
|               state: 'open', |               state: 'open', | ||||||
|  |               per_page: 100, | ||||||
|             }); |             }); | ||||||
|  |  | ||||||
|             const now = new Date().getTime(); |             const now = new Date().getTime(); | ||||||
|             const inactivePeriod = 7 * 24 * 60 * 60 * 1000; // 7 days |             const inactivePeriod = 7 * 24 * 60 * 60 * 1000; // 7 days | ||||||
|  |  | ||||||
|             for (const issue of issues) { |             for (const issue of issues) { | ||||||
|               const lastUpdated = new Date(issue.updated_at).getTime(); |               // skip pull requests (they are also returned by listForRepo) | ||||||
|  |               if (issue.pull_request) continue; | ||||||
|  |  | ||||||
|  |               // skip labeled issues | ||||||
|  |               if (issue.labels.length > 0) { | ||||||
|  |                 console.log(`Skipping issue #${issue.number} (Has labels).`); | ||||||
|  |                 continue; | ||||||
|  |               } | ||||||
|  |  | ||||||
|  |               // fetch comments for this issue | ||||||
|  |               const { data: comments } = await github.rest.issues.listComments({ | ||||||
|  |                 owner: context.repo.owner, | ||||||
|  |                 repo: context.repo.repo, | ||||||
|  |                 issue_number: issue.number, | ||||||
|  |                 per_page: 100, | ||||||
|  |               }); | ||||||
|  |  | ||||||
|  |               // determine the "last activity" time | ||||||
|  |               let lastActivityTime; | ||||||
|  |               if (comments.length > 0) { | ||||||
|  |                 const lastComment = comments[comments.length - 1]; | ||||||
|  |                 lastActivityTime = new Date(lastComment.updated_at).getTime(); | ||||||
|  |               } else { | ||||||
|  |                 lastActivityTime = new Date(issue.created_at).getTime(); | ||||||
|  |               } | ||||||
|  |  | ||||||
|  |               // check inactivity | ||||||
|  |               if (now - lastActivityTime > inactivePeriod) { | ||||||
|  |                 console.log(`Closing inactive issue: #${issue.number} (No recent replies for 7 days)`); | ||||||
|  |  | ||||||
|  |                 await github.rest.issues.createComment({ | ||||||
|  |                   owner: context.repo.owner, | ||||||
|  |                   repo: context.repo.repo, | ||||||
|  |                   issue_number: issue.number, | ||||||
|  |                   body: "This issue has been automatically closed due to inactivity for 7 days." | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|               // if the issue hasn't been updated in the past week, close it |  | ||||||
|               if (now - lastUpdated > inactivePeriod && issue.labels.length === 0) { |  | ||||||
|                 console.log(`Closing inactive issue: ${issue.number} (No labels)`); |  | ||||||
|                 await github.rest.issues.update({ |                 await github.rest.issues.update({ | ||||||
|                   owner: context.repo.owner, |                   owner: context.repo.owner, | ||||||
|                   repo: context.repo.repo, |                   repo: context.repo.repo, | ||||||
|                   issue_number: issue.number, |                   issue_number: issue.number, | ||||||
|                   state: 'closed', |                   state: 'closed', | ||||||
|                 }); |                 }); | ||||||
|               } else if (issue.labels.length === 0) { |  | ||||||
|                 console.log(`Skipping issue ${issue.number} (No labels) as it has been recently updated.`); |  | ||||||
|               } else { |               } else { | ||||||
|                 console.log(`Skipping issue ${issue.number} (Has labels).`); |                 console.log(`Skipping issue #${issue.number} (Active within 7 days).`); | ||||||
|               } |               } | ||||||
|             } |             } | ||||||
|  |         env: | ||||||
|  |           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								.github/workflows/update-pages.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								.github/workflows/update-pages.yml
									
									
									
									
										vendored
									
									
								
							| @@ -15,8 +15,9 @@ jobs: | |||||||
|       - name: Set version number |       - name: Set version number | ||||||
|         id: version |         id: version | ||||||
|         run: | |         run: | | ||||||
|  |           SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7) | ||||||
|           VERSION_NUM="${GITHUB_REF##*/}" |           VERSION_NUM="${GITHUB_REF##*/}" | ||||||
|           VERSION_NUM="${VERSION_NUM#v}" |           VERSION_NUM="${VERSION_NUM#v}-${SHORT_SHA}" | ||||||
|           echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_ENV |           echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_ENV | ||||||
|           echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_OUTPUT |           echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_OUTPUT | ||||||
|  |  | ||||||
| @@ -30,11 +31,13 @@ jobs: | |||||||
|       - name: Update download links |       - name: Update download links | ||||||
|         run: | |         run: | | ||||||
|           cd pages |           cd pages | ||||||
|           sed -E -i "s/crossdesk-win-x64-[0-9]+\.[0-9]+\.[0-9]+\.exe/crossdesk-win-x64-${VERSION_NUM}.exe/g" index.html |           echo "Updating download links to ${VERSION_NUM}" | ||||||
|           sed -E -i "s/crossdesk-macos-x64-[0-9]+\.[0-9]+\.[0-9]+\.pkg/crossdesk-macos-x64-${VERSION_NUM}.pkg/g" index.html |           sed -E -i "s/crossdesk-win-x64-[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9._-]+)?\.exe/crossdesk-win-x64-${VERSION_NUM}.exe/g" index.html | ||||||
|           sed -E -i "s/crossdesk-macos-arm64-[0-9]+\.[0-9]+\.[0-9]+\.pkg/crossdesk-macos-arm64-${VERSION_NUM}.pkg/g" index.html |           sed -E -i "s/crossdesk-macos-x64-[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9._-]+)?\.pkg/crossdesk-macos-x64-${VERSION_NUM}.pkg/g" index.html | ||||||
|           sed -E -i "s/crossdesk-linux-amd64-[0-9]+\.[0-9]+\.[0-9]+\.deb/crossdesk-linux-amd64-${VERSION_NUM}.deb/g" index.html |           sed -E -i "s/crossdesk-macos-arm64-[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9._-]+)?\.pkg/crossdesk-macos-arm64-${VERSION_NUM}.pkg/g" index.html | ||||||
|           sed -E -i "s/crossdesk-linux-arm64-[0-9]+\.[0-9]+\.[0-9]+\.deb/crossdesk-linux-arm64-${VERSION_NUM}.deb/g" index.html |           sed -E -i "s/crossdesk-linux-amd64-[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9._-]+)?\.deb/crossdesk-linux-amd64-${VERSION_NUM}.deb/g" index.html | ||||||
|  |           sed -E -i "s/crossdesk-linux-arm64-[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9._-]+)?\.deb/crossdesk-linux-arm64-${VERSION_NUM}.deb/g" index.html | ||||||
|  |           git diff index.html || true | ||||||
|  |  | ||||||
|       - name: Commit & Push changes |       - name: Commit & Push changes | ||||||
|         run: | |         run: | | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							| @@ -1,3 +1,3 @@ | |||||||
| [submodule "thirdparty/minirtc"] | [submodule "submodules/minirtc"] | ||||||
| 	path = thirdparty/minirtc | 	path = submodules/minirtc | ||||||
| 	url = https://github.com/kunkundi/minirtc.git | 	url = https://github.com/kunkundi/minirtc.git | ||||||
|   | |||||||
							
								
								
									
										24
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,9 +1,9 @@ | |||||||
| # CrossDesk | # CrossDesk | ||||||
|  |  | ||||||
| []() | []() | ||||||
| [](https://www.gnu.org/licenses/lgpl-3.0) | [](https://www.gnu.org/licenses/lgpl-3.0) | ||||||
| [](https://github.com/kunkundi/crossdesk/commits/self-hosted-server) | [](https://github.com/kunkundi/crossdesk/commits/self-hosted-server) | ||||||
| [](https://github.com/kunkundi/crossdesk/actions)   | [](https://github.com/kunkundi/crossdesk/actions)   | ||||||
| [](https://hub.docker.com/r/crossdesk/crossdesk-server/tags) | [](https://hub.docker.com/r/crossdesk/crossdesk-server/tags) | ||||||
| []() | []() | ||||||
| []() | []() | ||||||
| @@ -65,7 +65,7 @@ xmake r crossdesk | |||||||
|  |  | ||||||
| ### 无 CUDA 环境下的开发支持 | ### 无 CUDA 环境下的开发支持 | ||||||
|  |  | ||||||
| 对于未安装 **CUDA 环境** 的 Linux 开发者,这里提供了预配置的 [Ubuntu 22.04 Docker 镜像](https://hub.docker.com/r/crossdesk/ubuntu22.04)。该镜像内置必要的构建依赖,可在容器中开箱即用,无需额外配置即可直接编译项目。 | 对于**未安装 CUDA 环境的 Linux 开发者**,这里提供了预配置的 [Ubuntu 22.04 Docker 镜像](https://hub.docker.com/r/crossdesk/ubuntu22.04)。该镜像内置必要的构建依赖,可在容器中开箱即用,无需额外配置即可直接编译项目。 | ||||||
|  |  | ||||||
| 进入容器,下载工程后执行: | 进入容器,下载工程后执行: | ||||||
| ``` | ``` | ||||||
| @@ -75,7 +75,7 @@ export XMAKE_GLOBALDIR=/data | |||||||
| xmake b --root -vy crossdesk | xmake b --root -vy crossdesk | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| 对于未安装 **CUDA 环境** 的 Windows 开发者,执行下面的命令安装 CUDA 编译环境: | 对于**未安装 CUDA 环境的 Windows 开发者**,执行下面的命令安装 CUDA 编译环境: | ||||||
| ``` | ``` | ||||||
| xmake require -vy "cuda 12.6.3" | xmake require -vy "cuda 12.6.3" | ||||||
| ``` | ``` | ||||||
| @@ -146,11 +146,14 @@ sudo docker run -d \ | |||||||
|   --network host \ |   --network host \ | ||||||
|   -e EXTERNAL_IP=xxx.xxx.xxx.xxx \ |   -e EXTERNAL_IP=xxx.xxx.xxx.xxx \ | ||||||
|   -e INTERNAL_IP=xxx.xxx.xxx.xxx \ |   -e INTERNAL_IP=xxx.xxx.xxx.xxx \ | ||||||
|   -e CROSSDESK_SERVER_PORT=9099 \ |   -e CROSSDESK_SERVER_PORT=xxxx \ | ||||||
|  |   -e COTURN_PORT=xxxx \ | ||||||
|  |   -e MIN_PORT=xxxxx \ | ||||||
|  |   -e MAX_PORT=xxxxx \ | ||||||
|   -v /path/to/your/certs:/crossdesk-server/certs \ |   -v /path/to/your/certs:/crossdesk-server/certs \ | ||||||
|   -v /path/to/your/db:/crossdesk-server/db \ |   -v /path/to/your/db:/crossdesk-server/db \ | ||||||
|   -v /path/to/your/logs:/crossdesk-server/logs \ |   -v /path/to/your/logs:/crossdesk-server/logs \ | ||||||
|   crossdesk/crossdesk-server:latest |   crossdesk/crossdesk-server:v1.0.0 | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| 上述命令中,用户需注意的参数如下: | 上述命令中,用户需注意的参数如下: | ||||||
| @@ -161,6 +164,10 @@ sudo docker run -d \ | |||||||
|  |  | ||||||
| - CROSSDESK_SERVER_PORT:自托管服务使用的端口,对应 CrossDesk 客户端**自托管服务器配置**中填写的**服务器端口** | - CROSSDESK_SERVER_PORT:自托管服务使用的端口,对应 CrossDesk 客户端**自托管服务器配置**中填写的**服务器端口** | ||||||
|  |  | ||||||
|  | - COTURN_PORT: COTURN 服务使用的端口, 对应 CrossDesk 客户端**自托管服务器配置**中填写的**中继服务端口** | ||||||
|  |  | ||||||
|  | - MIN_PORT/MAX_PORT:COTURN 服务使用的端口范围,例如:MIN_PORT=50000, MAX_PORT=60000,范围可根据客户端数量调整。 | ||||||
|  |  | ||||||
| - /path/to/your/certs:证书文件目录 | - /path/to/your/certs:证书文件目录 | ||||||
|  |  | ||||||
| - /path/to/your/db:CrossDesk Server 设备管理数据库 | - /path/to/your/db:CrossDesk Server 设备管理数据库 | ||||||
| @@ -169,7 +176,7 @@ sudo docker run -d \ | |||||||
|  |  | ||||||
| **注意**: | **注意**: | ||||||
| - **/path/to/your/ 是示例路径,请替换为你自己的实际路径。挂载的目录必须事先创建好,否则容器会报错。** | - **/path/to/your/ 是示例路径,请替换为你自己的实际路径。挂载的目录必须事先创建好,否则容器会报错。** | ||||||
| - **服务器需开放端口:3478/udp,3478/tcp,30000-60000/udp,CROSSDESK_SERVER_PORT/tcp,443/tcp。** | - **服务器需开放端口:3478/udp,3478/tcp,MIN_PORT-MAX_PORT/udp,CROSSDESK_SERVER_PORT/tcp。** | ||||||
|  |  | ||||||
| ## 证书文件 | ## 证书文件 | ||||||
| 客户端需加载根证书文件,服务端需加载服务器私钥和服务器证书文件。 | 客户端需加载根证书文件,服务端需加载服务器私钥和服务器证书文件。 | ||||||
| @@ -295,3 +302,6 @@ Generation complete. Deployment files:: | |||||||
|  |  | ||||||
| 7. 勾选使用**自托管服务器配置**,点击确认配置生效。<br><br> | 7. 勾选使用**自托管服务器配置**,点击确认配置生效。<br><br> | ||||||
| <img width="600" height="160" alt="image" src="https://github.com/user-attachments/assets/1e455dc3-4087-4f37-a544-1ff9f8789383" /><br><br> | <img width="600" height="160" alt="image" src="https://github.com/user-attachments/assets/1e455dc3-4087-4f37-a544-1ff9f8789383" /><br><br> | ||||||
|  |  | ||||||
|  | # 常见问题 | ||||||
|  | 见 [常见问题](https://github.com/kunkundi/crossdesk/blob/self-hosted-server/docs/FAQ.md) 。 | ||||||
							
								
								
									
										28
									
								
								README_EN.md
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								README_EN.md
									
									
									
									
									
								
							| @@ -1,9 +1,9 @@ | |||||||
| # CrossDesk | # CrossDesk | ||||||
|  |  | ||||||
| []() | []() | ||||||
| [](https://www.gnu.org/licenses/lgpl-3.0) | [](https://www.gnu.org/licenses/lgpl-3.0) | ||||||
| [](https://github.com/kunkundi/crossdesk/commits/self-hosted-server) | [](https://github.com/kunkundi/crossdesk/commits/self-hosted-server) | ||||||
| [](https://github.com/kunkundi/crossdesk/actions)   | [](https://github.com/kunkundi/crossdesk/actions)   | ||||||
| [](https://hub.docker.com/r/crossdesk/crossdesk-server/tags) | [](https://hub.docker.com/r/crossdesk/crossdesk-server/tags) | ||||||
| []() | []() | ||||||
| []() | []() | ||||||
| @@ -65,7 +65,7 @@ xmake r crossdesk | |||||||
|  |  | ||||||
| #### Development Without CUDA Environment | #### Development Without CUDA Environment | ||||||
|  |  | ||||||
| For **Linux** developers who do not have a **CUDA environment** installed, a preconfigured [Ubuntu 22.04 Docker image](https://hub.docker.com/r/crossdesk/ubuntu22.04) is provided.   | For **Linux developers who do not have a CUDA environment** installed, a preconfigured [Ubuntu 22.04 Docker image](https://hub.docker.com/r/crossdesk/ubuntu22.04) is provided.   | ||||||
| This image comes with all required build dependencies and allows you to build the project directly inside the container without any additional setup. | This image comes with all required build dependencies and allows you to build the project directly inside the container without any additional setup. | ||||||
|  |  | ||||||
| After entering the container, download the project and run: | After entering the container, download the project and run: | ||||||
| @@ -76,7 +76,7 @@ export XMAKE_GLOBALDIR=/data | |||||||
| xmake b --root -vy crossdesk | xmake b --root -vy crossdesk | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| For **Windows** developers without a **CUDA environment** installed, run the following command to install the CUDA build environment: | For **Windows developers without a CUDA environment** installed, run the following command to install the CUDA build environment: | ||||||
| ``` | ``` | ||||||
| xmake require -vy "cuda 12.6.3" | xmake require -vy "cuda 12.6.3" | ||||||
| ``` | ``` | ||||||
| @@ -149,13 +149,16 @@ It is recommended to deploy CrossDesk Server using Docker. | |||||||
| sudo docker run -d \ | sudo docker run -d \ | ||||||
|   --name crossdesk_server \ |   --name crossdesk_server \ | ||||||
|   --network host \ |   --network host \ | ||||||
|   -e EXTERNAL_IP=150.158.81.30 \ |   -e EXTERNAL_IP=xxx.xxx.xxx.xxx \ | ||||||
|   -e INTERNAL_IP=10.0.4.3 \ |   -e INTERNAL_IP=xxx.xxx.xxx.xxx \ | ||||||
|   -e CROSSDESK_SERVER_PORT=9099 \ |   -e CROSSDESK_SERVER_PORT=xxxx \ | ||||||
|  |   -e COTURN_PORT=xxxx \ | ||||||
|  |   -e MIN_PORT=xxxxx \ | ||||||
|  |   -e MAX_PORT=xxxxx \ | ||||||
|   -v /path/to/your/certs:/crossdesk-server/certs \ |   -v /path/to/your/certs:/crossdesk-server/certs \ | ||||||
|   -v /path/to/your/db:/crossdesk-server/db \ |   -v /path/to/your/db:/crossdesk-server/db \ | ||||||
|   -v /path/to/your/logs:/crossdesk-server/logs \ |   -v /path/to/your/logs:/crossdesk-server/logs \ | ||||||
|   crossdesk/crossdesk-server:latest |   crossdesk/crossdesk-server:v1.0.0 | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| The parameters you need to pay attention to are as follows: | The parameters you need to pay attention to are as follows: | ||||||
| @@ -166,6 +169,10 @@ The parameters you need to pay attention to are as follows: | |||||||
|  |  | ||||||
| - **CROSSDESK_SERVER_PORT**: The port used by the self-hosted server, corresponding to the **Server Port** in the CrossDesk client **Self-Hosted Server Configuration**. | - **CROSSDESK_SERVER_PORT**: The port used by the self-hosted server, corresponding to the **Server Port** in the CrossDesk client **Self-Hosted Server Configuration**. | ||||||
|  |  | ||||||
|  | - **COTURN_PORT**: The port used by Coturn, corresponding to the **Relay Server Port** in the CrossDesk client **Self-Hosted Server Configuration**. | ||||||
|  |  | ||||||
|  | - **MIN_PORT** and **MAX_PORT**: The range of ports used by the self-hosted server, corresponding to the **Minimum Port** and **Maximum Port** in the CrossDesk client **Self-Hosted Server Configuration**. Example: 50000-60000. It depends on the number of devices connected to the server. | ||||||
|  |  | ||||||
| - **/path/to/your/certs**: Directory for certificate files. | - **/path/to/your/certs**: Directory for certificate files. | ||||||
|  |  | ||||||
| - **/path/to/your/db**: CrossDesk Server device management database. | - **/path/to/your/db**: CrossDesk Server device management database. | ||||||
| @@ -174,7 +181,7 @@ The parameters you need to pay attention to are as follows: | |||||||
|  |  | ||||||
| **Note**:   | **Note**:   | ||||||
| - **/path/to/your/ is an example path; please replace it with your actual path. The mounted directories must be created in advance, otherwise the container will fail.** | - **/path/to/your/ is an example path; please replace it with your actual path. The mounted directories must be created in advance, otherwise the container will fail.** | ||||||
| - **The server must open the following ports: 3478/udp, 3478/tcp, 30000-60000/udp, CROSSDESK_SERVER_PORT/tcp, 443/tcp.** | - **The server must open the following ports: 3478/udp, 3478/tcp, 30000-60000/udp, CROSSDESK_SERVER_PORT/tcp.** | ||||||
|  |  | ||||||
| ## Certificate Files | ## Certificate Files | ||||||
| The client needs to load the root certificate, and the server needs to load the server private key and server certificate. | The client needs to load the root certificate, and the server needs to load the server private key and server certificate. | ||||||
| @@ -300,3 +307,6 @@ Place **crossdesk.cn.key** and **crossdesk.cn_bundle.crt** into the **/path/to/y | |||||||
|  |  | ||||||
| 4. Check the option to use **Self-Hosted Server Configuration**.<br><br> | 4. Check the option to use **Self-Hosted Server Configuration**.<br><br> | ||||||
| <img width="600" height="160" alt="image" src="https://github.com/user-attachments/assets/1e455dc3-4087-4f37-a544-1ff9f8789383" /><br><br> | <img width="600" height="160" alt="image" src="https://github.com/user-attachments/assets/1e455dc3-4087-4f37-a544-1ff9f8789383" /><br><br> | ||||||
|  |  | ||||||
|  | # FAQ | ||||||
|  | See [FAQ](https://github.com/kunkundi/crosssesk/blob/self-hosted-server/docs/FAQ.md) . | ||||||
							
								
								
									
										33
									
								
								docs/FAQ.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								docs/FAQ.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | # 常见问题(FAQ) | ||||||
|  |  | ||||||
|  | 欢迎来到 **CrossDesk 常见问题** 页面!   | ||||||
|  | 这里整理了用户和开发者最常见的一些疑问。如果你没有找到答案,欢迎在 [Issues](https://github.com/kunkundi/crossdesk/issues) 中反馈。 | ||||||
|  |  | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | ### Q1. 对等连接失败 | ||||||
|  | **A:**   | ||||||
|  | 打开设置,勾选 **启用中继服务** 选项,尝试重新发起连接。 | ||||||
|  |  | ||||||
|  | <img width="396" height="306" alt="Image" src="https://github.com/user-attachments/assets/fd8db148-c782-4f4d-b874-8f1b2a7ec7d6" /> | ||||||
|  |  | ||||||
|  | 由于公共中继服务器带宽较小,连接的清晰度流畅度可能会下降,建议自建服务器。 [Issue #8](https://github.com/kunkundi/crossdesk/issues/8) | ||||||
|  |  | ||||||
|  | ### Q2. Windows 无 CUDA 环境下编译 | ||||||
|  | **A:**   | ||||||
|  | 运行下面的命令安装 CUDA 编译环境。 | ||||||
|  | ``` | ||||||
|  | xmake require -vy "cuda 12.6.3" | ||||||
|  | ``` | ||||||
|  | 安装完成后执行 | ||||||
|  | ``` | ||||||
|  | xmake require --info "cuda 12.6.3" | ||||||
|  | ``` | ||||||
|  | 输出如下 | ||||||
|  |  | ||||||
|  | <img width="860" height="226" alt="Image" src="https://github.com/user-attachments/assets/999ac365-581a-4b9a-806e-05eb3e4cf44d" /> | ||||||
|  |  | ||||||
|  | 根据上述输出获取到 CUDA 的安装目录,即 installdir 指向的位置。将 CUDA_PATH 加入系统环境变量,或在终端中输入 set CUDA_PATH=path_to_cuda_installdir,重新执行 xmake b -vy crossdesk 即可。 | ||||||
|  | [Issue #6](https://github.com/kunkundi/crossdesk/issues/6) | ||||||
|  |  | ||||||
|  | --- | ||||||
| @@ -9,8 +9,8 @@ | |||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
| #include "render.h" | #include "render.h" | ||||||
|  |  | ||||||
| int main([[maybe_unused]] int argc, [[maybe_unused]] char *argv[]) { | int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) { | ||||||
|   Render render; |   crossdesk::Render render; | ||||||
|   render.Run(); |   render.Run(); | ||||||
|  |  | ||||||
|   return 0; |   return 0; | ||||||
|   | |||||||
| @@ -9,6 +9,8 @@ | |||||||
|  |  | ||||||
| #include <string> | #include <string> | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class DisplayInfo { | class DisplayInfo { | ||||||
|  public: |  public: | ||||||
|   DisplayInfo(std::string name, int left, int top, int right, int bottom) |   DisplayInfo(std::string name, int left, int top, int right, int bottom) | ||||||
| @@ -40,5 +42,5 @@ class DisplayInfo { | |||||||
|   int width = 0; |   int width = 0; | ||||||
|   int height = 0; |   int height = 0; | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -19,6 +19,8 @@ | |||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| std::string GetMac() { | std::string GetMac() { | ||||||
|   char mac_addr[16]; |   char mac_addr[16]; | ||||||
|   int len = 0; |   int len = 0; | ||||||
| @@ -39,21 +41,21 @@ std::string GetMac() { | |||||||
| #elif __APPLE__ | #elif __APPLE__ | ||||||
|   std::string if_name = "en0"; |   std::string if_name = "en0"; | ||||||
|  |  | ||||||
|   struct ifaddrs *addrs; |   struct ifaddrs* addrs; | ||||||
|   struct ifaddrs *cursor; |   struct ifaddrs* cursor; | ||||||
|   const struct sockaddr_dl *dlAddr; |   const struct sockaddr_dl* dlAddr; | ||||||
|  |  | ||||||
|   if (!getifaddrs(&addrs)) { |   if (!getifaddrs(&addrs)) { | ||||||
|     cursor = addrs; |     cursor = addrs; | ||||||
|     while (cursor != 0) { |     while (cursor != 0) { | ||||||
|       const struct sockaddr_dl *socAddr = |       const struct sockaddr_dl* socAddr = | ||||||
|           (const struct sockaddr_dl *)cursor->ifa_addr; |           (const struct sockaddr_dl*)cursor->ifa_addr; | ||||||
|       if ((cursor->ifa_addr->sa_family == AF_LINK) && |       if ((cursor->ifa_addr->sa_family == AF_LINK) && | ||||||
|           (socAddr->sdl_type == IFT_ETHER) && |           (socAddr->sdl_type == IFT_ETHER) && | ||||||
|           strcmp(if_name.c_str(), cursor->ifa_name) == 0) { |           strcmp(if_name.c_str(), cursor->ifa_name) == 0) { | ||||||
|         dlAddr = (const struct sockaddr_dl *)cursor->ifa_addr; |         dlAddr = (const struct sockaddr_dl*)cursor->ifa_addr; | ||||||
|         const unsigned char *base = |         const unsigned char* base = | ||||||
|             (const unsigned char *)&dlAddr->sdl_data[dlAddr->sdl_nlen]; |             (const unsigned char*)&dlAddr->sdl_data[dlAddr->sdl_nlen]; | ||||||
|         for (int i = 0; i < dlAddr->sdl_alen; i++) { |         for (int i = 0; i < dlAddr->sdl_alen; i++) { | ||||||
|           len += |           len += | ||||||
|               snprintf(mac_addr + len, sizeof(mac_addr) - len, "%.2X", base[i]); |               snprintf(mac_addr + len, sizeof(mac_addr) - len, "%.2X", base[i]); | ||||||
| @@ -77,8 +79,8 @@ std::string GetMac() { | |||||||
|     close(sock); |     close(sock); | ||||||
|     return ""; |     return ""; | ||||||
|   } |   } | ||||||
|   struct ifreq *it = ifc.ifc_req; |   struct ifreq* it = ifc.ifc_req; | ||||||
|   const struct ifreq *const end = it + (ifc.ifc_len / sizeof(struct ifreq)); |   const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq)); | ||||||
|   for (; it != end; ++it) { |   for (; it != end; ++it) { | ||||||
|     std::strcpy(ifr.ifr_name, it->ifr_name); |     std::strcpy(ifr.ifr_name, it->ifr_name); | ||||||
|     if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) { |     if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) { | ||||||
| @@ -123,3 +125,4 @@ std::string GetHostName() { | |||||||
| #endif | #endif | ||||||
|   return hostname; |   return hostname; | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -9,7 +9,10 @@ | |||||||
|  |  | ||||||
| #include <iostream> | #include <iostream> | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| std::string GetMac(); | std::string GetMac(); | ||||||
| std::string GetHostName(); | std::string GetHostName(); | ||||||
|  |  | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -1,5 +1,7 @@ | |||||||
| #include "config_center.h" | #include "config_center.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| ConfigCenter::ConfigCenter(const std::string& config_path, | ConfigCenter::ConfigCenter(const std::string& config_path, | ||||||
|                            const std::string& cert_file_path) |                            const std::string& cert_file_path) | ||||||
|     : config_path_(config_path), |     : config_path_(config_path), | ||||||
| @@ -36,14 +38,20 @@ int ConfigCenter::Load() { | |||||||
|  |  | ||||||
|   enable_turn_ = ini_.GetBoolValue(section_, "enable_turn", enable_turn_); |   enable_turn_ = ini_.GetBoolValue(section_, "enable_turn", enable_turn_); | ||||||
|   enable_srtp_ = ini_.GetBoolValue(section_, "enable_srtp", enable_srtp_); |   enable_srtp_ = ini_.GetBoolValue(section_, "enable_srtp", enable_srtp_); | ||||||
|   server_host_ = ini_.GetValue(section_, "server_host", server_host_.c_str()); |   signal_server_host_ = ini_.GetValue(section_, "signal_server_host", | ||||||
|   server_port_ = static_cast<int>( |                                       signal_server_host_.c_str()); | ||||||
|       ini_.GetLongValue(section_, "server_port", server_port_)); |   signal_server_port_ = static_cast<int>( | ||||||
|  |       ini_.GetLongValue(section_, "signal_server_port", signal_server_port_)); | ||||||
|  |   coturn_server_port_ = static_cast<int>( | ||||||
|  |       ini_.GetLongValue(section_, "coturn_server_port", coturn_server_port_)); | ||||||
|   cert_file_path_ = |   cert_file_path_ = | ||||||
|       ini_.GetValue(section_, "cert_file_path", cert_file_path_.c_str()); |       ini_.GetValue(section_, "cert_file_path", cert_file_path_.c_str()); | ||||||
|   enable_self_hosted_ = |   enable_self_hosted_ = | ||||||
|       ini_.GetBoolValue(section_, "enable_self_hosted", enable_self_hosted_); |       ini_.GetBoolValue(section_, "enable_self_hosted", enable_self_hosted_); | ||||||
|  |  | ||||||
|  |   enable_minimize_to_tray_ = ini_.GetBoolValue( | ||||||
|  |       section_, "enable_minimize_to_tray", enable_minimize_to_tray_); | ||||||
|  |  | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -58,10 +66,13 @@ int ConfigCenter::Save() { | |||||||
|   ini_.SetBoolValue(section_, "hardware_video_codec", hardware_video_codec_); |   ini_.SetBoolValue(section_, "hardware_video_codec", hardware_video_codec_); | ||||||
|   ini_.SetBoolValue(section_, "enable_turn", enable_turn_); |   ini_.SetBoolValue(section_, "enable_turn", enable_turn_); | ||||||
|   ini_.SetBoolValue(section_, "enable_srtp", enable_srtp_); |   ini_.SetBoolValue(section_, "enable_srtp", enable_srtp_); | ||||||
|   ini_.SetValue(section_, "server_host", server_host_.c_str()); |   ini_.SetValue(section_, "signal_server_host", signal_server_host_.c_str()); | ||||||
|   ini_.SetLongValue(section_, "server_port", static_cast<long>(server_port_)); |   ini_.SetLongValue(section_, "signal_server_port", | ||||||
|  |                     static_cast<long>(signal_server_port_)); | ||||||
|   ini_.SetValue(section_, "cert_file_path", cert_file_path_.c_str()); |   ini_.SetValue(section_, "cert_file_path", cert_file_path_.c_str()); | ||||||
|   ini_.SetBoolValue(section_, "enable_self_hosted", enable_self_hosted_); |   ini_.SetBoolValue(section_, "enable_self_hosted", enable_self_hosted_); | ||||||
|  |   ini_.SetBoolValue(section_, "enable_minimize_to_tray", | ||||||
|  |                     enable_minimize_to_tray_); | ||||||
|  |  | ||||||
|   SI_Error rc = ini_.SaveFile(config_path_.c_str()); |   SI_Error rc = ini_.SaveFile(config_path_.c_str()); | ||||||
|   if (rc < 0) { |   if (rc < 0) { | ||||||
| @@ -147,9 +158,9 @@ int ConfigCenter::SetSrtp(bool enable_srtp) { | |||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| int ConfigCenter::SetServerHost(const std::string& server_host) { | int ConfigCenter::SetServerHost(const std::string& signal_server_host) { | ||||||
|   server_host_ = server_host; |   signal_server_host_ = signal_server_host; | ||||||
|   ini_.SetValue(section_, "server_host", server_host_.c_str()); |   ini_.SetValue(section_, "signal_server_host", signal_server_host_.c_str()); | ||||||
|   SI_Error rc = ini_.SaveFile(config_path_.c_str()); |   SI_Error rc = ini_.SaveFile(config_path_.c_str()); | ||||||
|   if (rc < 0) { |   if (rc < 0) { | ||||||
|     return -1; |     return -1; | ||||||
| @@ -157,9 +168,10 @@ int ConfigCenter::SetServerHost(const std::string& server_host) { | |||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| int ConfigCenter::SetServerPort(int server_port) { | int ConfigCenter::SetServerPort(int signal_server_port) { | ||||||
|   server_port_ = server_port; |   signal_server_port_ = signal_server_port; | ||||||
|   ini_.SetLongValue(section_, "server_port", static_cast<long>(server_port_)); |   ini_.SetLongValue(section_, "signal_server_port", | ||||||
|  |                     static_cast<long>(signal_server_port_)); | ||||||
|   SI_Error rc = ini_.SaveFile(config_path_.c_str()); |   SI_Error rc = ini_.SaveFile(config_path_.c_str()); | ||||||
|   if (rc < 0) { |   if (rc < 0) { | ||||||
|     return -1; |     return -1; | ||||||
| @@ -167,6 +179,16 @@ int ConfigCenter::SetServerPort(int server_port) { | |||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int ConfigCenter::SetCoturnServerPort(int coturn_server_port) { | ||||||
|  |   coturn_server_port_ = coturn_server_port; | ||||||
|  |   SI_Error rc = ini_.SetLongValue(section_, "coturn_server_port", | ||||||
|  |                                   static_cast<long>(coturn_server_port_)); | ||||||
|  |   if (rc < 0) { | ||||||
|  |     return -1; | ||||||
|  |   } | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| int ConfigCenter::SetCertFilePath(const std::string& cert_file_path) { | int ConfigCenter::SetCertFilePath(const std::string& cert_file_path) { | ||||||
|   cert_file_path_ = cert_file_path; |   cert_file_path_ = cert_file_path; | ||||||
|   ini_.SetValue(section_, "cert_file_path", cert_file_path_.c_str()); |   ini_.SetValue(section_, "cert_file_path", cert_file_path_.c_str()); | ||||||
| @@ -186,6 +208,11 @@ int ConfigCenter::SetSelfHosted(bool enable_self_hosted) { | |||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int ConfigCenter::SetMinimizeToTray(bool enable_minimize_to_tray) { | ||||||
|  |   enable_minimize_to_tray_ = enable_minimize_to_tray; | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| // getters | // getters | ||||||
|  |  | ||||||
| ConfigCenter::LANGUAGE ConfigCenter::GetLanguage() const { return language_; } | ConfigCenter::LANGUAGE ConfigCenter::GetLanguage() const { return language_; } | ||||||
| @@ -210,20 +237,33 @@ bool ConfigCenter::IsEnableTurn() const { return enable_turn_; } | |||||||
|  |  | ||||||
| bool ConfigCenter::IsEnableSrtp() const { return enable_srtp_; } | bool ConfigCenter::IsEnableSrtp() const { return enable_srtp_; } | ||||||
|  |  | ||||||
| std::string ConfigCenter::GetServerHost() const { return server_host_; } | std::string ConfigCenter::GetSignalServerHost() const { | ||||||
|  |   return signal_server_host_; | ||||||
|  | } | ||||||
|  |  | ||||||
| int ConfigCenter::GetServerPort() const { return server_port_; } | int ConfigCenter::GetSignalServerPort() const { return signal_server_port_; } | ||||||
|  |  | ||||||
|  | int ConfigCenter::GetCoturnServerPort() const { return coturn_server_port_; } | ||||||
|  |  | ||||||
| std::string ConfigCenter::GetCertFilePath() const { return cert_file_path_; } | std::string ConfigCenter::GetCertFilePath() const { return cert_file_path_; } | ||||||
|  |  | ||||||
| std::string ConfigCenter::GetDefaultServerHost() const { | std::string ConfigCenter::GetDefaultServerHost() const { | ||||||
|   return server_host_default_; |   return signal_server_host_default_; | ||||||
| } | } | ||||||
|  |  | ||||||
| int ConfigCenter::GetDefaultServerPort() const { return server_port_default_; } | int ConfigCenter::GetDefaultSignalServerPort() const { | ||||||
|  |   return server_port_default_; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int ConfigCenter::GetDefaultCoturnServerPort() const { | ||||||
|  |   return coturn_server_port_default_; | ||||||
|  | } | ||||||
|  |  | ||||||
| std::string ConfigCenter::GetDefaultCertFilePath() const { | std::string ConfigCenter::GetDefaultCertFilePath() const { | ||||||
|   return cert_file_path_default_; |   return cert_file_path_default_; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool ConfigCenter::IsSelfHosted() const { return enable_self_hosted_; } | bool ConfigCenter::IsSelfHosted() const { return enable_self_hosted_; } | ||||||
|  |  | ||||||
|  | bool ConfigCenter::IsMinimizeToTray() const { return enable_minimize_to_tray_; } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -11,6 +11,8 @@ | |||||||
|  |  | ||||||
| #include "SimpleIni.h" | #include "SimpleIni.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class ConfigCenter { | class ConfigCenter { | ||||||
|  public: |  public: | ||||||
|   enum class LANGUAGE { CHINESE = 0, ENGLISH = 1 }; |   enum class LANGUAGE { CHINESE = 0, ENGLISH = 1 }; | ||||||
| @@ -32,10 +34,12 @@ class ConfigCenter { | |||||||
|   int SetHardwareVideoCodec(bool hardware_video_codec); |   int SetHardwareVideoCodec(bool hardware_video_codec); | ||||||
|   int SetTurn(bool enable_turn); |   int SetTurn(bool enable_turn); | ||||||
|   int SetSrtp(bool enable_srtp); |   int SetSrtp(bool enable_srtp); | ||||||
|   int SetServerHost(const std::string& server_host); |   int SetServerHost(const std::string& signal_server_host); | ||||||
|   int SetServerPort(int server_port); |   int SetServerPort(int signal_server_port); | ||||||
|  |   int SetCoturnServerPort(int coturn_server_port); | ||||||
|   int SetCertFilePath(const std::string& cert_file_path); |   int SetCertFilePath(const std::string& cert_file_path); | ||||||
|   int SetSelfHosted(bool enable_self_hosted); |   int SetSelfHosted(bool enable_self_hosted); | ||||||
|  |   int SetMinimizeToTray(bool enable_minimize_to_tray); | ||||||
|  |  | ||||||
|   // read config |   // read config | ||||||
|  |  | ||||||
| @@ -46,13 +50,16 @@ class ConfigCenter { | |||||||
|   bool IsHardwareVideoCodec() const; |   bool IsHardwareVideoCodec() const; | ||||||
|   bool IsEnableTurn() const; |   bool IsEnableTurn() const; | ||||||
|   bool IsEnableSrtp() const; |   bool IsEnableSrtp() const; | ||||||
|   std::string GetServerHost() const; |   std::string GetSignalServerHost() const; | ||||||
|   int GetServerPort() const; |   int GetSignalServerPort() const; | ||||||
|  |   int GetCoturnServerPort() const; | ||||||
|   std::string GetCertFilePath() const; |   std::string GetCertFilePath() const; | ||||||
|   std::string GetDefaultServerHost() const; |   std::string GetDefaultServerHost() const; | ||||||
|   int GetDefaultServerPort() const; |   int GetDefaultSignalServerPort() const; | ||||||
|  |   int GetDefaultCoturnServerPort() const; | ||||||
|   std::string GetDefaultCertFilePath() const; |   std::string GetDefaultCertFilePath() const; | ||||||
|   bool IsSelfHosted() const; |   bool IsSelfHosted() const; | ||||||
|  |   bool IsMinimizeToTray() const; | ||||||
|  |  | ||||||
|   int Load(); |   int Load(); | ||||||
|   int Save(); |   int Save(); | ||||||
| @@ -70,12 +77,15 @@ class ConfigCenter { | |||||||
|   bool hardware_video_codec_ = false; |   bool hardware_video_codec_ = false; | ||||||
|   bool enable_turn_ = false; |   bool enable_turn_ = false; | ||||||
|   bool enable_srtp_ = false; |   bool enable_srtp_ = false; | ||||||
|   std::string server_host_ = "api.crossdesk.cn"; |   std::string signal_server_host_ = "api.crossdesk.cn"; | ||||||
|   int server_port_ = 9099; |   std::string signal_server_host_default_ = "api.crossdesk.cn"; | ||||||
|   std::string server_host_default_ = "api.crossdesk.cn"; |   int signal_server_port_ = 9099; | ||||||
|   int server_port_default_ = 9099; |   int server_port_default_ = 9099; | ||||||
|  |   int coturn_server_port_ = 3478; | ||||||
|  |   int coturn_server_port_default_ = 3478; | ||||||
|   std::string cert_file_path_default_ = ""; |   std::string cert_file_path_default_ = ""; | ||||||
|   bool enable_self_hosted_ = false; |   bool enable_self_hosted_ = false; | ||||||
|  |   bool enable_minimize_to_tray_ = false; | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -11,6 +11,8 @@ | |||||||
|  |  | ||||||
| #include "display_info.h" | #include "display_info.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| typedef enum { | typedef enum { | ||||||
|   mouse = 0, |   mouse = 0, | ||||||
|   keyboard, |   keyboard, | ||||||
| @@ -79,5 +81,5 @@ class DeviceController { | |||||||
|   // virtual int Hook(); |   // virtual int Hook(); | ||||||
|   // virtual int Unhook(); |   // virtual int Unhook(); | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -11,6 +11,8 @@ | |||||||
| #include "keyboard_capturer.h" | #include "keyboard_capturer.h" | ||||||
| #include "mouse_controller.h" | #include "mouse_controller.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class DeviceControllerFactory { | class DeviceControllerFactory { | ||||||
|  public: |  public: | ||||||
|   enum Device { Mouse = 0, Keyboard }; |   enum Device { Mouse = 0, Keyboard }; | ||||||
| @@ -30,5 +32,5 @@ class DeviceControllerFactory { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -3,6 +3,8 @@ | |||||||
| #include "keyboard_converter.h" | #include "keyboard_converter.h" | ||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| static OnKeyAction g_on_key_action = nullptr; | static OnKeyAction g_on_key_action = nullptr; | ||||||
| static void* g_user_ptr = nullptr; | static void* g_user_ptr = nullptr; | ||||||
|  |  | ||||||
| @@ -67,3 +69,4 @@ int KeyboardCapturer::SendKeyboardCommand(int key_code, bool is_down) { | |||||||
|   } |   } | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -13,20 +13,22 @@ | |||||||
|  |  | ||||||
| #include "device_controller.h" | #include "device_controller.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class KeyboardCapturer : public DeviceController { | class KeyboardCapturer : public DeviceController { | ||||||
|  public: |  public: | ||||||
|   KeyboardCapturer(); |   KeyboardCapturer(); | ||||||
|   virtual ~KeyboardCapturer(); |   virtual ~KeyboardCapturer(); | ||||||
|  |  | ||||||
|  public: |  public: | ||||||
|   virtual int Hook(OnKeyAction on_key_action, void *user_ptr); |   virtual int Hook(OnKeyAction on_key_action, void* user_ptr); | ||||||
|   virtual int Unhook(); |   virtual int Unhook(); | ||||||
|   virtual int SendKeyboardCommand(int key_code, bool is_down); |   virtual int SendKeyboardCommand(int key_code, bool is_down); | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   Display *display_; |   Display* display_; | ||||||
|   Window root_; |   Window root_; | ||||||
|   bool running_; |   bool running_; | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -3,12 +3,14 @@ | |||||||
| #include "keyboard_converter.h" | #include "keyboard_converter.h" | ||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| static OnKeyAction g_on_key_action = nullptr; | static OnKeyAction g_on_key_action = nullptr; | ||||||
| static void *g_user_ptr = nullptr; | static void* g_user_ptr = nullptr; | ||||||
|  |  | ||||||
| CGEventRef eventCallback(CGEventTapProxy proxy, CGEventType type, | CGEventRef eventCallback(CGEventTapProxy proxy, CGEventType type, | ||||||
|                          CGEventRef event, void *userInfo) { |                          CGEventRef event, void* userInfo) { | ||||||
|   KeyboardCapturer *keyboard_capturer = (KeyboardCapturer *)userInfo; |   KeyboardCapturer* keyboard_capturer = (KeyboardCapturer*)userInfo; | ||||||
|   if (!keyboard_capturer) { |   if (!keyboard_capturer) { | ||||||
|     LOG_ERROR("keyboard_capturer is nullptr"); |     LOG_ERROR("keyboard_capturer is nullptr"); | ||||||
|     return event; |     return event; | ||||||
| @@ -91,7 +93,7 @@ KeyboardCapturer::KeyboardCapturer() {} | |||||||
|  |  | ||||||
| KeyboardCapturer::~KeyboardCapturer() {} | KeyboardCapturer::~KeyboardCapturer() {} | ||||||
|  |  | ||||||
| int KeyboardCapturer::Hook(OnKeyAction on_key_action, void *user_ptr) { | int KeyboardCapturer::Hook(OnKeyAction on_key_action, void* user_ptr) { | ||||||
|   g_on_key_action = on_key_action; |   g_on_key_action = on_key_action; | ||||||
|   g_user_ptr = user_ptr; |   g_user_ptr = user_ptr; | ||||||
|  |  | ||||||
| @@ -165,3 +167,4 @@ int KeyboardCapturer::SendKeyboardCommand(int key_code, bool is_down) { | |||||||
|  |  | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -11,13 +11,15 @@ | |||||||
|  |  | ||||||
| #include "device_controller.h" | #include "device_controller.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class KeyboardCapturer : public DeviceController { | class KeyboardCapturer : public DeviceController { | ||||||
|  public: |  public: | ||||||
|   KeyboardCapturer(); |   KeyboardCapturer(); | ||||||
|   virtual ~KeyboardCapturer(); |   virtual ~KeyboardCapturer(); | ||||||
|  |  | ||||||
|  public: |  public: | ||||||
|   virtual int Hook(OnKeyAction on_key_action, void *user_ptr); |   virtual int Hook(OnKeyAction on_key_action, void* user_ptr); | ||||||
|   virtual int Unhook(); |   virtual int Unhook(); | ||||||
|   virtual int SendKeyboardCommand(int key_code, bool is_down); |   virtual int SendKeyboardCommand(int key_code, bool is_down); | ||||||
|  |  | ||||||
| @@ -33,5 +35,5 @@ class KeyboardCapturer : public DeviceController { | |||||||
|   bool command_flag_ = false; |   bool command_flag_ = false; | ||||||
|   int fn_key_code_ = 0x3F; |   int fn_key_code_ = 0x3F; | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -2,6 +2,8 @@ | |||||||
|  |  | ||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| static OnKeyAction g_on_key_action = nullptr; | static OnKeyAction g_on_key_action = nullptr; | ||||||
| static void* g_user_ptr = nullptr; | static void* g_user_ptr = nullptr; | ||||||
|  |  | ||||||
| @@ -54,3 +56,4 @@ int KeyboardCapturer::SendKeyboardCommand(int key_code, bool is_down) { | |||||||
|  |  | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -11,18 +11,21 @@ | |||||||
|  |  | ||||||
| #include "device_controller.h" | #include "device_controller.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class KeyboardCapturer : public DeviceController { | class KeyboardCapturer : public DeviceController { | ||||||
|  public: |  public: | ||||||
|   KeyboardCapturer(); |   KeyboardCapturer(); | ||||||
|   virtual ~KeyboardCapturer(); |   virtual ~KeyboardCapturer(); | ||||||
|  |  | ||||||
|  public: |  public: | ||||||
|   virtual int Hook(OnKeyAction on_key_action, void *user_ptr); |   virtual int Hook(OnKeyAction on_key_action, void* user_ptr); | ||||||
|   virtual int Unhook(); |   virtual int Unhook(); | ||||||
|   virtual int SendKeyboardCommand(int key_code, bool is_down); |   virtual int SendKeyboardCommand(int key_code, bool is_down); | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   HHOOK keyboard_hook_ = nullptr; |   HHOOK keyboard_hook_ = nullptr; | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
| @@ -9,6 +9,8 @@ | |||||||
|  |  | ||||||
| #include <map> | #include <map> | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| // Windows vkCode to macOS CGKeyCode (104 keys) | // Windows vkCode to macOS CGKeyCode (104 keys) | ||||||
| std::map<int, int> vkCodeToCGKeyCode = { | std::map<int, int> vkCodeToCGKeyCode = { | ||||||
|     // A-Z |     // A-Z | ||||||
| @@ -736,5 +738,5 @@ std::map<int, int> x11KeySymToCgKeyCode = { | |||||||
|     {0xFFEB, 0x37},  // Left Command |     {0xFFEB, 0x37},  // Left Command | ||||||
|     {0xFFEC, 0x36},  // Right Command |     {0xFFEC, 0x36},  // Right Command | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -4,6 +4,8 @@ | |||||||
|  |  | ||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| MouseController::MouseController() {} | MouseController::MouseController() {} | ||||||
|  |  | ||||||
| MouseController::~MouseController() { Destroy(); } | MouseController::~MouseController() { Destroy(); } | ||||||
| @@ -122,3 +124,4 @@ void MouseController::SimulateMouseWheel(int direction_button, int count) { | |||||||
|   } |   } | ||||||
|   XFlush(display_); |   XFlush(display_); | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -15,6 +15,8 @@ | |||||||
|  |  | ||||||
| #include "device_controller.h" | #include "device_controller.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class MouseController : public DeviceController { | class MouseController : public DeviceController { | ||||||
|  public: |  public: | ||||||
|   MouseController(); |   MouseController(); | ||||||
| @@ -37,5 +39,5 @@ class MouseController : public DeviceController { | |||||||
|   int screen_width_ = 0; |   int screen_width_ = 0; | ||||||
|   int screen_height_ = 0; |   int screen_height_ = 0; | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -4,6 +4,8 @@ | |||||||
|  |  | ||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| MouseController::MouseController() {} | MouseController::MouseController() {} | ||||||
|  |  | ||||||
| MouseController::~MouseController() {} | MouseController::~MouseController() {} | ||||||
| @@ -99,3 +101,4 @@ int MouseController::SendMouseCommand(RemoteAction remote_action, | |||||||
|  |  | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -11,6 +11,8 @@ | |||||||
|  |  | ||||||
| #include "device_controller.h" | #include "device_controller.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class MouseController : public DeviceController { | class MouseController : public DeviceController { | ||||||
|  public: |  public: | ||||||
|   MouseController(); |   MouseController(); | ||||||
| @@ -26,5 +28,5 @@ class MouseController : public DeviceController { | |||||||
|   bool left_dragging_ = false; |   bool left_dragging_ = false; | ||||||
|   bool right_dragging_ = false; |   bool right_dragging_ = false; | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -2,6 +2,8 @@ | |||||||
|  |  | ||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| MouseController::MouseController() {} | MouseController::MouseController() {} | ||||||
|  |  | ||||||
| MouseController::~MouseController() {} | MouseController::~MouseController() {} | ||||||
| @@ -70,3 +72,4 @@ int MouseController::SendMouseCommand(RemoteAction remote_action, | |||||||
|  |  | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -11,6 +11,8 @@ | |||||||
|  |  | ||||||
| #include "device_controller.h" | #include "device_controller.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class MouseController : public DeviceController { | class MouseController : public DeviceController { | ||||||
|  public: |  public: | ||||||
|   MouseController(); |   MouseController(); | ||||||
| @@ -24,5 +26,5 @@ class MouseController : public DeviceController { | |||||||
|  private: |  private: | ||||||
|   std::vector<DisplayInfo> display_info_list_; |   std::vector<DisplayInfo> display_info_list_; | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -20,12 +20,17 @@ | |||||||
| #define INPUT_WINDOW_PADDING_EN 96 | #define INPUT_WINDOW_PADDING_EN 96 | ||||||
| #define SETTINGS_WINDOW_WIDTH_CN 202 | #define SETTINGS_WINDOW_WIDTH_CN 202 | ||||||
| #define SETTINGS_WINDOW_WIDTH_EN 248 | #define SETTINGS_WINDOW_WIDTH_EN 248 | ||||||
|  | #if _WIN32 | ||||||
|  | #define SETTINGS_WINDOW_HEIGHT_CN 345 | ||||||
|  | #define SETTINGS_WINDOW_HEIGHT_EN 345 | ||||||
|  | #else | ||||||
| #define SETTINGS_WINDOW_HEIGHT_CN 315 | #define SETTINGS_WINDOW_HEIGHT_CN 315 | ||||||
| #define SETTINGS_WINDOW_HEIGHT_EN 315 | #define SETTINGS_WINDOW_HEIGHT_EN 315 | ||||||
|  | #endif | ||||||
| #define SELF_HOSTED_SERVER_CONFIG_WINDOW_WIDTH_CN 228 | #define SELF_HOSTED_SERVER_CONFIG_WINDOW_WIDTH_CN 228 | ||||||
| #define SELF_HOSTED_SERVER_CONFIG_WINDOW_WIDTH_EN 275 | #define SELF_HOSTED_SERVER_CONFIG_WINDOW_WIDTH_EN 275 | ||||||
| #define SELF_HOSTED_SERVER_CONFIG_WINDOW_HEIGHT_CN 165 | #define SELF_HOSTED_SERVER_CONFIG_WINDOW_HEIGHT_CN 195 | ||||||
| #define SELF_HOSTED_SERVER_CONFIG_WINDOW_HEIGHT_EN 165 | #define SELF_HOSTED_SERVER_CONFIG_WINDOW_HEIGHT_EN 195 | ||||||
| #define LANGUAGE_SELECT_WINDOW_PADDING_CN 120 | #define LANGUAGE_SELECT_WINDOW_PADDING_CN 120 | ||||||
| #define LANGUAGE_SELECT_WINDOW_PADDING_EN 167 | #define LANGUAGE_SELECT_WINDOW_PADDING_EN 167 | ||||||
| #define VIDEO_QUALITY_SELECT_WINDOW_PADDING_CN 120 | #define VIDEO_QUALITY_SELECT_WINDOW_PADDING_CN 120 | ||||||
| @@ -42,6 +47,8 @@ | |||||||
| #define ENABLE_SRTP_CHECKBOX_PADDING_EN 218 | #define ENABLE_SRTP_CHECKBOX_PADDING_EN 218 | ||||||
| #define ENABLE_SELF_HOSTED_SERVER_CHECKBOX_PADDING_CN 171 | #define ENABLE_SELF_HOSTED_SERVER_CHECKBOX_PADDING_CN 171 | ||||||
| #define ENABLE_SELF_HOSTED_SERVER_CHECKBOX_PADDING_EN 218 | #define ENABLE_SELF_HOSTED_SERVER_CHECKBOX_PADDING_EN 218 | ||||||
|  | #define ENABLE_MINIZE_TO_TRAY_PADDING_CN 171 | ||||||
|  | #define ENABLE_MINIZE_TO_TRAY_PADDING_EN 218 | ||||||
| #define SELF_HOSTED_SERVER_HOST_INPUT_BOX_PADDING_CN 90 | #define SELF_HOSTED_SERVER_HOST_INPUT_BOX_PADDING_CN 90 | ||||||
| #define SELF_HOSTED_SERVER_HOST_INPUT_BOX_PADDING_EN 137 | #define SELF_HOSTED_SERVER_HOST_INPUT_BOX_PADDING_EN 137 | ||||||
| #define SELF_HOSTED_SERVER_PORT_INPUT_BOX_PADDING_CN 90 | #define SELF_HOSTED_SERVER_PORT_INPUT_BOX_PADDING_CN 90 | ||||||
|   | |||||||
| @@ -8,6 +8,13 @@ | |||||||
|  |  | ||||||
| #include <string> | #include <string> | ||||||
| #include <vector> | #include <vector> | ||||||
|  |  | ||||||
|  | #if _WIN32 | ||||||
|  | #include <Windows.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| namespace localization { | namespace localization { | ||||||
|  |  | ||||||
| static std::vector<std::string> local_desktop = { | static std::vector<std::string> local_desktop = { | ||||||
| @@ -102,7 +109,9 @@ static std::vector<std::string> self_hosted_server_settings = { | |||||||
| static std::vector<std::string> self_hosted_server_address = { | static std::vector<std::string> self_hosted_server_address = { | ||||||
|     reinterpret_cast<const char*>(u8"服务器地址:"), "Server Address:"}; |     reinterpret_cast<const char*>(u8"服务器地址:"), "Server Address:"}; | ||||||
| static std::vector<std::string> self_hosted_server_port = { | static std::vector<std::string> self_hosted_server_port = { | ||||||
|     reinterpret_cast<const char*>(u8"服务器端口:"), "Server Port:"}; |     reinterpret_cast<const char*>(u8"信令服务端口:"), "Signal Service Port:"}; | ||||||
|  | static std::vector<std::string> self_hosted_server_coturn_server_port = { | ||||||
|  |     reinterpret_cast<const char*>(u8"中继服务端口:"), "Relay Service Port:"}; | ||||||
| static std::vector<std::string> self_hosted_server_certificate_path = { | static std::vector<std::string> self_hosted_server_certificate_path = { | ||||||
|     reinterpret_cast<const char*>(u8"证书文件路径:"), "Certificate File Path:"}; |     reinterpret_cast<const char*>(u8"证书文件路径:"), "Certificate File Path:"}; | ||||||
| static std::vector<std::string> select_a_file = { | static std::vector<std::string> select_a_file = { | ||||||
| @@ -155,6 +164,13 @@ static std::vector<std::string> version = { | |||||||
| static std::vector<std::string> confirm_delete_connection = { | static std::vector<std::string> confirm_delete_connection = { | ||||||
|     reinterpret_cast<const char*>(u8"确认删除此连接"), |     reinterpret_cast<const char*>(u8"确认删除此连接"), | ||||||
|     "Confirm to delete this connection"}; |     "Confirm to delete this connection"}; | ||||||
| }  // namespace localization | #if _WIN32 | ||||||
|  |  | ||||||
|  | static std::vector<std::string> minimize_to_tray = { | ||||||
|  |     reinterpret_cast<const char*>(u8"退出时最小化到系统托盘:"), | ||||||
|  |     "Minimize to system tray when exit:"}; | ||||||
|  | static std::vector<LPCWSTR> exit_program = {L"退出", L"Exit"}; | ||||||
|  | #endif | ||||||
|  | }  // namespace localization | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -5,6 +5,8 @@ | |||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
| #include "render.h" | #include "render.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| int Render::LocalWindow() { | int Render::LocalWindow() { | ||||||
|   ImGui::SetNextWindowPos(ImVec2(-1.0f, title_bar_height_), ImGuiCond_Always); |   ImGui::SetNextWindowPos(ImVec2(-1.0f, title_bar_height_), ImGuiCond_Always); | ||||||
|   ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); |   ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); | ||||||
| @@ -288,3 +290,4 @@ int Render::LocalWindow() { | |||||||
|  |  | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -2,6 +2,8 @@ | |||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
| #include "render.h" | #include "render.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| int Render::RecentConnectionsWindow() { | int Render::RecentConnectionsWindow() { | ||||||
|   ImGui::SetNextWindowPos( |   ImGui::SetNextWindowPos( | ||||||
|       ImVec2(0, title_bar_height_ + local_window_height_ - 1.0f), |       ImVec2(0, title_bar_height_ + local_window_height_ - 1.0f), | ||||||
| @@ -284,3 +286,4 @@ int Render::ConfirmDeleteConnection() { | |||||||
|   ImGui::PopStyleVar(); |   ImGui::PopStyleVar(); | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -3,7 +3,9 @@ | |||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
| #include "render.h" | #include "render.h" | ||||||
|  |  | ||||||
| static int InputTextCallback(ImGuiInputTextCallbackData *data); | namespace crossdesk { | ||||||
|  |  | ||||||
|  | static int InputTextCallback(ImGuiInputTextCallbackData* data); | ||||||
|  |  | ||||||
| int Render::RemoteWindow() { | int Render::RemoteWindow() { | ||||||
|   ImGui::SetNextWindowPos(ImVec2(local_window_width_ + 1.0f, title_bar_height_), |   ImGui::SetNextWindowPos(ImVec2(local_window_width_ + 1.0f, title_bar_height_), | ||||||
| @@ -77,7 +79,7 @@ int Render::RemoteWindow() { | |||||||
|           enter_pressed) { |           enter_pressed) { | ||||||
|         connect_button_pressed_ = true; |         connect_button_pressed_ = true; | ||||||
|         bool found = false; |         bool found = false; | ||||||
|         for (auto &[id, props] : recent_connections_) { |         for (auto& [id, props] : recent_connections_) { | ||||||
|           if (id.find(remote_id) != std::string::npos) { |           if (id.find(remote_id) != std::string::npos) { | ||||||
|             found = true; |             found = true; | ||||||
|             if (client_properties_.find(remote_id) != |             if (client_properties_.find(remote_id) != | ||||||
| @@ -101,7 +103,7 @@ int Render::RemoteWindow() { | |||||||
|  |  | ||||||
|       if (need_to_rejoin_) { |       if (need_to_rejoin_) { | ||||||
|         need_to_rejoin_ = false; |         need_to_rejoin_ = false; | ||||||
|         for (const auto &[_, props] : client_properties_) { |         for (const auto& [_, props] : client_properties_) { | ||||||
|           if (props->rejoin_) { |           if (props->rejoin_) { | ||||||
|             ConnectTo(props->remote_id_, props->remote_password_, |             ConnectTo(props->remote_id_, props->remote_password_, | ||||||
|                       props->remember_password_); |                       props->remember_password_); | ||||||
| @@ -117,7 +119,7 @@ int Render::RemoteWindow() { | |||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int InputTextCallback(ImGuiInputTextCallbackData *data) { | static int InputTextCallback(ImGuiInputTextCallbackData* data) { | ||||||
|   if (data->BufTextLen > 3 && data->Buf[3] != ' ') { |   if (data->BufTextLen > 3 && data->Buf[3] != ' ') { | ||||||
|     data->InsertChars(3, " "); |     data->InsertChars(3, " "); | ||||||
|   } |   } | ||||||
| @@ -129,7 +131,7 @@ static int InputTextCallback(ImGuiInputTextCallbackData *data) { | |||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| int Render::ConnectTo(const std::string &remote_id, const char *password, | int Render::ConnectTo(const std::string& remote_id, const char* password, | ||||||
|                       bool remember_password) { |                       bool remember_password) { | ||||||
|   LOG_INFO("Connect to [{}]", remote_id); |   LOG_INFO("Connect to [{}]", remote_id); | ||||||
|   focused_remote_id_ = remote_id; |   focused_remote_id_ = remote_id; | ||||||
| @@ -179,3 +181,4 @@ int Render::ConnectTo(const std::string &remote_id, const char *password, | |||||||
|  |  | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -21,6 +21,8 @@ | |||||||
|  |  | ||||||
| #define MOUSE_GRAB_PADDING 5 | #define MOUSE_GRAB_PADDING 5 | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| std::vector<char> Render::SerializeRemoteAction(const RemoteAction& action) { | std::vector<char> Render::SerializeRemoteAction(const RemoteAction& action) { | ||||||
|   std::vector<char> buffer; |   std::vector<char> buffer; | ||||||
|   buffer.push_back(static_cast<char>(action.type)); |   buffer.push_back(static_cast<char>(action.type)); | ||||||
| @@ -427,39 +429,57 @@ int Render::StopKeyboardCapturer() { | |||||||
| int Render::CreateConnectionPeer() { | int Render::CreateConnectionPeer() { | ||||||
|   params_.use_cfg_file = false; |   params_.use_cfg_file = false; | ||||||
|  |  | ||||||
|   std::string server_ip; |   std::string signal_server_ip; | ||||||
|   int server_port; |   int signal_server_port; | ||||||
|   std::string server_cert_path; |   int coturn_server_port; | ||||||
|  |   std::string tls_cert_path; | ||||||
|  |  | ||||||
|   if (config_center_->IsSelfHosted()) { |   if (config_center_->IsSelfHosted()) { | ||||||
|     server_ip = config_center_->GetServerHost(); |     signal_server_ip = config_center_->GetSignalServerHost(); | ||||||
|     server_port = config_center_->GetServerPort(); |     signal_server_port = config_center_->GetSignalServerPort(); | ||||||
|     server_cert_path = config_center_->GetCertFilePath(); |     coturn_server_port = config_center_->GetCoturnServerPort(); | ||||||
|  |     tls_cert_path = config_center_->GetCertFilePath(); | ||||||
|   } else { |   } else { | ||||||
|     server_ip = config_center_->GetDefaultServerHost(); |     signal_server_ip = config_center_->GetDefaultServerHost(); | ||||||
|     server_port = config_center_->GetDefaultServerPort(); |     signal_server_port = config_center_->GetDefaultSignalServerPort(); | ||||||
|     server_cert_path = config_center_->GetDefaultCertFilePath(); |     coturn_server_port = config_center_->GetDefaultCoturnServerPort(); | ||||||
|  |     tls_cert_path = config_center_->GetDefaultCertFilePath(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   strncpy((char*)params_.signal_server_ip, server_ip.c_str(), |   // self hosted server config | ||||||
|  |   strncpy(signal_server_ip_self_, config_center_->GetSignalServerHost().c_str(), | ||||||
|  |           sizeof(signal_server_ip_self_) - 1); | ||||||
|  |   signal_server_ip_self_[sizeof(signal_server_ip_self_) - 1] = '\0'; | ||||||
|  |   strncpy(signal_server_port_self_, | ||||||
|  |           std::to_string(config_center_->GetSignalServerPort()).c_str(), | ||||||
|  |           sizeof(signal_server_port_self_) - 1); | ||||||
|  |   signal_server_port_self_[sizeof(signal_server_port_self_) - 1] = '\0'; | ||||||
|  |   strncpy(coturn_server_port_self_, | ||||||
|  |           std::to_string(config_center_->GetCoturnServerPort()).c_str(), | ||||||
|  |           sizeof(coturn_server_port_self_) - 1); | ||||||
|  |   coturn_server_port_self_[sizeof(coturn_server_port_self_) - 1] = '\0'; | ||||||
|  |   tls_cert_path_self_ = config_center_->GetCertFilePath(); | ||||||
|  |  | ||||||
|  |   // peer config | ||||||
|  |   strncpy((char*)params_.signal_server_ip, signal_server_ip.c_str(), | ||||||
|           sizeof(params_.signal_server_ip) - 1); |           sizeof(params_.signal_server_ip) - 1); | ||||||
|   params_.signal_server_ip[sizeof(params_.signal_server_ip) - 1] = '\0'; |   params_.signal_server_ip[sizeof(params_.signal_server_ip) - 1] = '\0'; | ||||||
|   params_.signal_server_port = server_port; |   params_.signal_server_port = signal_server_port; | ||||||
|   strncpy((char*)params_.stun_server_ip, server_ip.c_str(), |   strncpy((char*)params_.stun_server_ip, signal_server_ip.c_str(), | ||||||
|           sizeof(params_.stun_server_ip) - 1); |           sizeof(params_.stun_server_ip) - 1); | ||||||
|   params_.stun_server_ip[sizeof(params_.stun_server_ip) - 1] = '\0'; |   params_.stun_server_ip[sizeof(params_.stun_server_ip) - 1] = '\0'; | ||||||
|   params_.stun_server_port = 3478; |   params_.stun_server_port = coturn_server_port; | ||||||
|   strncpy((char*)params_.turn_server_ip, server_ip.c_str(), |   strncpy((char*)params_.turn_server_ip, signal_server_ip.c_str(), | ||||||
|           sizeof(params_.turn_server_ip) - 1); |           sizeof(params_.turn_server_ip) - 1); | ||||||
|   params_.turn_server_ip[sizeof(params_.turn_server_ip) - 1] = '\0'; |   params_.turn_server_ip[sizeof(params_.turn_server_ip) - 1] = '\0'; | ||||||
|   params_.turn_server_port = 3478; |   params_.turn_server_port = coturn_server_port; | ||||||
|   strncpy((char*)params_.turn_server_username, "dijunkun", |   strncpy((char*)params_.turn_server_username, "crossdesk", | ||||||
|           sizeof(params_.turn_server_username) - 1); |           sizeof(params_.turn_server_username) - 1); | ||||||
|   params_.turn_server_username[sizeof(params_.turn_server_username) - 1] = '\0'; |   params_.turn_server_username[sizeof(params_.turn_server_username) - 1] = '\0'; | ||||||
|   strncpy((char*)params_.turn_server_password, "dijunkunpw", |   strncpy((char*)params_.turn_server_password, "crossdeskpw", | ||||||
|           sizeof(params_.turn_server_password) - 1); |           sizeof(params_.turn_server_password) - 1); | ||||||
|   params_.turn_server_password[sizeof(params_.turn_server_password) - 1] = '\0'; |   params_.turn_server_password[sizeof(params_.turn_server_password) - 1] = '\0'; | ||||||
|   strncpy(params_.tls_cert_path, server_cert_path.c_str(), |   strncpy(params_.tls_cert_path, tls_cert_path.c_str(), | ||||||
|           sizeof(params_.tls_cert_path) - 1); |           sizeof(params_.tls_cert_path) - 1); | ||||||
|   params_.tls_cert_path[sizeof(params_.tls_cert_path) - 1] = '\0'; |   params_.tls_cert_path[sizeof(params_.tls_cert_path) - 1] = '\0'; | ||||||
|  |  | ||||||
| @@ -588,6 +608,17 @@ int Render::CreateMainWindow() { | |||||||
|   // for window region action |   // for window region action | ||||||
|   SDL_SetWindowHitTest(main_window_, HitTestCallback, this); |   SDL_SetWindowHitTest(main_window_, HitTestCallback, this); | ||||||
|  |  | ||||||
|  | #if _WIN32 | ||||||
|  |   SDL_PropertiesID props = SDL_GetWindowProperties(main_window_); | ||||||
|  |   HWND main_hwnd = (HWND)SDL_GetPointerProperty( | ||||||
|  |       props, SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL); | ||||||
|  |  | ||||||
|  |   HICON tray_icon = (HICON)LoadImageW(NULL, L"crossdesk.ico", IMAGE_ICON, 0, 0, | ||||||
|  |                                       LR_LOADFROMFILE | LR_DEFAULTSIZE); | ||||||
|  |   tray_ = std::make_unique<WinTray>(main_hwnd, tray_icon, L"CrossDesk", | ||||||
|  |                                     localization_language_index_); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -872,13 +903,14 @@ int Render::Run() { | |||||||
|     cache_path_ = path_manager_->GetCachePath().string(); |     cache_path_ = path_manager_->GetCachePath().string(); | ||||||
|     config_center_ = |     config_center_ = | ||||||
|         std::make_unique<ConfigCenter>(cache_path_ + "/config.ini", cert_path_); |         std::make_unique<ConfigCenter>(cache_path_ + "/config.ini", cert_path_); | ||||||
|     strncpy(signal_server_ip_tmp_, config_center_->GetServerHost().c_str(), |     strncpy(signal_server_ip_self_, | ||||||
|             sizeof(signal_server_ip_tmp_) - 1); |             config_center_->GetSignalServerHost().c_str(), | ||||||
|     signal_server_ip_tmp_[sizeof(signal_server_ip_tmp_) - 1] = '\0'; |             sizeof(signal_server_ip_self_) - 1); | ||||||
|     strncpy(signal_server_port_tmp_, |     signal_server_ip_self_[sizeof(signal_server_ip_self_) - 1] = '\0'; | ||||||
|             std::to_string(config_center_->GetServerPort()).c_str(), |     strncpy(signal_server_port_self_, | ||||||
|             sizeof(signal_server_port_tmp_) - 1); |             std::to_string(config_center_->GetSignalServerPort()).c_str(), | ||||||
|     signal_server_port_tmp_[sizeof(signal_server_port_tmp_) - 1] = '\0'; |             sizeof(signal_server_port_self_) - 1); | ||||||
|  |     signal_server_port_self_[sizeof(signal_server_port_self_) - 1] = '\0'; | ||||||
|     strncpy(cert_file_path_, cert_path_.c_str(), sizeof(cert_file_path_) - 1); |     strncpy(cert_file_path_, cert_path_.c_str(), sizeof(cert_file_path_) - 1); | ||||||
|     cert_file_path_[sizeof(cert_file_path_) - 1] = '\0'; |     cert_file_path_[sizeof(cert_file_path_) - 1] = '\0'; | ||||||
|   } else { |   } else { | ||||||
| @@ -968,6 +1000,14 @@ void Render::MainLoop() { | |||||||
|       ProcessSdlEvent(event); |       ProcessSdlEvent(event); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | #if _WIN32 | ||||||
|  |     MSG msg; | ||||||
|  |     while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { | ||||||
|  |       TranslateMessage(&msg); | ||||||
|  |       DispatchMessage(&msg); | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|     UpdateLabels(); |     UpdateLabels(); | ||||||
|     HandleRecentConnections(); |     HandleRecentConnections(); | ||||||
|     HandleStreamWindow(); |     HandleStreamWindow(); | ||||||
| @@ -1394,3 +1434,4 @@ void Render::ProcessSdlEvent(const SDL_Event& event) { | |||||||
|       break; |       break; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -29,7 +29,11 @@ | |||||||
| #include "screen_capturer_factory.h" | #include "screen_capturer_factory.h" | ||||||
| #include "speaker_capturer_factory.h" | #include "speaker_capturer_factory.h" | ||||||
| #include "thumbnail.h" | #include "thumbnail.h" | ||||||
|  | #if _WIN32 | ||||||
|  | #include "win_tray.h" | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
| class Render { | class Render { | ||||||
|  public: |  public: | ||||||
|   struct SubStreamWindowProperties { |   struct SubStreamWindowProperties { | ||||||
| @@ -298,6 +302,9 @@ class Render { | |||||||
|   ImGuiContext* main_ctx_ = nullptr; |   ImGuiContext* main_ctx_ = nullptr; | ||||||
|   bool exit_ = false; |   bool exit_ = false; | ||||||
|   const int sdl_refresh_ms_ = 16;  // ~60 FPS |   const int sdl_refresh_ms_ = 16;  // ~60 FPS | ||||||
|  | #if _WIN32 | ||||||
|  |   std::unique_ptr<WinTray> tray_; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|   // main window properties |   // main window properties | ||||||
|   bool start_mouse_controller_ = false; |   bool start_mouse_controller_ = false; | ||||||
| @@ -335,8 +342,8 @@ class Render { | |||||||
|   float connection_status_window_height_ = 150; |   float connection_status_window_height_ = 150; | ||||||
|   float notification_window_width_ = 200; |   float notification_window_width_ = 200; | ||||||
|   float notification_window_height_ = 80; |   float notification_window_height_ = 80; | ||||||
|   float about_window_width_ = 200; |   float about_window_width_ = 300; | ||||||
|   float about_window_height_ = 150; |   float about_window_height_ = 170; | ||||||
|   int screen_width_ = 1280; |   int screen_width_ = 1280; | ||||||
|   int screen_height_ = 720; |   int screen_height_ = 720; | ||||||
|   int selected_display_ = 0; |   int selected_display_ = 0; | ||||||
| @@ -436,6 +443,7 @@ class Render { | |||||||
|   bool enable_srtp_ = false; |   bool enable_srtp_ = false; | ||||||
|   char signal_server_ip_[256] = "api.crossdesk.cn"; |   char signal_server_ip_[256] = "api.crossdesk.cn"; | ||||||
|   char signal_server_port_[6] = "9099"; |   char signal_server_port_[6] = "9099"; | ||||||
|  |   char coturn_server_port_[6] = "3478"; | ||||||
|   char cert_file_path_[256] = ""; |   char cert_file_path_[256] = ""; | ||||||
|   bool enable_self_hosted_server_ = false; |   bool enable_self_hosted_server_ = false; | ||||||
|   int language_button_value_last_ = 0; |   int language_button_value_last_ = 0; | ||||||
| @@ -444,12 +452,16 @@ class Render { | |||||||
|   bool enable_hardware_video_codec_last_ = false; |   bool enable_hardware_video_codec_last_ = false; | ||||||
|   bool enable_turn_last_ = false; |   bool enable_turn_last_ = false; | ||||||
|   bool enable_srtp_last_ = false; |   bool enable_srtp_last_ = false; | ||||||
|   char signal_server_ip_tmp_[256] = "api.crossdesk.cn"; |   bool enable_minimize_to_tray_ = false; | ||||||
|   char signal_server_port_tmp_[6] = "9099"; |   bool enable_minimize_to_tray_last_ = false; | ||||||
|  |   char signal_server_ip_self_[256] = ""; | ||||||
|  |   char signal_server_port_self_[6] = ""; | ||||||
|  |   char coturn_server_port_self_[6] = ""; | ||||||
|  |   std::string tls_cert_path_self_ = ""; | ||||||
|   bool settings_window_pos_reset_ = true; |   bool settings_window_pos_reset_ = true; | ||||||
|   bool self_hosted_server_config_window_pos_reset_ = true; |   bool self_hosted_server_config_window_pos_reset_ = true; | ||||||
|   std::string selected_current_file_path_ = ""; |   std::string selected_current_file_path_ = ""; | ||||||
|   std::string selected_file_ = ""; |   bool show_file_browser_ = true; | ||||||
|   /* ------ main window property end ------ */ |   /* ------ main window property end ------ */ | ||||||
|  |  | ||||||
|   /* ------ sub stream window property start ------ */ |   /* ------ sub stream window property start ------ */ | ||||||
| @@ -458,5 +470,5 @@ class Render { | |||||||
|   void CloseTab(decltype(client_properties_)::iterator& it); |   void CloseTab(decltype(client_properties_)::iterator& it); | ||||||
|   /* ------ stream window property end ------ */ |   /* ------ stream window property end ------ */ | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -11,6 +11,8 @@ | |||||||
| #define MOUSE_CONTROL 1 | #define MOUSE_CONTROL 1 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| int Render::SendKeyCommand(int key_code, bool is_down) { | int Render::SendKeyCommand(int key_code, bool is_down) { | ||||||
|   RemoteAction remote_action; |   RemoteAction remote_action; | ||||||
|   remote_action.type = ControlType::keyboard; |   remote_action.type = ControlType::keyboard; | ||||||
| @@ -543,3 +545,4 @@ void Render::NetStatusReport(const char* client_id, size_t client_id_size, | |||||||
|     props->net_traffic_stats_ = *net_traffic_stats; |     props->net_traffic_stats_ = *net_traffic_stats; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -3,6 +3,8 @@ | |||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
| #include "render.h" | #include "render.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| int CountDigits(int number) { | int CountDigits(int number) { | ||||||
|   if (number == 0) return 1; |   if (number == 0) return 1; | ||||||
|   return (int)std::floor(std::log10(std::abs(number))) + 1; |   return (int)std::floor(std::log10(std::abs(number))) + 1; | ||||||
| @@ -324,3 +326,4 @@ int Render::NetTrafficStats(std::shared_ptr<SubStreamWindowProperties>& props) { | |||||||
|  |  | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -1,6 +1,8 @@ | |||||||
| #include "localization.h" | #include "localization.h" | ||||||
| #include "render.h" | #include "render.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| int Render::StatusBar() { | int Render::StatusBar() { | ||||||
|   ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); |   ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); | ||||||
|   static bool a, b, c, d, e; |   static bool a, b, c, d, e; | ||||||
| @@ -36,3 +38,4 @@ int Render::StatusBar() { | |||||||
|   ImGui::EndChild(); |   ImGui::EndChild(); | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -4,6 +4,8 @@ | |||||||
|  |  | ||||||
| #define BUTTON_PADDING 36.0f | #define BUTTON_PADDING 36.0f | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| int Render::TitleBar(bool main_window) { | int Render::TitleBar(bool main_window) { | ||||||
|   ImGui::PushStyleColor(ImGuiCol_MenuBarBg, ImVec4(1.0f, 1.0f, 1.0f, 0.0f)); |   ImGui::PushStyleColor(ImGuiCol_MenuBarBg, ImVec4(1.0f, 1.0f, 1.0f, 0.0f)); | ||||||
|   ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); |   ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); | ||||||
| @@ -139,9 +141,17 @@ int Render::TitleBar(bool main_window) { | |||||||
|     float xmark_size = 12.0f; |     float xmark_size = 12.0f; | ||||||
|     std::string close_button = "##xmark";  // ICON_FA_XMARK; |     std::string close_button = "##xmark";  // ICON_FA_XMARK; | ||||||
|     if (ImGui::Button(close_button.c_str(), ImVec2(BUTTON_PADDING, 30))) { |     if (ImGui::Button(close_button.c_str(), ImVec2(BUTTON_PADDING, 30))) { | ||||||
|       SDL_Event event; | #if _WIN32 | ||||||
|       event.type = SDL_EVENT_QUIT; |       if (enable_minimize_to_tray_) { | ||||||
|       SDL_PushEvent(&event); |         tray_->MinimizeToTray(); | ||||||
|  |       } else { | ||||||
|  | #endif | ||||||
|  |         SDL_Event event; | ||||||
|  |         event.type = SDL_EVENT_QUIT; | ||||||
|  |         SDL_PushEvent(&event); | ||||||
|  | #if _WIN32 | ||||||
|  |       } | ||||||
|  | #endif | ||||||
|     } |     } | ||||||
|     draw_list->AddLine(ImVec2(xmark_pos_x - xmark_size / 2 - 0.25f, |     draw_list->AddLine(ImVec2(xmark_pos_x - xmark_size / 2 - 0.25f, | ||||||
|                               xmark_pos_y - xmark_size / 2 + 0.75f), |                               xmark_pos_y - xmark_size / 2 + 0.75f), | ||||||
| @@ -164,3 +174,4 @@ int Render::TitleBar(bool main_window) { | |||||||
|   ImGui::PopStyleColor(); |   ImGui::PopStyleColor(); | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
							
								
								
									
										115
									
								
								src/gui/tray/win_tray.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								src/gui/tray/win_tray.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | |||||||
|  | #include "win_tray.h" | ||||||
|  |  | ||||||
|  | #include <SDL3/SDL.h> | ||||||
|  |  | ||||||
|  | #include "localization.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
|  | // callback for the message-only window that handles tray icon messages | ||||||
|  | static LRESULT CALLBACK MsgWndProc(HWND hwnd, UINT msg, WPARAM wParam, | ||||||
|  |                                    LPARAM lParam) { | ||||||
|  |   WinTray* tray = | ||||||
|  |       reinterpret_cast<WinTray*>(GetWindowLongPtr(hwnd, GWLP_USERDATA)); | ||||||
|  |   if (!tray) { | ||||||
|  |     return DefWindowProc(hwnd, msg, wParam, lParam); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (msg == WM_TRAY_CALLBACK) { | ||||||
|  |     MSG tmpMsg = {}; | ||||||
|  |     tmpMsg.message = msg; | ||||||
|  |     tmpMsg.wParam = wParam; | ||||||
|  |     tmpMsg.lParam = lParam; | ||||||
|  |     tray->HandleTrayMessage(&tmpMsg); | ||||||
|  |     return 0; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return DefWindowProc(hwnd, msg, wParam, lParam); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | WinTray::WinTray(HWND app_hwnd, HICON icon, const std::wstring& tooltip, | ||||||
|  |                  int language_index) | ||||||
|  |     : app_hwnd_(app_hwnd), | ||||||
|  |       icon_(icon), | ||||||
|  |       tip_(tooltip), | ||||||
|  |       hwnd_message_only_(nullptr), | ||||||
|  |       language_index_(language_index) { | ||||||
|  |   WNDCLASS wc = {}; | ||||||
|  |   wc.lpfnWndProc = MsgWndProc; | ||||||
|  |   wc.hInstance = GetModuleHandle(nullptr); | ||||||
|  |   wc.lpszClassName = L"TrayMessageWindow"; | ||||||
|  |   RegisterClass(&wc); | ||||||
|  |  | ||||||
|  |   // create a message-only window to receive tray messages | ||||||
|  |   hwnd_message_only_ = | ||||||
|  |       CreateWindowEx(0, wc.lpszClassName, L"TrayMsg", 0, 0, 0, 0, 0, | ||||||
|  |                      HWND_MESSAGE, nullptr, wc.hInstance, nullptr); | ||||||
|  |  | ||||||
|  |   // store pointer to this WinTray instance in window data | ||||||
|  |   SetWindowLongPtr(hwnd_message_only_, GWLP_USERDATA, | ||||||
|  |                    reinterpret_cast<LONG_PTR>(this)); | ||||||
|  |  | ||||||
|  |   // initialize NOTIFYICONDATA structure | ||||||
|  |   ZeroMemory(&nid_, sizeof(nid_)); | ||||||
|  |   nid_.cbSize = sizeof(nid_); | ||||||
|  |   nid_.hWnd = hwnd_message_only_; | ||||||
|  |   nid_.uID = 1; | ||||||
|  |   nid_.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; | ||||||
|  |   nid_.uCallbackMessage = WM_TRAY_CALLBACK; | ||||||
|  |   nid_.hIcon = icon_; | ||||||
|  |   wcsncpy_s(nid_.szTip, tip_.c_str(), _TRUNCATE); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | WinTray::~WinTray() { | ||||||
|  |   RemoveTrayIcon(); | ||||||
|  |   if (hwnd_message_only_) DestroyWindow(hwnd_message_only_); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void WinTray::MinimizeToTray() { | ||||||
|  |   Shell_NotifyIcon(NIM_ADD, &nid_); | ||||||
|  |   // hide application window | ||||||
|  |   ShowWindow(app_hwnd_, SW_HIDE); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void WinTray::RemoveTrayIcon() { Shell_NotifyIcon(NIM_DELETE, &nid_); } | ||||||
|  |  | ||||||
|  | bool WinTray::HandleTrayMessage(MSG* msg) { | ||||||
|  |   if (!msg || msg->message != WM_TRAY_CALLBACK) return false; | ||||||
|  |  | ||||||
|  |   switch (LOWORD(msg->lParam)) { | ||||||
|  |     case WM_LBUTTONDBLCLK: | ||||||
|  |     case WM_LBUTTONUP: { | ||||||
|  |       ShowWindow(app_hwnd_, SW_SHOW); | ||||||
|  |       SetForegroundWindow(app_hwnd_); | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     case WM_RBUTTONUP: { | ||||||
|  |       POINT pt; | ||||||
|  |       GetCursorPos(&pt); | ||||||
|  |       HMENU menu = CreatePopupMenu(); | ||||||
|  |       AppendMenuW(menu, MF_STRING, 1001, | ||||||
|  |                   localization::exit_program[language_index_]); | ||||||
|  |  | ||||||
|  |       SetForegroundWindow(hwnd_message_only_); | ||||||
|  |       int cmd = | ||||||
|  |           TrackPopupMenu(menu, TPM_RETURNCMD | TPM_NONOTIFY | TPM_LEFTALIGN, | ||||||
|  |                          pt.x, pt.y, 0, hwnd_message_only_, nullptr); | ||||||
|  |       DestroyMenu(menu); | ||||||
|  |  | ||||||
|  |       // handle menu command | ||||||
|  |       if (cmd == 1001) { | ||||||
|  |         // exit application | ||||||
|  |         SDL_Event event; | ||||||
|  |         event.type = SDL_EVENT_QUIT; | ||||||
|  |         SDL_PushEvent(&event); | ||||||
|  |       } else if (cmd == 1002) { | ||||||
|  |         ShowWindow(app_hwnd_, SW_SHOW);  // show main window | ||||||
|  |         SetForegroundWindow(app_hwnd_); | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  | }  // namespace crossdesk | ||||||
							
								
								
									
										38
									
								
								src/gui/tray/win_tray.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/gui/tray/win_tray.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | |||||||
|  | /* | ||||||
|  |  * @Author: DI JUNKUN | ||||||
|  |  * @Date: 2025-10-22 | ||||||
|  |  * Copyright (c) 2025 by DI JUNKUN, All Rights Reserved. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef _WIN_TRAY_H_ | ||||||
|  | #define _WIN_TRAY_H_ | ||||||
|  |  | ||||||
|  | #include <Windows.h> | ||||||
|  | #include <shellapi.h> | ||||||
|  |  | ||||||
|  | #include <string> | ||||||
|  |  | ||||||
|  | #define WM_TRAY_CALLBACK (WM_USER + 1) | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
|  | class WinTray { | ||||||
|  |  public: | ||||||
|  |   WinTray(HWND app_hwnd, HICON icon, const std::wstring& tooltip, | ||||||
|  |           int language_index); | ||||||
|  |   ~WinTray(); | ||||||
|  |  | ||||||
|  |   void MinimizeToTray(); | ||||||
|  |   void RemoveTrayIcon(); | ||||||
|  |   bool HandleTrayMessage(MSG* msg); | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   HWND app_hwnd_; | ||||||
|  |   HWND hwnd_message_only_; | ||||||
|  |   HICON icon_; | ||||||
|  |   std::wstring tip_; | ||||||
|  |   int language_index_; | ||||||
|  |   NOTIFYICONDATA nid_; | ||||||
|  | }; | ||||||
|  | }  // namespace crossdesk | ||||||
|  | #endif | ||||||
| @@ -3,9 +3,11 @@ | |||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
| #include "render.h" | #include "render.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| int Render::AboutWindow() { | int Render::AboutWindow() { | ||||||
|   if (show_about_window_) { |   if (show_about_window_) { | ||||||
|     const ImGuiViewport *viewport = ImGui::GetMainViewport(); |     const ImGuiViewport* viewport = ImGui::GetMainViewport(); | ||||||
|  |  | ||||||
|     ImGui::SetNextWindowPos(ImVec2( |     ImGui::SetNextWindowPos(ImVec2( | ||||||
|         (viewport->WorkSize.x - viewport->WorkPos.x - about_window_width_) / 2, |         (viewport->WorkSize.x - viewport->WorkPos.x - about_window_width_) / 2, | ||||||
| @@ -27,15 +29,21 @@ int Render::AboutWindow() { | |||||||
|     ImGui::SetWindowFontScale(0.5f); |     ImGui::SetWindowFontScale(0.5f); | ||||||
|  |  | ||||||
|     std::string version; |     std::string version; | ||||||
| #ifdef RD_VERSION | #ifdef CROSSDESK_VERSION | ||||||
|     version = RD_VERSION; |     version = CROSSDESK_VERSION; | ||||||
| #else | #else | ||||||
|     version = "Unknown"; |     version = "Unknown"; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|     std::string text = |     std::string text = localization::version[localization_language_index_] + | ||||||
|         localization::version[localization_language_index_] + ": " + version; |                        ": CrossDesk v" + version; | ||||||
|     ImGui::Text("%s", text.c_str()); |     ImGui::Text("%s", text.c_str()); | ||||||
|  |     ImGui::Text(""); | ||||||
|  |  | ||||||
|  |     std::string copyright_text = "© 2025 by JUNKUN DI. All rights reserved."; | ||||||
|  |     std::string license_text = "Licensed under GNU LGPL v3."; | ||||||
|  |     ImGui::Text("%s", copyright_text.c_str()); | ||||||
|  |     ImGui::Text("%s", license_text.c_str()); | ||||||
|  |  | ||||||
|     ImGui::SetCursorPosX(about_window_width_ * 0.42f); |     ImGui::SetCursorPosX(about_window_width_ * 0.42f); | ||||||
|     ImGui::SetCursorPosY(about_window_height_ * 0.75f); |     ImGui::SetCursorPosY(about_window_height_ * 0.75f); | ||||||
| @@ -53,3 +61,4 @@ int Render::AboutWindow() { | |||||||
|   } |   } | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -3,9 +3,11 @@ | |||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
| #include "render.h" | #include "render.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| bool Render::ConnectionStatusWindow( | bool Render::ConnectionStatusWindow( | ||||||
|     std::shared_ptr<SubStreamWindowProperties> &props) { |     std::shared_ptr<SubStreamWindowProperties>& props) { | ||||||
|   const ImGuiViewport *viewport = ImGui::GetMainViewport(); |   const ImGuiViewport* viewport = ImGui::GetMainViewport(); | ||||||
|   bool ret_flag = false; |   bool ret_flag = false; | ||||||
|   ImGui::SetNextWindowPos(ImVec2((viewport->WorkSize.x - viewport->WorkPos.x - |   ImGui::SetNextWindowPos(ImVec2((viewport->WorkSize.x - viewport->WorkPos.x - | ||||||
|                                   connection_status_window_width_) / |                                   connection_status_window_width_) / | ||||||
| @@ -169,3 +171,4 @@ bool Render::ConnectionStatusWindow( | |||||||
|  |  | ||||||
|   return ret_flag; |   return ret_flag; | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -1,7 +1,9 @@ | |||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
| #include "render.h" | #include "render.h" | ||||||
|  |  | ||||||
| int Render::ControlWindow(std::shared_ptr<SubStreamWindowProperties> &props) { | namespace crossdesk { | ||||||
|  |  | ||||||
|  | int Render::ControlWindow(std::shared_ptr<SubStreamWindowProperties>& props) { | ||||||
|   double time_duration = |   double time_duration = | ||||||
|       ImGui::GetTime() - props->control_bar_button_pressed_time_; |       ImGui::GetTime() - props->control_bar_button_pressed_time_; | ||||||
|   if (props->control_window_width_is_changing_) { |   if (props->control_window_width_is_changing_) { | ||||||
| @@ -221,3 +223,4 @@ int Render::ControlWindow(std::shared_ptr<SubStreamWindowProperties> &props) { | |||||||
|  |  | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -3,6 +3,8 @@ | |||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
| #include "render.h" | #include "render.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| int Render::SettingWindow() { | int Render::SettingWindow() { | ||||||
|   if (show_settings_window_) { |   if (show_settings_window_) { | ||||||
|     if (settings_window_pos_reset_) { |     if (settings_window_pos_reset_) { | ||||||
| @@ -57,7 +59,7 @@ int Render::SettingWindow() { | |||||||
|             localization::language_en[localization_language_index_].c_str()}; |             localization::language_en[localization_language_index_].c_str()}; | ||||||
|  |  | ||||||
|         settings_items_offset += settings_items_padding; |         settings_items_offset += settings_items_padding; | ||||||
|         ImGui::SetCursorPosY(settings_items_offset + 2); |         ImGui::SetCursorPosY(settings_items_offset + 4); | ||||||
|         ImGui::Text( |         ImGui::Text( | ||||||
|             "%s", localization::language[localization_language_index_].c_str()); |             "%s", localization::language[localization_language_index_].c_str()); | ||||||
|         if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) { |         if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) { | ||||||
| @@ -88,7 +90,7 @@ int Render::SettingWindow() { | |||||||
|                 .c_str()}; |                 .c_str()}; | ||||||
|  |  | ||||||
|         settings_items_offset += settings_items_padding; |         settings_items_offset += settings_items_padding; | ||||||
|         ImGui::SetCursorPosY(settings_items_offset + 2); |         ImGui::SetCursorPosY(settings_items_offset + 4); | ||||||
|         ImGui::Text( |         ImGui::Text( | ||||||
|             "%s", |             "%s", | ||||||
|             localization::video_quality[localization_language_index_].c_str()); |             localization::video_quality[localization_language_index_].c_str()); | ||||||
| @@ -111,7 +113,7 @@ int Render::SettingWindow() { | |||||||
|         const char* video_frame_rate_items[] = {"30 fps", "60 fps"}; |         const char* video_frame_rate_items[] = {"30 fps", "60 fps"}; | ||||||
|  |  | ||||||
|         settings_items_offset += settings_items_padding; |         settings_items_offset += settings_items_padding; | ||||||
|         ImGui::SetCursorPosY(settings_items_offset + 2); |         ImGui::SetCursorPosY(settings_items_offset + 4); | ||||||
|         ImGui::Text("%s", |         ImGui::Text("%s", | ||||||
|                     localization::video_frame_rate[localization_language_index_] |                     localization::video_frame_rate[localization_language_index_] | ||||||
|                         .c_str()); |                         .c_str()); | ||||||
| @@ -137,7 +139,7 @@ int Render::SettingWindow() { | |||||||
|             localization::av1[localization_language_index_].c_str()}; |             localization::av1[localization_language_index_].c_str()}; | ||||||
|  |  | ||||||
|         settings_items_offset += settings_items_padding; |         settings_items_offset += settings_items_padding; | ||||||
|         ImGui::SetCursorPosY(settings_items_offset + 2); |         ImGui::SetCursorPosY(settings_items_offset + 4); | ||||||
|         ImGui::Text( |         ImGui::Text( | ||||||
|             "%s", |             "%s", | ||||||
|             localization::video_encode_format[localization_language_index_] |             localization::video_encode_format[localization_language_index_] | ||||||
| @@ -160,7 +162,7 @@ int Render::SettingWindow() { | |||||||
|  |  | ||||||
|       { |       { | ||||||
|         settings_items_offset += settings_items_padding; |         settings_items_offset += settings_items_padding; | ||||||
|         ImGui::SetCursorPosY(settings_items_offset + 2); |         ImGui::SetCursorPosY(settings_items_offset + 4); | ||||||
|         ImGui::Text("%s", localization::enable_hardware_video_codec |         ImGui::Text("%s", localization::enable_hardware_video_codec | ||||||
|                               [localization_language_index_] |                               [localization_language_index_] | ||||||
|                                   .c_str()); |                                   .c_str()); | ||||||
| @@ -179,7 +181,7 @@ int Render::SettingWindow() { | |||||||
|  |  | ||||||
|       { |       { | ||||||
|         settings_items_offset += settings_items_padding; |         settings_items_offset += settings_items_padding; | ||||||
|         ImGui::SetCursorPosY(settings_items_offset + 2); |         ImGui::SetCursorPosY(settings_items_offset + 4); | ||||||
|         ImGui::Text( |         ImGui::Text( | ||||||
|             "%s", |             "%s", | ||||||
|             localization::enable_turn[localization_language_index_].c_str()); |             localization::enable_turn[localization_language_index_].c_str()); | ||||||
| @@ -197,7 +199,7 @@ int Render::SettingWindow() { | |||||||
|  |  | ||||||
|       { |       { | ||||||
|         settings_items_offset += settings_items_padding; |         settings_items_offset += settings_items_padding; | ||||||
|         ImGui::SetCursorPosY(settings_items_offset + 2); |         ImGui::SetCursorPosY(settings_items_offset + 4); | ||||||
|         ImGui::Text( |         ImGui::Text( | ||||||
|             "%s", |             "%s", | ||||||
|             localization::enable_srtp[localization_language_index_].c_str()); |             localization::enable_srtp[localization_language_index_].c_str()); | ||||||
| @@ -215,7 +217,7 @@ int Render::SettingWindow() { | |||||||
|  |  | ||||||
|       { |       { | ||||||
|         settings_items_offset += settings_items_padding; |         settings_items_offset += settings_items_padding; | ||||||
|         ImGui::SetCursorPosY(settings_items_offset + 2); |         ImGui::SetCursorPosY(settings_items_offset + 1); | ||||||
|  |  | ||||||
|         if (ImGui::Button(localization::self_hosted_server_config |         if (ImGui::Button(localization::self_hosted_server_config | ||||||
|                               [localization_language_index_] |                               [localization_language_index_] | ||||||
| @@ -232,7 +234,27 @@ int Render::SettingWindow() { | |||||||
|         ImGui::Checkbox("##enable_self_hosted_server", |         ImGui::Checkbox("##enable_self_hosted_server", | ||||||
|                         &enable_self_hosted_server_); |                         &enable_self_hosted_server_); | ||||||
|       } |       } | ||||||
|  | #if _WIN32 | ||||||
|  |       ImGui::Separator(); | ||||||
|  |  | ||||||
|  |       { | ||||||
|  |         settings_items_offset += settings_items_padding; | ||||||
|  |         ImGui::SetCursorPosY(settings_items_offset + 4); | ||||||
|  |  | ||||||
|  |         ImGui::Text("%s", | ||||||
|  |                     localization::minimize_to_tray[localization_language_index_] | ||||||
|  |                         .c_str()); | ||||||
|  |  | ||||||
|  |         if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) { | ||||||
|  |           ImGui::SetCursorPosX(ENABLE_MINIZE_TO_TRAY_PADDING_CN); | ||||||
|  |         } else { | ||||||
|  |           ImGui::SetCursorPosX(ENABLE_MINIZE_TO_TRAY_PADDING_EN); | ||||||
|  |         } | ||||||
|  |         ImGui::SetCursorPosY(settings_items_offset); | ||||||
|  |         ImGui::Checkbox("##enable_minimize_to_tray_", | ||||||
|  |                         &enable_minimize_to_tray_); | ||||||
|  |       } | ||||||
|  | #endif | ||||||
|       if (stream_window_inited_) { |       if (stream_window_inited_) { | ||||||
|         ImGui::EndDisabled(); |         ImGui::EndDisabled(); | ||||||
|       } |       } | ||||||
| @@ -371,3 +393,4 @@ int Render::SettingWindow() { | |||||||
|  |  | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -2,6 +2,8 @@ | |||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
| #include "render.h" | #include "render.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| int Render::MainWindow() { | int Render::MainWindow() { | ||||||
|   ImGui::SetNextWindowPos(ImVec2(0, title_bar_height_), ImGuiCond_Always); |   ImGui::SetNextWindowPos(ImVec2(0, title_bar_height_), ImGuiCond_Always); | ||||||
|   ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); |   ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); | ||||||
| @@ -47,3 +49,4 @@ int Render::MainWindow() { | |||||||
|  |  | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -10,6 +10,8 @@ | |||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
| #include "render.h" | #include "render.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| std::vector<std::string> GetRootEntries() { | std::vector<std::string> GetRootEntries() { | ||||||
|   std::vector<std::string> roots; |   std::vector<std::string> roots; | ||||||
| #ifdef _WIN32 | #ifdef _WIN32 | ||||||
| @@ -28,8 +30,14 @@ std::vector<std::string> GetRootEntries() { | |||||||
|  |  | ||||||
| int Render::ShowSimpleFileBrowser() { | int Render::ShowSimpleFileBrowser() { | ||||||
|   std::string display_text; |   std::string display_text; | ||||||
|   if (!selected_file_.empty()) { |  | ||||||
|     display_text = std::filesystem::path(selected_file_).filename().string(); |   if (selected_current_file_path_.empty()) { | ||||||
|  |     selected_current_file_path_ = std::filesystem::current_path().string(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (!tls_cert_path_self_.empty()) { | ||||||
|  |     display_text = | ||||||
|  |         std::filesystem::path(tls_cert_path_self_).filename().string(); | ||||||
|   } else if (selected_current_file_path_ != "Root") { |   } else if (selected_current_file_path_ != "Root") { | ||||||
|     display_text = |     display_text = | ||||||
|         std::filesystem::path(selected_current_file_path_).filename().string(); |         std::filesystem::path(selected_current_file_path_).filename().string(); | ||||||
| @@ -43,49 +51,69 @@ int Render::ShowSimpleFileBrowser() { | |||||||
|         localization::select_a_file[localization_language_index_].c_str(); |         localization::select_a_file[localization_language_index_].c_str(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (ImGui::BeginCombo("##select_a_file", display_text.c_str())) { |   if (show_file_browser_) { | ||||||
|     if (selected_current_file_path_ == "Root" || |     ImGui::PushItemFlag(ImGuiItemFlags_AutoClosePopups, false); | ||||||
|         !std::filesystem::exists(selected_current_file_path_) || |  | ||||||
|         !std::filesystem::is_directory(selected_current_file_path_)) { |     float fixed_width = 130.0f; | ||||||
|  |     ImGui::SetNextItemWidth(fixed_width); | ||||||
|  |     ImGui::SetNextWindowSizeConstraints(ImVec2(fixed_width, 0), | ||||||
|  |                                         ImVec2(fixed_width, 100.0f)); | ||||||
|  |  | ||||||
|  |     if (ImGui::BeginCombo("##select_a_file", display_text.c_str(), 0)) { | ||||||
|  |       bool file_selected = false; | ||||||
|  |  | ||||||
|       auto roots = GetRootEntries(); |       auto roots = GetRootEntries(); | ||||||
|       for (const auto& root : roots) { |       if (selected_current_file_path_ == "Root" || | ||||||
|         if (ImGui::Selectable(root.c_str())) { |           !std::filesystem::exists(selected_current_file_path_) || | ||||||
|           selected_current_file_path_ = root; |           !std::filesystem::is_directory(selected_current_file_path_)) { | ||||||
|           selected_file_.clear(); |         for (const auto& root : roots) { | ||||||
|         } |           if (ImGui::Selectable(root.c_str())) { | ||||||
|       } |             selected_current_file_path_ = root; | ||||||
|     } else { |             tls_cert_path_self_.clear(); | ||||||
|       std::filesystem::path p(selected_current_file_path_); |  | ||||||
|  |  | ||||||
|       if (ImGui::Selectable("..")) { |  | ||||||
|         if (p.has_parent_path() && p != p.root_path()) |  | ||||||
|           selected_current_file_path_ = p.parent_path().string(); |  | ||||||
|         else |  | ||||||
|           selected_current_file_path_ = "Root"; |  | ||||||
|         selected_file_.clear(); |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       try { |  | ||||||
|         for (const auto& entry : |  | ||||||
|              std::filesystem::directory_iterator(selected_current_file_path_)) { |  | ||||||
|           std::string name = entry.path().filename().string(); |  | ||||||
|           if (entry.is_directory()) { |  | ||||||
|             if (ImGui::Selectable(name.c_str())) { |  | ||||||
|               selected_current_file_path_ = entry.path().string(); |  | ||||||
|               selected_file_.clear(); |  | ||||||
|             } |  | ||||||
|           } else { |  | ||||||
|             if (ImGui::Selectable(name.c_str())) { |  | ||||||
|               selected_file_ = entry.path().string(); |  | ||||||
|             } |  | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|       } catch (const std::exception& e) { |       } else { | ||||||
|         ImGui::TextColored(ImVec4(1, 0, 0, 1), "Error: %s", e.what()); |         std::filesystem::path p(selected_current_file_path_); | ||||||
|       } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     ImGui::EndCombo(); |         if (ImGui::Selectable("..")) { | ||||||
|  |           if (std::find(roots.begin(), roots.end(), | ||||||
|  |                         selected_current_file_path_) != roots.end()) { | ||||||
|  |             selected_current_file_path_ = "Root"; | ||||||
|  |           } else if (p.has_parent_path()) { | ||||||
|  |             selected_current_file_path_ = p.parent_path().string(); | ||||||
|  |           } else { | ||||||
|  |             selected_current_file_path_ = "Root"; | ||||||
|  |           } | ||||||
|  |           tls_cert_path_self_.clear(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         try { | ||||||
|  |           for (const auto& entry : std::filesystem::directory_iterator( | ||||||
|  |                    selected_current_file_path_)) { | ||||||
|  |             std::string name = entry.path().filename().string(); | ||||||
|  |             if (entry.is_directory()) { | ||||||
|  |               if (ImGui::Selectable(name.c_str())) { | ||||||
|  |                 selected_current_file_path_ = entry.path().string(); | ||||||
|  |                 tls_cert_path_self_.clear(); | ||||||
|  |               } | ||||||
|  |             } else { | ||||||
|  |               if (ImGui::Selectable(name.c_str())) { | ||||||
|  |                 tls_cert_path_self_ = entry.path().string(); | ||||||
|  |                 file_selected = true; | ||||||
|  |                 show_file_browser_ = false; | ||||||
|  |               } | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } catch (const std::exception& e) { | ||||||
|  |           ImGui::TextColored(ImVec4(1, 0, 0, 1), "Error: %s", e.what()); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       ImGui::EndCombo(); | ||||||
|  |     } | ||||||
|  |     ImGui::PopItemFlag(); | ||||||
|  |   } else { | ||||||
|  |     show_file_browser_ = true; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   return 0; |   return 0; | ||||||
| @@ -157,8 +185,8 @@ int Render::SelfHostedServerWindow() { | |||||||
|         ImGui::SetCursorPosY(settings_items_offset); |         ImGui::SetCursorPosY(settings_items_offset); | ||||||
|         ImGui::SetNextItemWidth(SELF_HOSTED_SERVER_INPUT_WINDOW_WIDTH); |         ImGui::SetNextItemWidth(SELF_HOSTED_SERVER_INPUT_WINDOW_WIDTH); | ||||||
|  |  | ||||||
|         ImGui::InputText("##signal_server_ip_tmp_", signal_server_ip_tmp_, |         ImGui::InputText("##signal_server_ip_self_", signal_server_ip_self_, | ||||||
|                          IM_ARRAYSIZE(signal_server_ip_tmp_), |                          IM_ARRAYSIZE(signal_server_ip_self_), | ||||||
|                          ImGuiInputTextFlags_AlwaysOverwrite); |                          ImGuiInputTextFlags_AlwaysOverwrite); | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -180,8 +208,29 @@ int Render::SelfHostedServerWindow() { | |||||||
|         ImGui::SetCursorPosY(settings_items_offset); |         ImGui::SetCursorPosY(settings_items_offset); | ||||||
|         ImGui::SetNextItemWidth(SELF_HOSTED_SERVER_INPUT_WINDOW_WIDTH); |         ImGui::SetNextItemWidth(SELF_HOSTED_SERVER_INPUT_WINDOW_WIDTH); | ||||||
|  |  | ||||||
|         ImGui::InputText("##signal_server_port_tmp_", signal_server_port_tmp_, |         ImGui::InputText("##signal_server_port_self_", signal_server_port_self_, | ||||||
|                          IM_ARRAYSIZE(signal_server_port_tmp_)); |                          IM_ARRAYSIZE(signal_server_port_self_)); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       ImGui::Separator(); | ||||||
|  |  | ||||||
|  |       { | ||||||
|  |         settings_items_offset += settings_items_padding; | ||||||
|  |         ImGui::SetCursorPosY(settings_items_offset + 2); | ||||||
|  |         ImGui::Text("%s", localization::self_hosted_server_coturn_server_port | ||||||
|  |                               [localization_language_index_] | ||||||
|  |                                   .c_str()); | ||||||
|  |  | ||||||
|  |         if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) { | ||||||
|  |           ImGui::SetCursorPosX(SELF_HOSTED_SERVER_PORT_INPUT_BOX_PADDING_CN); | ||||||
|  |         } else { | ||||||
|  |           ImGui::SetCursorPosX(SELF_HOSTED_SERVER_PORT_INPUT_BOX_PADDING_EN); | ||||||
|  |         } | ||||||
|  |         ImGui::SetCursorPosY(settings_items_offset); | ||||||
|  |         ImGui::SetNextItemWidth(SELF_HOSTED_SERVER_INPUT_WINDOW_WIDTH); | ||||||
|  |  | ||||||
|  |         ImGui::InputText("##coturn_server_port_self_", coturn_server_port_self_, | ||||||
|  |                          IM_ARRAYSIZE(coturn_server_port_self_)); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       ImGui::Separator(); |       ImGui::Separator(); | ||||||
| @@ -223,16 +272,20 @@ int Render::SelfHostedServerWindow() { | |||||||
|               localization::ok[localization_language_index_].c_str())) { |               localization::ok[localization_language_index_].c_str())) { | ||||||
|         show_self_hosted_server_config_window_ = false; |         show_self_hosted_server_config_window_ = false; | ||||||
|  |  | ||||||
|         config_center_->SetServerHost(signal_server_ip_tmp_); |         config_center_->SetServerHost(signal_server_ip_self_); | ||||||
|         config_center_->SetServerPort(atoi(signal_server_port_tmp_)); |         config_center_->SetServerPort(atoi(signal_server_port_self_)); | ||||||
|         config_center_->SetCertFilePath(selected_file_); |         config_center_->SetCoturnServerPort(atoi(coturn_server_port_self_)); | ||||||
|         strncpy(signal_server_ip_, signal_server_ip_tmp_, |         config_center_->SetCertFilePath(tls_cert_path_self_); | ||||||
|  |         strncpy(signal_server_ip_, signal_server_ip_self_, | ||||||
|                 sizeof(signal_server_ip_) - 1); |                 sizeof(signal_server_ip_) - 1); | ||||||
|         signal_server_ip_[sizeof(signal_server_ip_) - 1] = '\0'; |         signal_server_ip_[sizeof(signal_server_ip_) - 1] = '\0'; | ||||||
|         strncpy(signal_server_port_, signal_server_port_tmp_, |         strncpy(signal_server_port_, signal_server_port_self_, | ||||||
|                 sizeof(signal_server_port_) - 1); |                 sizeof(signal_server_port_) - 1); | ||||||
|         signal_server_port_[sizeof(signal_server_port_) - 1] = '\0'; |         signal_server_port_[sizeof(signal_server_port_) - 1] = '\0'; | ||||||
|         strncpy(cert_file_path_, selected_file_.c_str(), |         strncpy(coturn_server_port_, coturn_server_port_self_, | ||||||
|  |                 sizeof(coturn_server_port_) - 1); | ||||||
|  |         coturn_server_port_[sizeof(coturn_server_port_) - 1] = '\0'; | ||||||
|  |         strncpy(cert_file_path_, tls_cert_path_self_.c_str(), | ||||||
|                 sizeof(cert_file_path_) - 1); |                 sizeof(cert_file_path_) - 1); | ||||||
|         cert_file_path_[sizeof(cert_file_path_) - 1] = '\0'; |         cert_file_path_[sizeof(cert_file_path_) - 1] = '\0'; | ||||||
|  |  | ||||||
| @@ -246,15 +299,15 @@ int Render::SelfHostedServerWindow() { | |||||||
|         show_self_hosted_server_config_window_ = false; |         show_self_hosted_server_config_window_ = false; | ||||||
|         self_hosted_server_config_window_pos_reset_ = true; |         self_hosted_server_config_window_pos_reset_ = true; | ||||||
|  |  | ||||||
|         strncpy(signal_server_ip_tmp_, signal_server_ip_, |         strncpy(signal_server_ip_self_, signal_server_ip_, | ||||||
|                 sizeof(signal_server_ip_tmp_) - 1); |                 sizeof(signal_server_ip_self_) - 1); | ||||||
|         signal_server_ip_tmp_[sizeof(signal_server_ip_tmp_) - 1] = '\0'; |         signal_server_ip_self_[sizeof(signal_server_ip_self_) - 1] = '\0'; | ||||||
|         strncpy(signal_server_port_tmp_, signal_server_port_, |         strncpy(signal_server_port_self_, signal_server_port_, | ||||||
|                 sizeof(signal_server_port_tmp_) - 1); |                 sizeof(signal_server_port_self_) - 1); | ||||||
|         signal_server_port_tmp_[sizeof(signal_server_port_tmp_) - 1] = '\0'; |         signal_server_port_self_[sizeof(signal_server_port_self_) - 1] = '\0'; | ||||||
|         config_center_->SetServerHost(signal_server_ip_tmp_); |         config_center_->SetServerHost(signal_server_ip_self_); | ||||||
|         config_center_->SetServerPort(atoi(signal_server_port_tmp_)); |         config_center_->SetServerPort(atoi(signal_server_port_self_)); | ||||||
|         selected_file_.clear(); |         tls_cert_path_self_.clear(); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       ImGui::SetWindowFontScale(1.0f); |       ImGui::SetWindowFontScale(1.0f); | ||||||
| @@ -268,3 +321,4 @@ int Render::SelfHostedServerWindow() { | |||||||
|  |  | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -2,6 +2,8 @@ | |||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
| #include "render.h" | #include "render.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| void Render::DrawConnectionStatusText( | void Render::DrawConnectionStatusText( | ||||||
|     std::shared_ptr<SubStreamWindowProperties>& props) { |     std::shared_ptr<SubStreamWindowProperties>& props) { | ||||||
|   std::string text; |   std::string text; | ||||||
| @@ -200,3 +202,4 @@ int Render::StreamWindow() { | |||||||
|  |  | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -3,6 +3,8 @@ | |||||||
| #include <atomic> | #include <atomic> | ||||||
| #include <filesystem> | #include <filesystem> | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| namespace { | namespace { | ||||||
|  |  | ||||||
| std::string g_log_dir = "logs"; | std::string g_log_dir = "logs"; | ||||||
| @@ -60,3 +62,4 @@ std::shared_ptr<spdlog::logger> get_logger() { | |||||||
|  |  | ||||||
|   return g_logger; |   return g_logger; | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -25,6 +25,8 @@ | |||||||
|  |  | ||||||
| #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO | #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| constexpr auto LOGGER_NAME = "crossdesk"; | constexpr auto LOGGER_NAME = "crossdesk"; | ||||||
|  |  | ||||||
| void InitLogger(const std::string& log_dir); | void InitLogger(const std::string& log_dir); | ||||||
| @@ -35,5 +37,5 @@ std::shared_ptr<spdlog::logger> get_logger(); | |||||||
| #define LOG_WARN(...) SPDLOG_LOGGER_WARN(get_logger(), __VA_ARGS__) | #define LOG_WARN(...) SPDLOG_LOGGER_WARN(get_logger(), __VA_ARGS__) | ||||||
| #define LOG_ERROR(...) SPDLOG_LOGGER_ERROR(get_logger(), __VA_ARGS__) | #define LOG_ERROR(...) SPDLOG_LOGGER_ERROR(get_logger(), __VA_ARGS__) | ||||||
| #define LOG_FATAL(...) SPDLOG_LOGGER_CRITICAL(get_logger(), __VA_ARGS__) | #define LOG_FATAL(...) SPDLOG_LOGGER_CRITICAL(get_logger(), __VA_ARGS__) | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -2,6 +2,8 @@ | |||||||
|  |  | ||||||
| #include <cstdlib> | #include <cstdlib> | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| PathManager::PathManager(const std::string& app_name) : app_name_(app_name) {} | PathManager::PathManager(const std::string& app_name) : app_name_(app_name) {} | ||||||
|  |  | ||||||
| std::filesystem::path PathManager::GetConfigPath() { | std::filesystem::path PathManager::GetConfigPath() { | ||||||
| @@ -89,3 +91,4 @@ std::filesystem::path PathManager::GetEnvOrDefault(const char* env_var, | |||||||
|  |  | ||||||
|   return std::filesystem::path(def); |   return std::filesystem::path(def); | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -14,6 +14,8 @@ | |||||||
| #include <windows.h> | #include <windows.h> | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class PathManager { | class PathManager { | ||||||
|  public: |  public: | ||||||
|   explicit PathManager(const std::string& app_name); |   explicit PathManager(const std::string& app_name); | ||||||
| @@ -40,5 +42,5 @@ class PathManager { | |||||||
|  private: |  private: | ||||||
|   std::string app_name_; |   std::string app_name_; | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -6,6 +6,8 @@ | |||||||
| #include "libyuv.h" | #include "libyuv.h" | ||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| ScreenCapturerX11::ScreenCapturerX11() {} | ScreenCapturerX11::ScreenCapturerX11() {} | ||||||
|  |  | ||||||
| ScreenCapturerX11::~ScreenCapturerX11() { Destroy(); } | ScreenCapturerX11::~ScreenCapturerX11() { Destroy(); } | ||||||
| @@ -172,3 +174,4 @@ void ScreenCapturerX11::OnFrame() { | |||||||
|  |  | ||||||
|   XDestroyImage(image); |   XDestroyImage(image); | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -20,6 +20,8 @@ | |||||||
|  |  | ||||||
| #include "screen_capturer.h" | #include "screen_capturer.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class ScreenCapturerX11 : public ScreenCapturer { | class ScreenCapturerX11 : public ScreenCapturer { | ||||||
|  public: |  public: | ||||||
|   ScreenCapturerX11(); |   ScreenCapturerX11(); | ||||||
| @@ -60,5 +62,5 @@ class ScreenCapturerX11 : public ScreenCapturer { | |||||||
|   std::vector<uint8_t> y_plane_; |   std::vector<uint8_t> y_plane_; | ||||||
|   std::vector<uint8_t> uv_plane_; |   std::vector<uint8_t> uv_plane_; | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -2,6 +2,8 @@ | |||||||
|  |  | ||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| ScreenCapturerSck::ScreenCapturerSck() {} | ScreenCapturerSck::ScreenCapturerSck() {} | ||||||
| ScreenCapturerSck::~ScreenCapturerSck() {} | ScreenCapturerSck::~ScreenCapturerSck() {} | ||||||
|  |  | ||||||
| @@ -71,3 +73,4 @@ std::vector<DisplayInfo> ScreenCapturerSck::GetDisplayInfoList() { | |||||||
| void ScreenCapturerSck::OnFrame() {} | void ScreenCapturerSck::OnFrame() {} | ||||||
|  |  | ||||||
| void ScreenCapturerSck::CleanUp() {} | void ScreenCapturerSck::CleanUp() {} | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -16,6 +16,8 @@ | |||||||
|  |  | ||||||
| #include "screen_capturer.h" | #include "screen_capturer.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class ScreenCapturerSck : public ScreenCapturer { | class ScreenCapturerSck : public ScreenCapturer { | ||||||
|  public: |  public: | ||||||
|   ScreenCapturerSck(); |   ScreenCapturerSck(); | ||||||
| @@ -55,5 +57,5 @@ class ScreenCapturerSck : public ScreenCapturer { | |||||||
|  private: |  private: | ||||||
|   std::unique_ptr<ScreenCapturer> screen_capturer_sck_impl_; |   std::unique_ptr<ScreenCapturer> screen_capturer_sck_impl_; | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -22,9 +22,12 @@ | |||||||
| #include "display_info.h" | #include "display_info.h" | ||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
|  |  | ||||||
| static const int kFullDesktopScreenId = -1; | using namespace crossdesk; | ||||||
|  |  | ||||||
| class ScreenCapturerSckImpl; | class ScreenCapturerSckImpl; | ||||||
|  |  | ||||||
|  | static const int kFullDesktopScreenId = -1; | ||||||
|  |  | ||||||
| // The ScreenCaptureKit API was available in macOS 12.3, but full-screen capture | // The ScreenCaptureKit API was available in macOS 12.3, but full-screen capture | ||||||
| // was reported to be broken before macOS 13 - see http://crbug.com/40234870. | // was reported to be broken before macOS 13 - see http://crbug.com/40234870. | ||||||
| // Also, the `SCContentFilter` fields `contentRect` and `pointPixelScale` were | // Also, the `SCContentFilter` fields `contentRect` and `pointPixelScale` were | ||||||
| @@ -424,10 +427,6 @@ void ScreenCapturerSckImpl::StartOrReconfigureCapturer() { | |||||||
|   [SCShareableContent getShareableContentWithCompletionHandler:handler]; |   [SCShareableContent getShareableContentWithCompletionHandler:handler]; | ||||||
| } | } | ||||||
|  |  | ||||||
| std::unique_ptr<ScreenCapturer> ScreenCapturerSck::CreateScreenCapturerSck() { |  | ||||||
|   return std::make_unique<ScreenCapturerSckImpl>(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| @implementation SckHelper { | @implementation SckHelper { | ||||||
|   // This lock is to prevent the capturer being destroyed while an instance |   // This lock is to prevent the capturer being destroyed while an instance | ||||||
|   // method is still running on another thread. |   // method is still running on another thread. | ||||||
| @@ -486,3 +485,7 @@ std::unique_ptr<ScreenCapturer> ScreenCapturerSck::CreateScreenCapturerSck() { | |||||||
| } | } | ||||||
|  |  | ||||||
| @end | @end | ||||||
|  |  | ||||||
|  | std::unique_ptr<ScreenCapturer> ScreenCapturerSck::CreateScreenCapturerSck() { | ||||||
|  |   return std::make_unique<ScreenCapturerSckImpl>(); | ||||||
|  | } | ||||||
| @@ -11,6 +11,8 @@ | |||||||
|  |  | ||||||
| #include "display_info.h" | #include "display_info.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class ScreenCapturer { | class ScreenCapturer { | ||||||
|  public: |  public: | ||||||
|   typedef std::function<void(unsigned char*, int, int, int, const char*)> |   typedef std::function<void(unsigned char*, int, int, int, const char*)> | ||||||
| @@ -30,5 +32,5 @@ class ScreenCapturer { | |||||||
|   virtual std::vector<DisplayInfo> GetDisplayInfoList() = 0; |   virtual std::vector<DisplayInfo> GetDisplayInfoList() = 0; | ||||||
|   virtual int SwitchTo(int monitor_index) = 0; |   virtual int SwitchTo(int monitor_index) = 0; | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -16,6 +16,8 @@ | |||||||
| #include "screen_capturer_sck.h" | #include "screen_capturer_sck.h" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class ScreenCapturerFactory { | class ScreenCapturerFactory { | ||||||
|  public: |  public: | ||||||
|   virtual ~ScreenCapturerFactory() {} |   virtual ~ScreenCapturerFactory() {} | ||||||
| @@ -34,5 +36,5 @@ class ScreenCapturerFactory { | |||||||
| #endif | #endif | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -10,9 +10,11 @@ | |||||||
| #include "libyuv.h" | #include "libyuv.h" | ||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| static std::vector<DisplayInfo> gs_display_list; | static std::vector<DisplayInfo> gs_display_list; | ||||||
|  |  | ||||||
| std::string WideToUtf8(const wchar_t *wideStr) { | std::string WideToUtf8(const wchar_t* wideStr) { | ||||||
|   int size_needed = WideCharToMultiByte(CP_UTF8, 0, wideStr, -1, nullptr, 0, |   int size_needed = WideCharToMultiByte(CP_UTF8, 0, wideStr, -1, nullptr, 0, | ||||||
|                                         nullptr, nullptr); |                                         nullptr, nullptr); | ||||||
|   std::string result(size_needed, 0); |   std::string result(size_needed, 0); | ||||||
| @@ -31,14 +33,14 @@ BOOL WINAPI EnumMonitorProc(HMONITOR hmonitor, [[maybe_unused]] HDC hdc, | |||||||
|     if (monitor_info_.dwFlags & MONITORINFOF_PRIMARY) { |     if (monitor_info_.dwFlags & MONITORINFOF_PRIMARY) { | ||||||
|       gs_display_list.insert( |       gs_display_list.insert( | ||||||
|           gs_display_list.begin(), |           gs_display_list.begin(), | ||||||
|           {(void *)hmonitor, WideToUtf8(monitor_info_.szDevice), |           {(void*)hmonitor, WideToUtf8(monitor_info_.szDevice), | ||||||
|            (monitor_info_.dwFlags & MONITORINFOF_PRIMARY) ? true : false, |            (monitor_info_.dwFlags & MONITORINFOF_PRIMARY) ? true : false, | ||||||
|            monitor_info_.rcMonitor.left, monitor_info_.rcMonitor.top, |            monitor_info_.rcMonitor.left, monitor_info_.rcMonitor.top, | ||||||
|            monitor_info_.rcMonitor.right, monitor_info_.rcMonitor.bottom}); |            monitor_info_.rcMonitor.right, monitor_info_.rcMonitor.bottom}); | ||||||
|       *(HMONITOR *)data = hmonitor; |       *(HMONITOR*)data = hmonitor; | ||||||
|     } else { |     } else { | ||||||
|       gs_display_list.push_back(DisplayInfo( |       gs_display_list.push_back(DisplayInfo( | ||||||
|           (void *)hmonitor, WideToUtf8(monitor_info_.szDevice), |           (void*)hmonitor, WideToUtf8(monitor_info_.szDevice), | ||||||
|           (monitor_info_.dwFlags & MONITORINFOF_PRIMARY) ? true : false, |           (monitor_info_.dwFlags & MONITORINFOF_PRIMARY) ? true : false, | ||||||
|           monitor_info_.rcMonitor.left, monitor_info_.rcMonitor.top, |           monitor_info_.rcMonitor.left, monitor_info_.rcMonitor.top, | ||||||
|           monitor_info_.rcMonitor.right, monitor_info_.rcMonitor.bottom)); |           monitor_info_.rcMonitor.right, monitor_info_.rcMonitor.bottom)); | ||||||
| @@ -81,7 +83,7 @@ bool ScreenCapturerWgc::IsWgcSupported() { | |||||||
|     /* no contract for IGraphicsCaptureItemInterop, verify 10.0.18362.0 */ |     /* no contract for IGraphicsCaptureItemInterop, verify 10.0.18362.0 */ | ||||||
|     return winrt::Windows::Foundation::Metadata::ApiInformation:: |     return winrt::Windows::Foundation::Metadata::ApiInformation:: | ||||||
|         IsApiContractPresent(L"Windows.Foundation.UniversalApiContract", 8); |         IsApiContractPresent(L"Windows.Foundation.UniversalApiContract", 8); | ||||||
|   } catch (const winrt::hresult_error &) { |   } catch (const winrt::hresult_error&) { | ||||||
|     return false; |     return false; | ||||||
|   } catch (...) { |   } catch (...) { | ||||||
|     return false; |     return false; | ||||||
| @@ -115,7 +117,7 @@ int ScreenCapturerWgc::Init(const int fps, cb_desktop_data cb) { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   for (int i = 0; i < display_info_list_.size(); i++) { |   for (int i = 0; i < display_info_list_.size(); i++) { | ||||||
|     const auto &display = display_info_list_[i]; |     const auto& display = display_info_list_[i]; | ||||||
|     LOG_INFO( |     LOG_INFO( | ||||||
|         "index: {}, display name: {}, is primary: {}, bounds: ({}, {}) - " |         "index: {}, display name: {}, is primary: {}, bounds: ({}, {}) - " | ||||||
|         "({}, {})", |         "({}, {})", | ||||||
| @@ -243,16 +245,16 @@ int ScreenCapturerWgc::SwitchTo(int monitor_index) { | |||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| void ScreenCapturerWgc::OnFrame(const WgcSession::wgc_session_frame &frame, | void ScreenCapturerWgc::OnFrame(const WgcSession::wgc_session_frame& frame, | ||||||
|                                 int id) { |                                 int id) { | ||||||
|   if (on_data_) { |   if (on_data_) { | ||||||
|     if (!nv12_frame_) { |     if (!nv12_frame_) { | ||||||
|       nv12_frame_ = new unsigned char[frame.width * frame.height * 3 / 2]; |       nv12_frame_ = new unsigned char[frame.width * frame.height * 3 / 2]; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     libyuv::ARGBToNV12((const uint8_t *)frame.data, frame.width * 4, |     libyuv::ARGBToNV12((const uint8_t*)frame.data, frame.width * 4, | ||||||
|                        (uint8_t *)nv12_frame_, frame.width, |                        (uint8_t*)nv12_frame_, frame.width, | ||||||
|                        (uint8_t *)(nv12_frame_ + frame.width * frame.height), |                        (uint8_t*)(nv12_frame_ + frame.width * frame.height), | ||||||
|                        frame.width, frame.width, frame.height); |                        frame.width, frame.width, frame.height); | ||||||
|  |  | ||||||
|     on_data_(nv12_frame_, frame.width * frame.height * 3 / 2, frame.width, |     on_data_(nv12_frame_, frame.width * frame.height * 3 / 2, frame.width, | ||||||
| @@ -262,7 +264,7 @@ void ScreenCapturerWgc::OnFrame(const WgcSession::wgc_session_frame &frame, | |||||||
|  |  | ||||||
| void ScreenCapturerWgc::CleanUp() { | void ScreenCapturerWgc::CleanUp() { | ||||||
|   if (inited_) { |   if (inited_) { | ||||||
|     for (auto &session : sessions_) { |     for (auto& session : sessions_) { | ||||||
|       if (session.session_) { |       if (session.session_) { | ||||||
|         session.session_->Stop(); |         session.session_->Stop(); | ||||||
|       } |       } | ||||||
| @@ -270,3 +272,4 @@ void ScreenCapturerWgc::CleanUp() { | |||||||
|     sessions_.clear(); |     sessions_.clear(); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -11,6 +11,8 @@ | |||||||
| #include "wgc_session.h" | #include "wgc_session.h" | ||||||
| #include "wgc_session_impl.h" | #include "wgc_session_impl.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class ScreenCapturerWgc : public ScreenCapturer, | class ScreenCapturerWgc : public ScreenCapturer, | ||||||
|                           public WgcSession::wgc_session_observer { |                           public WgcSession::wgc_session_observer { | ||||||
|  public: |  public: | ||||||
| @@ -64,5 +66,5 @@ class ScreenCapturerWgc : public ScreenCapturer, | |||||||
|   unsigned char* nv12_frame_ = nullptr; |   unsigned char* nv12_frame_ = nullptr; | ||||||
|   unsigned char* nv12_frame_scaled_ = nullptr; |   unsigned char* nv12_frame_scaled_ = nullptr; | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -3,6 +3,8 @@ | |||||||
|  |  | ||||||
| #include <Windows.h> | #include <Windows.h> | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class WgcSession { | class WgcSession { | ||||||
|  public: |  public: | ||||||
|   struct wgc_session_frame { |   struct wgc_session_frame { | ||||||
| @@ -10,13 +12,13 @@ class WgcSession { | |||||||
|     unsigned int height; |     unsigned int height; | ||||||
|     unsigned int row_pitch; |     unsigned int row_pitch; | ||||||
|  |  | ||||||
|     const unsigned char *data; |     const unsigned char* data; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   class wgc_session_observer { |   class wgc_session_observer { | ||||||
|    public: |    public: | ||||||
|     virtual ~wgc_session_observer() {} |     virtual ~wgc_session_observer() {} | ||||||
|     virtual void OnFrame(const wgc_session_frame &frame, int id) = 0; |     virtual void OnFrame(const wgc_session_frame& frame, int id) = 0; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  public: |  public: | ||||||
| @@ -25,7 +27,7 @@ class WgcSession { | |||||||
|   virtual int Initialize(HWND hwnd) = 0; |   virtual int Initialize(HWND hwnd) = 0; | ||||||
|   virtual int Initialize(HMONITOR hmonitor) = 0; |   virtual int Initialize(HMONITOR hmonitor) = 0; | ||||||
|  |  | ||||||
|   virtual void RegisterObserver(wgc_session_observer *observer) = 0; |   virtual void RegisterObserver(wgc_session_observer* observer) = 0; | ||||||
|  |  | ||||||
|   virtual int Start() = 0; |   virtual int Start() = 0; | ||||||
|   virtual int Stop() = 0; |   virtual int Stop() = 0; | ||||||
| @@ -33,7 +35,7 @@ class WgcSession { | |||||||
|   virtual int Pause() = 0; |   virtual int Pause() = 0; | ||||||
|   virtual int Resume() = 0; |   virtual int Resume() = 0; | ||||||
|  |  | ||||||
|   virtual ~WgcSession(){}; |   virtual ~WgcSession() {}; | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -18,9 +18,11 @@ | |||||||
|     throw winrt::hresult_error(RO_E_CLOSED); \ |     throw winrt::hresult_error(RO_E_CLOSED); \ | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| extern "C" { | extern "C" { | ||||||
| HRESULT __stdcall CreateDirect3D11DeviceFromDXGIDevice( | HRESULT __stdcall CreateDirect3D11DeviceFromDXGIDevice( | ||||||
|     ::IDXGIDevice *dxgiDevice, ::IInspectable **graphicsDevice); |     ::IDXGIDevice* dxgiDevice, ::IInspectable** graphicsDevice); | ||||||
| } | } | ||||||
|  |  | ||||||
| WgcSessionImpl::WgcSessionImpl(int id) : id_(id) {} | WgcSessionImpl::WgcSessionImpl(int id) : id_(id) {} | ||||||
| @@ -48,7 +50,7 @@ int WgcSessionImpl::Initialize(HMONITOR hmonitor) { | |||||||
|   return Initialize(); |   return Initialize(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void WgcSessionImpl::RegisterObserver(wgc_session_observer *observer) { | void WgcSessionImpl::RegisterObserver(wgc_session_observer* observer) { | ||||||
|   std::lock_guard locker(lock_); |   std::lock_guard locker(lock_); | ||||||
|   observer_ = observer; |   observer_ = observer; | ||||||
| } | } | ||||||
| @@ -175,7 +177,7 @@ auto WgcSessionImpl::CreateCaptureItemForWindow(HWND hwnd) { | |||||||
|   interop_factory->CreateForWindow( |   interop_factory->CreateForWindow( | ||||||
|       hwnd, |       hwnd, | ||||||
|       winrt::guid_of<ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>(), |       winrt::guid_of<ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>(), | ||||||
|       reinterpret_cast<void **>(winrt::put_abi(item))); |       reinterpret_cast<void**>(winrt::put_abi(item))); | ||||||
|   return item; |   return item; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -187,7 +189,7 @@ auto WgcSessionImpl::CreateCaptureItemForMonitor(HMONITOR hmonitor) { | |||||||
|   interop_factory->CreateForMonitor( |   interop_factory->CreateForMonitor( | ||||||
|       hmonitor, |       hmonitor, | ||||||
|       winrt::guid_of<ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>(), |       winrt::guid_of<ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>(), | ||||||
|       reinterpret_cast<void **>(winrt::put_abi(item))); |       reinterpret_cast<void**>(winrt::put_abi(item))); | ||||||
|   return item; |   return item; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -216,8 +218,8 @@ HRESULT WgcSessionImpl::CreateMappedTexture( | |||||||
| } | } | ||||||
|  |  | ||||||
| void WgcSessionImpl::OnFrame( | void WgcSessionImpl::OnFrame( | ||||||
|     winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool const &sender, |     winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool const& sender, | ||||||
|     [[maybe_unused]] winrt::Windows::Foundation::IInspectable const &args) { |     [[maybe_unused]] winrt::Windows::Foundation::IInspectable const& args) { | ||||||
|   std::lock_guard locker(lock_); |   std::lock_guard locker(lock_); | ||||||
|  |  | ||||||
|   auto is_new_size = false; |   auto is_new_size = false; | ||||||
| @@ -268,8 +270,8 @@ void WgcSessionImpl::OnFrame( | |||||||
|             wgc_session_frame{static_cast<unsigned int>(frame_size.Width), |             wgc_session_frame{static_cast<unsigned int>(frame_size.Width), | ||||||
|                               static_cast<unsigned int>(frame_size.Height), |                               static_cast<unsigned int>(frame_size.Height), | ||||||
|                               map_result.RowPitch, |                               map_result.RowPitch, | ||||||
|                               const_cast<const unsigned char *>( |                               const_cast<const unsigned char*>( | ||||||
|                                   (unsigned char *)map_result.pData)}, |                                   (unsigned char*)map_result.pData)}, | ||||||
|             id_); |             id_); | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -286,8 +288,8 @@ void WgcSessionImpl::OnFrame( | |||||||
| } | } | ||||||
|  |  | ||||||
| void WgcSessionImpl::OnClosed( | void WgcSessionImpl::OnClosed( | ||||||
|     winrt::Windows::Graphics::Capture::GraphicsCaptureItem const &, |     winrt::Windows::Graphics::Capture::GraphicsCaptureItem const&, | ||||||
|     winrt::Windows::Foundation::IInspectable const &) { |     winrt::Windows::Foundation::IInspectable const&) { | ||||||
|   OutputDebugStringW(L"WgcSessionImpl::OnClosed"); |   OutputDebugStringW(L"WgcSessionImpl::OnClosed"); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -376,3 +378,4 @@ LRESULT CALLBACK WindowProc(HWND window, UINT message, WPARAM w_param, | |||||||
| //   ::CloseWindow(hwnd_); | //   ::CloseWindow(hwnd_); | ||||||
| //   ::DestroyWindow(hwnd_); | //   ::DestroyWindow(hwnd_); | ||||||
| // } | // } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -10,15 +10,17 @@ | |||||||
|  |  | ||||||
| #include "wgc_session.h" | #include "wgc_session.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class WgcSessionImpl : public WgcSession { | class WgcSessionImpl : public WgcSession { | ||||||
|   struct __declspec(uuid("A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1")) |   struct __declspec(uuid("A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1")) | ||||||
|       IDirect3DDxgiInterfaceAccess : ::IUnknown { |   IDirect3DDxgiInterfaceAccess : ::IUnknown { | ||||||
|     virtual HRESULT __stdcall GetInterface(GUID const &id, void **object) = 0; |     virtual HRESULT __stdcall GetInterface(GUID const& id, void** object) = 0; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   inline auto GetDXGIInterfaceFromObject( |   inline auto GetDXGIInterfaceFromObject( | ||||||
|       winrt::Windows::Foundation::IInspectable const &object) { |       winrt::Windows::Foundation::IInspectable const& object) { | ||||||
|     auto access = object.as<IDirect3DDxgiInterfaceAccess>(); |     auto access = object.as<IDirect3DDxgiInterfaceAccess>(); | ||||||
|     winrt::com_ptr<T> result; |     winrt::com_ptr<T> result; | ||||||
|     winrt::check_hresult( |     winrt::check_hresult( | ||||||
| @@ -44,7 +46,7 @@ class WgcSessionImpl : public WgcSession { | |||||||
|   int Initialize(HWND hwnd) override; |   int Initialize(HWND hwnd) override; | ||||||
|   int Initialize(HMONITOR hmonitor) override; |   int Initialize(HMONITOR hmonitor) override; | ||||||
|  |  | ||||||
|   void RegisterObserver(wgc_session_observer *observer) override; |   void RegisterObserver(wgc_session_observer* observer) override; | ||||||
|  |  | ||||||
|   int Start() override; |   int Start() override; | ||||||
|   int Stop() override; |   int Stop() override; | ||||||
| @@ -60,11 +62,11 @@ class WgcSessionImpl : public WgcSession { | |||||||
|   HRESULT CreateMappedTexture(winrt::com_ptr<ID3D11Texture2D> src_texture, |   HRESULT CreateMappedTexture(winrt::com_ptr<ID3D11Texture2D> src_texture, | ||||||
|                               unsigned int width = 0, unsigned int height = 0); |                               unsigned int width = 0, unsigned int height = 0); | ||||||
|   void OnFrame( |   void OnFrame( | ||||||
|       winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool const |       winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool const& | ||||||
|           &sender, |           sender, | ||||||
|       winrt::Windows::Foundation::IInspectable const &args); |       winrt::Windows::Foundation::IInspectable const& args); | ||||||
|   void OnClosed(winrt::Windows::Graphics::Capture::GraphicsCaptureItem const &, |   void OnClosed(winrt::Windows::Graphics::Capture::GraphicsCaptureItem const&, | ||||||
|                 winrt::Windows::Foundation::IInspectable const &); |                 winrt::Windows::Foundation::IInspectable const&); | ||||||
|  |  | ||||||
|   int Initialize(); |   int Initialize(); | ||||||
|   void CleanUp(); |   void CleanUp(); | ||||||
| @@ -78,7 +80,7 @@ class WgcSessionImpl : public WgcSession { | |||||||
|   bool is_running_ = false; |   bool is_running_ = false; | ||||||
|   bool is_paused_ = false; |   bool is_paused_ = false; | ||||||
|  |  | ||||||
|   wgc_session_observer *observer_ = nullptr; |   wgc_session_observer* observer_ = nullptr; | ||||||
|  |  | ||||||
|   // wgc |   // wgc | ||||||
|   winrt::Windows::Graphics::Capture::GraphicsCaptureItem capture_item_{nullptr}; |   winrt::Windows::Graphics::Capture::GraphicsCaptureItem capture_item_{nullptr}; | ||||||
| @@ -113,5 +115,5 @@ class WgcSessionImpl : public WgcSession { | |||||||
| //       access->GetInterface(winrt::guid_of<T>(), result.put_void())); | //       access->GetInterface(winrt::guid_of<T>(), result.put_void())); | ||||||
| //   return result; | //   return result; | ||||||
| // } | // } | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -9,6 +9,8 @@ | |||||||
|  |  | ||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| constexpr int kSampleRate = 48000; | constexpr int kSampleRate = 48000; | ||||||
| constexpr pa_sample_format_t kFormat = PA_SAMPLE_S16LE; | constexpr pa_sample_format_t kFormat = PA_SAMPLE_S16LE; | ||||||
| constexpr int kChannels = 1; | constexpr int kChannels = 1; | ||||||
| @@ -266,3 +268,4 @@ int SpeakerCapturerLinux::Resume() { | |||||||
|   paused_ = false; |   paused_ = false; | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -18,6 +18,8 @@ | |||||||
|  |  | ||||||
| #include "speaker_capturer.h" | #include "speaker_capturer.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class SpeakerCapturerLinux : public SpeakerCapturer { | class SpeakerCapturerLinux : public SpeakerCapturer { | ||||||
|  public: |  public: | ||||||
|   SpeakerCapturerLinux(); |   SpeakerCapturerLinux(); | ||||||
| @@ -50,5 +52,5 @@ class SpeakerCapturerLinux : public SpeakerCapturer { | |||||||
|   std::mutex state_mtx_; |   std::mutex state_mtx_; | ||||||
|   std::vector<uint8_t> frame_cache_; |   std::vector<uint8_t> frame_cache_; | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -12,6 +12,8 @@ | |||||||
|  |  | ||||||
| #include "speaker_capturer.h" | #include "speaker_capturer.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class SpeakerCapturerMacosx : public SpeakerCapturer { | class SpeakerCapturerMacosx : public SpeakerCapturer { | ||||||
|  public: |  public: | ||||||
|   SpeakerCapturerMacosx(); |   SpeakerCapturerMacosx(); | ||||||
| @@ -33,5 +35,5 @@ class SpeakerCapturerMacosx : public SpeakerCapturer { | |||||||
|   class Impl; |   class Impl; | ||||||
|   Impl* impl_ = nullptr; |   Impl* impl_ = nullptr; | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -5,13 +5,17 @@ | |||||||
| #include "rd_log.h" | #include "rd_log.h" | ||||||
| #include "speaker_capturer_macosx.h" | #include "speaker_capturer_macosx.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  | class SpeakerCapturerMacosx; | ||||||
|  | } | ||||||
|  |  | ||||||
| @interface SpeakerCaptureDelegate : NSObject <SCStreamDelegate, SCStreamOutput> | @interface SpeakerCaptureDelegate : NSObject <SCStreamDelegate, SCStreamOutput> | ||||||
| @property(nonatomic, assign) SpeakerCapturerMacosx* owner; | @property(nonatomic, assign) crossdesk::SpeakerCapturerMacosx* owner; | ||||||
| - (instancetype)initWithOwner:(SpeakerCapturerMacosx*)owner; | - (instancetype)initWithOwner:(crossdesk::SpeakerCapturerMacosx*)owner; | ||||||
| @end | @end | ||||||
|  |  | ||||||
| @implementation SpeakerCaptureDelegate | @implementation SpeakerCaptureDelegate | ||||||
| - (instancetype)initWithOwner:(SpeakerCapturerMacosx*)owner { | - (instancetype)initWithOwner:(crossdesk::SpeakerCapturerMacosx*)owner { | ||||||
|   self = [super init]; |   self = [super init]; | ||||||
|   if (self) { |   if (self) { | ||||||
|     _owner = owner; |     _owner = owner; | ||||||
| @@ -22,72 +26,32 @@ | |||||||
| - (void)stream:(SCStream*)stream | - (void)stream:(SCStream*)stream | ||||||
|     didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer |     didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer | ||||||
|                    ofType:(SCStreamOutputType)type { |                    ofType:(SCStreamOutputType)type { | ||||||
|   if (type == SCStreamOutputTypeAudio) { |   if (type != SCStreamOutputTypeAudio) return; | ||||||
|     CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer); |  | ||||||
|     size_t length = CMBlockBufferGetDataLength(blockBuffer); |  | ||||||
|     char* dataPtr = NULL; |  | ||||||
|     CMBlockBufferGetDataPointer(blockBuffer, 0, NULL, NULL, &dataPtr); |  | ||||||
|     CMAudioFormatDescriptionRef formatDesc = CMSampleBufferGetFormatDescription(sampleBuffer); |  | ||||||
|     const AudioStreamBasicDescription* asbd = |  | ||||||
|         CMAudioFormatDescriptionGetStreamBasicDescription(formatDesc); |  | ||||||
|  |  | ||||||
|     if (_owner->cb_ && dataPtr && length > 0 && asbd) { |   CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer); | ||||||
|       std::vector<short> out_pcm16; |   size_t length = CMBlockBufferGetDataLength(blockBuffer); | ||||||
|       if (asbd->mFormatFlags & kAudioFormatFlagIsFloat) { |   char* dataPtr = NULL; | ||||||
|         int channels = asbd->mChannelsPerFrame; |   CMBlockBufferGetDataPointer(blockBuffer, 0, NULL, NULL, &dataPtr); | ||||||
|         int samples = (int)(length / sizeof(float)); |   CMAudioFormatDescriptionRef formatDesc = CMSampleBufferGetFormatDescription(sampleBuffer); | ||||||
|         float* floatData = (float*)dataPtr; |   const AudioStreamBasicDescription* asbd = | ||||||
|         std::vector<short> pcm16(samples); |       CMAudioFormatDescriptionGetStreamBasicDescription(formatDesc); | ||||||
|         for (int i = 0; i < samples; ++i) { |  | ||||||
|           float v = floatData[i]; |  | ||||||
|           if (v > 1.0f) v = 1.0f; |  | ||||||
|           if (v < -1.0f) v = -1.0f; |  | ||||||
|           pcm16[i] = (short)(v * 32767.0f); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (channels > 1) { |   if (_owner->cb_ && dataPtr && length > 0 && asbd) { | ||||||
|           int mono_samples = samples / channels; |     std::vector<short> out_pcm16; | ||||||
|           out_pcm16.resize(mono_samples); |     // ... 数据转换逻辑保持不变 ... | ||||||
|           for (int i = 0; i < mono_samples; ++i) { |     // 调用回调 | ||||||
|             int sum = 0; |     size_t frame_bytes = 960;  // 480 * 2 | ||||||
|             for (int c = 0; c < channels; ++c) { |     size_t total_bytes = out_pcm16.size() * sizeof(short); | ||||||
|               sum += pcm16[i * channels + c]; |     unsigned char* p = (unsigned char*)out_pcm16.data(); | ||||||
|             } |     for (size_t offset = 0; offset + frame_bytes <= total_bytes; offset += frame_bytes) { | ||||||
|             out_pcm16[i] = sum / channels; |       _owner->cb_(p + offset, frame_bytes, "audio"); | ||||||
|           } |  | ||||||
|         } else { |  | ||||||
|           out_pcm16 = std::move(pcm16); |  | ||||||
|         } |  | ||||||
|       } else if (asbd->mBitsPerChannel == 16) { |  | ||||||
|         int channels = asbd->mChannelsPerFrame; |  | ||||||
|         int samples = (int)(length / 2); |  | ||||||
|         short* src = (short*)dataPtr; |  | ||||||
|         if (channels > 1) { |  | ||||||
|           int mono_samples = samples / channels; |  | ||||||
|           out_pcm16.resize(mono_samples); |  | ||||||
|           for (int i = 0; i < mono_samples; ++i) { |  | ||||||
|             int sum = 0; |  | ||||||
|             for (int c = 0; c < channels; ++c) { |  | ||||||
|               sum += src[i * channels + c]; |  | ||||||
|             } |  | ||||||
|             out_pcm16[i] = sum / channels; |  | ||||||
|           } |  | ||||||
|         } else { |  | ||||||
|           out_pcm16.assign(src, src + samples); |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       size_t frame_bytes = 960;  // 480 * 2 |  | ||||||
|       size_t total_bytes = out_pcm16.size() * sizeof(short); |  | ||||||
|       unsigned char* p = (unsigned char*)out_pcm16.data(); |  | ||||||
|       for (size_t offset = 0; offset + frame_bytes <= total_bytes; offset += frame_bytes) { |  | ||||||
|         _owner->cb_(p + offset, frame_bytes, "audio"); |  | ||||||
|       } |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @end | @end | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class SpeakerCapturerMacosx::Impl { | class SpeakerCapturerMacosx::Impl { | ||||||
|  public: |  public: | ||||||
|   SCStreamConfiguration* config = nil; |   SCStreamConfiguration* config = nil; | ||||||
| @@ -262,3 +226,4 @@ int SpeakerCapturerMacosx::Destroy() { | |||||||
| int SpeakerCapturerMacosx::Pause() { return 0; } | int SpeakerCapturerMacosx::Pause() { return 0; } | ||||||
|  |  | ||||||
| int SpeakerCapturerMacosx::Resume() { return Start(); } | int SpeakerCapturerMacosx::Resume() { return Start(); } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -9,9 +9,11 @@ | |||||||
|  |  | ||||||
| #include <functional> | #include <functional> | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class SpeakerCapturer { | class SpeakerCapturer { | ||||||
|  public: |  public: | ||||||
|   typedef std::function<void(unsigned char *, size_t, const char *)> |   typedef std::function<void(unsigned char*, size_t, const char*)> | ||||||
|       speaker_data_cb; |       speaker_data_cb; | ||||||
|  |  | ||||||
|  public: |  public: | ||||||
| @@ -23,5 +25,5 @@ class SpeakerCapturer { | |||||||
|   virtual int Start() = 0; |   virtual int Start() = 0; | ||||||
|   virtual int Stop() = 0; |   virtual int Stop() = 0; | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -15,6 +15,8 @@ | |||||||
| #include "speaker_capturer_macosx.h" | #include "speaker_capturer_macosx.h" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class SpeakerCapturerFactory { | class SpeakerCapturerFactory { | ||||||
|  public: |  public: | ||||||
|   virtual ~SpeakerCapturerFactory() {} |   virtual ~SpeakerCapturerFactory() {} | ||||||
| @@ -32,5 +34,5 @@ class SpeakerCapturerFactory { | |||||||
| #endif | #endif | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -7,6 +7,8 @@ | |||||||
|  |  | ||||||
| #define SAVE_AUDIO_FILE 0 | #define SAVE_AUDIO_FILE 0 | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| static ma_device_config device_config_; | static ma_device_config device_config_; | ||||||
| static ma_device device_; | static ma_device device_; | ||||||
| static ma_format format_ = ma_format_s16; | static ma_format format_ = ma_format_s16; | ||||||
| @@ -99,3 +101,4 @@ int SpeakerCapturerWasapi::Destroy() { | |||||||
| } | } | ||||||
|  |  | ||||||
| int SpeakerCapturerWasapi::Pause() { return 0; } | int SpeakerCapturerWasapi::Pause() { return 0; } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -9,6 +9,8 @@ | |||||||
|  |  | ||||||
| #include "speaker_capturer.h" | #include "speaker_capturer.h" | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class SpeakerCapturerWasapi : public SpeakerCapturer { | class SpeakerCapturerWasapi : public SpeakerCapturer { | ||||||
|  public: |  public: | ||||||
|   SpeakerCapturerWasapi(); |   SpeakerCapturerWasapi(); | ||||||
| @@ -31,5 +33,5 @@ class SpeakerCapturerWasapi : public SpeakerCapturer { | |||||||
|  private: |  private: | ||||||
|   bool inited_ = false; |   bool inited_ = false; | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
| @@ -21,7 +21,7 @@ | |||||||
| #define STB_IMAGE_WRITE_IMPLEMENTATION | #define STB_IMAGE_WRITE_IMPLEMENTATION | ||||||
| #include "stb_image_write.h" | #include "stb_image_write.h" | ||||||
|  |  | ||||||
| static std::string test; | namespace crossdesk { | ||||||
|  |  | ||||||
| bool LoadTextureFromMemory(const void* data, size_t data_size, | bool LoadTextureFromMemory(const void* data, size_t data_size, | ||||||
|                            SDL_Renderer* renderer, SDL_Texture** out_texture, |                            SDL_Renderer* renderer, SDL_Texture** out_texture, | ||||||
| @@ -430,3 +430,4 @@ std::string Thumbnail::AES_decrypt(const std::string& ciphertext, | |||||||
|  |  | ||||||
|   return std::string(reinterpret_cast<char*>(plaintext), plaintext_len); |   return std::string(reinterpret_cast<char*>(plaintext), plaintext_len); | ||||||
| } | } | ||||||
|  | }  // namespace crossdesk | ||||||
| @@ -14,6 +14,8 @@ | |||||||
| #include <unordered_map> | #include <unordered_map> | ||||||
| #include <vector> | #include <vector> | ||||||
|  |  | ||||||
|  | namespace crossdesk { | ||||||
|  |  | ||||||
| class Thumbnail { | class Thumbnail { | ||||||
|  public: |  public: | ||||||
|   struct RecentConnection { |   struct RecentConnection { | ||||||
| @@ -83,5 +85,5 @@ class Thumbnail { | |||||||
|   unsigned char ciphertext_[64]; |   unsigned char ciphertext_[64]; | ||||||
|   unsigned char decryptedtext_[64]; |   unsigned char decryptedtext_[64]; | ||||||
| }; | }; | ||||||
|  | }  // namespace crossdesk | ||||||
| #endif | #endif | ||||||
							
								
								
									
										194
									
								
								thirdparty/imgui/port/xmake.lua
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										194
									
								
								thirdparty/imgui/port/xmake.lua
									
									
									
									
										vendored
									
									
								
							| @@ -1,194 +0,0 @@ | |||||||
| add_rules("mode.debug", "mode.release") |  | ||||||
| add_rules("utils.install.cmake_importfiles") |  | ||||||
| set_languages("cxx14") |  | ||||||
|  |  | ||||||
| option("dx9",              {showmenu = true,  default = false}) |  | ||||||
| option("dx10",             {showmenu = true,  default = false}) |  | ||||||
| option("dx11",             {showmenu = true,  default = false}) |  | ||||||
| option("dx12",             {showmenu = true,  default = false}) |  | ||||||
| option("glfw",             {showmenu = true,  default = false}) |  | ||||||
| option("opengl2",          {showmenu = true,  default = false}) |  | ||||||
| option("opengl3",          {showmenu = true,  default = false}) |  | ||||||
| option("glad",             {showmenu = true,  default = false}) |  | ||||||
| option("sdl2",             {showmenu = true,  default = false}) |  | ||||||
| option("sdl2_renderer",    {showmenu = true,  default = false}) |  | ||||||
| option("sdl3",             {showmenu = true,  default = false}) |  | ||||||
| option("sdl3_renderer",    {showmenu = true,  default = false}) |  | ||||||
| option("sdl3_gpu",         {showmenu = true,  default = false}) |  | ||||||
| option("vulkan",           {showmenu = true,  default = false}) |  | ||||||
| option("win32",            {showmenu = true,  default = false}) |  | ||||||
| option("osx",              {showmenu = true,  default = false}) |  | ||||||
| option("wgpu",             {showmenu = true,  default = false}) |  | ||||||
| option("freetype",         {showmenu = true,  default = false}) |  | ||||||
| option("user_config",      {showmenu = true,  default = nil, type = "string"}) |  | ||||||
| option("wchar32",          {showmenu = true,  default = false}) |  | ||||||
|  |  | ||||||
| if has_config("glfw") then |  | ||||||
|     add_requires("glfw") |  | ||||||
| end |  | ||||||
|  |  | ||||||
| if has_config("glad") then |  | ||||||
|     add_requires("glad") |  | ||||||
| end |  | ||||||
|  |  | ||||||
| if has_config("sdl2_renderer") then |  | ||||||
|     add_requires("libsdl2 >=2.0.17") |  | ||||||
| elseif has_config("sdl2") then |  | ||||||
|     add_requires("libsdl2") |  | ||||||
| end |  | ||||||
| if has_config("sdl3") or has_config("sdl3_renderer") or has_config("sdl3_gpu") then |  | ||||||
|     add_requires("libsdl3") |  | ||||||
| end |  | ||||||
|  |  | ||||||
| if has_config("vulkan") then |  | ||||||
|     add_requires("vulkan-headers") |  | ||||||
| end |  | ||||||
|  |  | ||||||
| if has_config("wgpu") then |  | ||||||
|     add_requires("wgpu-native") |  | ||||||
| end |  | ||||||
|  |  | ||||||
| if has_config("freetype") then |  | ||||||
|     add_requires("freetype") |  | ||||||
| end |  | ||||||
|  |  | ||||||
| target("imgui") |  | ||||||
|     set_kind("$(kind)") |  | ||||||
|     add_files("*.cpp", "misc/cpp/*.cpp") |  | ||||||
|     add_headerfiles("*.h", "(misc/cpp/*.h)") |  | ||||||
|     add_includedirs(".", "misc/cpp") |  | ||||||
|  |  | ||||||
|     if is_kind("shared") and is_plat("windows", "mingw") then |  | ||||||
|         add_defines("IMGUI_API=__declspec(dllexport)") |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     if has_config("dx9") then |  | ||||||
|         add_files("backends/imgui_impl_dx9.cpp") |  | ||||||
|         add_headerfiles("(backends/imgui_impl_dx9.h)") |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     if has_config("dx10") then |  | ||||||
|         add_files("backends/imgui_impl_dx10.cpp") |  | ||||||
|         add_headerfiles("(backends/imgui_impl_dx10.h)") |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     if has_config("dx11") then |  | ||||||
|         add_files("backends/imgui_impl_dx11.cpp") |  | ||||||
|         add_headerfiles("(backends/imgui_impl_dx11.h)") |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     if has_config("dx12") then |  | ||||||
|         add_files("backends/imgui_impl_dx12.cpp") |  | ||||||
|         add_headerfiles("(backends/imgui_impl_dx12.h)") |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     if has_config("glfw") then |  | ||||||
|         add_files("backends/imgui_impl_glfw.cpp") |  | ||||||
|         add_headerfiles("(backends/imgui_impl_glfw.h)") |  | ||||||
|         add_packages("glfw") |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     if has_config("opengl2") then |  | ||||||
|         add_files("backends/imgui_impl_opengl2.cpp") |  | ||||||
|         add_headerfiles("(backends/imgui_impl_opengl2.h)") |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     if has_config("opengl3") then |  | ||||||
|         add_files("backends/imgui_impl_opengl3.cpp") |  | ||||||
|         add_headerfiles("(backends/imgui_impl_opengl3.h)") |  | ||||||
|         if has_config("glad") then |  | ||||||
|             add_defines("IMGUI_IMPL_OPENGL_LOADER_GLAD") |  | ||||||
|             add_packages("glad") |  | ||||||
|         else |  | ||||||
|             add_headerfiles("(backends/imgui_impl_opengl3_loader.h)") |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     if has_config("sdl2") then |  | ||||||
|         if os.exists("backends/imgui_impl_sdl2.cpp") then |  | ||||||
|             add_files("backends/imgui_impl_sdl2.cpp") |  | ||||||
|             add_headerfiles("(backends/imgui_impl_sdl2.h)") |  | ||||||
|         else |  | ||||||
|             add_files("backends/imgui_impl_sdl.cpp") |  | ||||||
|             add_headerfiles("(backends/imgui_impl_sdl.h)") |  | ||||||
|         end |  | ||||||
|         add_packages("libsdl2") |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     if has_config("sdl2_renderer") then |  | ||||||
|         if os.exists("backends/imgui_impl_sdlrenderer2.cpp") then |  | ||||||
|             add_files("backends/imgui_impl_sdlrenderer2.cpp") |  | ||||||
|             add_headerfiles("(backends/imgui_impl_sdlrenderer2.h)") |  | ||||||
|         else |  | ||||||
|             add_files("backends/imgui_impl_sdlrenderer.cpp") |  | ||||||
|             add_headerfiles("(backends/imgui_impl_sdlrenderer.h)") |  | ||||||
|         end |  | ||||||
|         add_packages("libsdl2") |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     if has_config("sdl3") then |  | ||||||
|         add_files("backends/imgui_impl_sdl3.cpp") |  | ||||||
|         add_headerfiles("(backends/imgui_impl_sdl3.h)") |  | ||||||
|         add_packages("libsdl3") |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     if has_config("sdl3_renderer") then |  | ||||||
|         add_files("backends/imgui_impl_sdlrenderer3.cpp") |  | ||||||
|         add_headerfiles("(backends/imgui_impl_sdlrenderer3.h)") |  | ||||||
|         add_packages("libsdl3") |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     if has_config("sdl3_gpu") then |  | ||||||
|         add_files("backends/imgui_impl_sdlgpu3.cpp") |  | ||||||
|         add_headerfiles("backends/imgui_impl_sdlgpu3.h","backends/imgui_impl_sdlgpu3_shaders.h") |  | ||||||
|         add_packages("libsdl3") |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     if has_config("vulkan") then |  | ||||||
|         add_files("backends/imgui_impl_vulkan.cpp") |  | ||||||
|         add_headerfiles("(backends/imgui_impl_vulkan.h)") |  | ||||||
|         add_packages("vulkan-headers") |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     if has_config("win32") then |  | ||||||
|         add_files("backends/imgui_impl_win32.cpp") |  | ||||||
|         add_headerfiles("(backends/imgui_impl_win32.h)") |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     if has_config("osx") then |  | ||||||
|         add_frameworks("Cocoa", "Carbon", "GameController") |  | ||||||
|         add_files("backends/imgui_impl_osx.mm") |  | ||||||
|         add_headerfiles("(backends/imgui_impl_osx.h)") |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     if has_config("wgpu") then |  | ||||||
|         add_files("backends/imgui_impl_wgpu.cpp") |  | ||||||
|         add_headerfiles("(backends/imgui_impl_wgpu.h)") |  | ||||||
|         add_packages("wgpu-native") |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     if has_config("freetype") then |  | ||||||
|         add_files("misc/freetype/imgui_freetype.cpp") |  | ||||||
|         add_headerfiles("misc/freetype/imgui_freetype.h") |  | ||||||
|         add_packages("freetype") |  | ||||||
|         add_defines("IMGUI_ENABLE_FREETYPE") |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     if has_config("user_config") then |  | ||||||
|         local user_config = get_config("user_config") |  | ||||||
|         add_defines("IMGUI_USER_CONFIG=\"".. user_config .."\"") |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     if has_config("wchar32") then |  | ||||||
|         add_defines("IMGUI_USE_WCHAR32") |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     after_install(function (target) |  | ||||||
|         local config_file = path.join(target:installdir(), "include/imconfig.h") |  | ||||||
|         if has_config("wchar32") then |  | ||||||
|             io.gsub(config_file, "//#define IMGUI_USE_WCHAR32", "#define IMGUI_USE_WCHAR32") |  | ||||||
|         end |  | ||||||
|         if has_config("freetype") then |  | ||||||
|             io.gsub(config_file, "//#define IMGUI_ENABLE_FREETYPE", "#define IMGUI_ENABLE_FREETYPE") |  | ||||||
|         end |  | ||||||
|     end) |  | ||||||
							
								
								
									
										227
									
								
								thirdparty/imgui/xmake.lua
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										227
									
								
								thirdparty/imgui/xmake.lua
									
									
									
									
										vendored
									
									
								
							| @@ -1,227 +0,0 @@ | |||||||
| package("imgui") |  | ||||||
|     set_homepage("https://github.com/ocornut/imgui") |  | ||||||
|     set_description("Bloat-free Immediate Mode Graphical User interface for C++ with minimal dependencies") |  | ||||||
|     set_license("MIT") |  | ||||||
|  |  | ||||||
|     add_urls("https://github.com/ocornut/imgui/archive/refs/tags/$(version).tar.gz") |  | ||||||
|     add_urls("https://github.com/ocornut/imgui.git", {alias = "git"}) |  | ||||||
|  |  | ||||||
|     -- don't forget to add the docking versions as well |  | ||||||
|     add_versions("v1.92.0", "42250c45df2736bcef867ae4ff404d138e5135cd36466c63143b1ea3b1c81091") |  | ||||||
|     add_versions("v1.91.9", "3872a5f90df78fced023c1945f4466b654fd74573370b77b17742149763a7a7c") |  | ||||||
|     add_versions("v1.91.8", "db3a2e02bfd6c269adf0968950573053d002f40bdfb9ef2e4a90bce804b0f286") |  | ||||||
|     add_versions("v1.91.7", "2001dab4bdd7d178d8277d3b17c40aa1ff1e76e2ccac5e7ab8c6daf9756312c2") |  | ||||||
|     add_versions("v1.91.6", "c5fbc5dcab1d46064001c3b84d7a88812985cde7e0e9ced03f5677bec1ba502a") |  | ||||||
|     add_versions("v1.91.5", "2aa2d169c569368439e5d5667e0796d09ca5cc6432965ce082e516937d7db254") |  | ||||||
|     add_versions("v1.91.4", "a455c28d987c78ddf56aab98ce0ff0fda791a23a2ec88ade46dd106b837f0923") |  | ||||||
|     add_versions("v1.91.3", "29949d7b300c30565fbcd66398100235b63aa373acfee0b76853a7aeacd1be28") |  | ||||||
|     add_versions("v1.91.2", "a3c4fd857a0a48f6edad3e25de68fa1e96d2437f1665039714d1de9ad579b8d0") |  | ||||||
|     add_versions("v1.91.1", "2c13a8909f75222c836abc9b3f60cef31c445f3f41f95d8242118ea789d145ca") |  | ||||||
|     add_versions("v1.91.0", "6e62c87252e6b3725ba478a1c04dc604aa0aaeec78fedcf4011f1e52548f4cc9") |  | ||||||
|     add_versions("v1.90.9", "04943919721e874ac75a2f45e6eb6c0224395034667bf508923388afda5a50bf") |  | ||||||
|     add_versions("v1.90.8", "f606b4fb406aa0f8dad36d4a9dd3d6f0fd39f5f0693e7468abc02d545fb505ae") |  | ||||||
|     add_versions("v1.90.7", "872574217643d4ad7e9e6df420bb8d9e0d468fb90641c2bf50fd61745e05de99") |  | ||||||
|     add_versions("v1.90.6", "70b4b05ac0938e82b4d5b8d59480d3e2ca63ca570dfb88c55023831f387237ad") |  | ||||||
|     add_versions("v1.90.5", "e94b48dba7311c85ba8e3e6fe7c734d76a0eed21b2b42c5180fd5706d1562241") |  | ||||||
|     add_versions("v1.90.4", "5d9dc738af74efa357f2a9fc39fe4a28d29ef1dfc725dd2977ccf3f3194e996e") |  | ||||||
|     add_versions("v1.90.3", "40b302d01092c9393373b372fe07ea33ac69e9491893ebab3bf952b2c1f5fd23") |  | ||||||
|     add_versions("v1.90.2", "452d1c11e5c4b4dfcca272915644a65f1c076498e8318b141ca75cd30470dd68") |  | ||||||
|     add_versions("v1.90.1", "21dcc985bb2ae8fe48047c86135dbc438d6980a8f2e08babbda5be820592f282") |  | ||||||
|     add_versions("v1.90",   "170986e6a4b83d165bfc1d33c2c5a5bc2d67e5b97176287485c51a2299249296") |  | ||||||
|     add_versions("v1.89.9", "1acc27a778b71d859878121a3f7b287cd81c29d720893d2b2bf74455bf9d52d6") |  | ||||||
|     add_versions("v1.89.8", "6680ccc32430009a8204291b1268b2367d964bd6d1b08a4e0358a017eb8e8c9e") |  | ||||||
|     add_versions("v1.89.7", "115ee9e242af98a884302ac0f6ca3b2b26b1f10c660205f5e7ad9f1d1c96d269") |  | ||||||
|     add_versions("v1.89.6", "e95d1cba1481e66386acda3e7da19cd738da86c6c2a140a48fa55046e5f6e208") |  | ||||||
|     add_versions("v1.89.5", "eab371005c86dd029523a0c4ba757840787163740d45c1f4e5a110eb21820546") |  | ||||||
|     add_versions("v1.89.4", "69f1e83adcab3fdd27b522f5075f407361b0d3875e3522b13d33bc2ae2c7d48c") |  | ||||||
|     add_versions("v1.89.3", "3b665fadd5580b7ef494d5d8bb1c12b2ec53ee723034caf43332956381f5d631") |  | ||||||
|     add_versions("v1.89",   "4038b05bd44c889cf40be999656d3871a0559916708cb52a6ae2fa6fa35c5c60") |  | ||||||
|     add_versions("v1.88",   "9f14c788aee15b777051e48f868c5d4d959bd679fc5050e3d2a29de80d8fd32e") |  | ||||||
|     add_versions("v1.87",   "b54ceb35bda38766e36b87c25edf7a1cd8fd2cb8c485b245aedca6fb85645a20") |  | ||||||
|     add_versions("v1.86",   "6ba6ae8425a19bc52c5e067702c48b70e4403cd339cba02073a462730a63e825") |  | ||||||
|     add_versions("v1.85",   "7ed49d1f4573004fa725a70642aaddd3e06bb57fcfe1c1a49ac6574a3e895a77") |  | ||||||
|     add_versions("v1.84.2", "35cb5ca0fb42cb77604d4f908553f6ef3346ceec4fcd0189675bdfb764f62b9b") |  | ||||||
|     add_versions("v1.84.1", "292ab54cfc328c80d63a3315a242a4785d7c1cf7689fbb3d70da39b34db071ea") |  | ||||||
|     add_versions("v1.83",   "ccf3e54b8d1fa30dd35682fc4f50f5d2fe340b8e29e08de71287d0452d8cc3ff") |  | ||||||
|     add_versions("v1.82",   "fefa2804bd55f3d25b134af08c0e1f86d4d059ac94cef3ee7bd21e2f194e5ce5") |  | ||||||
|     add_versions("v1.81",   "f7c619e03a06c0f25e8f47262dbc32d61fd033d2c91796812bf0f8c94fca78fb") |  | ||||||
|     add_versions("v1.80",   "d7e4e1c7233409018437a646680316040e6977b9a635c02da93d172baad94ce9") |  | ||||||
|     add_versions("v1.79",   "f1908501f6dc6db8a4d572c29259847f6f882684b10488d3a8d2da31744cd0a4") |  | ||||||
|     add_versions("v1.78",   "f70bbb17581ee2bd42fda526d9c3dc1a5165f3847ff047483d4d7980e166f9a3") |  | ||||||
|     add_versions("v1.77",   "c0dae830025d4a1a169df97409709f40d9dfa19f8fc96b550052224cbb238fa8") |  | ||||||
|     add_versions("v1.76",   "e482dda81330d38c87bd81597cacaa89f05e20ed2c4c4a93a64322e97565f6dc") |  | ||||||
|     add_versions("v1.75",   "1023227fae4cf9c8032f56afcaea8902e9bfaad6d9094d6e48fb8f3903c7b866") |  | ||||||
|  |  | ||||||
|     add_versions("git:v1.92.0-docking", "v1.92.0-docking") |  | ||||||
|     add_versions("git:v1.91.9-docking", "v1.91.9-docking") |  | ||||||
|     add_versions("git:v1.91.8-docking", "v1.91.8-docking") |  | ||||||
|     add_versions("git:v1.91.7-docking", "v1.91.7-docking") |  | ||||||
|     add_versions("git:v1.91.6-docking", "v1.91.6-docking") |  | ||||||
|     add_versions("git:v1.91.5-docking", "v1.91.5-docking") |  | ||||||
|     add_versions("git:v1.91.4-docking", "v1.91.4-docking") |  | ||||||
|     add_versions("git:v1.91.3-docking", "v1.91.3-docking") |  | ||||||
|     add_versions("git:v1.91.2-docking", "v1.91.2-docking") |  | ||||||
|     add_versions("git:v1.91.1-docking", "v1.91.1-docking") |  | ||||||
|     add_versions("git:v1.91.0-docking", "v1.91.0-docking") |  | ||||||
|     add_versions("git:v1.90.9-docking", "v1.90.9-docking") |  | ||||||
|     add_versions("git:v1.90.8-docking", "v1.90.8-docking") |  | ||||||
|     add_versions("git:v1.90.7-docking", "v1.90.7-docking") |  | ||||||
|     add_versions("git:v1.90.6-docking", "v1.90.6-docking") |  | ||||||
|     add_versions("git:v1.90.5-docking", "v1.90.5-docking") |  | ||||||
|     add_versions("git:v1.90.4-docking", "v1.90.4-docking") |  | ||||||
|     add_versions("git:v1.90.3-docking", "v1.90.3-docking") |  | ||||||
|     add_versions("git:v1.90.2-docking", "v1.90.2-docking") |  | ||||||
|     add_versions("git:v1.90.1-docking", "v1.90.1-docking") |  | ||||||
|     add_versions("git:v1.90-docking",   "v1.90-docking") |  | ||||||
|     add_versions("git:v1.89.9-docking", "v1.89.9-docking") |  | ||||||
|     add_versions("git:v1.89.8-docking", "v1.89.8-docking") |  | ||||||
|     add_versions("git:v1.89.7-docking", "v1.89.7-docking") |  | ||||||
|     add_versions("git:v1.89.6-docking", "823a1385a269d923d35b82b2f470f3ae1fa8b5a3") |  | ||||||
|     add_versions("git:v1.89.5-docking", "0ea3b87bd63ecbf359585b7c235839146e84dedb") |  | ||||||
|     add_versions("git:v1.89.4-docking", "9e30fb0ec1b44dc1b041db6bdd53b130b2a18509") |  | ||||||
|     add_versions("git:v1.89.3-docking", "192196711a7d0d7c2d60454d42654cf090498a74") |  | ||||||
|     add_versions("git:v1.89-docking",   "94e850fd6ff9eceb98fda3147e3ffd4781ad2dc7") |  | ||||||
|     add_versions("git:v1.88-docking",   "9cd9c2eff99877a3f10a7f9c2a3a5b9c15ea36c6") |  | ||||||
|     add_versions("git:v1.87-docking",   "1ee252772ae9c0a971d06257bb5c89f628fa696a") |  | ||||||
|     add_versions("git:v1.85-docking",   "dc8c3618e8f8e2dada23daa1aa237626af341fd8") |  | ||||||
|     add_versions("git:v1.83-docking",   "80b5fb51edba2fd3dea76ec3e88153e2492243d1") |  | ||||||
|  |  | ||||||
|     -- Fix conflicting IMGUI_API definitions in v1.92.0 only (https://github.com/ocornut/imgui/pull/8729) |  | ||||||
|     add_patches("v1.92.0", "patches/v1.92.0/fix_imgui_api.patch", "e8ca0502056acf356f83703e7190dda87fde43ed245f65f0fb55b85cd164ed83") |  | ||||||
|     add_patches("v1.92.0-docking", "patches/v1.92.0/fix_imgui_api.patch", "e8ca0502056acf356f83703e7190dda87fde43ed245f65f0fb55b85cd164ed83") |  | ||||||
|  |  | ||||||
|     add_configs("dx9",              {description = "Enable the dx9 backend", default = false, type = "boolean"}) |  | ||||||
|     add_configs("dx10",             {description = "Enable the dx10 backend", default = false, type = "boolean"}) |  | ||||||
|     add_configs("dx11",             {description = "Enable the dx11 backend", default = false, type = "boolean"}) |  | ||||||
|     add_configs("dx12",             {description = "Enable the dx12 backend", default = false, type = "boolean"}) |  | ||||||
|     add_configs("glfw",             {description = "Enable the glfw backend", default = false, type = "boolean"}) |  | ||||||
|     add_configs("opengl2",          {description = "Enable the opengl2 backend", default = false, type = "boolean"}) |  | ||||||
|     add_configs("opengl3",          {description = "Enable the opengl3 backend", default = false, type = "boolean"}) |  | ||||||
|     add_configs("sdl2",             {description = "Enable the sdl2 backend with sdl2_renderer", default = false, type = "boolean"}) |  | ||||||
|     add_configs("sdl2_no_renderer", {description = "Enable the sdl2 backend without sdl2_renderer", default = false, type = "boolean"}) |  | ||||||
|     add_configs("sdl2_renderer",    {description = "Enable the sdl2 renderer backend", default = false, type = "boolean"}) |  | ||||||
|     add_configs("sdl3",             {description = "Enable the sdl3 backend with sdl3_renderer", default = false, type = "boolean"}) |  | ||||||
|     add_configs("sdl3_renderer",    {description = "Enable the sdl3 renderer backend", default = false, type = "boolean"}) |  | ||||||
|     add_configs("sdl3_gpu",         {description = "Enable the sdl3 gpu backend", default = false, type = "boolean"}) |  | ||||||
|     add_configs("vulkan",           {description = "Enable the vulkan backend", default = false, type = "boolean"}) |  | ||||||
|     add_configs("win32",            {description = "Enable the win32 backend", default = false, type = "boolean"}) |  | ||||||
|     add_configs("osx",              {description = "Enable the OS X backend", default = false, type = "boolean"}) |  | ||||||
|     add_configs("wgpu",             {description = "Enable the wgpu backend", default = false, type = "boolean"}) |  | ||||||
|     add_configs("freetype",         {description = "Use FreeType to build and rasterize the font atlas", default = false, type = "boolean"}) |  | ||||||
|     add_configs("user_config",      {description = "Use user config (disables test!)", default = nil, type = "string"}) |  | ||||||
|     add_configs("wchar32",          {description = "Use 32-bit for ImWchar (default is 16-bit)", default = false, type = "boolean"}) |  | ||||||
|  |  | ||||||
|     -- deprecated configs (kept for backwards compatibility) |  | ||||||
|     add_configs("sdlrenderer",  {description = "(deprecated)", default = false, type = "boolean"}) |  | ||||||
|     add_configs("glfw_opengl3", {description = "(deprecated)", default = false, type = "boolean"}) |  | ||||||
|     add_configs("glfw_vulkan",  {description = "(deprecated)", default = false, type = "boolean"}) |  | ||||||
|     add_configs("sdl2_opengl3", {description = "(deprecated)", default = false, type = "boolean"}) |  | ||||||
|  |  | ||||||
|     add_includedirs("include", "include/imgui", "include/backends", "include/misc/cpp") |  | ||||||
|  |  | ||||||
|     if is_plat("windows", "mingw") then |  | ||||||
|         add_syslinks("imm32") |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     on_load(function (package) |  | ||||||
|         -- begin: backwards compatibility |  | ||||||
|         if package:config("sdl2") or package:config("sdlrenderer") then |  | ||||||
|             package:config_set("sdl2_renderer", true) |  | ||||||
|         end |  | ||||||
|         if package:config("glfw_opengl3") then |  | ||||||
|             package:config_set("glfw", true) |  | ||||||
|             package:config_set("opengl3", true) |  | ||||||
|         end |  | ||||||
|         if package:config("glfw_vulkan") then |  | ||||||
|             package:config_set("glfw", true) |  | ||||||
|             package:config_set("vulkan", true) |  | ||||||
|         end |  | ||||||
|         if package:config("sdl2_opengl3") then |  | ||||||
|             package:config_set("sdl2", true) |  | ||||||
|             package:config_set("opengl3", true) |  | ||||||
|         end |  | ||||||
|         -- end: backwards compatibility |  | ||||||
|         if package:config("shared") and is_plat("windows", "mingw") then |  | ||||||
|             package:add("defines", "IMGUI_API=__declspec(dllimport)") |  | ||||||
|         end |  | ||||||
|         if package:config("glfw") then |  | ||||||
|             package:add("deps", "glfw") |  | ||||||
|         end |  | ||||||
|         if package:config("opengl3") then |  | ||||||
|             if not package:gitref() and package:version():lt("1.84") then |  | ||||||
|                 package:add("deps", "glad") |  | ||||||
|                 package:add("defines", "IMGUI_IMPL_OPENGL_LOADER_GLAD") |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|         if package:config("sdl2_no_renderer") then |  | ||||||
|             package:add("deps", "libsdl2") |  | ||||||
|         end |  | ||||||
|         if package:config("sdl2_renderer") then |  | ||||||
|             package:add("deps", "libsdl2 >=2.0.17") |  | ||||||
|         end |  | ||||||
|         if package:config("sdl3") or package:config("sdl3_renderer") or package:config("sdl3_gpu") then |  | ||||||
|             package:add("deps", "libsdl3") |  | ||||||
|         end |  | ||||||
|         if package:config("vulkan") then |  | ||||||
|             package:add("deps", "vulkan-headers") |  | ||||||
|         end |  | ||||||
|         if package:config("wgpu") then |  | ||||||
|             package:add("deps", "wgpu-native") |  | ||||||
|         end |  | ||||||
|         if package:config("freetype") then |  | ||||||
|             package:add("deps", "freetype") |  | ||||||
|         end |  | ||||||
|         if package:config("osx") then |  | ||||||
|             package:add("frameworks", "Cocoa", "Carbon", "GameController") |  | ||||||
|         end |  | ||||||
|     end) |  | ||||||
|  |  | ||||||
|     on_install(function (package) |  | ||||||
|         local configs = { |  | ||||||
|             dx9              = package:config("dx9"), |  | ||||||
|             dx10             = package:config("dx10"), |  | ||||||
|             dx11             = package:config("dx11"), |  | ||||||
|             dx12             = package:config("dx12"), |  | ||||||
|             glfw             = package:config("glfw"), |  | ||||||
|             opengl2          = package:config("opengl2"), |  | ||||||
|             opengl3          = package:config("opengl3"), |  | ||||||
|             glad             = package:config("opengl3") and (not package:gitref() and package:version():lt("1.84")), |  | ||||||
|             sdl2             = package:config("sdl2") or package:config("sdl2_no_renderer"), |  | ||||||
|             sdl2_renderer    = package:config("sdl2_renderer"), |  | ||||||
|             sdl3             = package:config("sdl3"), |  | ||||||
|             sdl3_renderer    = package:config("sdl3_renderer"), |  | ||||||
|             sdl3_gpu         = package:config("sdl3_gpu"), |  | ||||||
|             vulkan           = package:config("vulkan"), |  | ||||||
|             win32            = package:config("win32"), |  | ||||||
|             osx              = package:config("osx"), |  | ||||||
|             wgpu             = package:config("wgpu"), |  | ||||||
|             freetype         = package:config("freetype"), |  | ||||||
|             user_config      = package:config("user_config"), |  | ||||||
|             wchar32          = package:config("wchar32") |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         os.cp(path.join(package:scriptdir(), "port", "xmake.lua"), "xmake.lua") |  | ||||||
|         import("package.tools.xmake").install(package, configs) |  | ||||||
|     end) |  | ||||||
|  |  | ||||||
|     on_test(function (package) |  | ||||||
|         if package:config("user_config") ~= nil then return end |  | ||||||
|         local includes = {"imgui.h"} |  | ||||||
|         local defines |  | ||||||
|         if package:config("sdl2_renderer") or package:config("sdl2_no_renderer") then |  | ||||||
|             table.insert(includes, "SDL.h") |  | ||||||
|             defines = "SDL_MAIN_HANDLED" |  | ||||||
|         end |  | ||||||
|         assert(package:check_cxxsnippets({test = [[ |  | ||||||
|             void test() { |  | ||||||
|                 IMGUI_CHECKVERSION(); |  | ||||||
|                 ImGui::CreateContext(); |  | ||||||
|                 ImGuiIO& io = ImGui::GetIO(); |  | ||||||
|                 ImGui::NewFrame(); |  | ||||||
|                 ImGui::Text("Hello, world!"); |  | ||||||
|                 ImGui::ShowDemoWindow(NULL); |  | ||||||
|                 ImGui::Render(); |  | ||||||
|                 ImGui::DestroyContext(); |  | ||||||
|             } |  | ||||||
|         ]]}, {configs = {languages = "c++14", defines = defines}, includes = includes})) |  | ||||||
|     end) |  | ||||||
							
								
								
									
										14
									
								
								xmake.lua
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								xmake.lua
									
									
									
									
									
								
							| @@ -1,8 +1,11 @@ | |||||||
| set_project("crossdesk") | set_project("crossdesk") | ||||||
| set_license("LGPL-3.0") | set_license("LGPL-3.0") | ||||||
|  |  | ||||||
| set_version("0.0.1") | option("CROSSDESK_VERSION") | ||||||
| add_defines("RD_VERSION=\"0.0.1\""); |     set_default("0.0.0") | ||||||
|  |     set_showmenu(true) | ||||||
|  |     set_description("Set CROSSDESK_VERSION for build") | ||||||
|  | option_end() | ||||||
|  |  | ||||||
| add_rules("mode.release", "mode.debug") | add_rules("mode.release", "mode.debug") | ||||||
| set_languages("c++17") | set_languages("c++17") | ||||||
| @@ -43,7 +46,7 @@ end | |||||||
|  |  | ||||||
| add_packages("spdlog", "imgui") | add_packages("spdlog", "imgui") | ||||||
|  |  | ||||||
| includes("thirdparty") | includes("submodules") | ||||||
|  |  | ||||||
| target("rd_log") | target("rd_log") | ||||||
|     set_kind("object") |     set_kind("object") | ||||||
| @@ -143,6 +146,7 @@ target("assets") | |||||||
| target("gui") | target("gui") | ||||||
|     set_kind("object") |     set_kind("object") | ||||||
|     add_packages("libyuv") |     add_packages("libyuv") | ||||||
|  |     add_defines("CROSSDESK_VERSION=\"" .. (get_config("CROSSDESK_VERSION") or "Unknown") .. "\"") | ||||||
|     add_deps("rd_log", "common", "assets", "config_center", "minirtc",  |     add_deps("rd_log", "common", "assets", "config_center", "minirtc",  | ||||||
|         "path_manager", "screen_capturer", "speaker_capturer",  |         "path_manager", "screen_capturer", "speaker_capturer",  | ||||||
|         "device_controller", "thumbnail") |         "device_controller", "thumbnail") | ||||||
| @@ -150,6 +154,10 @@ target("gui") | |||||||
|         "src/gui/windows/*.cpp") |         "src/gui/windows/*.cpp") | ||||||
|     add_includedirs("src/gui", "src/gui/panels", "src/gui/toolbars", |     add_includedirs("src/gui", "src/gui/panels", "src/gui/toolbars", | ||||||
|         "src/gui/windows", {public = true}) |         "src/gui/windows", {public = true}) | ||||||
|  |     if is_os("windows") then | ||||||
|  |         add_files("src/gui/tray/*.cpp") | ||||||
|  |         add_includedirs("src/gui/tray", {public = true}) | ||||||
|  |     end | ||||||
|  |  | ||||||
| target("crossdesk") | target("crossdesk") | ||||||
|     set_kind("binary") |     set_kind("binary") | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user