mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-12-19 05:36:32 +08:00
Compare commits
22 Commits
d21e1bd422
...
switch-ser
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f5941c7eda | ||
|
|
3c2ebe602e | ||
|
|
2f64172ead | ||
|
|
a83206a346 | ||
|
|
46e769976f | ||
|
|
58c24b798e | ||
|
|
5cc31e5ba3 | ||
|
|
74fe9bebf5 | ||
|
|
1f6a2182be | ||
|
|
1a883f0d6c | ||
|
|
a560b4ca70 | ||
|
|
46f45ed216 | ||
|
|
5c23f1c5e8 | ||
|
|
70ae02549f | ||
|
|
68de995c64 | ||
|
|
ed5ddb96fd | ||
|
|
436dfafc2a | ||
|
|
5221b193e5 | ||
|
|
fafced23c2 | ||
|
|
1e48b645ca | ||
|
|
49ed0200e7 | ||
|
|
24873afe64 |
2
.github/ISSUE_TEMPLATE/问题反馈.md
vendored
2
.github/ISSUE_TEMPLATE/问题反馈.md
vendored
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: 问题反馈
|
name: 问题反馈
|
||||||
about: Create a report to help us improve
|
about: 请在此提交问题报告,以便持续优化产品。
|
||||||
title: ''
|
title: ''
|
||||||
labels: bug
|
labels: bug
|
||||||
assignees: kunkundi
|
assignees: kunkundi
|
||||||
|
|||||||
28
.github/ISSUE_TEMPLATE/需求建议.md
vendored
Normal file
28
.github/ISSUE_TEMPLATE/需求建议.md
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
name: 需求建议
|
||||||
|
about: 请在此提交功能需求或改进建议,以便后续迭代参考。
|
||||||
|
title: ''
|
||||||
|
labels: enhancement
|
||||||
|
assignees: kunkundi
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**功能/改进建议描述**
|
||||||
|
清晰简洁地描述希望新增的功能或改进的内容。
|
||||||
|
|
||||||
|
**使用场景 / 背景**
|
||||||
|
说明该功能或改进的使用场景,以及解决后带来的价值。
|
||||||
|
|
||||||
|
**预期效果**
|
||||||
|
描述你认为最理想的功能表现或改进效果。
|
||||||
|
|
||||||
|
**参考示例(可选)**
|
||||||
|
提供类似功能截图、参考链接或其他说明,帮助更好理解需求。
|
||||||
|
|
||||||
|
**优先级(可选)**
|
||||||
|
- [ ] 高
|
||||||
|
- [ ] 中
|
||||||
|
- [ ] 低
|
||||||
|
|
||||||
|
**补充信息(可选)**
|
||||||
|
其他相关信息或特殊要求。
|
||||||
165
README.md
165
README.md
@@ -169,7 +169,7 @@ xmake r -d crossdesk
|
|||||||
|
|
||||||
## 自托管服务器
|
## 自托管服务器
|
||||||
推荐使用Docker部署CrossDesk Server。
|
推荐使用Docker部署CrossDesk Server。
|
||||||
```
|
```bash
|
||||||
sudo docker run -d \
|
sudo docker run -d \
|
||||||
--name crossdesk_server \
|
--name crossdesk_server \
|
||||||
--network host \
|
--network host \
|
||||||
@@ -179,145 +179,58 @@ sudo docker run -d \
|
|||||||
-e COTURN_PORT=xxxx \
|
-e COTURN_PORT=xxxx \
|
||||||
-e MIN_PORT=xxxxx \
|
-e MIN_PORT=xxxxx \
|
||||||
-e MAX_PORT=xxxxx \
|
-e MAX_PORT=xxxxx \
|
||||||
-v /path/to/your/certs:/crossdesk-server/certs \
|
-v /var/lib/crossdesk:/var/lib/crossdesk \
|
||||||
-v /path/to/your/db:/crossdesk-server/db \
|
-v /var/log/crossdesk:/var/log/crossdesk \
|
||||||
-v /path/to/your/logs:/crossdesk-server/logs \
|
crossdesk/crossdesk-server:v1.1.2
|
||||||
crossdesk/crossdesk-server:v1.1.1
|
|
||||||
```
|
```
|
||||||
|
|
||||||
上述命令中,用户需注意的参数如下:
|
上述命令中,用户需注意的参数如下:
|
||||||
|
|
||||||
|
**参数**
|
||||||
- EXTERNAL_IP:服务器公网 IP , 对应 CrossDesk 客户端**自托管服务器配置**中填写的**服务器地址**
|
- EXTERNAL_IP:服务器公网 IP , 对应 CrossDesk 客户端**自托管服务器配置**中填写的**服务器地址**
|
||||||
|
|
||||||
- INTERNAL_IP:服务器内网 IP
|
- INTERNAL_IP:服务器内网 IP
|
||||||
|
|
||||||
- CROSSDESK_SERVER_PORT:自托管服务使用的端口,对应 CrossDesk 客户端**自托管服务器配置**中填写的**服务器端口**
|
- CROSSDESK_SERVER_PORT:自托管服务使用的端口,对应 CrossDesk 客户端**自托管服务器配置**中填写的**服务器端口**
|
||||||
|
|
||||||
- COTURN_PORT: COTURN 服务使用的端口, 对应 CrossDesk 客户端**自托管服务器配置**中填写的**中继服务端口**
|
- COTURN_PORT: COTURN 服务使用的端口, 对应 CrossDesk 客户端**自托管服务器配置**中填写的**中继服务端口**
|
||||||
|
|
||||||
- MIN_PORT/MAX_PORT:COTURN 服务使用的端口范围,例如:MIN_PORT=50000, MAX_PORT=60000,范围可根据客户端数量调整。
|
- MIN_PORT/MAX_PORT:COTURN 服务使用的端口范围,例如:MIN_PORT=50000, MAX_PORT=60000,范围可根据客户端数量调整。
|
||||||
|
- `-v /var/lib/crossdesk:/var/lib/crossdesk`:持久化数据库和证书文件到宿主机
|
||||||
|
- `-v /var/log/crossdesk:/var/log/crossdesk`:持久化日志文件到宿主机
|
||||||
|
|
||||||
- /path/to/your/certs:证书文件目录
|
**示例**:
|
||||||
|
```bash
|
||||||
- /path/to/your/db:CrossDesk Server 设备管理数据库
|
sudo docker run -d \
|
||||||
|
--name crossdesk_server \
|
||||||
- /path/to/your/logs:日志目录
|
--network host \
|
||||||
|
-e EXTERNAL_IP=114.114.114.114 \
|
||||||
|
-e INTERNAL_IP=10.0.0.1 \
|
||||||
|
-e CROSSDESK_SERVER_PORT=9099 \
|
||||||
|
-e COTURN_PORT=3478 \
|
||||||
|
-e MIN_PORT=50000 \
|
||||||
|
-e MAX_PORT=60000 \
|
||||||
|
-v /var/lib/crossdesk:/var/lib/crossdesk \
|
||||||
|
-v /var/log/crossdesk:/var/log/crossdesk \
|
||||||
|
crossdesk/crossdesk-server:v1.1.3
|
||||||
|
```
|
||||||
|
|
||||||
**注意**:
|
**注意**:
|
||||||
- **/path/to/your/ 是示例路径,请替换为你自己的实际路径。挂载的目录必须事先创建好,否则容器会报错。**
|
- **服务器需开放端口:COTURN_PORT/udp,COTURN_PORT/tcp,MIN_PORT-MAX_PORT/udp,CROSSDESK_SERVER_PORT/tcp。**
|
||||||
- **服务器需开放端口:3478/udp,3478/tcp,MIN_PORT-MAX_PORT/udp,CROSSDESK_SERVER_PORT/tcp。**
|
- 如果不挂载 volume,容器删除后数据会丢失
|
||||||
|
- 证书文件会在首次启动时自动生成并持久化到宿主机的 `/var/lib/crossdesk/certs` 路径下
|
||||||
|
- 数据库文件会自动创建并持久化到宿主机的 `/var/lib/crossdesk/db/crossdesk-server.db` 路径下
|
||||||
|
- 日志文件会自动创建并持久化到宿主机的 `/var/log/crossdesk/` 路径下
|
||||||
|
|
||||||
|
**权限注意**:如果 Docker 自动创建的目录权限不足(属于 root),容器内用户无法写入,会导致:
|
||||||
|
- 证书生成失败,容器启动脚本会报错退出
|
||||||
|
- 数据库目录创建失败,程序会抛出异常并崩溃
|
||||||
|
- 日志目录创建失败,日志文件无法写入(但程序可能继续运行)
|
||||||
|
|
||||||
|
**解决方案**:在启动容器前手动设置权限:
|
||||||
|
```bash
|
||||||
|
sudo mkdir -p /var/lib/crossdesk /var/log/crossdesk
|
||||||
|
sudo chown -R $(id -u):$(id -g) /var/lib/crossdesk /var/log/crossdesk
|
||||||
|
```
|
||||||
|
|
||||||
## 证书文件
|
## 证书文件
|
||||||
客户端需加载根证书文件,服务端需加载服务器私钥和服务器证书文件。
|
在宿主机的 `/var/lib/crossdesk/certs` 路径下可找到证书文件 `crossdesk.cn_root.crt`,下载到你的客户端主机,并在客户端的**自托管服务器设置**中选择相应的**证书文件路径**。
|
||||||
|
|
||||||
如果已有SSL证书的用户,可以忽略下面的证书生成步骤。
|
|
||||||
|
|
||||||
对于无证书的用户,可使用下面的脚本自行生成证书文件:
|
|
||||||
```
|
|
||||||
# 创建证书生成脚本
|
|
||||||
vim generate_certs.sh
|
|
||||||
```
|
|
||||||
拷贝到脚本中
|
|
||||||
```
|
|
||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# 检查参数
|
|
||||||
if [ "$#" -ne 1 ]; then
|
|
||||||
echo "Usage: $0 <SERVER_IP>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
SERVER_IP="$1"
|
|
||||||
|
|
||||||
# 文件名
|
|
||||||
ROOT_KEY="crossdesk.cn_root.key"
|
|
||||||
ROOT_CERT="crossdesk.cn_root.crt"
|
|
||||||
SERVER_KEY="crossdesk.cn.key"
|
|
||||||
SERVER_CSR="crossdesk.cn.csr"
|
|
||||||
SERVER_CERT="crossdesk.cn_bundle.crt"
|
|
||||||
FULLCHAIN_CERT="crossdesk.cn_fullchain.crt"
|
|
||||||
|
|
||||||
# 证书主题
|
|
||||||
SUBJ="/C=CN/ST=Zhejiang/L=Hangzhou/O=CrossDesk/OU=CrossDesk/CN=$SERVER_IP"
|
|
||||||
|
|
||||||
# 1. 生成根证书
|
|
||||||
echo "Generating root private key..."
|
|
||||||
openssl genrsa -out "$ROOT_KEY" 4096
|
|
||||||
|
|
||||||
echo "Generating self-signed root certificate..."
|
|
||||||
openssl req -x509 -new -nodes -key "$ROOT_KEY" -sha256 -days 3650 -out "$ROOT_CERT" -subj "$SUBJ"
|
|
||||||
|
|
||||||
# 2. 生成服务器私钥
|
|
||||||
echo "Generating server private key..."
|
|
||||||
openssl genrsa -out "$SERVER_KEY" 2048
|
|
||||||
|
|
||||||
# 3. 生成服务器 CSR
|
|
||||||
echo "Generating server CSR..."
|
|
||||||
openssl req -new -key "$SERVER_KEY" -out "$SERVER_CSR" -subj "$SUBJ"
|
|
||||||
|
|
||||||
# 4. 生成临时 OpenSSL 配置文件,加入 SAN
|
|
||||||
SAN_CONF="san.cnf"
|
|
||||||
cat > $SAN_CONF <<EOL
|
|
||||||
[ req ]
|
|
||||||
default_bits = 2048
|
|
||||||
distinguished_name = req_distinguished_name
|
|
||||||
req_extensions = req_ext
|
|
||||||
prompt = no
|
|
||||||
|
|
||||||
[ req_distinguished_name ]
|
|
||||||
C = CN
|
|
||||||
ST = Zhejiang
|
|
||||||
L = Hangzhou
|
|
||||||
O = CrossDesk
|
|
||||||
OU = CrossDesk
|
|
||||||
CN = $SERVER_IP
|
|
||||||
|
|
||||||
[ req_ext ]
|
|
||||||
subjectAltName = IP:$SERVER_IP
|
|
||||||
EOL
|
|
||||||
|
|
||||||
# 5. 用根证书签发服务器证书(包含 SAN)
|
|
||||||
echo "Signing server certificate with root certificate..."
|
|
||||||
openssl x509 -req -in "$SERVER_CSR" -CA "$ROOT_CERT" -CAkey "$ROOT_KEY" -CAcreateserial \
|
|
||||||
-out "$SERVER_CERT" -days 3650 -sha256 -extfile "$SAN_CONF" -extensions req_ext
|
|
||||||
|
|
||||||
# 6. 生成完整链证书
|
|
||||||
cat "$SERVER_CERT" "$ROOT_CERT" > "$FULLCHAIN_CERT"
|
|
||||||
|
|
||||||
# 7. 清理中间文件
|
|
||||||
rm -f "$ROOT_CERT.srl" "$SAN_CONF" "$ROOT_KEY" "$SERVER_CSR" "FULLCHAIN_CERT"
|
|
||||||
|
|
||||||
echo "Generation complete. Deployment files:"
|
|
||||||
echo " Client root certificate: $ROOT_CERT"
|
|
||||||
echo " Server private key: $SERVER_KEY"
|
|
||||||
echo " Server certificate: $SERVER_CERT"
|
|
||||||
```
|
|
||||||
执行
|
|
||||||
```
|
|
||||||
chmod +x generate_certs.sh
|
|
||||||
./generate_certs.sh 服务器公网IP
|
|
||||||
|
|
||||||
# 例如 ./generate_certs.sh 111.111.111.111
|
|
||||||
```
|
|
||||||
输出如下:
|
|
||||||
```
|
|
||||||
Generating root private key...
|
|
||||||
Generating self-signed root certificate...
|
|
||||||
Generating server private key...
|
|
||||||
Generating server CSR...
|
|
||||||
Signing server certificate with root certificate...
|
|
||||||
Certificate request self-signature ok
|
|
||||||
subject=C = CN, ST = Zhejiang, L = Hangzhou, O = CrossDesk, OU = CrossDesk, CN = xxx.xxx.xxx.xxx
|
|
||||||
cleaning up intermediate files...
|
|
||||||
Generation complete. Deployment files::
|
|
||||||
Client root certificate:: crossdesk.cn_root.crt
|
|
||||||
Server private key: crossdesk.cn.key
|
|
||||||
Server certificate: crossdesk.cn_bundle.crt
|
|
||||||
```
|
|
||||||
|
|
||||||
### 服务端
|
|
||||||
将 **crossdesk.cn.key** 和 **crossdesk.cn_bundle.crt** 放置到 **/path/to/your/certs** 目录下。
|
|
||||||
|
|
||||||
### 客户端
|
### 客户端
|
||||||
1. 点击右上角设置进入设置页面。<br>
|
1. 点击右上角设置进入设置页面。<br>
|
||||||
|
|||||||
174
README_EN.md
174
README_EN.md
@@ -187,142 +187,60 @@ sudo docker run -d \
|
|||||||
-e COTURN_PORT=xxxx \
|
-e COTURN_PORT=xxxx \
|
||||||
-e MIN_PORT=xxxxx \
|
-e MIN_PORT=xxxxx \
|
||||||
-e MAX_PORT=xxxxx \
|
-e MAX_PORT=xxxxx \
|
||||||
-v /path/to/your/certs:/crossdesk-server/certs \
|
-v /var/lib/crossdesk:/var/lib/crossdesk \
|
||||||
-v /path/to/your/db:/crossdesk-server/db \
|
-v /var/log/crossdesk:/var/log/crossdesk \
|
||||||
-v /path/to/your/logs:/crossdesk-server/logs \
|
crossdesk/crossdesk-server:v1.1.2
|
||||||
crossdesk/crossdesk-server:v1.1.1
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The parameters you need to pay attention to are as follows:
|
The parameters you need to pay attention to are as follows:
|
||||||
|
|
||||||
- **EXTERNAL_IP**: The server's public IP, corresponding to the **Server Address** in the CrossDesk client **Self-Hosted Server Configuration**.
|
**Parameters**
|
||||||
|
- **EXTERNAL_IP**: The server’s public IP. This corresponds to **Server Address** in the CrossDesk client’s **Self-Hosted Server Configuration**.
|
||||||
|
- **INTERNAL_IP**: The server’s internal IP.
|
||||||
|
- **CROSSDESK_SERVER_PORT**: The port used by the self-hosted service. This corresponds to **Server Port** in the CrossDesk client’s **Self-Hosted Server Configuration**.
|
||||||
|
- **COTURN_PORT**: The port used by the COTURN service. This corresponds to **Relay Service Port** in the CrossDesk client’s **Self-Hosted Server Configuration**.
|
||||||
|
- **MIN_PORT / MAX_PORT**: The port range used by the COTURN service. Example: `MIN_PORT=50000`, `MAX_PORT=60000`. Adjust the range depending on the number of clients.
|
||||||
|
- `-v /var/lib/crossdesk:/var/lib/crossdesk`: Persists database and certificate files on the host machine.
|
||||||
|
- `-v /var/log/crossdesk:/var/log/crossdesk`: Persists log files on the host machine.
|
||||||
|
|
||||||
- **INTERNAL_IP**: The server's internal IP.
|
**Example**:
|
||||||
|
```bash
|
||||||
- **CROSSDESK_SERVER_PORT**: The port used by the self-hosted server, corresponding to the **Server Port** in the CrossDesk client **Self-Hosted Server Configuration**.
|
sudo docker run -d \
|
||||||
|
--name crossdesk_server \
|
||||||
- **COTURN_PORT**: The port used by Coturn, corresponding to the **Relay Server Port** in the CrossDesk client **Self-Hosted Server Configuration**.
|
--network host \
|
||||||
|
-e EXTERNAL_IP=114.114.114.114 \
|
||||||
- **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.
|
-e INTERNAL_IP=10.0.0.1 \
|
||||||
|
-e CROSSDESK_SERVER_PORT=9099 \
|
||||||
- **/path/to/your/certs**: Directory for certificate files.
|
-e COTURN_PORT=3478 \
|
||||||
|
-e MIN_PORT=50000 \
|
||||||
- **/path/to/your/db**: CrossDesk Server device management database.
|
-e MAX_PORT=60000 \
|
||||||
|
-v /var/lib/crossdesk:/var/lib/crossdesk \
|
||||||
- **/path/to/your/logs**: Log directory.
|
-v /var/log/crossdesk:/var/log/crossdesk \
|
||||||
|
crossdesk/crossdesk-server:v1.1.3
|
||||||
**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.**
|
|
||||||
- **The server must open the following ports: 3478/udp, 3478/tcp, 30000-60000/udp, CROSSDESK_SERVER_PORT/tcp.**
|
|
||||||
|
|
||||||
## Certificate Files
|
|
||||||
The client needs to load the root certificate, and the server needs to load the server private key and server certificate.
|
|
||||||
|
|
||||||
If you already have an SSL certificate, you can skip the following certificate generation steps.
|
|
||||||
|
|
||||||
For users without a certificate, you can use the script below to generate the certificate files:
|
|
||||||
```
|
```
|
||||||
# Create certificate generation script
|
|
||||||
vim generate_certs.sh
|
**Notes**
|
||||||
|
- **The server must open the following ports: COTURN_PORT/udp, COTURN_PORT/tcp, MIN_PORT–MAX_PORT/udp, and CROSSDESK_SERVER_PORT/tcp.**
|
||||||
|
- If you don’t mount volumes, all data will be lost when the container is removed.
|
||||||
|
- Certificate files will be automatically generated on first startup and persisted to the host at `/var/lib/crossdesk/certs`.
|
||||||
|
- The database file will be automatically created and stored at `/var/lib/crossdesk/db/crossdesk-server.db`.
|
||||||
|
- Log files will be created and stored at `/var/log/crossdesk/`.
|
||||||
|
|
||||||
|
**Permission Notice**
|
||||||
|
If the directories automatically created by Docker belong to root and have insufficient write permissions, the container user may not be able to write to them. This can cause:
|
||||||
|
- Certificate generation failure, leading to startup script errors and container exit.
|
||||||
|
- Database directory creation failure, causing the program to throw exceptions and crash.
|
||||||
|
- Log directory creation failure, preventing logs from being written (though the program may continue running).
|
||||||
|
|
||||||
|
**Solution:** Manually set permissions before starting the container:
|
||||||
|
```bash
|
||||||
|
sudo mkdir -p /var/lib/crossdesk /var/log/crossdesk
|
||||||
|
sudo chown -R $(id -u):$(id -g) /var/lib/crossdesk /var/log/crossdesk
|
||||||
```
|
```
|
||||||
Copy the following into the script:
|
|
||||||
```
|
|
||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Check arguments
|
### Certificate Files
|
||||||
if [ "$#" -ne 1 ]; then
|
You can find the certificate file `crossdesk.cn_root.crt` at `/var/lib/crossdesk/certs` on the host machine.
|
||||||
echo "Usage: $0 <SERVER_IP>"
|
Download it to your client device and select it in the **Certificate File Path** field under the CrossDesk client’s **Self-Hosted Server Settings**.
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
SERVER_IP="$1"
|
|
||||||
|
|
||||||
# Filenames
|
|
||||||
ROOT_KEY="crossdesk.cn_root.key"
|
|
||||||
ROOT_CERT="crossdesk.cn_root.crt"
|
|
||||||
SERVER_KEY="crossdesk.cn.key"
|
|
||||||
SERVER_CSR="crossdesk.cn.csr"
|
|
||||||
SERVER_CERT="crossdesk.cn_bundle.crt"
|
|
||||||
FULLCHAIN_CERT="crossdesk.cn_fullchain.crt"
|
|
||||||
|
|
||||||
# Certificate subject
|
|
||||||
SUBJ="/C=CN/ST=Zhejiang/L=Hangzhou/O=CrossDesk/OU=CrossDesk/CN=$SERVER_IP"
|
|
||||||
|
|
||||||
# 1. Generate root certificate
|
|
||||||
echo "Generating root private key..."
|
|
||||||
openssl genrsa -out "$ROOT_KEY" 4096
|
|
||||||
|
|
||||||
echo "Generating self-signed root certificate..."
|
|
||||||
openssl req -x509 -new -nodes -key "$ROOT_KEY" -sha256 -days 3650 -out "$ROOT_CERT" -subj "$SUBJ"
|
|
||||||
|
|
||||||
# 2. Generate server private key
|
|
||||||
echo "Generating server private key..."
|
|
||||||
openssl genrsa -out "$SERVER_KEY" 2048
|
|
||||||
|
|
||||||
# 3. Generate server CSR
|
|
||||||
echo "Generating server CSR..."
|
|
||||||
openssl req -new -key "$SERVER_KEY" -out "$SERVER_CSR" -subj "$SUBJ"
|
|
||||||
|
|
||||||
# 4. Create temporary OpenSSL config file with SAN
|
|
||||||
SAN_CONF="san.cnf"
|
|
||||||
cat > $SAN_CONF <<EOL
|
|
||||||
[ req ]
|
|
||||||
default_bits = 2048
|
|
||||||
distinguished_name = req_distinguished_name
|
|
||||||
req_extensions = req_ext
|
|
||||||
prompt = no
|
|
||||||
|
|
||||||
[ req_distinguished_name ]
|
|
||||||
C = CN
|
|
||||||
ST = Zhejiang
|
|
||||||
L = Hangzhou
|
|
||||||
O = CrossDesk
|
|
||||||
OU = CrossDesk
|
|
||||||
CN = $SERVER_IP
|
|
||||||
|
|
||||||
[ req_ext ]
|
|
||||||
subjectAltName = IP:$SERVER_IP
|
|
||||||
EOL
|
|
||||||
|
|
||||||
# 5. Sign server certificate with root certificate (including SAN)
|
|
||||||
echo "Signing server certificate with root certificate..."
|
|
||||||
openssl x509 -req -in "$SERVER_CSR" -CA "$ROOT_CERT" -CAkey "$ROOT_KEY" -CAcreateserial \
|
|
||||||
-out "$SERVER_CERT" -days 3650 -sha256 -extfile "$SAN_CONF" -extensions req_ext
|
|
||||||
|
|
||||||
# 6. Generate full chain certificate
|
|
||||||
cat "$SERVER_CERT" "$ROOT_CERT" > "$FULLCHAIN_CERT"
|
|
||||||
|
|
||||||
# 7. Clean up intermediate files
|
|
||||||
rm -f "$ROOT_CERT.srl" "$SAN_CONF" "$ROOT_KEY" "$SERVER_CSR" "FULLCHAIN_CERT"
|
|
||||||
|
|
||||||
echo "Generation complete. Deployment files:"
|
|
||||||
echo " Client root certificate: $ROOT_CERT"
|
|
||||||
echo " Server private key: $SERVER_KEY"
|
|
||||||
echo " Server certificate: $SERVER_CERT"
|
|
||||||
```
|
|
||||||
Execute:
|
|
||||||
```
|
|
||||||
chmod +x generate_certs.sh
|
|
||||||
./generate_certs.sh EXTERNAL_IP
|
|
||||||
|
|
||||||
# example ./generate_certs.sh 111.111.111.111
|
|
||||||
```
|
|
||||||
Expected output:
|
|
||||||
```
|
|
||||||
Generating root private key...
|
|
||||||
Generating self-signed root certificate...
|
|
||||||
Generating server private key...
|
|
||||||
Generating server CSR...
|
|
||||||
Signing server certificate with root certificate...
|
|
||||||
Certificate request self-signature ok
|
|
||||||
subject=C = CN, ST = Zhejiang, L = Hangzhou, O = CrossDesk, OU = CrossDesk, CN = xxx.xxx.xxx.xxx
|
|
||||||
cleaning up intermediate files...
|
|
||||||
Generation complete. Deployment files::
|
|
||||||
Client root certificate:: crossdesk.cn_root.crt
|
|
||||||
Server private key: crossdesk.cn.key
|
|
||||||
Server certificate: crossdesk.cn_bundle.crt
|
|
||||||
```
|
|
||||||
|
|
||||||
### Server Side
|
### Server Side
|
||||||
Place **crossdesk.cn.key** and **crossdesk.cn_bundle.crt** into the **/path/to/your/certs** directory.
|
Place **crossdesk.cn.key** and **crossdesk.cn_bundle.crt** into the **/path/to/your/certs** directory.
|
||||||
|
|||||||
@@ -41,16 +41,43 @@ 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_);
|
||||||
signal_server_host_ = ini_.GetValue(section_, "signal_server_host",
|
|
||||||
signal_server_host_.c_str());
|
|
||||||
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_ =
|
|
||||||
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_);
|
||||||
|
|
||||||
|
const char* signal_server_host_value =
|
||||||
|
ini_.GetValue(section_, "signal_server_host", nullptr);
|
||||||
|
if (signal_server_host_value != nullptr &&
|
||||||
|
strlen(signal_server_host_value) > 0) {
|
||||||
|
signal_server_host_ = signal_server_host_value;
|
||||||
|
} else {
|
||||||
|
signal_server_host_ = "";
|
||||||
|
}
|
||||||
|
const char* signal_server_port_value =
|
||||||
|
ini_.GetValue(section_, "signal_server_port", nullptr);
|
||||||
|
if (signal_server_port_value != nullptr &&
|
||||||
|
strlen(signal_server_port_value) > 0) {
|
||||||
|
signal_server_port_ =
|
||||||
|
static_cast<int>(ini_.GetLongValue(section_, "signal_server_port", 0));
|
||||||
|
} else {
|
||||||
|
signal_server_port_ = 0;
|
||||||
|
}
|
||||||
|
const char* coturn_server_port_value =
|
||||||
|
ini_.GetValue(section_, "coturn_server_port", nullptr);
|
||||||
|
if (coturn_server_port_value != nullptr &&
|
||||||
|
strlen(coturn_server_port_value) > 0) {
|
||||||
|
coturn_server_port_ =
|
||||||
|
static_cast<int>(ini_.GetLongValue(section_, "coturn_server_port", 0));
|
||||||
|
} else {
|
||||||
|
coturn_server_port_ = 0;
|
||||||
|
}
|
||||||
|
const char* cert_file_path_value =
|
||||||
|
ini_.GetValue(section_, "cert_file_path", nullptr);
|
||||||
|
if (cert_file_path_value != nullptr && strlen(cert_file_path_value) > 0) {
|
||||||
|
cert_file_path_ = cert_file_path_value;
|
||||||
|
} else {
|
||||||
|
cert_file_path_ = "";
|
||||||
|
}
|
||||||
|
|
||||||
enable_autostart_ =
|
enable_autostart_ =
|
||||||
ini_.GetBoolValue(section_, "enable_autostart", enable_autostart_);
|
ini_.GetBoolValue(section_, "enable_autostart", enable_autostart_);
|
||||||
enable_daemon_ = ini_.GetBoolValue(section_, "enable_daemon", enable_daemon_);
|
enable_daemon_ = ini_.GetBoolValue(section_, "enable_daemon", enable_daemon_);
|
||||||
@@ -71,11 +98,18 @@ 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_, "signal_server_host", signal_server_host_.c_str());
|
|
||||||
ini_.SetLongValue(section_, "signal_server_port",
|
|
||||||
static_cast<long>(signal_server_port_));
|
|
||||||
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_);
|
||||||
|
|
||||||
|
// only save when self hosted
|
||||||
|
if (enable_self_hosted_) {
|
||||||
|
ini_.SetValue(section_, "signal_server_host", signal_server_host_.c_str());
|
||||||
|
ini_.SetLongValue(section_, "signal_server_port",
|
||||||
|
static_cast<long>(signal_server_port_));
|
||||||
|
ini_.SetLongValue(section_, "coturn_server_port",
|
||||||
|
static_cast<long>(coturn_server_port_));
|
||||||
|
ini_.SetValue(section_, "cert_file_path", cert_file_path_.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
ini_.SetBoolValue(section_, "enable_autostart", enable_autostart_);
|
ini_.SetBoolValue(section_, "enable_autostart", enable_autostart_);
|
||||||
ini_.SetBoolValue(section_, "enable_daemon", enable_daemon_);
|
ini_.SetBoolValue(section_, "enable_daemon", enable_daemon_);
|
||||||
ini_.SetBoolValue(section_, "enable_minimize_to_tray",
|
ini_.SetBoolValue(section_, "enable_minimize_to_tray",
|
||||||
@@ -210,6 +244,43 @@ int ConfigCenter::SetCertFilePath(const std::string& cert_file_path) {
|
|||||||
int ConfigCenter::SetSelfHosted(bool enable_self_hosted) {
|
int ConfigCenter::SetSelfHosted(bool enable_self_hosted) {
|
||||||
enable_self_hosted_ = enable_self_hosted;
|
enable_self_hosted_ = enable_self_hosted;
|
||||||
ini_.SetBoolValue(section_, "enable_self_hosted", enable_self_hosted_);
|
ini_.SetBoolValue(section_, "enable_self_hosted", enable_self_hosted_);
|
||||||
|
|
||||||
|
// load from config if self hosted is enabled
|
||||||
|
if (enable_self_hosted_) {
|
||||||
|
const char* signal_server_host_value =
|
||||||
|
ini_.GetValue(section_, "signal_server_host", nullptr);
|
||||||
|
if (signal_server_host_value != nullptr &&
|
||||||
|
strlen(signal_server_host_value) > 0) {
|
||||||
|
signal_server_host_ = signal_server_host_value;
|
||||||
|
}
|
||||||
|
const char* signal_server_port_value =
|
||||||
|
ini_.GetValue(section_, "signal_server_port", nullptr);
|
||||||
|
if (signal_server_port_value != nullptr &&
|
||||||
|
strlen(signal_server_port_value) > 0) {
|
||||||
|
signal_server_port_ = static_cast<int>(
|
||||||
|
ini_.GetLongValue(section_, "signal_server_port", 0));
|
||||||
|
}
|
||||||
|
const char* coturn_server_port_value =
|
||||||
|
ini_.GetValue(section_, "coturn_server_port", nullptr);
|
||||||
|
if (coturn_server_port_value != nullptr &&
|
||||||
|
strlen(coturn_server_port_value) > 0) {
|
||||||
|
coturn_server_port_ = static_cast<int>(
|
||||||
|
ini_.GetLongValue(section_, "coturn_server_port", 0));
|
||||||
|
}
|
||||||
|
const char* cert_file_path_value =
|
||||||
|
ini_.GetValue(section_, "cert_file_path", nullptr);
|
||||||
|
if (cert_file_path_value != nullptr && strlen(cert_file_path_value) > 0) {
|
||||||
|
cert_file_path_ = cert_file_path_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ini_.SetValue(section_, "signal_server_host", signal_server_host_.c_str());
|
||||||
|
ini_.SetLongValue(section_, "signal_server_port",
|
||||||
|
static_cast<long>(signal_server_port_));
|
||||||
|
ini_.SetLongValue(section_, "coturn_server_port",
|
||||||
|
static_cast<long>(coturn_server_port_));
|
||||||
|
ini_.SetValue(section_, "cert_file_path", cert_file_path_.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;
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ class ConfigCenter {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::string config_path_;
|
std::string config_path_;
|
||||||
std::string cert_file_path_;
|
|
||||||
CSimpleIniA ini_;
|
CSimpleIniA ini_;
|
||||||
const char* section_ = "Settings";
|
const char* section_ = "Settings";
|
||||||
|
|
||||||
@@ -81,12 +80,13 @@ class ConfigCenter {
|
|||||||
bool hardware_video_codec_ = false;
|
bool hardware_video_codec_ = false;
|
||||||
bool enable_turn_ = true;
|
bool enable_turn_ = true;
|
||||||
bool enable_srtp_ = false;
|
bool enable_srtp_ = false;
|
||||||
std::string signal_server_host_ = "api.crossdesk.cn";
|
std::string signal_server_host_ = "";
|
||||||
std::string signal_server_host_default_ = "api.crossdesk.cn";
|
std::string signal_server_host_default_ = "api.crossdesk.cn";
|
||||||
int signal_server_port_ = 9099;
|
int signal_server_port_ = 0;
|
||||||
int server_port_default_ = 9099;
|
int server_port_default_ = 9099;
|
||||||
int coturn_server_port_ = 3478;
|
int coturn_server_port_ = 0;
|
||||||
int coturn_server_port_default_ = 3478;
|
int coturn_server_port_default_ = 3478;
|
||||||
|
std::string cert_file_path_ = "";
|
||||||
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;
|
bool enable_minimize_to_tray_ = false;
|
||||||
|
|||||||
@@ -233,15 +233,41 @@ int Render::LocalWindow() {
|
|||||||
sizeof(password_saved_) - 1);
|
sizeof(password_saved_) - 1);
|
||||||
password_saved_[sizeof(password_saved_) - 1] = '\0';
|
password_saved_[sizeof(password_saved_) - 1] = '\0';
|
||||||
|
|
||||||
std::string client_id_with_password =
|
// if self hosted
|
||||||
std::string(client_id_) + "@" + password_saved_;
|
if (config_center_->IsSelfHosted()) {
|
||||||
strncpy(client_id_with_password_, client_id_with_password.c_str(),
|
std::string self_hosted_id_str;
|
||||||
sizeof(client_id_with_password_) - 1);
|
if (strlen(self_hosted_id_) > 0) {
|
||||||
client_id_with_password_[sizeof(client_id_with_password_) - 1] =
|
const char* at_pos = strchr(self_hosted_id_, '@');
|
||||||
'\0';
|
if (at_pos != nullptr) {
|
||||||
|
self_hosted_id_str =
|
||||||
|
std::string(self_hosted_id_, at_pos - self_hosted_id_);
|
||||||
|
} else {
|
||||||
|
self_hosted_id_str = self_hosted_id_;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self_hosted_id_str = client_id_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string new_self_hosted_id =
|
||||||
|
self_hosted_id_str + "@" + password_saved_;
|
||||||
|
memset(&self_hosted_id_, 0, sizeof(self_hosted_id_));
|
||||||
|
strncpy(self_hosted_id_, new_self_hosted_id.c_str(),
|
||||||
|
sizeof(self_hosted_id_) - 1);
|
||||||
|
self_hosted_id_[sizeof(self_hosted_id_) - 1] = '\0';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
std::string client_id_with_password =
|
||||||
|
std::string(client_id_) + "@" + password_saved_;
|
||||||
|
strncpy(client_id_with_password_, client_id_with_password.c_str(),
|
||||||
|
sizeof(client_id_with_password_) - 1);
|
||||||
|
client_id_with_password_[sizeof(client_id_with_password_) - 1] =
|
||||||
|
'\0';
|
||||||
|
}
|
||||||
|
|
||||||
SaveSettingsIntoCacheFile();
|
SaveSettingsIntoCacheFile();
|
||||||
|
|
||||||
|
memset(new_password_, 0, sizeof(new_password_));
|
||||||
|
|
||||||
LeaveConnection(peer_, client_id_);
|
LeaveConnection(peer_, client_id_);
|
||||||
DestroyPeer(&peer_);
|
DestroyPeer(&peer_);
|
||||||
focus_on_input_widget_ = true;
|
focus_on_input_widget_ = true;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include "layout_relative.h"
|
||||||
#include "localization.h"
|
#include "localization.h"
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
@@ -5,25 +6,25 @@
|
|||||||
namespace crossdesk {
|
namespace crossdesk {
|
||||||
|
|
||||||
int Render::RecentConnectionsWindow() {
|
int Render::RecentConnectionsWindow() {
|
||||||
ImGui::SetNextWindowPos(
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
ImVec2(0, title_bar_height_ + local_window_height_ - 1.0f),
|
float recent_connection_window_width = io.DisplaySize.x;
|
||||||
ImGuiCond_Always);
|
float recent_connection_window_height =
|
||||||
|
io.DisplaySize.y * (0.46f - STATUS_BAR_HEIGHT);
|
||||||
|
ImGui::SetNextWindowPos(ImVec2(0, io.DisplaySize.y * 0.55f),
|
||||||
|
ImGuiCond_Always);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.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));
|
||||||
ImGui::BeginChild(
|
ImGui::BeginChild(
|
||||||
"RecentConnectionsWindow",
|
"RecentConnectionsWindow",
|
||||||
ImVec2(main_window_width_, main_window_height_ - title_bar_height_ -
|
ImVec2(recent_connection_window_width, recent_connection_window_height),
|
||||||
local_window_height_ - status_bar_height_ +
|
|
||||||
1.0f),
|
|
||||||
ImGuiChildFlags_Border,
|
ImGuiChildFlags_Border,
|
||||||
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse |
|
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove |
|
||||||
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar |
|
|
||||||
ImGuiWindowFlags_NoBringToFrontOnFocus);
|
ImGuiWindowFlags_NoBringToFrontOnFocus);
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
|
|
||||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + main_window_text_y_padding_);
|
ImGui::SetCursorPos(
|
||||||
ImGui::Indent(main_child_window_x_padding_);
|
ImVec2(io.DisplaySize.x * 0.045f, io.DisplaySize.y * 0.02f));
|
||||||
|
|
||||||
ImGui::TextColored(
|
ImGui::TextColored(
|
||||||
ImVec4(0.0f, 0.0f, 0.0f, 0.5f), "%s",
|
ImVec4(0.0f, 0.0f, 0.0f, 0.5f), "%s",
|
||||||
@@ -37,35 +38,40 @@ int Render::RecentConnectionsWindow() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Render::ShowRecentConnections() {
|
int Render::ShowRecentConnections() {
|
||||||
float recent_connection_window_padding = 25.0f * dpi_scale_;
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
float recent_connection_window_width =
|
float recent_connection_panel_width = io.DisplaySize.x * 0.912f;
|
||||||
main_window_width_ - 2 * recent_connection_window_padding;
|
float recent_connection_panel_height = io.DisplaySize.y * 0.29f;
|
||||||
ImGui::SetCursorPosX(recent_connection_window_padding);
|
float recent_connection_image_height = recent_connection_panel_height * 0.6f;
|
||||||
ImVec2 sub_window_pos = ImGui::GetCursorPos();
|
float recent_connection_image_width = recent_connection_image_height * 16 / 9;
|
||||||
std::map<std::string, ImVec2> sub_containers_pos;
|
|
||||||
float recent_connection_sub_container_width =
|
float recent_connection_sub_container_width =
|
||||||
recent_connection_image_width_ + 16.0f * dpi_scale_;
|
recent_connection_image_width * 1.2f;
|
||||||
float recent_connection_sub_container_height =
|
float recent_connection_sub_container_height =
|
||||||
recent_connection_image_height_ + 36.0f * dpi_scale_;
|
recent_connection_image_height * 1.4f;
|
||||||
|
float recent_connection_button_width = recent_connection_image_width * 0.15f;
|
||||||
|
float recent_connection_button_height =
|
||||||
|
recent_connection_image_height * 0.25f;
|
||||||
|
float recent_connection_dummy_button_width =
|
||||||
|
recent_connection_image_width - 2 * recent_connection_button_width;
|
||||||
|
|
||||||
|
ImGui::SetCursorPos(
|
||||||
|
ImVec2(io.DisplaySize.x * 0.045f, io.DisplaySize.y * 0.1f));
|
||||||
|
|
||||||
|
std::map<std::string, ImVec2> sub_containers_pos;
|
||||||
ImGui::PushStyleColor(ImGuiCol_ChildBg,
|
ImGui::PushStyleColor(ImGuiCol_ChildBg,
|
||||||
ImVec4(239.0f / 255, 240.0f / 255, 242.0f / 255, 1.0f));
|
ImVec4(239.0f / 255, 240.0f / 255, 242.0f / 255, 1.0f));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 10.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 10.0f);
|
||||||
ImGui::BeginChild("RecentConnectionsContainer",
|
ImGui::BeginChild(
|
||||||
ImVec2(recent_connection_window_width,
|
"RecentConnectionsContainer",
|
||||||
recent_connection_sub_container_height * 1.1f),
|
ImVec2(recent_connection_panel_width, recent_connection_panel_height),
|
||||||
ImGuiChildFlags_Border,
|
ImGuiChildFlags_Border,
|
||||||
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse |
|
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove |
|
||||||
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar |
|
ImGuiWindowFlags_NoBringToFrontOnFocus |
|
||||||
ImGuiWindowFlags_NoBringToFrontOnFocus |
|
ImGuiWindowFlags_AlwaysHorizontalScrollbar |
|
||||||
ImGuiWindowFlags_AlwaysHorizontalScrollbar |
|
ImGuiWindowFlags_NoScrollWithMouse);
|
||||||
ImGuiWindowFlags_NoScrollbar |
|
|
||||||
ImGuiWindowFlags_NoScrollWithMouse);
|
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
size_t recent_connections_count = recent_connections_.size();
|
size_t recent_connections_count = recent_connections_.size();
|
||||||
int count = 0;
|
int count = 0;
|
||||||
float button_width = 22 * dpi_scale_;
|
|
||||||
float button_height = 22 * dpi_scale_;
|
|
||||||
for (auto& it : recent_connections_) {
|
for (auto& it : recent_connections_) {
|
||||||
sub_containers_pos[it.first] = ImGui::GetCursorPos();
|
sub_containers_pos[it.first] = ImGui::GetCursorPos();
|
||||||
std::string recent_connection_sub_window_name =
|
std::string recent_connection_sub_window_name =
|
||||||
@@ -75,11 +81,8 @@ int Render::ShowRecentConnections() {
|
|||||||
ImVec2(recent_connection_sub_container_width,
|
ImVec2(recent_connection_sub_container_width,
|
||||||
recent_connection_sub_container_height),
|
recent_connection_sub_container_height),
|
||||||
ImGuiChildFlags_None,
|
ImGuiChildFlags_None,
|
||||||
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse |
|
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove |
|
||||||
ImGuiWindowFlags_NoMove |
|
ImGuiWindowFlags_NoBringToFrontOnFocus);
|
||||||
ImGuiWindowFlags_NoTitleBar |
|
|
||||||
ImGuiWindowFlags_NoBringToFrontOnFocus |
|
|
||||||
ImGuiWindowFlags_NoScrollbar);
|
|
||||||
std::string connection_info = it.first;
|
std::string connection_info = it.first;
|
||||||
|
|
||||||
// remote id length is 9
|
// remote id length is 9
|
||||||
@@ -118,15 +121,16 @@ int Render::ShowRecentConnections() {
|
|||||||
it.second.remote_host_name = "unknown";
|
it.second.remote_host_name = "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
ImVec2 image_screen_pos =
|
ImVec2 image_screen_pos = ImVec2(
|
||||||
ImVec2(ImGui::GetCursorScreenPos().x + 5.0f * dpi_scale_,
|
ImGui::GetCursorScreenPos().x + recent_connection_image_width * 0.04f,
|
||||||
ImGui::GetCursorScreenPos().y + 5.0f * dpi_scale_);
|
ImGui::GetCursorScreenPos().y + recent_connection_image_height * 0.08f);
|
||||||
ImVec2 image_pos = ImVec2(ImGui::GetCursorPosX() + 5.0f * dpi_scale_,
|
ImVec2 image_pos =
|
||||||
ImGui::GetCursorPosY() + 5.0f * dpi_scale_);
|
ImVec2(ImGui::GetCursorPosX() + recent_connection_image_width * 0.05f,
|
||||||
|
ImGui::GetCursorPosY() + recent_connection_image_height * 0.08f);
|
||||||
ImGui::SetCursorPos(image_pos);
|
ImGui::SetCursorPos(image_pos);
|
||||||
ImGui::Image((ImTextureID)(intptr_t)it.second.texture,
|
ImGui::Image(
|
||||||
ImVec2((float)recent_connection_image_width_,
|
(ImTextureID)(intptr_t)it.second.texture,
|
||||||
(float)recent_connection_image_height_));
|
ImVec2(recent_connection_image_width, recent_connection_image_height));
|
||||||
|
|
||||||
// remote id display button
|
// remote id display button
|
||||||
{
|
{
|
||||||
@@ -135,16 +139,17 @@ int Render::ShowRecentConnections() {
|
|||||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0, 0, 0, 0.2f));
|
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0, 0, 0, 0.2f));
|
||||||
|
|
||||||
ImVec2 dummy_button_pos =
|
ImVec2 dummy_button_pos =
|
||||||
ImVec2(image_pos.x, image_pos.y + recent_connection_image_height_);
|
ImVec2(image_pos.x, image_pos.y + recent_connection_image_height);
|
||||||
std::string dummy_button_name = "##DummyButton" + it.second.remote_id;
|
std::string dummy_button_name = "##DummyButton" + it.second.remote_id;
|
||||||
ImGui::SetCursorPos(dummy_button_pos);
|
ImGui::SetCursorPos(dummy_button_pos);
|
||||||
ImGui::SetWindowFontScale(0.6f);
|
ImGui::SetWindowFontScale(0.6f);
|
||||||
ImGui::Button(dummy_button_name.c_str(),
|
ImGui::Button(dummy_button_name.c_str(),
|
||||||
ImVec2(recent_connection_image_width_ - 2 * button_width,
|
ImVec2(recent_connection_dummy_button_width,
|
||||||
button_height));
|
recent_connection_button_height));
|
||||||
ImGui::SetWindowFontScale(1.0f);
|
ImGui::SetWindowFontScale(1.0f);
|
||||||
ImGui::SetCursorPos(
|
ImGui::SetCursorPos(ImVec2(
|
||||||
ImVec2(dummy_button_pos.x + 2.0f, dummy_button_pos.y + 1.0f));
|
dummy_button_pos.x + recent_connection_dummy_button_width * 0.05f,
|
||||||
|
dummy_button_pos.y + recent_connection_button_height * 0.05f));
|
||||||
ImGui::SetWindowFontScale(0.65f);
|
ImGui::SetWindowFontScale(0.65f);
|
||||||
ImGui::Text("%s", it.second.remote_id.c_str());
|
ImGui::Text("%s", it.second.remote_id.c_str());
|
||||||
ImGui::SetWindowFontScale(1.0f);
|
ImGui::SetWindowFontScale(1.0f);
|
||||||
@@ -167,16 +172,18 @@ int Render::ShowRecentConnections() {
|
|||||||
ImGui::SetWindowFontScale(0.5f);
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
// trash button
|
// trash button
|
||||||
{
|
{
|
||||||
ImVec2 trash_can_button_pos = ImVec2(
|
ImVec2 trash_can_button_pos =
|
||||||
image_pos.x + recent_connection_image_width_ - 2 * button_width,
|
ImVec2(image_pos.x + recent_connection_image_width -
|
||||||
image_pos.y + recent_connection_image_height_);
|
2 * recent_connection_button_width,
|
||||||
|
image_pos.y + recent_connection_image_height);
|
||||||
ImGui::SetCursorPos(trash_can_button_pos);
|
ImGui::SetCursorPos(trash_can_button_pos);
|
||||||
std::string trash_can = ICON_FA_TRASH_CAN;
|
std::string trash_can = ICON_FA_TRASH_CAN;
|
||||||
std::string recent_connection_delete_button_name =
|
std::string recent_connection_delete_button_name =
|
||||||
trash_can + "##RecentConnectionDelete" +
|
trash_can + "##RecentConnectionDelete" +
|
||||||
std::to_string(trash_can_button_pos.x);
|
std::to_string(trash_can_button_pos.x);
|
||||||
if (ImGui::Button(recent_connection_delete_button_name.c_str(),
|
if (ImGui::Button(recent_connection_delete_button_name.c_str(),
|
||||||
ImVec2(button_width, button_height))) {
|
ImVec2(recent_connection_button_width,
|
||||||
|
recent_connection_button_height))) {
|
||||||
show_confirm_delete_connection_ = true;
|
show_confirm_delete_connection_ = true;
|
||||||
delete_connection_name_ = it.first;
|
delete_connection_name_ = it.first;
|
||||||
}
|
}
|
||||||
@@ -192,14 +199,16 @@ int Render::ShowRecentConnections() {
|
|||||||
// connect button
|
// connect button
|
||||||
{
|
{
|
||||||
ImVec2 connect_button_pos =
|
ImVec2 connect_button_pos =
|
||||||
ImVec2(image_pos.x + recent_connection_image_width_ - button_width,
|
ImVec2(image_pos.x + recent_connection_image_width -
|
||||||
image_pos.y + recent_connection_image_height_);
|
recent_connection_button_width,
|
||||||
|
image_pos.y + recent_connection_image_height);
|
||||||
ImGui::SetCursorPos(connect_button_pos);
|
ImGui::SetCursorPos(connect_button_pos);
|
||||||
std::string connect = ICON_FA_ARROW_RIGHT_LONG;
|
std::string connect = ICON_FA_ARROW_RIGHT_LONG;
|
||||||
std::string connect_to_this_connection_button_name =
|
std::string connect_to_this_connection_button_name =
|
||||||
connect + "##ConnectionTo" + it.first;
|
connect + "##ConnectionTo" + it.first;
|
||||||
if (ImGui::Button(connect_to_this_connection_button_name.c_str(),
|
if (ImGui::Button(connect_to_this_connection_button_name.c_str(),
|
||||||
ImVec2(button_width, button_height))) {
|
ImVec2(recent_connection_button_width,
|
||||||
|
recent_connection_button_height))) {
|
||||||
ConnectTo(it.second.remote_id, it.second.password.c_str(),
|
ConnectTo(it.second.remote_id, it.second.password.c_str(),
|
||||||
it.second.remember_password);
|
it.second.remember_password);
|
||||||
}
|
}
|
||||||
@@ -211,20 +220,20 @@ int Render::ShowRecentConnections() {
|
|||||||
|
|
||||||
if (count != recent_connections_count - 1) {
|
if (count != recent_connections_count - 1) {
|
||||||
ImVec2 line_start =
|
ImVec2 line_start =
|
||||||
ImVec2(image_screen_pos.x + recent_connection_image_width_ +
|
ImVec2(image_screen_pos.x + recent_connection_image_width * 1.19f,
|
||||||
20.0f * dpi_scale_,
|
|
||||||
image_screen_pos.y);
|
image_screen_pos.y);
|
||||||
ImVec2 line_end = ImVec2(
|
ImVec2 line_end =
|
||||||
image_screen_pos.x + recent_connection_image_width_ +
|
ImVec2(image_screen_pos.x + recent_connection_image_width * 1.19f,
|
||||||
20.0f * dpi_scale_,
|
image_screen_pos.y + recent_connection_image_height +
|
||||||
image_screen_pos.y + recent_connection_image_height_ + button_height);
|
recent_connection_button_height);
|
||||||
ImGui::GetWindowDrawList()->AddLine(line_start, line_end,
|
ImGui::GetWindowDrawList()->AddLine(line_start, line_end,
|
||||||
IM_COL32(0, 0, 0, 122), 1.0f);
|
IM_COL32(0, 0, 0, 122), 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
ImGui::SameLine(
|
ImGui::SameLine(0, count != recent_connections_count
|
||||||
0, count != recent_connections_count ? (25.0f * dpi_scale_) : 0.0f);
|
? (recent_connection_image_width * 0.165f)
|
||||||
|
: 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
@@ -237,32 +246,30 @@ int Render::ShowRecentConnections() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Render::ConfirmDeleteConnection() {
|
int Render::ConfirmDeleteConnection() {
|
||||||
const ImGuiViewport* viewport = ImGui::GetMainViewport();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
ImGui::SetNextWindowPos(ImVec2((viewport->WorkSize.x - viewport->WorkPos.x -
|
ImGui::SetNextWindowPos(
|
||||||
connection_status_window_width_) /
|
ImVec2(io.DisplaySize.x * 0.33f, io.DisplaySize.y * 0.33f));
|
||||||
2,
|
ImGui::SetNextWindowSize(
|
||||||
(viewport->WorkSize.y - viewport->WorkPos.y -
|
ImVec2(io.DisplaySize.x * 0.33f, io.DisplaySize.y * 0.33f));
|
||||||
connection_status_window_height_) /
|
|
||||||
2));
|
|
||||||
|
|
||||||
ImGui::SetNextWindowSize(ImVec2(connection_status_window_width_,
|
|
||||||
connection_status_window_height_));
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
|
||||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0, 1.0, 1.0, 1.0));
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0, 1.0, 1.0, 1.0));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 5.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 5.0f);
|
||||||
|
|
||||||
ImGui::Begin("ConfirmDeleteConnectionWindow", nullptr,
|
ImGui::Begin("ConfirmDeleteConnectionWindow", nullptr,
|
||||||
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse |
|
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove |
|
||||||
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar |
|
|
||||||
ImGuiWindowFlags_NoSavedSettings);
|
ImGuiWindowFlags_NoSavedSettings);
|
||||||
ImGui::PopStyleVar(2);
|
ImGui::PopStyleVar(2);
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
|
|
||||||
|
auto connection_status_window_width = ImGui::GetWindowSize().x;
|
||||||
|
auto connection_status_window_height = ImGui::GetWindowSize().y;
|
||||||
|
|
||||||
std::string text =
|
std::string text =
|
||||||
localization::confirm_delete_connection[localization_language_index_];
|
localization::confirm_delete_connection[localization_language_index_];
|
||||||
ImGui::SetCursorPosX(connection_status_window_width_ * 6 / 19);
|
ImGui::SetCursorPosX(connection_status_window_width * 0.33f);
|
||||||
ImGui::SetCursorPosY(connection_status_window_height_ * 2 / 3);
|
ImGui::SetCursorPosY(connection_status_window_height * 0.67f);
|
||||||
|
|
||||||
// ok
|
// ok
|
||||||
ImGui::SetWindowFontScale(0.5f);
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
@@ -281,12 +288,9 @@ int Render::ConfirmDeleteConnection() {
|
|||||||
show_confirm_delete_connection_ = false;
|
show_confirm_delete_connection_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto window_width = ImGui::GetWindowSize().x;
|
|
||||||
auto window_height = ImGui::GetWindowSize().y;
|
|
||||||
|
|
||||||
auto text_width = ImGui::CalcTextSize(text.c_str()).x;
|
auto text_width = ImGui::CalcTextSize(text.c_str()).x;
|
||||||
ImGui::SetCursorPosX((window_width - text_width) * 0.5f);
|
ImGui::SetCursorPosX((connection_status_window_width - text_width) * 0.5f);
|
||||||
ImGui::SetCursorPosY(window_height * 0.2f);
|
ImGui::SetCursorPosY(connection_status_window_height * 0.2f);
|
||||||
ImGui::Text("%s", text.c_str());
|
ImGui::Text("%s", text.c_str());
|
||||||
ImGui::SetWindowFontScale(1.0f);
|
ImGui::SetWindowFontScale(1.0f);
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ int Render::RemoteWindow() {
|
|||||||
float remote_window_width = io.DisplaySize.x * 0.5f;
|
float remote_window_width = io.DisplaySize.x * 0.5f;
|
||||||
float remote_window_height =
|
float remote_window_height =
|
||||||
io.DisplaySize.y * (1 - TITLE_BAR_HEIGHT - STATUS_BAR_HEIGHT);
|
io.DisplaySize.y * (1 - TITLE_BAR_HEIGHT - STATUS_BAR_HEIGHT);
|
||||||
float remote_window_button_width = io.DisplaySize.x * 0.046f;
|
float remote_window_arrow_button_width = io.DisplaySize.x * 0.1f;
|
||||||
float remote_window_button_height = io.DisplaySize.y * 0.075f;
|
float remote_window_arrow_button_height = io.DisplaySize.y * 0.078f;
|
||||||
|
|
||||||
ImGui::SetNextWindowPos(
|
ImGui::SetNextWindowPos(
|
||||||
ImVec2(io.DisplaySize.x * 0.5f, io.DisplaySize.y * TITLE_BAR_HEIGHT),
|
ImVec2(io.DisplaySize.x * 0.5f, io.DisplaySize.y * TITLE_BAR_HEIGHT),
|
||||||
@@ -29,7 +29,7 @@ int Render::RemoteWindow() {
|
|||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
|
|
||||||
ImGui::SetCursorPos(
|
ImGui::SetCursorPos(
|
||||||
ImVec2(io.DisplaySize.x * 0.545f, io.DisplaySize.y * 0.02f));
|
ImVec2(io.DisplaySize.x * 0.057f, io.DisplaySize.y * 0.02f));
|
||||||
|
|
||||||
ImGui::TextColored(
|
ImGui::TextColored(
|
||||||
ImVec4(0.0f, 0.0f, 0.0f, 0.5f), "%s",
|
ImVec4(0.0f, 0.0f, 0.0f, 0.5f), "%s",
|
||||||
@@ -38,7 +38,7 @@ int Render::RemoteWindow() {
|
|||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
{
|
{
|
||||||
ImGui::SetNextWindowPos(
|
ImGui::SetNextWindowPos(
|
||||||
ImVec2(io.DisplaySize.x * 0.56f, io.DisplaySize.y * 0.15f),
|
ImVec2(io.DisplaySize.x * 0.557f, io.DisplaySize.y * 0.15f),
|
||||||
ImGuiCond_Always);
|
ImGuiCond_Always);
|
||||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(239.0f / 255, 240.0f / 255,
|
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(239.0f / 255, 240.0f / 255,
|
||||||
242.0f / 255, 1.0f));
|
242.0f / 255, 1.0f));
|
||||||
@@ -58,7 +58,7 @@ int Render::RemoteWindow() {
|
|||||||
"%s", localization::remote_id[localization_language_index_].c_str());
|
"%s", localization::remote_id[localization_language_index_].c_str());
|
||||||
|
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
ImGui::SetNextItemWidth(IPUT_WINDOW_WIDTH);
|
ImGui::SetNextItemWidth(io.DisplaySize.x * 0.25f);
|
||||||
ImGui::SetWindowFontScale(1.0f);
|
ImGui::SetWindowFontScale(1.0f);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
|
||||||
if (re_enter_remote_id_) {
|
if (re_enter_remote_id_) {
|
||||||
@@ -81,7 +81,8 @@ int Render::RemoteWindow() {
|
|||||||
static_cast<int (*)(int)>(&isspace)),
|
static_cast<int (*)(int)>(&isspace)),
|
||||||
remote_id.end());
|
remote_id.end());
|
||||||
if (ImGui::Button(ICON_FA_ARROW_RIGHT_LONG,
|
if (ImGui::Button(ICON_FA_ARROW_RIGHT_LONG,
|
||||||
ImVec2(55 * dpi_scale_, 38 * dpi_scale_)) ||
|
ImVec2(remote_window_arrow_button_width,
|
||||||
|
remote_window_arrow_button_height)) ||
|
||||||
enter_pressed) {
|
enter_pressed) {
|
||||||
connect_button_pressed_ = true;
|
connect_button_pressed_ = true;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
@@ -187,20 +188,13 @@ int Render::ConnectTo(const std::string& remote_id, const char* password,
|
|||||||
memcpy(&props->params_, ¶ms_, sizeof(Params));
|
memcpy(&props->params_, ¶ms_, sizeof(Params));
|
||||||
props->params_.user_id = props->local_id_.c_str();
|
props->params_.user_id = props->local_id_.c_str();
|
||||||
props->peer_ = CreatePeer(&props->params_);
|
props->peer_ = CreatePeer(&props->params_);
|
||||||
props->control_window_min_width_ =
|
|
||||||
props->control_window_min_width_ * dpi_scale_;
|
props->control_window_width_ = title_bar_height_ * 8.0f;
|
||||||
props->control_window_min_height_ =
|
props->control_window_height_ = title_bar_height_ * 1.3f;
|
||||||
props->control_window_min_height_ * dpi_scale_;
|
props->control_window_min_width_ = title_bar_height_ * 0.65f;
|
||||||
props->control_window_max_width_ =
|
props->control_window_min_height_ = title_bar_height_ * 1.3f;
|
||||||
props->control_window_max_width_ * dpi_scale_;
|
props->control_window_max_width_ = title_bar_height_ * 8.0f;
|
||||||
props->control_window_max_height_ =
|
props->control_window_max_height_ = title_bar_height_ * 6.0f;
|
||||||
props->control_window_max_height_ * dpi_scale_;
|
|
||||||
props->control_window_width_ =
|
|
||||||
props->control_window_width_ * dpi_scale_;
|
|
||||||
props->control_window_height_ =
|
|
||||||
props->control_window_height_ * dpi_scale_;
|
|
||||||
// props->control_bar_pos_x_ = props->control_bar_pos_x_ * dpi_scale_;
|
|
||||||
// props->control_bar_pos_y_ = props->control_bar_pos_y_ * dpi_scale_;
|
|
||||||
|
|
||||||
if (!props->peer_) {
|
if (!props->peer_) {
|
||||||
LOG_INFO("Create peer [{}] instance failed", props->local_id_);
|
LOG_INFO("Create peer [{}] instance failed", props->local_id_);
|
||||||
|
|||||||
@@ -6,12 +6,13 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#include "OPPOSans_Regular.h"
|
#include "OPPOSans_Regular.h"
|
||||||
#include "device_controller_factory.h"
|
#include "device_controller_factory.h"
|
||||||
#include "fa_regular_400.h"
|
#include "fa_regular_400.h"
|
||||||
#include "fa_solid_900.h"
|
#include "fa_solid_900.h"
|
||||||
#include "layout.h"
|
#include "layout_relative.h"
|
||||||
#include "localization.h"
|
#include "localization.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
@@ -20,8 +21,6 @@
|
|||||||
|
|
||||||
#define NV12_BUFFER_SIZE 1280 * 720 * 3 / 2
|
#define NV12_BUFFER_SIZE 1280 * 720 * 3 / 2
|
||||||
|
|
||||||
#define MOUSE_GRAB_PADDING 5
|
|
||||||
|
|
||||||
namespace crossdesk {
|
namespace crossdesk {
|
||||||
|
|
||||||
std::vector<char> Render::SerializeRemoteAction(const RemoteAction& action) {
|
std::vector<char> Render::SerializeRemoteAction(const RemoteAction& action) {
|
||||||
@@ -133,9 +132,39 @@ SDL_HitTestResult Render::HitTestCallback(SDL_Window* window,
|
|||||||
int window_width, window_height;
|
int window_width, window_height;
|
||||||
SDL_GetWindowSize(window, &window_width, &window_height);
|
SDL_GetWindowSize(window, &window_width, &window_height);
|
||||||
|
|
||||||
if (area->y < 30 * render->dpi_scale_ && area->y > MOUSE_GRAB_PADDING &&
|
// check if curosor is in tab bar
|
||||||
area->x < window_width - 120 * render->dpi_scale_ &&
|
if (render->stream_window_inited_ && render->stream_window_created_ &&
|
||||||
area->x > MOUSE_GRAB_PADDING && !render->is_tab_bar_hovered_) {
|
!render->fullscreen_button_pressed_ && render->stream_ctx_) {
|
||||||
|
ImGuiContext* prev_ctx = ImGui::GetCurrentContext();
|
||||||
|
ImGui::SetCurrentContext(render->stream_ctx_);
|
||||||
|
|
||||||
|
ImGuiWindow* tab_bar_window = ImGui::FindWindowByName("TabBar");
|
||||||
|
if (tab_bar_window && tab_bar_window->Active) {
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
float scale_x = io.DisplayFramebufferScale.x;
|
||||||
|
float scale_y = io.DisplayFramebufferScale.y;
|
||||||
|
|
||||||
|
float tab_bar_x = tab_bar_window->Pos.x * scale_x;
|
||||||
|
float tab_bar_y = tab_bar_window->Pos.y * scale_y;
|
||||||
|
float tab_bar_width = tab_bar_window->Size.x * scale_x;
|
||||||
|
float tab_bar_height = tab_bar_window->Size.y * scale_y;
|
||||||
|
|
||||||
|
ImGui::SetCurrentContext(prev_ctx);
|
||||||
|
|
||||||
|
if (area->x >= tab_bar_x && area->x <= tab_bar_x + tab_bar_width &&
|
||||||
|
area->y >= tab_bar_y && area->y <= tab_bar_y + tab_bar_height) {
|
||||||
|
return SDL_HITTEST_NORMAL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ImGui::SetCurrentContext(prev_ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float mouse_grab_padding = render->title_bar_button_width_ * 0.16f;
|
||||||
|
if (area->y < render->title_bar_button_width_ &&
|
||||||
|
area->y > mouse_grab_padding &&
|
||||||
|
area->x < window_width - render->title_bar_button_width_ * 4.0f &&
|
||||||
|
area->x > mouse_grab_padding) {
|
||||||
return SDL_HITTEST_DRAGGABLE;
|
return SDL_HITTEST_DRAGGABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,25 +172,25 @@ SDL_HitTestResult Render::HitTestCallback(SDL_Window* window,
|
|||||||
// return SDL_HITTEST_NORMAL;
|
// return SDL_HITTEST_NORMAL;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if (area->y < MOUSE_GRAB_PADDING) {
|
if (area->y < mouse_grab_padding) {
|
||||||
if (area->x < MOUSE_GRAB_PADDING) {
|
if (area->x < mouse_grab_padding) {
|
||||||
return SDL_HITTEST_RESIZE_TOPLEFT;
|
return SDL_HITTEST_RESIZE_TOPLEFT;
|
||||||
} else if (area->x > window_width - MOUSE_GRAB_PADDING) {
|
} else if (area->x > window_width - mouse_grab_padding) {
|
||||||
return SDL_HITTEST_RESIZE_TOPRIGHT;
|
return SDL_HITTEST_RESIZE_TOPRIGHT;
|
||||||
} else {
|
} else {
|
||||||
return SDL_HITTEST_RESIZE_TOP;
|
return SDL_HITTEST_RESIZE_TOP;
|
||||||
}
|
}
|
||||||
} else if (area->y > window_height - MOUSE_GRAB_PADDING) {
|
} else if (area->y > window_height - mouse_grab_padding) {
|
||||||
if (area->x < MOUSE_GRAB_PADDING) {
|
if (area->x < mouse_grab_padding) {
|
||||||
return SDL_HITTEST_RESIZE_BOTTOMLEFT;
|
return SDL_HITTEST_RESIZE_BOTTOMLEFT;
|
||||||
} else if (area->x > window_width - MOUSE_GRAB_PADDING) {
|
} else if (area->x > window_width - mouse_grab_padding) {
|
||||||
return SDL_HITTEST_RESIZE_BOTTOMRIGHT;
|
return SDL_HITTEST_RESIZE_BOTTOMRIGHT;
|
||||||
} else {
|
} else {
|
||||||
return SDL_HITTEST_RESIZE_BOTTOM;
|
return SDL_HITTEST_RESIZE_BOTTOM;
|
||||||
}
|
}
|
||||||
} else if (area->x < MOUSE_GRAB_PADDING) {
|
} else if (area->x < mouse_grab_padding) {
|
||||||
return SDL_HITTEST_RESIZE_LEFT;
|
return SDL_HITTEST_RESIZE_LEFT;
|
||||||
} else if (area->x > window_width - MOUSE_GRAB_PADDING) {
|
} else if (area->x > window_width - mouse_grab_padding) {
|
||||||
return SDL_HITTEST_RESIZE_RIGHT;
|
return SDL_HITTEST_RESIZE_RIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,22 +203,41 @@ Render::~Render() {}
|
|||||||
|
|
||||||
int Render::SaveSettingsIntoCacheFile() {
|
int Render::SaveSettingsIntoCacheFile() {
|
||||||
cd_cache_mutex_.lock();
|
cd_cache_mutex_.lock();
|
||||||
std::ofstream cd_cache_file(cache_path_ + "/secure_cache.enc",
|
|
||||||
std::ios::binary);
|
std::ofstream cd_cache_v2_file(cache_path_ + "/secure_cache_v2.enc",
|
||||||
if (!cd_cache_file) {
|
std::ios::binary);
|
||||||
|
if (!cd_cache_v2_file) {
|
||||||
cd_cache_mutex_.unlock();
|
cd_cache_mutex_.unlock();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&cd_cache_.client_id_with_password, 0,
|
memset(&cd_cache_v2_.client_id_with_password, 0,
|
||||||
sizeof(cd_cache_.client_id_with_password));
|
sizeof(cd_cache_v2_.client_id_with_password));
|
||||||
memcpy(cd_cache_.client_id_with_password, client_id_with_password_,
|
memcpy(cd_cache_v2_.client_id_with_password, client_id_with_password_,
|
||||||
sizeof(client_id_with_password_));
|
sizeof(client_id_with_password_));
|
||||||
memcpy(&cd_cache_.key, &aes128_key_, sizeof(aes128_key_));
|
memcpy(&cd_cache_v2_.key, &aes128_key_, sizeof(aes128_key_));
|
||||||
memcpy(&cd_cache_.iv, &aes128_iv_, sizeof(aes128_iv_));
|
memcpy(&cd_cache_v2_.iv, &aes128_iv_, sizeof(aes128_iv_));
|
||||||
|
|
||||||
|
memset(&cd_cache_v2_.self_hosted_id, 0, sizeof(cd_cache_v2_.self_hosted_id));
|
||||||
|
memcpy(cd_cache_v2_.self_hosted_id, self_hosted_id_, sizeof(self_hosted_id_));
|
||||||
|
|
||||||
|
cd_cache_v2_file.write(reinterpret_cast<char*>(&cd_cache_v2_),
|
||||||
|
sizeof(CDCacheV2));
|
||||||
|
cd_cache_v2_file.close();
|
||||||
|
|
||||||
|
std::ofstream cd_cache_file(cache_path_ + "/secure_cache.enc",
|
||||||
|
std::ios::binary);
|
||||||
|
if (cd_cache_file) {
|
||||||
|
memset(&cd_cache_.client_id_with_password, 0,
|
||||||
|
sizeof(cd_cache_.client_id_with_password));
|
||||||
|
memcpy(cd_cache_.client_id_with_password, client_id_with_password_,
|
||||||
|
sizeof(client_id_with_password_));
|
||||||
|
memcpy(&cd_cache_.key, &aes128_key_, sizeof(aes128_key_));
|
||||||
|
memcpy(&cd_cache_.iv, &aes128_iv_, sizeof(aes128_iv_));
|
||||||
|
cd_cache_file.write(reinterpret_cast<char*>(&cd_cache_), sizeof(CDCache));
|
||||||
|
cd_cache_file.close();
|
||||||
|
}
|
||||||
|
|
||||||
cd_cache_file.write(reinterpret_cast<char*>(&cd_cache_), sizeof(CDCache));
|
|
||||||
cd_cache_file.close();
|
|
||||||
cd_cache_mutex_.unlock();
|
cd_cache_mutex_.unlock();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -197,33 +245,81 @@ int Render::SaveSettingsIntoCacheFile() {
|
|||||||
|
|
||||||
int Render::LoadSettingsFromCacheFile() {
|
int Render::LoadSettingsFromCacheFile() {
|
||||||
cd_cache_mutex_.lock();
|
cd_cache_mutex_.lock();
|
||||||
std::ifstream cd_cache_file(cache_path_ + "/secure_cache.enc",
|
|
||||||
std::ios::binary);
|
std::ifstream cd_cache_v2_file(cache_path_ + "/secure_cache_v2.enc",
|
||||||
if (!cd_cache_file) {
|
std::ios::binary);
|
||||||
|
bool v2_file_exists = cd_cache_v2_file.good();
|
||||||
|
|
||||||
|
if (v2_file_exists) {
|
||||||
|
cd_cache_v2_file.read(reinterpret_cast<char*>(&cd_cache_v2_),
|
||||||
|
sizeof(CDCacheV2));
|
||||||
|
cd_cache_v2_file.close();
|
||||||
|
|
||||||
|
memset(&client_id_with_password_, 0, sizeof(client_id_with_password_));
|
||||||
|
memcpy(client_id_with_password_, cd_cache_v2_.client_id_with_password,
|
||||||
|
sizeof(client_id_with_password_));
|
||||||
|
|
||||||
|
memset(&self_hosted_id_, 0, sizeof(self_hosted_id_));
|
||||||
|
memcpy(self_hosted_id_, cd_cache_v2_.self_hosted_id,
|
||||||
|
sizeof(self_hosted_id_));
|
||||||
|
|
||||||
|
memcpy(aes128_key_, cd_cache_v2_.key, sizeof(cd_cache_v2_.key));
|
||||||
|
memcpy(aes128_iv_, cd_cache_v2_.iv, sizeof(cd_cache_v2_.iv));
|
||||||
|
|
||||||
|
LOG_INFO("Load settings from v2 cache file");
|
||||||
|
} else {
|
||||||
|
std::ifstream cd_cache_file(cache_path_ + "/secure_cache.enc",
|
||||||
|
std::ios::binary);
|
||||||
|
if (!cd_cache_file) {
|
||||||
|
cd_cache_mutex_.unlock();
|
||||||
|
|
||||||
|
memset(password_saved_, 0, sizeof(password_saved_));
|
||||||
|
memset(aes128_key_, 0, sizeof(aes128_key_));
|
||||||
|
memset(aes128_iv_, 0, sizeof(aes128_iv_));
|
||||||
|
memset(self_hosted_id_, 0, sizeof(self_hosted_id_));
|
||||||
|
|
||||||
|
thumbnail_.reset();
|
||||||
|
thumbnail_ = std::make_shared<Thumbnail>(cache_path_ + "/thumbnails/");
|
||||||
|
thumbnail_->GetKeyAndIv(aes128_key_, aes128_iv_);
|
||||||
|
thumbnail_->DeleteAllFilesInDirectory();
|
||||||
|
|
||||||
|
SaveSettingsIntoCacheFile();
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cd_cache_file.read(reinterpret_cast<char*>(&cd_cache_), sizeof(CDCache));
|
||||||
|
cd_cache_file.close();
|
||||||
|
|
||||||
|
memset(&cd_cache_v2_.client_id_with_password, 0,
|
||||||
|
sizeof(cd_cache_v2_.client_id_with_password));
|
||||||
|
memcpy(cd_cache_v2_.client_id_with_password,
|
||||||
|
cd_cache_.client_id_with_password,
|
||||||
|
sizeof(cd_cache_.client_id_with_password));
|
||||||
|
memcpy(&cd_cache_v2_.key, &cd_cache_.key, sizeof(cd_cache_.key));
|
||||||
|
memcpy(&cd_cache_v2_.iv, &cd_cache_.iv, sizeof(cd_cache_.iv));
|
||||||
|
|
||||||
|
memset(&cd_cache_v2_.self_hosted_id, 0,
|
||||||
|
sizeof(cd_cache_v2_.self_hosted_id));
|
||||||
|
|
||||||
|
memset(&client_id_with_password_, 0, sizeof(client_id_with_password_));
|
||||||
|
memcpy(client_id_with_password_, cd_cache_.client_id_with_password,
|
||||||
|
sizeof(client_id_with_password_));
|
||||||
|
|
||||||
|
memset(&self_hosted_id_, 0, sizeof(self_hosted_id_));
|
||||||
|
|
||||||
|
memcpy(aes128_key_, cd_cache_.key, sizeof(cd_cache_.key));
|
||||||
|
memcpy(aes128_iv_, cd_cache_.iv, sizeof(cd_cache_.iv));
|
||||||
|
|
||||||
cd_cache_mutex_.unlock();
|
cd_cache_mutex_.unlock();
|
||||||
|
|
||||||
memset(password_saved_, 0, sizeof(password_saved_));
|
|
||||||
memset(aes128_key_, 0, sizeof(aes128_key_));
|
|
||||||
memset(aes128_iv_, 0, sizeof(aes128_iv_));
|
|
||||||
|
|
||||||
thumbnail_.reset();
|
|
||||||
thumbnail_ = std::make_unique<Thumbnail>(cache_path_ + "/thumbnails/");
|
|
||||||
thumbnail_->GetKeyAndIv(aes128_key_, aes128_iv_);
|
|
||||||
thumbnail_->DeleteAllFilesInDirectory();
|
|
||||||
|
|
||||||
SaveSettingsIntoCacheFile();
|
SaveSettingsIntoCacheFile();
|
||||||
|
cd_cache_mutex_.lock();
|
||||||
|
|
||||||
return -1;
|
LOG_INFO("Migrated settings from v1 to v2 cache file");
|
||||||
}
|
}
|
||||||
|
|
||||||
cd_cache_file.read(reinterpret_cast<char*>(&cd_cache_), sizeof(CDCache));
|
|
||||||
cd_cache_file.close();
|
|
||||||
cd_cache_mutex_.unlock();
|
cd_cache_mutex_.unlock();
|
||||||
|
|
||||||
memset(&client_id_with_password_, 0, sizeof(client_id_with_password_));
|
|
||||||
memcpy(client_id_with_password_, cd_cache_.client_id_with_password,
|
|
||||||
sizeof(client_id_with_password_));
|
|
||||||
|
|
||||||
if (strchr(client_id_with_password_, '@') != nullptr) {
|
if (strchr(client_id_with_password_, '@') != nullptr) {
|
||||||
std::string id, password;
|
std::string id, password;
|
||||||
const char* at_pos = strchr(client_id_with_password_, '@');
|
const char* at_pos = strchr(client_id_with_password_, '@');
|
||||||
@@ -244,11 +340,8 @@ int Render::LoadSettingsFromCacheFile() {
|
|||||||
password_saved_[sizeof(password_saved_) - 1] = '\0';
|
password_saved_[sizeof(password_saved_) - 1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(aes128_key_, cd_cache_.key, sizeof(cd_cache_.key));
|
|
||||||
memcpy(aes128_iv_, cd_cache_.iv, sizeof(cd_cache_.iv));
|
|
||||||
|
|
||||||
thumbnail_.reset();
|
thumbnail_.reset();
|
||||||
thumbnail_ = std::make_unique<Thumbnail>(cache_path_ + "/thumbnails/",
|
thumbnail_ = std::make_shared<Thumbnail>(cache_path_ + "/thumbnails/",
|
||||||
aes128_key_, aes128_iv_);
|
aes128_key_, aes128_iv_);
|
||||||
|
|
||||||
language_button_value_ = (int)config_center_->GetLanguage();
|
language_button_value_ = (int)config_center_->GetLanguage();
|
||||||
@@ -451,25 +544,90 @@ int Render::CreateConnectionPeer() {
|
|||||||
signal_server_port = config_center_->GetSignalServerPort();
|
signal_server_port = config_center_->GetSignalServerPort();
|
||||||
coturn_server_port = config_center_->GetCoturnServerPort();
|
coturn_server_port = config_center_->GetCoturnServerPort();
|
||||||
tls_cert_path = config_center_->GetCertFilePath();
|
tls_cert_path = config_center_->GetCertFilePath();
|
||||||
|
|
||||||
|
std::string current_self_hosted_ip = config_center_->GetSignalServerHost();
|
||||||
|
bool use_cached_id = false;
|
||||||
|
|
||||||
|
// Check secure_cache_v2.enc exists or not
|
||||||
|
std::ifstream v2_file(cache_path_ + "/secure_cache_v2.enc",
|
||||||
|
std::ios::binary);
|
||||||
|
if (v2_file.good()) {
|
||||||
|
CDCacheV2 temp_cache;
|
||||||
|
v2_file.read(reinterpret_cast<char*>(&temp_cache), sizeof(CDCacheV2));
|
||||||
|
v2_file.close();
|
||||||
|
|
||||||
|
if (strlen(temp_cache.self_hosted_id) > 0) {
|
||||||
|
memset(&self_hosted_id_, 0, sizeof(self_hosted_id_));
|
||||||
|
strncpy(self_hosted_id_, temp_cache.self_hosted_id,
|
||||||
|
sizeof(self_hosted_id_) - 1);
|
||||||
|
self_hosted_id_[sizeof(self_hosted_id_) - 1] = '\0';
|
||||||
|
use_cached_id = true;
|
||||||
|
|
||||||
|
std::string id, password;
|
||||||
|
const char* at_pos = strchr(self_hosted_id_, '@');
|
||||||
|
if (at_pos == nullptr) {
|
||||||
|
id = self_hosted_id_;
|
||||||
|
password.clear();
|
||||||
|
} else {
|
||||||
|
id.assign(self_hosted_id_, at_pos - self_hosted_id_);
|
||||||
|
password = at_pos + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&client_id_, 0, sizeof(client_id_));
|
||||||
|
strncpy(client_id_, id.c_str(), sizeof(client_id_) - 1);
|
||||||
|
client_id_[sizeof(client_id_) - 1] = '\0';
|
||||||
|
|
||||||
|
memset(&password_saved_, 0, sizeof(password_saved_));
|
||||||
|
strncpy(password_saved_, password.c_str(), sizeof(password_saved_) - 1);
|
||||||
|
password_saved_[sizeof(password_saved_) - 1] = '\0';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
memset(&self_hosted_id_, 0, sizeof(self_hosted_id_));
|
||||||
|
LOG_INFO(
|
||||||
|
"secure_cache_v2.enc not found, will use empty id to get new id from "
|
||||||
|
"server");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (use_cached_id && strlen(self_hosted_id_) > 0) {
|
||||||
|
memset(&self_hosted_user_id_, 0, sizeof(self_hosted_user_id_));
|
||||||
|
strncpy(self_hosted_user_id_, self_hosted_id_,
|
||||||
|
sizeof(self_hosted_user_id_) - 1);
|
||||||
|
self_hosted_user_id_[sizeof(self_hosted_user_id_) - 1] = '\0';
|
||||||
|
params_.user_id = self_hosted_user_id_;
|
||||||
|
} else {
|
||||||
|
memset(&self_hosted_user_id_, 0, sizeof(self_hosted_user_id_));
|
||||||
|
params_.user_id = self_hosted_user_id_;
|
||||||
|
LOG_INFO(
|
||||||
|
"Using empty id for self-hosted server, server will assign new id");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
signal_server_ip = config_center_->GetDefaultServerHost();
|
signal_server_ip = config_center_->GetDefaultServerHost();
|
||||||
signal_server_port = config_center_->GetDefaultSignalServerPort();
|
signal_server_port = config_center_->GetDefaultSignalServerPort();
|
||||||
coturn_server_port = config_center_->GetDefaultCoturnServerPort();
|
coturn_server_port = config_center_->GetDefaultCoturnServerPort();
|
||||||
tls_cert_path = config_center_->GetDefaultCertFilePath();
|
tls_cert_path = config_center_->GetDefaultCertFilePath();
|
||||||
|
params_.user_id = client_id_with_password_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// self hosted server config
|
// self hosted server config
|
||||||
strncpy(signal_server_ip_self_, config_center_->GetSignalServerHost().c_str(),
|
strncpy(signal_server_ip_self_, config_center_->GetSignalServerHost().c_str(),
|
||||||
sizeof(signal_server_ip_self_) - 1);
|
sizeof(signal_server_ip_self_) - 1);
|
||||||
signal_server_ip_self_[sizeof(signal_server_ip_self_) - 1] = '\0';
|
signal_server_ip_self_[sizeof(signal_server_ip_self_) - 1] = '\0';
|
||||||
strncpy(signal_server_port_self_,
|
int signal_port = config_center_->GetSignalServerPort();
|
||||||
std::to_string(config_center_->GetSignalServerPort()).c_str(),
|
if (signal_port > 0) {
|
||||||
sizeof(signal_server_port_self_) - 1);
|
strncpy(signal_server_port_self_, std::to_string(signal_port).c_str(),
|
||||||
signal_server_port_self_[sizeof(signal_server_port_self_) - 1] = '\0';
|
sizeof(signal_server_port_self_) - 1);
|
||||||
strncpy(coturn_server_port_self_,
|
signal_server_port_self_[sizeof(signal_server_port_self_) - 1] = '\0';
|
||||||
std::to_string(config_center_->GetCoturnServerPort()).c_str(),
|
} else {
|
||||||
sizeof(coturn_server_port_self_) - 1);
|
signal_server_port_self_[0] = '\0';
|
||||||
coturn_server_port_self_[sizeof(coturn_server_port_self_) - 1] = '\0';
|
}
|
||||||
|
int coturn_port = config_center_->GetCoturnServerPort();
|
||||||
|
if (coturn_port > 0) {
|
||||||
|
strncpy(coturn_server_port_self_, std::to_string(coturn_port).c_str(),
|
||||||
|
sizeof(coturn_server_port_self_) - 1);
|
||||||
|
coturn_server_port_self_[sizeof(coturn_server_port_self_) - 1] = '\0';
|
||||||
|
} else {
|
||||||
|
coturn_server_port_self_[0] = '\0';
|
||||||
|
}
|
||||||
tls_cert_path_self_ = config_center_->GetCertFilePath();
|
tls_cert_path_self_ = config_center_->GetCertFilePath();
|
||||||
|
|
||||||
// peer config
|
// peer config
|
||||||
@@ -517,7 +675,6 @@ int Render::CreateConnectionPeer() {
|
|||||||
params_.on_connection_status = OnConnectionStatusCb;
|
params_.on_connection_status = OnConnectionStatusCb;
|
||||||
params_.net_status_report = NetStatusReport;
|
params_.net_status_report = NetStatusReport;
|
||||||
|
|
||||||
params_.user_id = client_id_with_password_;
|
|
||||||
params_.user_data = this;
|
params_.user_data = this;
|
||||||
|
|
||||||
peer_ = CreatePeer(¶ms_);
|
peer_ = CreatePeer(¶ms_);
|
||||||
@@ -605,53 +762,6 @@ void Render::UpdateInteractions() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Render::UpdateWindowSizeWithDpiScale(float dpi_scale) {
|
|
||||||
main_window_width_ = (int)(main_window_width_default_ * dpi_scale);
|
|
||||||
main_window_height_ = (int)(main_window_height_default_ * dpi_scale);
|
|
||||||
stream_window_width_ = (int)(stream_window_width_default_ * dpi_scale);
|
|
||||||
stream_window_height_ = (int)(stream_window_height_default_ * dpi_scale);
|
|
||||||
|
|
||||||
local_window_width_ = (int)(local_window_width_ * dpi_scale);
|
|
||||||
local_window_height_ = (int)(local_window_height_ * dpi_scale);
|
|
||||||
remote_window_width_ = (int)(remote_window_width_ * dpi_scale);
|
|
||||||
remote_window_height_ = (int)(remote_window_height_ * dpi_scale);
|
|
||||||
local_child_window_width_ = (int)(local_child_window_width_ * dpi_scale);
|
|
||||||
local_child_window_height_ = (int)(local_child_window_height_ * dpi_scale);
|
|
||||||
remote_child_window_width_ = (int)(remote_child_window_width_ * dpi_scale);
|
|
||||||
remote_child_window_height_ = (int)(remote_child_window_height_ * dpi_scale);
|
|
||||||
main_window_text_y_padding_ = (int)(main_window_text_y_padding_ * dpi_scale);
|
|
||||||
main_child_window_x_padding_ =
|
|
||||||
(int)(main_child_window_x_padding_ * dpi_scale);
|
|
||||||
main_child_window_y_padding_ =
|
|
||||||
(int)(main_child_window_y_padding_ * dpi_scale);
|
|
||||||
title_bar_width_ = (int)(title_bar_width_ * dpi_scale);
|
|
||||||
title_bar_height_ = (int)(title_bar_height_ * dpi_scale);
|
|
||||||
status_bar_height_ = (int)(status_bar_height_ * dpi_scale);
|
|
||||||
connection_status_window_width_ =
|
|
||||||
(int)(connection_status_window_width_ * dpi_scale);
|
|
||||||
connection_status_window_height_ =
|
|
||||||
(int)(connection_status_window_height_ * dpi_scale);
|
|
||||||
notification_window_width_ = (int)(notification_window_width_ * dpi_scale);
|
|
||||||
notification_window_height_ = (int)(notification_window_height_ * dpi_scale);
|
|
||||||
about_window_width_ = (int)(about_window_width_ * dpi_scale);
|
|
||||||
about_window_height_ = (int)(about_window_height_ * dpi_scale);
|
|
||||||
update_notification_window_width_ =
|
|
||||||
(int)(update_notification_window_width_ * dpi_scale);
|
|
||||||
update_notification_window_height_ =
|
|
||||||
(int)(update_notification_window_height_ * dpi_scale);
|
|
||||||
|
|
||||||
recent_connection_image_width_ =
|
|
||||||
(int)(recent_connection_image_width_ * dpi_scale);
|
|
||||||
recent_connection_image_height_ =
|
|
||||||
(int)(recent_connection_image_height_ * dpi_scale);
|
|
||||||
|
|
||||||
if (thumbnail_) {
|
|
||||||
thumbnail_->SetThumbnailDpiScale(dpi_scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Render::CreateMainWindow() {
|
int Render::CreateMainWindow() {
|
||||||
main_ctx_ = ImGui::CreateContext();
|
main_ctx_ = ImGui::CreateContext();
|
||||||
if (!main_ctx_) {
|
if (!main_ctx_) {
|
||||||
@@ -759,6 +869,10 @@ int Render::CreateStreamWindow() {
|
|||||||
|
|
||||||
SetupFontAndStyle(false);
|
SetupFontAndStyle(false);
|
||||||
|
|
||||||
|
ImGuiStyle& style = ImGui::GetStyle();
|
||||||
|
style.ScaleAllSizes(dpi_scale_);
|
||||||
|
style.FontScaleDpi = dpi_scale_;
|
||||||
|
|
||||||
ImGui_ImplSDL3_InitForSDLRenderer(stream_window_, stream_renderer_);
|
ImGui_ImplSDL3_InitForSDLRenderer(stream_window_, stream_renderer_);
|
||||||
ImGui_ImplSDLRenderer3_Init(stream_renderer_);
|
ImGui_ImplSDLRenderer3_Init(stream_renderer_);
|
||||||
|
|
||||||
@@ -924,16 +1038,16 @@ int Render::DrawMainWindow() {
|
|||||||
ImGui::SetNextWindowSize(ImVec2(io.DisplaySize.x, io.DisplaySize.y),
|
ImGui::SetNextWindowSize(ImVec2(io.DisplaySize.x, io.DisplaySize.y),
|
||||||
ImGuiCond_Always);
|
ImGuiCond_Always);
|
||||||
ImGui::Begin("MainRender", nullptr,
|
ImGui::Begin("MainRender", nullptr,
|
||||||
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar |
|
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration |
|
||||||
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar |
|
ImGuiWindowFlags_NoBringToFrontOnFocus |
|
||||||
ImGuiWindowFlags_NoBringToFrontOnFocus);
|
ImGuiWindowFlags_NoDocking);
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
|
|
||||||
TitleBar(true);
|
TitleBar(true);
|
||||||
|
|
||||||
MainWindow();
|
MainWindow();
|
||||||
|
|
||||||
// UpdateNotificationWindow();
|
UpdateNotificationWindow();
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
if (show_request_permission_window_) {
|
if (show_request_permission_window_) {
|
||||||
@@ -968,23 +1082,31 @@ int Render::DrawStreamWindow() {
|
|||||||
|
|
||||||
StreamWindow();
|
StreamWindow();
|
||||||
|
|
||||||
if (!fullscreen_button_pressed_) {
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always);
|
float stream_title_window_height =
|
||||||
ImGui::SetNextWindowSize(
|
fullscreen_button_pressed_ ? 0 : title_bar_height_;
|
||||||
ImVec2(stream_window_width_,
|
|
||||||
fullscreen_button_pressed_ ? 0 : title_bar_height_),
|
|
||||||
ImGuiCond_Always);
|
|
||||||
ImGui::Begin("StreamWindowTitleBar", nullptr,
|
|
||||||
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration |
|
|
||||||
ImGuiWindowFlags_NoBringToFrontOnFocus |
|
|
||||||
ImGuiWindowFlags_NoDocking);
|
|
||||||
|
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
|
// Set minimum window size to 0 to allow exact height control
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0, 0));
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
|
||||||
|
ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always);
|
||||||
|
ImGui::SetNextWindowSize(ImVec2(io.DisplaySize.x, stream_title_window_height),
|
||||||
|
ImGuiCond_Always);
|
||||||
|
ImGui::Begin("StreamTitleWindow", nullptr,
|
||||||
|
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration |
|
||||||
|
ImGuiWindowFlags_NoBringToFrontOnFocus |
|
||||||
|
ImGuiWindowFlags_NoDocking);
|
||||||
|
ImGui::PopStyleVar(2);
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
|
||||||
|
if (!fullscreen_button_pressed_) {
|
||||||
TitleBar(false);
|
TitleBar(false);
|
||||||
ImGui::End();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::End();
|
||||||
|
|
||||||
// Rendering
|
// Rendering
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
(void)io;
|
(void)io;
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
SDL_SetRenderScale(stream_renderer_, io.DisplayFramebufferScale.x,
|
SDL_SetRenderScale(stream_renderer_, io.DisplayFramebufferScale.x,
|
||||||
@@ -1044,10 +1166,15 @@ int Render::Run() {
|
|||||||
config_center_->GetSignalServerHost().c_str(),
|
config_center_->GetSignalServerHost().c_str(),
|
||||||
sizeof(signal_server_ip_self_) - 1);
|
sizeof(signal_server_ip_self_) - 1);
|
||||||
signal_server_ip_self_[sizeof(signal_server_ip_self_) - 1] = '\0';
|
signal_server_ip_self_[sizeof(signal_server_ip_self_) - 1] = '\0';
|
||||||
strncpy(signal_server_port_self_,
|
int signal_port_init = config_center_->GetSignalServerPort();
|
||||||
std::to_string(config_center_->GetSignalServerPort()).c_str(),
|
if (signal_port_init > 0) {
|
||||||
sizeof(signal_server_port_self_) - 1);
|
strncpy(signal_server_port_self_,
|
||||||
signal_server_port_self_[sizeof(signal_server_port_self_) - 1] = '\0';
|
std::to_string(signal_port_init).c_str(),
|
||||||
|
sizeof(signal_server_port_self_) - 1);
|
||||||
|
signal_server_port_self_[sizeof(signal_server_port_self_) - 1] = '\0';
|
||||||
|
} else {
|
||||||
|
signal_server_port_self_[0] = '\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 {
|
||||||
@@ -1272,6 +1399,9 @@ void Render::Cleanup() {
|
|||||||
|
|
||||||
CleanupFactories();
|
CleanupFactories();
|
||||||
CleanupPeers();
|
CleanupPeers();
|
||||||
|
|
||||||
|
WaitForThumbnailSaveTasks();
|
||||||
|
|
||||||
AudioDeviceDestroy();
|
AudioDeviceDestroy();
|
||||||
DestroyMainWindowContext();
|
DestroyMainWindowContext();
|
||||||
DestroyMainWindow();
|
DestroyMainWindow();
|
||||||
@@ -1299,10 +1429,29 @@ void Render::CleanupPeer(std::shared_ptr<SubStreamWindowProperties> props) {
|
|||||||
SDL_FlushEvent(STREAM_REFRESH_EVENT);
|
SDL_FlushEvent(STREAM_REFRESH_EVENT);
|
||||||
|
|
||||||
if (props->dst_buffer_) {
|
if (props->dst_buffer_) {
|
||||||
thumbnail_->SaveToThumbnail(
|
size_t buffer_size = props->dst_buffer_capacity_;
|
||||||
(char*)props->dst_buffer_, props->video_width_, props->video_height_,
|
std::vector<unsigned char> buffer_copy(buffer_size);
|
||||||
props->remote_id_, props->remote_host_name_,
|
memcpy(buffer_copy.data(), props->dst_buffer_, buffer_size);
|
||||||
props->remember_password_ ? props->remote_password_ : "");
|
|
||||||
|
int video_width = props->video_width_;
|
||||||
|
int video_height = props->video_height_;
|
||||||
|
std::string remote_id = props->remote_id_;
|
||||||
|
std::string remote_host_name = props->remote_host_name_;
|
||||||
|
std::string password =
|
||||||
|
props->remember_password_ ? props->remote_password_ : "";
|
||||||
|
|
||||||
|
std::thread save_thread([buffer_copy, video_width, video_height, remote_id,
|
||||||
|
remote_host_name, password,
|
||||||
|
thumbnail = thumbnail_]() {
|
||||||
|
thumbnail->SaveToThumbnail((char*)buffer_copy.data(), video_width,
|
||||||
|
video_height, remote_id, remote_host_name,
|
||||||
|
password);
|
||||||
|
});
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(thumbnail_save_threads_mutex_);
|
||||||
|
thumbnail_save_threads_.emplace_back(std::move(save_thread));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props->peer_) {
|
if (props->peer_) {
|
||||||
@@ -1340,6 +1489,25 @@ void Render::CleanupPeers() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Render::WaitForThumbnailSaveTasks() {
|
||||||
|
std::vector<std::thread> threads_to_join;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(thumbnail_save_threads_mutex_);
|
||||||
|
threads_to_join.swap(thumbnail_save_threads_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (threads_to_join.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& thread : threads_to_join) {
|
||||||
|
if (thread.joinable()) {
|
||||||
|
thread.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Render::CleanSubStreamWindowProperties(
|
void Render::CleanSubStreamWindowProperties(
|
||||||
std::shared_ptr<SubStreamWindowProperties> props) {
|
std::shared_ptr<SubStreamWindowProperties> props) {
|
||||||
if (props->stream_texture_) {
|
if (props->stream_texture_) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include <shared_mutex>
|
#include <shared_mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "IconsFontAwesome6.h"
|
#include "IconsFontAwesome6.h"
|
||||||
#include "config_center.h"
|
#include "config_center.h"
|
||||||
@@ -175,7 +176,6 @@ class Render {
|
|||||||
private:
|
private:
|
||||||
int ConnectTo(const std::string& remote_id, const char* password,
|
int ConnectTo(const std::string& remote_id, const char* password,
|
||||||
bool remember_password);
|
bool remember_password);
|
||||||
int UpdateWindowSizeWithDpiScale(float dpi_scale);
|
|
||||||
int CreateMainWindow();
|
int CreateMainWindow();
|
||||||
int DestroyMainWindow();
|
int DestroyMainWindow();
|
||||||
int CreateStreamWindow();
|
int CreateStreamWindow();
|
||||||
@@ -277,8 +277,25 @@ class Render {
|
|||||||
unsigned char iv[16];
|
unsigned char iv[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CDCacheV2 {
|
||||||
|
char client_id_with_password[17];
|
||||||
|
int language;
|
||||||
|
int video_quality;
|
||||||
|
int video_frame_rate;
|
||||||
|
int video_encode_format;
|
||||||
|
bool enable_hardware_video_codec;
|
||||||
|
bool enable_turn;
|
||||||
|
bool enable_srtp;
|
||||||
|
|
||||||
|
unsigned char key[16];
|
||||||
|
unsigned char iv[16];
|
||||||
|
|
||||||
|
char self_hosted_id[17];
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CDCache cd_cache_;
|
CDCache cd_cache_;
|
||||||
|
CDCacheV2 cd_cache_v2_;
|
||||||
std::mutex cd_cache_mutex_;
|
std::mutex cd_cache_mutex_;
|
||||||
std::unique_ptr<ConfigCenter> config_center_;
|
std::unique_ptr<ConfigCenter> config_center_;
|
||||||
ConfigCenter::LANGUAGE localization_language_ =
|
ConfigCenter::LANGUAGE localization_language_ =
|
||||||
@@ -294,13 +311,15 @@ class Render {
|
|||||||
/* ------ all windows property start ------ */
|
/* ------ all windows property start ------ */
|
||||||
float title_bar_width_ = 640;
|
float title_bar_width_ = 640;
|
||||||
float title_bar_height_ = 30;
|
float title_bar_height_ = 30;
|
||||||
|
float title_bar_button_width_ = 30;
|
||||||
|
float title_bar_button_height_ = 30;
|
||||||
/* ------ all windows property end ------ */
|
/* ------ all windows property end ------ */
|
||||||
|
|
||||||
/* ------ main window property start ------ */
|
/* ------ main window property start ------ */
|
||||||
// thumbnail
|
// thumbnail
|
||||||
unsigned char aes128_key_[16];
|
unsigned char aes128_key_[16];
|
||||||
unsigned char aes128_iv_[16];
|
unsigned char aes128_iv_[16];
|
||||||
std::unique_ptr<Thumbnail> thumbnail_;
|
std::shared_ptr<Thumbnail> thumbnail_;
|
||||||
|
|
||||||
// recent connections
|
// recent connections
|
||||||
std::vector<std::pair<std::string, Thumbnail::RecentConnection>>
|
std::vector<std::pair<std::string, Thumbnail::RecentConnection>>
|
||||||
@@ -468,6 +487,8 @@ class Render {
|
|||||||
char client_id_display_[12] = "";
|
char client_id_display_[12] = "";
|
||||||
char client_id_with_password_[17] = "";
|
char client_id_with_password_[17] = "";
|
||||||
char password_saved_[7] = "";
|
char password_saved_[7] = "";
|
||||||
|
char self_hosted_id_[17] = "";
|
||||||
|
char self_hosted_user_id_[17] = "";
|
||||||
int language_button_value_ = 0;
|
int language_button_value_ = 0;
|
||||||
int video_quality_button_value_ = 0;
|
int video_quality_button_value_ = 0;
|
||||||
int video_frame_rate_button_value_ = 1;
|
int video_frame_rate_button_value_ = 1;
|
||||||
@@ -511,6 +532,11 @@ class Render {
|
|||||||
void CloseTab(decltype(client_properties_)::iterator& it);
|
void CloseTab(decltype(client_properties_)::iterator& it);
|
||||||
/* ------ stream window property end ------ */
|
/* ------ stream window property end ------ */
|
||||||
|
|
||||||
|
/* ------ async thumbnail save tasks ------ */
|
||||||
|
std::vector<std::thread> thumbnail_save_threads_;
|
||||||
|
std::mutex thumbnail_save_threads_mutex_;
|
||||||
|
void WaitForThumbnailSaveTasks();
|
||||||
|
|
||||||
/* ------ server mode ------ */
|
/* ------ server mode ------ */
|
||||||
std::unordered_map<std::string, ConnectionStatus> connection_status_;
|
std::unordered_map<std::string, ConnectionStatus> connection_status_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
#include "device_controller.h"
|
#include "device_controller.h"
|
||||||
#include "localization.h"
|
#include "localization.h"
|
||||||
@@ -556,24 +557,93 @@ void Render::NetStatusReport(const char* client_id, size_t client_id_size,
|
|||||||
password = at_pos + 1;
|
password = at_pos + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&render->client_id_, 0, sizeof(render->client_id_));
|
bool is_self_hosted = render->config_center_->IsSelfHosted();
|
||||||
strncpy(render->client_id_, id.c_str(), sizeof(render->client_id_) - 1);
|
|
||||||
render->client_id_[sizeof(render->client_id_) - 1] = '\0';
|
|
||||||
|
|
||||||
memset(&render->password_saved_, 0, sizeof(render->password_saved_));
|
if (is_self_hosted) {
|
||||||
strncpy(render->password_saved_, password.c_str(),
|
memset(&render->client_id_, 0, sizeof(render->client_id_));
|
||||||
sizeof(render->password_saved_) - 1);
|
strncpy(render->client_id_, id.c_str(), sizeof(render->client_id_) - 1);
|
||||||
render->password_saved_[sizeof(render->password_saved_) - 1] = '\0';
|
render->client_id_[sizeof(render->client_id_) - 1] = '\0';
|
||||||
|
|
||||||
memset(&render->client_id_with_password_, 0,
|
memset(&render->password_saved_, 0, sizeof(render->password_saved_));
|
||||||
sizeof(render->client_id_with_password_));
|
strncpy(render->password_saved_, password.c_str(),
|
||||||
strncpy(render->client_id_with_password_, client_id,
|
sizeof(render->password_saved_) - 1);
|
||||||
sizeof(render->client_id_with_password_) - 1);
|
render->password_saved_[sizeof(render->password_saved_) - 1] = '\0';
|
||||||
render->client_id_with_password_[sizeof(render->client_id_with_password_) -
|
|
||||||
|
memset(&render->self_hosted_id_, 0, sizeof(render->self_hosted_id_));
|
||||||
|
strncpy(render->self_hosted_id_, client_id,
|
||||||
|
sizeof(render->self_hosted_id_) - 1);
|
||||||
|
render->self_hosted_id_[sizeof(render->self_hosted_id_) - 1] = '\0';
|
||||||
|
|
||||||
|
LOG_INFO("Use self-hosted client id [{}] and save to cache file", id);
|
||||||
|
|
||||||
|
render->cd_cache_mutex_.lock();
|
||||||
|
|
||||||
|
std::ifstream v2_file_read(render->cache_path_ + "/secure_cache_v2.enc",
|
||||||
|
std::ios::binary);
|
||||||
|
if (v2_file_read.good()) {
|
||||||
|
v2_file_read.read(reinterpret_cast<char*>(&render->cd_cache_v2_),
|
||||||
|
sizeof(CDCacheV2));
|
||||||
|
v2_file_read.close();
|
||||||
|
} else {
|
||||||
|
memset(&render->cd_cache_v2_, 0, sizeof(CDCacheV2));
|
||||||
|
memset(&render->cd_cache_v2_.client_id_with_password, 0,
|
||||||
|
sizeof(render->cd_cache_v2_.client_id_with_password));
|
||||||
|
strncpy(render->cd_cache_v2_.client_id_with_password,
|
||||||
|
render->client_id_with_password_,
|
||||||
|
sizeof(render->cd_cache_v2_.client_id_with_password));
|
||||||
|
memcpy(&render->cd_cache_v2_.key, &render->aes128_key_,
|
||||||
|
sizeof(render->cd_cache_v2_.key));
|
||||||
|
memcpy(&render->cd_cache_v2_.iv, &render->aes128_iv_,
|
||||||
|
sizeof(render->cd_cache_v2_.iv));
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&render->cd_cache_v2_.self_hosted_id, 0,
|
||||||
|
sizeof(render->cd_cache_v2_.self_hosted_id));
|
||||||
|
strncpy(render->cd_cache_v2_.self_hosted_id, client_id,
|
||||||
|
sizeof(render->cd_cache_v2_.self_hosted_id) - 1);
|
||||||
|
render->cd_cache_v2_
|
||||||
|
.self_hosted_id[sizeof(render->cd_cache_v2_.self_hosted_id) - 1] =
|
||||||
|
'\0';
|
||||||
|
|
||||||
|
memset(&render->cd_cache_v2_.client_id_with_password, 0,
|
||||||
|
sizeof(render->cd_cache_v2_.client_id_with_password));
|
||||||
|
strncpy(render->cd_cache_v2_.client_id_with_password,
|
||||||
|
render->client_id_with_password_,
|
||||||
|
sizeof(render->cd_cache_v2_.client_id_with_password));
|
||||||
|
memcpy(&render->cd_cache_v2_.key, &render->aes128_key_,
|
||||||
|
sizeof(render->cd_cache_v2_.key));
|
||||||
|
memcpy(&render->cd_cache_v2_.iv, &render->aes128_iv_,
|
||||||
|
sizeof(render->cd_cache_v2_.iv));
|
||||||
|
std::ofstream cd_cache_v2_file(
|
||||||
|
render->cache_path_ + "/secure_cache_v2.enc", std::ios::binary);
|
||||||
|
if (cd_cache_v2_file) {
|
||||||
|
cd_cache_v2_file.write(reinterpret_cast<char*>(&render->cd_cache_v2_),
|
||||||
|
sizeof(CDCacheV2));
|
||||||
|
cd_cache_v2_file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
render->cd_cache_mutex_.unlock();
|
||||||
|
} else {
|
||||||
|
memset(&render->client_id_, 0, sizeof(render->client_id_));
|
||||||
|
strncpy(render->client_id_, id.c_str(), sizeof(render->client_id_) - 1);
|
||||||
|
render->client_id_[sizeof(render->client_id_) - 1] = '\0';
|
||||||
|
|
||||||
|
memset(&render->password_saved_, 0, sizeof(render->password_saved_));
|
||||||
|
strncpy(render->password_saved_, password.c_str(),
|
||||||
|
sizeof(render->password_saved_) - 1);
|
||||||
|
render->password_saved_[sizeof(render->password_saved_) - 1] = '\0';
|
||||||
|
|
||||||
|
memset(&render->client_id_with_password_, 0,
|
||||||
|
sizeof(render->client_id_with_password_));
|
||||||
|
strncpy(render->client_id_with_password_, client_id,
|
||||||
|
sizeof(render->client_id_with_password_) - 1);
|
||||||
|
render
|
||||||
|
->client_id_with_password_[sizeof(render->client_id_with_password_) -
|
||||||
1] = '\0';
|
1] = '\0';
|
||||||
|
|
||||||
LOG_INFO("Use client id [{}] and save id into cache file", id);
|
LOG_INFO("Use client id [{}] and save id into cache file", id);
|
||||||
render->SaveSettingsIntoCacheFile();
|
render->SaveSettingsIntoCacheFile();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string remote_id(user_id, user_id_size);
|
std::string remote_id(user_id, user_id_size);
|
||||||
|
|||||||
@@ -32,28 +32,25 @@ int LossRateDisplay(float loss_rate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Render::ControlBar(std::shared_ptr<SubStreamWindowProperties>& props) {
|
int Render::ControlBar(std::shared_ptr<SubStreamWindowProperties>& props) {
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f * dpi_scale_);
|
float button_width = title_bar_height_ * 0.8f;
|
||||||
|
float button_height = title_bar_height_ * 0.8f;
|
||||||
|
float line_padding = title_bar_height_ * 0.12f;
|
||||||
|
float line_thickness = title_bar_height_ * 0.07f;
|
||||||
|
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
|
||||||
if (props->control_bar_expand_) {
|
if (props->control_bar_expand_) {
|
||||||
float button_width = 24.0f * dpi_scale_;
|
ImGui::SetCursorPosX(props->is_control_bar_in_left_
|
||||||
float button_height = 24.0f * dpi_scale_;
|
? props->control_window_width_ * 1.03f
|
||||||
float line_padding = 4.0f * dpi_scale_;
|
: props->control_window_width_ * 0.2f);
|
||||||
|
|
||||||
ImGui::SetCursorPosX(
|
|
||||||
props->is_control_bar_in_left_
|
|
||||||
? (props->control_window_width_ + 5.0f * dpi_scale_)
|
|
||||||
: 50.0f * dpi_scale_);
|
|
||||||
// mouse control button
|
|
||||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||||
|
if (!props->is_control_bar_in_left_) {
|
||||||
if (props->is_control_bar_in_left_) {
|
|
||||||
draw_list->AddLine(
|
draw_list->AddLine(
|
||||||
ImVec2(ImGui::GetCursorScreenPos().x - 5.0f * dpi_scale_,
|
ImVec2(ImGui::GetCursorScreenPos().x - button_height * 0.56f,
|
||||||
ImGui::GetCursorScreenPos().y - 7.0f * dpi_scale_),
|
ImGui::GetCursorScreenPos().y + button_height * 0.2f),
|
||||||
ImVec2(ImGui::GetCursorScreenPos().x - 5.0f * dpi_scale_,
|
ImVec2(ImGui::GetCursorScreenPos().x - button_height * 0.56f,
|
||||||
ImGui::GetCursorScreenPos().y - 7.0f * dpi_scale_ +
|
ImGui::GetCursorScreenPos().y + button_height * 0.8f),
|
||||||
props->control_window_height_),
|
IM_COL32(178, 178, 178, 255), 2.0f);
|
||||||
IM_COL32(178, 178, 178, 255), 1.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string display = ICON_FA_DISPLAY;
|
std::string display = ICON_FA_DISPLAY;
|
||||||
@@ -90,7 +87,7 @@ int Render::ControlBar(std::shared_ptr<SubStreamWindowProperties>& props) {
|
|||||||
std::to_string(props->selected_display_ + 1).c_str());
|
std::to_string(props->selected_display_ + 1).c_str());
|
||||||
ImVec2 text_pos =
|
ImVec2 text_pos =
|
||||||
ImVec2(btn_min.x + (btn_size_actual.x - text_size.x) * 0.5f,
|
ImVec2(btn_min.x + (btn_size_actual.x - text_size.x) * 0.5f,
|
||||||
btn_min.y + (btn_size_actual.y - text_size.y) * 0.5f - 2.0f);
|
btn_min.y + (btn_size_actual.y - text_size.y) * 0.35f);
|
||||||
ImGui::GetWindowDrawList()->AddText(
|
ImGui::GetWindowDrawList()->AddText(
|
||||||
text_pos, IM_COL32(0, 0, 0, 255),
|
text_pos, IM_COL32(0, 0, 0, 255),
|
||||||
std::to_string(props->selected_display_ + 1).c_str());
|
std::to_string(props->selected_display_ + 1).c_str());
|
||||||
@@ -103,6 +100,7 @@ int Render::ControlBar(std::shared_ptr<SubStreamWindowProperties>& props) {
|
|||||||
std::string mouse = props->mouse_control_button_pressed_
|
std::string mouse = props->mouse_control_button_pressed_
|
||||||
? ICON_FA_COMPUTER_MOUSE
|
? ICON_FA_COMPUTER_MOUSE
|
||||||
: ICON_FA_COMPUTER_MOUSE;
|
: ICON_FA_COMPUTER_MOUSE;
|
||||||
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
if (ImGui::Button(mouse.c_str(), ImVec2(button_width, button_height))) {
|
if (ImGui::Button(mouse.c_str(), ImVec2(button_width, button_height))) {
|
||||||
if (props->connection_established_) {
|
if (props->connection_established_) {
|
||||||
start_keyboard_capturer_ = !start_keyboard_capturer_;
|
start_keyboard_capturer_ = !start_keyboard_capturer_;
|
||||||
@@ -117,7 +115,6 @@ int Render::ControlBar(std::shared_ptr<SubStreamWindowProperties>& props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!props->mouse_control_button_pressed_) {
|
if (!props->mouse_control_button_pressed_) {
|
||||||
float line_thickness = 2.0f * dpi_scale_;
|
|
||||||
draw_list->AddLine(ImVec2(disable_mouse_x, disable_mouse_y),
|
draw_list->AddLine(ImVec2(disable_mouse_x, disable_mouse_y),
|
||||||
ImVec2(mouse_x + button_width - line_padding,
|
ImVec2(mouse_x + button_width - line_padding,
|
||||||
mouse_y + button_height - line_padding),
|
mouse_y + button_height - line_padding),
|
||||||
@@ -143,6 +140,7 @@ int Render::ControlBar(std::shared_ptr<SubStreamWindowProperties>& props) {
|
|||||||
std::string audio = props->audio_capture_button_pressed_
|
std::string audio = props->audio_capture_button_pressed_
|
||||||
? ICON_FA_VOLUME_HIGH
|
? ICON_FA_VOLUME_HIGH
|
||||||
: ICON_FA_VOLUME_HIGH;
|
: ICON_FA_VOLUME_HIGH;
|
||||||
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
if (ImGui::Button(audio.c_str(), ImVec2(button_width, button_height))) {
|
if (ImGui::Button(audio.c_str(), ImVec2(button_width, button_height))) {
|
||||||
if (props->connection_established_) {
|
if (props->connection_established_) {
|
||||||
props->audio_capture_button_pressed_ =
|
props->audio_capture_button_pressed_ =
|
||||||
@@ -162,7 +160,6 @@ int Render::ControlBar(std::shared_ptr<SubStreamWindowProperties>& props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!props->audio_capture_button_pressed_) {
|
if (!props->audio_capture_button_pressed_) {
|
||||||
float line_thickness = 2.0f * dpi_scale_;
|
|
||||||
draw_list->AddLine(ImVec2(disable_audio_x, disable_audio_y),
|
draw_list->AddLine(ImVec2(disable_audio_x, disable_audio_y),
|
||||||
ImVec2(audio_x + button_width - line_padding,
|
ImVec2(audio_x + button_width - line_padding,
|
||||||
audio_y + button_height - line_padding),
|
audio_y + button_height - line_padding),
|
||||||
@@ -187,6 +184,7 @@ int Render::ControlBar(std::shared_ptr<SubStreamWindowProperties>& props) {
|
|||||||
button_color_style_pushed = true;
|
button_color_style_pushed = true;
|
||||||
}
|
}
|
||||||
std::string net_traffic_stats = ICON_FA_SIGNAL;
|
std::string net_traffic_stats = ICON_FA_SIGNAL;
|
||||||
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
if (ImGui::Button(net_traffic_stats.c_str(),
|
if (ImGui::Button(net_traffic_stats.c_str(),
|
||||||
ImVec2(button_width, button_height))) {
|
ImVec2(button_width, button_height))) {
|
||||||
props->net_traffic_stats_button_pressed_ =
|
props->net_traffic_stats_button_pressed_ =
|
||||||
@@ -210,6 +208,7 @@ int Render::ControlBar(std::shared_ptr<SubStreamWindowProperties>& props) {
|
|||||||
// fullscreen button
|
// fullscreen button
|
||||||
std::string fullscreen =
|
std::string fullscreen =
|
||||||
fullscreen_button_pressed_ ? ICON_FA_COMPRESS : ICON_FA_EXPAND;
|
fullscreen_button_pressed_ ? ICON_FA_COMPRESS : ICON_FA_EXPAND;
|
||||||
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
if (ImGui::Button(fullscreen.c_str(),
|
if (ImGui::Button(fullscreen.c_str(),
|
||||||
ImVec2(button_width, button_height))) {
|
ImVec2(button_width, button_height))) {
|
||||||
fullscreen_button_pressed_ = !fullscreen_button_pressed_;
|
fullscreen_button_pressed_ = !fullscreen_button_pressed_;
|
||||||
@@ -229,6 +228,7 @@ int Render::ControlBar(std::shared_ptr<SubStreamWindowProperties>& props) {
|
|||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
// close button
|
// close button
|
||||||
std::string close_button = ICON_FA_XMARK;
|
std::string close_button = ICON_FA_XMARK;
|
||||||
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
if (ImGui::Button(close_button.c_str(),
|
if (ImGui::Button(close_button.c_str(),
|
||||||
ImVec2(button_width, button_height))) {
|
ImVec2(button_width, button_height))) {
|
||||||
CleanupPeer(props);
|
CleanupPeer(props);
|
||||||
@@ -236,20 +236,27 @@ int Render::ControlBar(std::shared_ptr<SubStreamWindowProperties>& props) {
|
|||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
if (!props->is_control_bar_in_left_) {
|
if (props->is_control_bar_in_left_) {
|
||||||
draw_list->AddLine(ImVec2(ImGui::GetCursorScreenPos().x - 3.0f,
|
draw_list->AddLine(
|
||||||
ImGui::GetCursorScreenPos().y - 7.0f),
|
ImVec2(ImGui::GetCursorScreenPos().x + button_height * 0.2f,
|
||||||
ImVec2(ImGui::GetCursorScreenPos().x - 3.0f,
|
ImGui::GetCursorScreenPos().y + button_height * 0.2f),
|
||||||
ImGui::GetCursorScreenPos().y - 7.0f +
|
ImVec2(ImGui::GetCursorScreenPos().x + button_height * 0.2f,
|
||||||
props->control_window_height_),
|
ImGui::GetCursorScreenPos().y + button_height * 0.8f),
|
||||||
IM_COL32(178, 178, 178, 255), 1.0f);
|
IM_COL32(178, 178, 178, 255), 2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SetCursorPosX(
|
float expand_button_pos_x =
|
||||||
props->is_control_bar_in_left_
|
props->control_bar_expand_ ? (props->is_control_bar_in_left_
|
||||||
? (props->control_window_width_ * 2 - 20.0f * dpi_scale_)
|
? props->control_window_width_ * 1.91f
|
||||||
: 5.0f * dpi_scale_);
|
: props->control_window_width_ * 0.03f)
|
||||||
|
: (props->is_control_bar_in_left_
|
||||||
|
? props->control_window_width_ * 1.02f
|
||||||
|
: props->control_window_width_ * 0.23f);
|
||||||
|
|
||||||
|
ImGui::SetCursorPosX(expand_button_pos_x);
|
||||||
|
|
||||||
std::string control_bar =
|
std::string control_bar =
|
||||||
props->control_bar_expand_
|
props->control_bar_expand_
|
||||||
@@ -258,13 +265,13 @@ int Render::ControlBar(std::shared_ptr<SubStreamWindowProperties>& props) {
|
|||||||
: (props->is_control_bar_in_left_ ? ICON_FA_ANGLE_RIGHT
|
: (props->is_control_bar_in_left_ ? ICON_FA_ANGLE_RIGHT
|
||||||
: ICON_FA_ANGLE_LEFT);
|
: ICON_FA_ANGLE_LEFT);
|
||||||
if (ImGui::Button(control_bar.c_str(),
|
if (ImGui::Button(control_bar.c_str(),
|
||||||
ImVec2(15.0f * dpi_scale_, 25.0f * dpi_scale_))) {
|
ImVec2(button_height * 0.6f, button_height))) {
|
||||||
props->control_bar_expand_ = !props->control_bar_expand_;
|
props->control_bar_expand_ = !props->control_bar_expand_;
|
||||||
props->control_bar_button_pressed_time_ = ImGui::GetTime();
|
props->control_bar_button_pressed_time_ = ImGui::GetTime();
|
||||||
props->control_window_width_is_changing_ = true;
|
props->control_window_width_is_changing_ = true;
|
||||||
|
|
||||||
if (!props->control_bar_expand_) {
|
if (!props->control_bar_expand_) {
|
||||||
props->control_window_height_ = 35 * dpi_scale_;
|
props->control_window_height_ = props->control_window_min_height_;
|
||||||
props->net_traffic_stats_button_pressed_ = false;
|
props->net_traffic_stats_button_pressed_ = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -280,12 +287,13 @@ int Render::ControlBar(std::shared_ptr<SubStreamWindowProperties>& props) {
|
|||||||
|
|
||||||
int Render::NetTrafficStats(std::shared_ptr<SubStreamWindowProperties>& props) {
|
int Render::NetTrafficStats(std::shared_ptr<SubStreamWindowProperties>& props) {
|
||||||
ImGui::SetCursorPos(ImVec2(props->is_control_bar_in_left_
|
ImGui::SetCursorPos(ImVec2(props->is_control_bar_in_left_
|
||||||
? (props->control_window_width_ + 5.0f)
|
? props->control_window_width_ * 1.02f
|
||||||
: 5.0f,
|
: props->control_window_width_ * 0.02f,
|
||||||
35.0f * dpi_scale_));
|
props->control_window_min_height_));
|
||||||
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
if (ImGui::BeginTable("NetTrafficStats", 4, ImGuiTableFlags_BordersH,
|
if (ImGui::BeginTable("NetTrafficStats", 4, ImGuiTableFlags_BordersH,
|
||||||
ImVec2(props->control_window_max_width_ - 10.0f,
|
ImVec2(props->control_window_max_width_ * 0.9f,
|
||||||
props->control_window_max_height_ - 60.0f))) {
|
props->control_window_max_height_ - 0.9f))) {
|
||||||
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed);
|
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed);
|
||||||
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);
|
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);
|
||||||
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);
|
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);
|
||||||
@@ -344,9 +352,12 @@ int Render::NetTrafficStats(std::shared_ptr<SubStreamWindowProperties>& props) {
|
|||||||
ImGui::Text("FPS");
|
ImGui::Text("FPS");
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::Text("%d", props->fps_);
|
ImGui::Text("%d", props->fps_);
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
}
|
}
|
||||||
|
ImGui::SetWindowFontScale(1.0f);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,16 +9,32 @@ namespace crossdesk {
|
|||||||
|
|
||||||
int Render::TitleBar(bool main_window) {
|
int Render::TitleBar(bool main_window) {
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
float title_bar_width = io.DisplaySize.x;
|
float title_bar_width = title_bar_width_;
|
||||||
float title_bar_height = io.DisplaySize.y * TITLE_BAR_HEIGHT;
|
float title_bar_height = title_bar_height_;
|
||||||
float title_bar_button_width = io.DisplaySize.x * TITLE_BAR_BUTTON_WIDTH;
|
float title_bar_height_padding = title_bar_height_;
|
||||||
float title_bar_button_height = io.DisplaySize.y * TITLE_BAR_BUTTON_HEIGHT;
|
float title_bar_button_width = title_bar_button_width_;
|
||||||
|
float title_bar_button_height = title_bar_button_height_;
|
||||||
|
if (main_window) {
|
||||||
|
title_bar_width = io.DisplaySize.x;
|
||||||
|
title_bar_height = io.DisplaySize.y * TITLE_BAR_HEIGHT;
|
||||||
|
title_bar_height_padding = io.DisplaySize.y * (TITLE_BAR_HEIGHT + 0.01f);
|
||||||
|
title_bar_button_width = io.DisplaySize.x * TITLE_BAR_BUTTON_WIDTH;
|
||||||
|
title_bar_button_height = io.DisplaySize.y * TITLE_BAR_BUTTON_HEIGHT;
|
||||||
|
title_bar_height_ = title_bar_height;
|
||||||
|
title_bar_button_width_ = title_bar_button_width;
|
||||||
|
title_bar_button_height_ = title_bar_button_height;
|
||||||
|
} else {
|
||||||
|
title_bar_width = io.DisplaySize.x;
|
||||||
|
title_bar_height = title_bar_button_height_;
|
||||||
|
title_bar_button_width = title_bar_button_width_;
|
||||||
|
title_bar_button_height = title_bar_button_height_;
|
||||||
|
}
|
||||||
|
|
||||||
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));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
|
||||||
ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always);
|
ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always);
|
||||||
ImGui::BeginChild(main_window ? "MainTitleBar" : "StreamTitleBar",
|
ImGui::BeginChild(main_window ? "MainTitleBar" : "StreamTitleBar",
|
||||||
ImVec2(title_bar_width, title_bar_height),
|
ImVec2(title_bar_width, title_bar_height_padding),
|
||||||
ImGuiChildFlags_Border,
|
ImGuiChildFlags_Border,
|
||||||
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove |
|
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove |
|
||||||
ImGuiWindowFlags_NoBringToFrontOnFocus);
|
ImGuiWindowFlags_NoBringToFrontOnFocus);
|
||||||
@@ -106,7 +122,7 @@ int Render::TitleBar(bool main_window) {
|
|||||||
|
|
||||||
if (update_available_ && ImGui::IsItemHovered()) {
|
if (update_available_ && ImGui::IsItemHovered()) {
|
||||||
ImGui::BeginTooltip();
|
ImGui::BeginTooltip();
|
||||||
ImGui::SetWindowFontScale(0.5f * dpi_scale_);
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
std::string new_version_available_str =
|
std::string new_version_available_str =
|
||||||
localization::new_version_available[localization_language_index_] +
|
localization::new_version_available[localization_language_index_] +
|
||||||
": " + latest_version_;
|
": " + latest_version_;
|
||||||
@@ -115,7 +131,7 @@ int Render::TitleBar(bool main_window) {
|
|||||||
ImGui::EndTooltip();
|
ImGui::EndTooltip();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndPopup();
|
||||||
} else {
|
} else {
|
||||||
show_new_version_icon_in_menu_ = true;
|
show_new_version_icon_in_menu_ = true;
|
||||||
}
|
}
|
||||||
@@ -136,7 +152,9 @@ int Render::TitleBar(bool main_window) {
|
|||||||
// render for 1 second
|
// render for 1 second
|
||||||
if (show_new_version_icon_) {
|
if (show_new_version_icon_) {
|
||||||
ImGui::SetWindowFontScale(0.6f);
|
ImGui::SetWindowFontScale(0.6f);
|
||||||
ImGui::SetCursorPos(ImVec2(bar_pos_x + 10, bar_pos_y - 17));
|
ImGui::SetCursorPos(
|
||||||
|
ImVec2(bar_pos_x + title_bar_button_width * 0.15f,
|
||||||
|
bar_pos_y - title_bar_button_width * 0.325f));
|
||||||
ImGui::Text(ICON_FA_TRIANGLE_EXCLAMATION);
|
ImGui::Text(ICON_FA_TRIANGLE_EXCLAMATION);
|
||||||
ImGui::SetWindowFontScale(1.0f);
|
ImGui::SetWindowFontScale(1.0f);
|
||||||
|
|
||||||
@@ -165,7 +183,7 @@ int Render::TitleBar(bool main_window) {
|
|||||||
float minimize_pos_x = title_bar_width -
|
float minimize_pos_x = title_bar_width -
|
||||||
title_bar_button_width * (main_window ? 2 : 3) +
|
title_bar_button_width * (main_window ? 2 : 3) +
|
||||||
title_bar_button_width * 0.33f;
|
title_bar_button_width * 0.33f;
|
||||||
float minimize_pos_y = title_bar_height * 0.5f;
|
float minimize_pos_y = title_bar_button_height * 0.5f;
|
||||||
std::string window_minimize_button = "##minimize"; // ICON_FA_MINUS;
|
std::string window_minimize_button = "##minimize"; // ICON_FA_MINUS;
|
||||||
if (ImGui::Button(window_minimize_button.c_str(),
|
if (ImGui::Button(window_minimize_button.c_str(),
|
||||||
ImVec2(title_bar_button_width, title_bar_button_height))) {
|
ImVec2(title_bar_button_width, title_bar_button_height))) {
|
||||||
@@ -185,7 +203,7 @@ int Render::TitleBar(bool main_window) {
|
|||||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive,
|
ImGui::PushStyleColor(ImGuiCol_ButtonActive,
|
||||||
ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
|
|
||||||
if (!window_maximized_) {
|
if (window_maximized_) {
|
||||||
float pos_x_top = title_bar_width - title_bar_button_width * 1.65f;
|
float pos_x_top = title_bar_width - title_bar_button_width * 1.65f;
|
||||||
float pos_y_top = title_bar_button_height * 0.36f;
|
float pos_y_top = title_bar_button_height * 0.36f;
|
||||||
float pos_x_bottom = title_bar_width - title_bar_button_width * 1.6f;
|
float pos_x_bottom = title_bar_width - title_bar_button_width * 1.6f;
|
||||||
@@ -249,7 +267,7 @@ int Render::TitleBar(bool main_window) {
|
|||||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1.0f, 0, 0, 0.5f));
|
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1.0f, 0, 0, 0.5f));
|
||||||
|
|
||||||
float xmark_pos_x = xmark_button_pos_x + title_bar_button_width * 0.5f;
|
float xmark_pos_x = xmark_button_pos_x + title_bar_button_width * 0.5f;
|
||||||
float xmark_pos_y = title_bar_height * 0.5f;
|
float xmark_pos_y = title_bar_button_height * 0.5f;
|
||||||
float xmark_size = title_bar_button_width * 0.33f;
|
float xmark_size = title_bar_button_width * 0.33f;
|
||||||
std::string close_button = "##xmark"; // ICON_FA_XMARK;
|
std::string close_button = "##xmark"; // ICON_FA_XMARK;
|
||||||
if (ImGui::Button(close_button.c_str(),
|
if (ImGui::Button(close_button.c_str(),
|
||||||
|
|||||||
@@ -37,17 +37,18 @@ void Render::Hyperlink(const std::string& label, const std::string& url,
|
|||||||
|
|
||||||
int Render::AboutWindow() {
|
int Render::AboutWindow() {
|
||||||
if (show_about_window_) {
|
if (show_about_window_) {
|
||||||
const ImGuiViewport* viewport = ImGui::GetMainViewport();
|
float about_window_width = title_bar_button_width_ * 7.5f;
|
||||||
|
|
||||||
float about_window_height = latest_version_.empty()
|
float about_window_height = latest_version_.empty()
|
||||||
? about_window_height_
|
? title_bar_button_width_ * 4.0f
|
||||||
: about_window_height_ + 20.0f;
|
: title_bar_button_width_ * 4.6f;
|
||||||
|
|
||||||
|
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,
|
||||||
(viewport->WorkSize.y - viewport->WorkPos.y - about_window_height) /
|
(viewport->WorkSize.y - viewport->WorkPos.y - about_window_height) /
|
||||||
2));
|
2));
|
||||||
|
|
||||||
ImGui::SetNextWindowSize(ImVec2(about_window_width_, about_window_height));
|
ImGui::SetNextWindowSize(ImVec2(about_window_width, about_window_height));
|
||||||
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f);
|
||||||
@@ -70,7 +71,7 @@ int Render::AboutWindow() {
|
|||||||
|
|
||||||
std::string text = localization::version[localization_language_index_] +
|
std::string text = localization::version[localization_language_index_] +
|
||||||
": CrossDesk " + version;
|
": CrossDesk " + version;
|
||||||
ImGui::SetCursorPosX(about_window_width_ * 0.1f);
|
ImGui::SetCursorPosX(about_window_width * 0.1f);
|
||||||
ImGui::Text("%s", text.c_str());
|
ImGui::Text("%s", text.c_str());
|
||||||
|
|
||||||
if (update_available_) {
|
if (update_available_) {
|
||||||
@@ -79,19 +80,19 @@ int Render::AboutWindow() {
|
|||||||
": " + latest_version_;
|
": " + latest_version_;
|
||||||
std::string access_website =
|
std::string access_website =
|
||||||
localization::access_website[localization_language_index_];
|
localization::access_website[localization_language_index_];
|
||||||
Hyperlink(latest_version, "https://crossdesk.cn", about_window_width_);
|
Hyperlink(latest_version, "https://crossdesk.cn", about_window_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Text("");
|
ImGui::Text("");
|
||||||
|
|
||||||
std::string copyright_text = "© 2025 by JUNKUN DI. All rights reserved.";
|
std::string copyright_text = "© 2025 by JUNKUN DI. All rights reserved.";
|
||||||
std::string license_text = "Licensed under GNU LGPL v3.";
|
std::string license_text = "Licensed under GNU LGPL v3.";
|
||||||
ImGui::SetCursorPosX(about_window_width_ * 0.1f);
|
ImGui::SetCursorPosX(about_window_width * 0.1f);
|
||||||
ImGui::Text("%s", copyright_text.c_str());
|
ImGui::Text("%s", copyright_text.c_str());
|
||||||
ImGui::SetCursorPosX(about_window_width_ * 0.1f);
|
ImGui::SetCursorPosX(about_window_width * 0.1f);
|
||||||
ImGui::Text("%s", license_text.c_str());
|
ImGui::Text("%s", license_text.c_str());
|
||||||
|
|
||||||
ImGui::SetCursorPosX(about_window_width_ * 0.42f);
|
ImGui::SetCursorPosX(about_window_width * 0.445f);
|
||||||
ImGui::SetCursorPosY(about_window_height * 0.75f);
|
ImGui::SetCursorPosY(about_window_height * 0.75f);
|
||||||
// OK
|
// OK
|
||||||
if (ImGui::Button(localization::ok[localization_language_index_].c_str())) {
|
if (ImGui::Button(localization::ok[localization_language_index_].c_str())) {
|
||||||
|
|||||||
@@ -7,42 +7,39 @@ namespace crossdesk {
|
|||||||
|
|
||||||
bool Render::ConnectionStatusWindow(
|
bool Render::ConnectionStatusWindow(
|
||||||
std::shared_ptr<SubStreamWindowProperties>& props) {
|
std::shared_ptr<SubStreamWindowProperties>& props) {
|
||||||
const ImGuiViewport* viewport = ImGui::GetMainViewport();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
bool ret_flag = false;
|
bool ret_flag = false;
|
||||||
ImGui::SetNextWindowPos(ImVec2((viewport->WorkSize.x - viewport->WorkPos.x -
|
|
||||||
connection_status_window_width_) /
|
|
||||||
2,
|
|
||||||
(viewport->WorkSize.y - viewport->WorkPos.y -
|
|
||||||
connection_status_window_height_) /
|
|
||||||
2));
|
|
||||||
|
|
||||||
ImGui::SetNextWindowSize(ImVec2(connection_status_window_width_,
|
ImGui::SetNextWindowPos(
|
||||||
connection_status_window_height_));
|
ImVec2(io.DisplaySize.x * 0.33f, io.DisplaySize.y * 0.33f));
|
||||||
|
ImGui::SetNextWindowSize(
|
||||||
|
ImVec2(io.DisplaySize.x * 0.33f, io.DisplaySize.y * 0.33f));
|
||||||
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0, 1.0, 1.0, 1.0));
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 5.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 5.0f);
|
||||||
|
|
||||||
ImGui::Begin("ConnectionStatusWindow", nullptr,
|
ImGui::Begin("ConnectionStatusWindow", nullptr,
|
||||||
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse |
|
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove |
|
||||||
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar |
|
|
||||||
ImGuiWindowFlags_NoSavedSettings);
|
ImGuiWindowFlags_NoSavedSettings);
|
||||||
ImGui::PopStyleVar(2);
|
ImGui::PopStyleVar(2);
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
|
|
||||||
|
auto connection_status_window_width = ImGui::GetWindowSize().x;
|
||||||
|
auto connection_status_window_height = ImGui::GetWindowSize().y;
|
||||||
|
|
||||||
ImGui::SetWindowFontScale(0.5f);
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
std::string text;
|
std::string text;
|
||||||
|
|
||||||
if (ConnectionStatus::Connecting == props->connection_status_) {
|
if (ConnectionStatus::Connecting == props->connection_status_) {
|
||||||
text = localization::p2p_connecting[localization_language_index_];
|
text = localization::p2p_connecting[localization_language_index_];
|
||||||
ImGui::SetCursorPosX(connection_status_window_width_ * 3 / 7);
|
ImGui::SetCursorPosX(connection_status_window_width * 0.43f);
|
||||||
ImGui::SetCursorPosY(connection_status_window_height_ * 2 / 3);
|
ImGui::SetCursorPosY(connection_status_window_height * 0.67f);
|
||||||
} else if (ConnectionStatus::Connected == props->connection_status_) {
|
} else if (ConnectionStatus::Connected == props->connection_status_) {
|
||||||
text = localization::p2p_connected[localization_language_index_];
|
text = localization::p2p_connected[localization_language_index_];
|
||||||
ImGui::SetCursorPosX(connection_status_window_width_ * 3 / 7);
|
ImGui::SetCursorPosX(connection_status_window_width * 0.43f);
|
||||||
ImGui::SetCursorPosY(connection_status_window_height_ * 2 / 3);
|
ImGui::SetCursorPosY(connection_status_window_height * 0.67f);
|
||||||
// ok
|
// ok
|
||||||
if (ImGui::Button(localization::ok[localization_language_index_].c_str()) ||
|
if (ImGui::Button(localization::ok[localization_language_index_].c_str()) ||
|
||||||
ImGui::IsKeyPressed(ImGuiKey_Enter) ||
|
ImGui::IsKeyPressed(ImGuiKey_Enter) ||
|
||||||
@@ -51,8 +48,8 @@ bool Render::ConnectionStatusWindow(
|
|||||||
}
|
}
|
||||||
} else if (ConnectionStatus::Disconnected == props->connection_status_) {
|
} else if (ConnectionStatus::Disconnected == props->connection_status_) {
|
||||||
text = localization::p2p_disconnected[localization_language_index_];
|
text = localization::p2p_disconnected[localization_language_index_];
|
||||||
ImGui::SetCursorPosX(connection_status_window_width_ * 3 / 7);
|
ImGui::SetCursorPosX(connection_status_window_width * 0.43f);
|
||||||
ImGui::SetCursorPosY(connection_status_window_height_ * 2 / 3);
|
ImGui::SetCursorPosY(connection_status_window_height * 0.67f);
|
||||||
// ok
|
// ok
|
||||||
if (ImGui::Button(localization::ok[localization_language_index_].c_str()) ||
|
if (ImGui::Button(localization::ok[localization_language_index_].c_str()) ||
|
||||||
ImGui::IsKeyPressed(ImGuiKey_Enter) ||
|
ImGui::IsKeyPressed(ImGuiKey_Enter) ||
|
||||||
@@ -61,8 +58,8 @@ bool Render::ConnectionStatusWindow(
|
|||||||
}
|
}
|
||||||
} else if (ConnectionStatus::Failed == props->connection_status_) {
|
} else if (ConnectionStatus::Failed == props->connection_status_) {
|
||||||
text = localization::p2p_failed[localization_language_index_];
|
text = localization::p2p_failed[localization_language_index_];
|
||||||
ImGui::SetCursorPosX(connection_status_window_width_ * 3 / 7);
|
ImGui::SetCursorPosX(connection_status_window_width * 0.43f);
|
||||||
ImGui::SetCursorPosY(connection_status_window_height_ * 2 / 3);
|
ImGui::SetCursorPosY(connection_status_window_height * 0.67f);
|
||||||
// ok
|
// ok
|
||||||
if (ImGui::Button(localization::ok[localization_language_index_].c_str()) ||
|
if (ImGui::Button(localization::ok[localization_language_index_].c_str()) ||
|
||||||
ImGui::IsKeyPressed(ImGuiKey_Enter) ||
|
ImGui::IsKeyPressed(ImGuiKey_Enter) ||
|
||||||
@@ -71,8 +68,8 @@ bool Render::ConnectionStatusWindow(
|
|||||||
}
|
}
|
||||||
} else if (ConnectionStatus::Closed == props->connection_status_) {
|
} else if (ConnectionStatus::Closed == props->connection_status_) {
|
||||||
text = localization::p2p_closed[localization_language_index_];
|
text = localization::p2p_closed[localization_language_index_];
|
||||||
ImGui::SetCursorPosX(connection_status_window_width_ * 3 / 7);
|
ImGui::SetCursorPosX(connection_status_window_width * 0.43f);
|
||||||
ImGui::SetCursorPosY(connection_status_window_height_ * 2 / 3);
|
ImGui::SetCursorPosY(connection_status_window_height * 0.67f);
|
||||||
// ok
|
// ok
|
||||||
if (ImGui::Button(localization::ok[localization_language_index_].c_str()) ||
|
if (ImGui::Button(localization::ok[localization_language_index_].c_str()) ||
|
||||||
ImGui::IsKeyPressed(ImGuiKey_Enter) ||
|
ImGui::IsKeyPressed(ImGuiKey_Enter) ||
|
||||||
@@ -87,11 +84,9 @@ bool Render::ConnectionStatusWindow(
|
|||||||
text = localization::reinput_password[localization_language_index_];
|
text = localization::reinput_password[localization_language_index_];
|
||||||
}
|
}
|
||||||
|
|
||||||
auto window_width = ImGui::GetWindowSize().x;
|
ImGui::SetCursorPosX(connection_status_window_width * 0.336f);
|
||||||
auto window_height = ImGui::GetWindowSize().y;
|
ImGui::SetCursorPosY(connection_status_window_height * 0.4f);
|
||||||
ImGui::SetCursorPosX((window_width - IPUT_WINDOW_WIDTH / 2) * 0.5f);
|
ImGui::SetNextItemWidth(connection_status_window_width * 0.33f);
|
||||||
ImGui::SetCursorPosY(window_height * 0.4f);
|
|
||||||
ImGui::SetNextItemWidth(IPUT_WINDOW_WIDTH / 2);
|
|
||||||
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
|
||||||
|
|
||||||
@@ -109,15 +104,16 @@ bool Render::ConnectionStatusWindow(
|
|||||||
ImVec2 text_size = ImGui::CalcTextSize(
|
ImVec2 text_size = ImGui::CalcTextSize(
|
||||||
localization::remember_password[localization_language_index_]
|
localization::remember_password[localization_language_index_]
|
||||||
.c_str());
|
.c_str());
|
||||||
ImGui::SetCursorPosX((window_width - text_size.x) * 0.5f - 13.0f);
|
ImGui::SetCursorPosX((connection_status_window_width - text_size.x) *
|
||||||
|
0.45f);
|
||||||
ImGui::Checkbox(
|
ImGui::Checkbox(
|
||||||
localization::remember_password[localization_language_index_].c_str(),
|
localization::remember_password[localization_language_index_].c_str(),
|
||||||
&(props->remember_password_));
|
&(props->remember_password_));
|
||||||
ImGui::SetWindowFontScale(0.5f);
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
|
|
||||||
ImGui::SetCursorPosX(window_width * 0.315f);
|
ImGui::SetCursorPosX(connection_status_window_width * 0.325f);
|
||||||
ImGui::SetCursorPosY(window_height * 0.75f);
|
ImGui::SetCursorPosY(connection_status_window_height * 0.75f);
|
||||||
// ok
|
// ok
|
||||||
if (ImGui::Button(
|
if (ImGui::Button(
|
||||||
localization::ok[localization_language_index_].c_str()) ||
|
localization::ok[localization_language_index_].c_str()) ||
|
||||||
@@ -140,14 +136,14 @@ bool Render::ConnectionStatusWindow(
|
|||||||
}
|
}
|
||||||
} else if (password_validating_) {
|
} else if (password_validating_) {
|
||||||
text = localization::validate_password[localization_language_index_];
|
text = localization::validate_password[localization_language_index_];
|
||||||
ImGui::SetCursorPosX(connection_status_window_width_ * 3 / 7);
|
ImGui::SetCursorPosX(connection_status_window_width * 0.43f);
|
||||||
ImGui::SetCursorPosY(connection_status_window_height_ * 2 / 3);
|
ImGui::SetCursorPosY(connection_status_window_height * 0.67f);
|
||||||
}
|
}
|
||||||
} else if (ConnectionStatus::NoSuchTransmissionId ==
|
} else if (ConnectionStatus::NoSuchTransmissionId ==
|
||||||
props->connection_status_) {
|
props->connection_status_) {
|
||||||
text = localization::no_such_id[localization_language_index_];
|
text = localization::no_such_id[localization_language_index_];
|
||||||
ImGui::SetCursorPosX(connection_status_window_width_ * 3 / 7);
|
ImGui::SetCursorPosX(connection_status_window_width * 0.43f);
|
||||||
ImGui::SetCursorPosY(connection_status_window_height_ * 2 / 3);
|
ImGui::SetCursorPosY(connection_status_window_height * 0.67f);
|
||||||
// ok
|
// ok
|
||||||
if (ImGui::Button(localization::ok[localization_language_index_].c_str()) ||
|
if (ImGui::Button(localization::ok[localization_language_index_].c_str()) ||
|
||||||
ImGui::IsKeyPressed(ImGuiKey_Enter)) {
|
ImGui::IsKeyPressed(ImGuiKey_Enter)) {
|
||||||
@@ -158,11 +154,9 @@ bool Render::ConnectionStatusWindow(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto window_width = ImGui::GetWindowSize().x;
|
|
||||||
auto window_height = ImGui::GetWindowSize().y;
|
|
||||||
auto text_width = ImGui::CalcTextSize(text.c_str()).x;
|
auto text_width = ImGui::CalcTextSize(text.c_str()).x;
|
||||||
ImGui::SetCursorPosX((window_width - text_width) * 0.5f);
|
ImGui::SetCursorPosX((connection_status_window_width - text_width) * 0.5f);
|
||||||
ImGui::SetCursorPosY(window_height * 0.2f);
|
ImGui::SetCursorPosY(connection_status_window_height * 0.2f);
|
||||||
ImGui::Text("%s", text.c_str());
|
ImGui::Text("%s", text.c_str());
|
||||||
ImGui::SetWindowFontScale(1.0f);
|
ImGui::SetWindowFontScale(1.0f);
|
||||||
|
|
||||||
|
|||||||
@@ -53,11 +53,11 @@ int Render::ControlWindow(std::shared_ptr<SubStreamWindowProperties>& props) {
|
|||||||
ImVec2(props->control_window_width_, props->control_window_height_),
|
ImVec2(props->control_window_width_, props->control_window_height_),
|
||||||
ImGuiCond_Always);
|
ImGuiCond_Always);
|
||||||
|
|
||||||
ImGui::SetNextWindowPos(ImVec2(0, title_bar_height_ + 1), ImGuiCond_Once);
|
ImGui::SetNextWindowPos(ImVec2(0, title_bar_height_), ImGuiCond_Once);
|
||||||
|
|
||||||
float pos_x = 0;
|
float pos_x = 0;
|
||||||
float pos_y = 0;
|
float pos_y = 0;
|
||||||
float y_boundary = fullscreen_button_pressed_ ? 0 : (title_bar_height_ + 1);
|
float y_boundary = fullscreen_button_pressed_ ? 0 : title_bar_height_;
|
||||||
|
|
||||||
if (props->reset_control_bar_pos_) {
|
if (props->reset_control_bar_pos_) {
|
||||||
float new_cursor_pos_x = 0;
|
float new_cursor_pos_x = 0;
|
||||||
@@ -94,7 +94,7 @@ int Render::ControlWindow(std::shared_ptr<SubStreamWindowProperties>& props) {
|
|||||||
} else if (!props->reset_control_bar_pos_ &&
|
} else if (!props->reset_control_bar_pos_ &&
|
||||||
ImGui::IsMouseReleased(ImGuiMouseButton_Left) ||
|
ImGui::IsMouseReleased(ImGuiMouseButton_Left) ||
|
||||||
props->control_window_width_is_changing_) {
|
props->control_window_width_is_changing_) {
|
||||||
if (props->control_window_pos_.x <= stream_window_width_ / 2) {
|
if (props->control_window_pos_.x <= stream_window_width_ * 0.5f) {
|
||||||
if (props->control_window_pos_.y + props->control_window_height_ >
|
if (props->control_window_pos_.y + props->control_window_height_ >
|
||||||
stream_window_height_) {
|
stream_window_height_) {
|
||||||
pos_y = stream_window_height_ - props->control_window_height_;
|
pos_y = stream_window_height_ - props->control_window_height_;
|
||||||
@@ -118,18 +118,16 @@ int Render::ControlWindow(std::shared_ptr<SubStreamWindowProperties>& props) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
props->is_control_bar_in_left_ = true;
|
props->is_control_bar_in_left_ = true;
|
||||||
} else if (props->control_window_pos_.x > stream_window_width_ / 2) {
|
} else if (props->control_window_pos_.x > stream_window_width_ * 0.5f) {
|
||||||
pos_x = 0;
|
pos_x = 0;
|
||||||
pos_y =
|
pos_y =
|
||||||
(props->control_window_pos_.y >= y_boundary &&
|
(props->control_window_pos_.y >= y_boundary &&
|
||||||
props->control_window_pos_.y <=
|
props->control_window_pos_.y <=
|
||||||
stream_window_height_ - props->control_window_height_)
|
stream_window_height_ - props->control_window_height_)
|
||||||
? props->control_window_pos_.y
|
? props->control_window_pos_.y
|
||||||
: (props->control_window_pos_.y < (fullscreen_button_pressed_
|
: (props->control_window_pos_.y <
|
||||||
? 0
|
(fullscreen_button_pressed_ ? 0 : title_bar_height_)
|
||||||
: (title_bar_height_ + 1))
|
? (fullscreen_button_pressed_ ? 0 : title_bar_height_)
|
||||||
? (fullscreen_button_pressed_ ? 0
|
|
||||||
: (title_bar_height_ + 1))
|
|
||||||
: (stream_window_height_ - props->control_window_height_));
|
: (stream_window_height_ - props->control_window_height_));
|
||||||
|
|
||||||
if (props->control_bar_expand_) {
|
if (props->control_bar_expand_) {
|
||||||
@@ -205,10 +203,10 @@ int Render::ControlWindow(std::shared_ptr<SubStreamWindowProperties>& props) {
|
|||||||
|
|
||||||
std::string control_child_window_title =
|
std::string control_child_window_title =
|
||||||
props->remote_id_ + "ControlChildWindow";
|
props->remote_id_ + "ControlChildWindow";
|
||||||
ImGui::BeginChild(
|
ImGui::BeginChild(control_child_window_title.c_str(),
|
||||||
control_child_window_title.c_str(),
|
ImVec2(props->control_window_width_ * 2.0f,
|
||||||
ImVec2(props->control_window_width_ * 2, props->control_window_height_),
|
props->control_window_height_),
|
||||||
ImGuiChildFlags_Border, ImGuiWindowFlags_NoDecoration);
|
ImGuiChildFlags_Border, ImGuiWindowFlags_NoDecoration);
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
|
|
||||||
ControlBar(props);
|
ControlBar(props);
|
||||||
|
|||||||
@@ -6,31 +6,38 @@
|
|||||||
namespace crossdesk {
|
namespace crossdesk {
|
||||||
|
|
||||||
int Render::SettingWindow() {
|
int Render::SettingWindow() {
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
if (show_settings_window_) {
|
if (show_settings_window_) {
|
||||||
if (settings_window_pos_reset_) {
|
if (settings_window_pos_reset_) {
|
||||||
const ImGuiViewport* viewport = ImGui::GetMainViewport();
|
const ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
|
#if (((defined(_WIN32) || defined(__linux__)) && !defined(__aarch64__) && \
|
||||||
|
!defined(__arm__) && USE_CUDA) || \
|
||||||
|
defined(__APPLE__))
|
||||||
ImGui::SetNextWindowPos(
|
ImGui::SetNextWindowPos(
|
||||||
ImVec2((viewport->WorkSize.x - viewport->WorkPos.x -
|
ImVec2(io.DisplaySize.x * 0.343f, io.DisplaySize.y * 0.07f));
|
||||||
SETTINGS_WINDOW_WIDTH_CN) /
|
|
||||||
2,
|
|
||||||
(viewport->WorkSize.y - viewport->WorkPos.y -
|
|
||||||
SETTINGS_WINDOW_HEIGHT_CN) /
|
|
||||||
2));
|
|
||||||
|
|
||||||
ImGui::SetNextWindowSize(
|
ImGui::SetNextWindowSize(
|
||||||
ImVec2(SETTINGS_WINDOW_WIDTH_CN, SETTINGS_WINDOW_HEIGHT_CN));
|
ImVec2(io.DisplaySize.x * 0.315f, io.DisplaySize.y * 0.85f));
|
||||||
|
#else
|
||||||
|
ImGui::SetNextWindowPos(
|
||||||
|
ImVec2(io.DisplaySize.x * 0.343f, io.DisplaySize.y * 0.1f));
|
||||||
|
ImGui::SetNextWindowSize(
|
||||||
|
ImVec2(io.DisplaySize.x * 0.315f, io.DisplaySize.y * 0.8f));
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
|
#if (((defined(_WIN32) || defined(__linux__)) && !defined(__aarch64__) && \
|
||||||
|
!defined(__arm__) && USE_CUDA) || \
|
||||||
|
defined(__APPLE__))
|
||||||
ImGui::SetNextWindowPos(
|
ImGui::SetNextWindowPos(
|
||||||
ImVec2((viewport->WorkSize.x - viewport->WorkPos.x -
|
ImVec2(io.DisplaySize.x * 0.297f, io.DisplaySize.y * 0.07f));
|
||||||
SETTINGS_WINDOW_WIDTH_EN) /
|
|
||||||
2,
|
|
||||||
(viewport->WorkSize.y - viewport->WorkPos.y -
|
|
||||||
SETTINGS_WINDOW_HEIGHT_EN) /
|
|
||||||
2));
|
|
||||||
|
|
||||||
ImGui::SetNextWindowSize(
|
ImGui::SetNextWindowSize(
|
||||||
ImVec2(SETTINGS_WINDOW_WIDTH_EN, SETTINGS_WINDOW_HEIGHT_EN));
|
ImVec2(io.DisplaySize.x * 0.407f, io.DisplaySize.y * 0.85f));
|
||||||
|
#else
|
||||||
|
ImGui::SetNextWindowPos(
|
||||||
|
ImVec2(io.DisplaySize.x * 0.297f, io.DisplaySize.y * 0.1f));
|
||||||
|
ImGui::SetNextWindowSize(
|
||||||
|
ImVec2(io.DisplaySize.x * 0.407f, io.DisplaySize.y * 0.8f));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
settings_window_pos_reset_ = false;
|
settings_window_pos_reset_ = false;
|
||||||
@@ -38,7 +45,7 @@ int Render::SettingWindow() {
|
|||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
{
|
{
|
||||||
static int settings_items_padding = 30 * dpi_scale_;
|
static int settings_items_padding = title_bar_button_width_ * 0.75f;
|
||||||
int settings_items_offset = 0;
|
int settings_items_offset = 0;
|
||||||
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
@@ -57,17 +64,18 @@ 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 + 4 * dpi_scale_);
|
ImGui::SetCursorPosY(settings_items_offset);
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::Text(
|
ImGui::Text(
|
||||||
"%s", localization::language[localization_language_index_].c_str());
|
"%s", localization::language[localization_language_index_].c_str());
|
||||||
|
ImGui::SameLine();
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
ImGui::SetCursorPosX(LANGUAGE_SELECT_WINDOW_PADDING_CN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 3.0f);
|
||||||
} else {
|
} else {
|
||||||
ImGui::SetCursorPosX(LANGUAGE_SELECT_WINDOW_PADDING_EN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 4.5f);
|
||||||
}
|
}
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
|
||||||
ImGui::SetNextItemWidth(SETTINGS_SELECT_WINDOW_WIDTH);
|
|
||||||
|
|
||||||
|
ImGui::SetNextItemWidth(title_bar_button_width_ * 1.8f);
|
||||||
if (ImGui::BeginCombo("##language",
|
if (ImGui::BeginCombo("##language",
|
||||||
language_items[language_button_value_])) {
|
language_items[language_button_value_])) {
|
||||||
ImGui::SetWindowFontScale(0.5f);
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
@@ -97,19 +105,19 @@ int Render::SettingWindow() {
|
|||||||
.c_str()};
|
.c_str()};
|
||||||
|
|
||||||
settings_items_offset += settings_items_padding;
|
settings_items_offset += settings_items_padding;
|
||||||
ImGui::SetCursorPosY(settings_items_offset + 4 * dpi_scale_);
|
ImGui::SetCursorPosY(settings_items_offset);
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::Text(
|
ImGui::Text(
|
||||||
"%s",
|
"%s",
|
||||||
localization::video_quality[localization_language_index_].c_str());
|
localization::video_quality[localization_language_index_].c_str());
|
||||||
|
ImGui::SameLine();
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
ImGui::SetCursorPosX(VIDEO_QUALITY_SELECT_WINDOW_PADDING_CN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 3.0f);
|
||||||
} else {
|
} else {
|
||||||
ImGui::SetCursorPosX(VIDEO_QUALITY_SELECT_WINDOW_PADDING_EN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 4.5f);
|
||||||
}
|
}
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
|
||||||
ImGui::SetNextItemWidth(SETTINGS_SELECT_WINDOW_WIDTH);
|
|
||||||
|
|
||||||
|
ImGui::SetNextItemWidth(title_bar_button_width_ * 1.8f);
|
||||||
if (ImGui::BeginCombo(
|
if (ImGui::BeginCombo(
|
||||||
"##video_quality",
|
"##video_quality",
|
||||||
video_quality_items[video_quality_button_value_])) {
|
video_quality_items[video_quality_button_value_])) {
|
||||||
@@ -130,19 +138,19 @@ 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 + 4);
|
ImGui::SetCursorPosY(settings_items_offset);
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::Text("%s",
|
ImGui::Text("%s",
|
||||||
localization::video_frame_rate[localization_language_index_]
|
localization::video_frame_rate[localization_language_index_]
|
||||||
.c_str());
|
.c_str());
|
||||||
|
ImGui::SameLine();
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
ImGui::SetCursorPosX(VIDEO_FRAME_RATE_SELECT_WINDOW_PADDING_CN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 3.0f);
|
||||||
} else {
|
} else {
|
||||||
ImGui::SetCursorPosX(VIDEO_FRAME_RATE_SELECT_WINDOW_PADDING_EN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 4.5f);
|
||||||
}
|
}
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
|
||||||
ImGui::SetNextItemWidth(SETTINGS_SELECT_WINDOW_WIDTH);
|
|
||||||
|
|
||||||
|
ImGui::SetNextItemWidth(title_bar_button_width_ * 1.8f);
|
||||||
if (ImGui::BeginCombo(
|
if (ImGui::BeginCombo(
|
||||||
"##video_frame_rate",
|
"##video_frame_rate",
|
||||||
video_frame_rate_items[video_frame_rate_button_value_])) {
|
video_frame_rate_items[video_frame_rate_button_value_])) {
|
||||||
@@ -165,20 +173,20 @@ 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 + 4);
|
ImGui::SetCursorPosY(settings_items_offset);
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::Text(
|
ImGui::Text(
|
||||||
"%s",
|
"%s",
|
||||||
localization::video_encode_format[localization_language_index_]
|
localization::video_encode_format[localization_language_index_]
|
||||||
.c_str());
|
.c_str());
|
||||||
|
ImGui::SameLine();
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
ImGui::SetCursorPosX(VIDEO_ENCODE_FORMAT_SELECT_WINDOW_PADDING_CN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 3.0f);
|
||||||
} else {
|
} else {
|
||||||
ImGui::SetCursorPosX(VIDEO_ENCODE_FORMAT_SELECT_WINDOW_PADDING_EN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 4.5f);
|
||||||
}
|
}
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
|
||||||
ImGui::SetNextItemWidth(SETTINGS_SELECT_WINDOW_WIDTH);
|
|
||||||
|
|
||||||
|
ImGui::SetNextItemWidth(title_bar_button_width_ * 1.8f);
|
||||||
if (ImGui::BeginCombo(
|
if (ImGui::BeginCombo(
|
||||||
"##video_encode_format",
|
"##video_encode_format",
|
||||||
video_encode_format_items[video_encode_format_button_value_])) {
|
video_encode_format_items[video_encode_format_button_value_])) {
|
||||||
@@ -193,22 +201,25 @@ int Render::SettingWindow() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if USE_CUDA && !defined(__aarch64__) && !defined(__arm__)
|
#if (((defined(_WIN32) || defined(__linux__)) && !defined(__aarch64__) && \
|
||||||
|
!defined(__arm__) && USE_CUDA) || \
|
||||||
|
defined(__APPLE__))
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
{
|
{
|
||||||
settings_items_offset += settings_items_padding;
|
settings_items_offset += settings_items_padding;
|
||||||
ImGui::SetCursorPosY(settings_items_offset + 4);
|
ImGui::SetCursorPosY(settings_items_offset);
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
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());
|
||||||
|
ImGui::SameLine();
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
ImGui::SetCursorPosX(ENABLE_HARDWARE_VIDEO_CODEC_CHECKBOX_PADDING_CN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 4.275f);
|
||||||
} else {
|
} else {
|
||||||
ImGui::SetCursorPosX(ENABLE_HARDWARE_VIDEO_CODEC_CHECKBOX_PADDING_EN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 5.755f);
|
||||||
}
|
}
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
|
||||||
ImGui::Checkbox("##enable_hardware_video_codec",
|
ImGui::Checkbox("##enable_hardware_video_codec",
|
||||||
&enable_hardware_video_codec_);
|
&enable_hardware_video_codec_);
|
||||||
}
|
}
|
||||||
@@ -218,17 +229,18 @@ int Render::SettingWindow() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
settings_items_offset += settings_items_padding;
|
settings_items_offset += settings_items_padding;
|
||||||
ImGui::SetCursorPosY(settings_items_offset + 4);
|
ImGui::SetCursorPosY(settings_items_offset);
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::Text(
|
ImGui::Text(
|
||||||
"%s",
|
"%s",
|
||||||
localization::enable_turn[localization_language_index_].c_str());
|
localization::enable_turn[localization_language_index_].c_str());
|
||||||
|
ImGui::SameLine();
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
ImGui::SetCursorPosX(ENABLE_TURN_CHECKBOX_PADDING_CN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 4.275f);
|
||||||
} else {
|
} else {
|
||||||
ImGui::SetCursorPosX(ENABLE_TURN_CHECKBOX_PADDING_EN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 5.755f);
|
||||||
}
|
}
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
|
||||||
ImGui::Checkbox("##enable_turn", &enable_turn_);
|
ImGui::Checkbox("##enable_turn", &enable_turn_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,17 +248,18 @@ int Render::SettingWindow() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
settings_items_offset += settings_items_padding;
|
settings_items_offset += settings_items_padding;
|
||||||
ImGui::SetCursorPosY(settings_items_offset + 4);
|
ImGui::SetCursorPosY(settings_items_offset);
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::Text(
|
ImGui::Text(
|
||||||
"%s",
|
"%s",
|
||||||
localization::enable_srtp[localization_language_index_].c_str());
|
localization::enable_srtp[localization_language_index_].c_str());
|
||||||
|
ImGui::SameLine();
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
ImGui::SetCursorPosX(ENABLE_SRTP_CHECKBOX_PADDING_CN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 4.275f);
|
||||||
} else {
|
} else {
|
||||||
ImGui::SetCursorPosX(ENABLE_SRTP_CHECKBOX_PADDING_EN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 5.755f);
|
||||||
}
|
}
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
|
||||||
ImGui::Checkbox("##enable_srtp", &enable_srtp_);
|
ImGui::Checkbox("##enable_srtp", &enable_srtp_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,19 +268,19 @@ int Render::SettingWindow() {
|
|||||||
{
|
{
|
||||||
settings_items_offset += settings_items_padding;
|
settings_items_offset += settings_items_padding;
|
||||||
ImGui::SetCursorPosY(settings_items_offset + 1);
|
ImGui::SetCursorPosY(settings_items_offset + 1);
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
if (ImGui::Button(localization::self_hosted_server_config
|
if (ImGui::Button(localization::self_hosted_server_config
|
||||||
[localization_language_index_]
|
[localization_language_index_]
|
||||||
.c_str())) {
|
.c_str())) {
|
||||||
show_self_hosted_server_config_window_ = true;
|
show_self_hosted_server_config_window_ = true;
|
||||||
}
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
ImGui::SetCursorPosX(ENABLE_SELF_HOSTED_SERVER_CHECKBOX_PADDING_CN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 4.275f);
|
||||||
} else {
|
} else {
|
||||||
ImGui::SetCursorPosX(ENABLE_SELF_HOSTED_SERVER_CHECKBOX_PADDING_EN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 5.755f);
|
||||||
}
|
}
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
|
||||||
ImGui::Checkbox("##enable_self_hosted", &enable_self_hosted_);
|
ImGui::Checkbox("##enable_self_hosted", &enable_self_hosted_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,18 +288,18 @@ int Render::SettingWindow() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
settings_items_offset += settings_items_padding;
|
settings_items_offset += settings_items_padding;
|
||||||
ImGui::SetCursorPosY(settings_items_offset + 4);
|
ImGui::SetCursorPosY(settings_items_offset);
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::Text("%s",
|
ImGui::Text("%s",
|
||||||
localization::enable_autostart[localization_language_index_]
|
localization::enable_autostart[localization_language_index_]
|
||||||
.c_str());
|
.c_str());
|
||||||
|
ImGui::SameLine();
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
ImGui::SetCursorPosX(ENABLE_AUTOSTART_PADDING_CN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 4.275f);
|
||||||
} else {
|
} else {
|
||||||
ImGui::SetCursorPosX(ENABLE_AUTOSTART_PADDING_EN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 5.755f);
|
||||||
}
|
}
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
|
||||||
ImGui::Checkbox("##enable_autostart_", &enable_autostart_);
|
ImGui::Checkbox("##enable_autostart_", &enable_autostart_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,18 +307,18 @@ int Render::SettingWindow() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
settings_items_offset += settings_items_padding;
|
settings_items_offset += settings_items_padding;
|
||||||
ImGui::SetCursorPosY(settings_items_offset + 4);
|
ImGui::SetCursorPosY(settings_items_offset);
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::Text(
|
ImGui::Text(
|
||||||
"%s",
|
"%s",
|
||||||
localization::enable_daemon[localization_language_index_].c_str());
|
localization::enable_daemon[localization_language_index_].c_str());
|
||||||
|
ImGui::SameLine();
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
ImGui::SetCursorPosX(ENABLE_DAEMON_PADDING_CN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 4.275f);
|
||||||
} else {
|
} else {
|
||||||
ImGui::SetCursorPosX(ENABLE_DAEMON_PADDING_EN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 5.755f);
|
||||||
}
|
}
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
|
||||||
ImGui::Checkbox("##enable_daemon_", &enable_daemon_);
|
ImGui::Checkbox("##enable_daemon_", &enable_daemon_);
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
ImGui::BeginTooltip();
|
ImGui::BeginTooltip();
|
||||||
@@ -322,18 +335,18 @@ int Render::SettingWindow() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
settings_items_offset += settings_items_padding;
|
settings_items_offset += settings_items_padding;
|
||||||
ImGui::SetCursorPosY(settings_items_offset + 4);
|
ImGui::SetCursorPosY(settings_items_offset);
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::Text("%s",
|
ImGui::Text("%s",
|
||||||
localization::minimize_to_tray[localization_language_index_]
|
localization::minimize_to_tray[localization_language_index_]
|
||||||
.c_str());
|
.c_str());
|
||||||
|
ImGui::SameLine();
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
ImGui::SetCursorPosX(ENABLE_MINIZE_TO_TRAY_PADDING_CN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 4.275f);
|
||||||
} else {
|
} else {
|
||||||
ImGui::SetCursorPosX(ENABLE_MINIZE_TO_TRAY_PADDING_EN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 5.755f);
|
||||||
}
|
}
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
|
||||||
ImGui::Checkbox("##enable_minimize_to_tray_",
|
ImGui::Checkbox("##enable_minimize_to_tray_",
|
||||||
&enable_minimize_to_tray_);
|
&enable_minimize_to_tray_);
|
||||||
}
|
}
|
||||||
@@ -343,13 +356,15 @@ int Render::SettingWindow() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
ImGui::SetCursorPosX(SETTINGS_OK_BUTTON_PADDING_CN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 1.59f);
|
||||||
} else {
|
} else {
|
||||||
ImGui::SetCursorPosX(SETTINGS_OK_BUTTON_PADDING_EN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 2.22f);
|
||||||
}
|
}
|
||||||
|
|
||||||
settings_items_offset += settings_items_padding + 10;
|
settings_items_offset +=
|
||||||
|
settings_items_padding + title_bar_button_width_ * 0.3f;
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
ImGui::SetCursorPosY(settings_items_offset);
|
||||||
|
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
|
|
||||||
// OK
|
// OK
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ int Render::MainWindow() {
|
|||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
float local_remote_window_width = io.DisplaySize.x;
|
float local_remote_window_width = io.DisplaySize.x;
|
||||||
float local_remote_window_height =
|
float local_remote_window_height =
|
||||||
io.DisplaySize.y * (1 - TITLE_BAR_HEIGHT - STATUS_BAR_HEIGHT);
|
io.DisplaySize.y * (0.56f - TITLE_BAR_HEIGHT);
|
||||||
|
|
||||||
ImGui::SetNextWindowPos(ImVec2(0.0f, io.DisplaySize.y * TITLE_BAR_HEIGHT),
|
ImGui::SetNextWindowPos(ImVec2(0.0f, io.DisplaySize.y * (TITLE_BAR_HEIGHT)),
|
||||||
ImGuiCond_Always);
|
ImGuiCond_Always);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.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));
|
||||||
@@ -34,7 +34,7 @@ int Render::MainWindow() {
|
|||||||
RemoteWindow();
|
RemoteWindow();
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
|
||||||
// RecentConnectionsWindow();
|
RecentConnectionsWindow();
|
||||||
StatusBar();
|
StatusBar();
|
||||||
|
|
||||||
if (show_connection_status_window_) {
|
if (show_connection_status_window_) {
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ int Render::ShowSimpleFileBrowser() {
|
|||||||
if (show_file_browser_) {
|
if (show_file_browser_) {
|
||||||
ImGui::PushItemFlag(ImGuiItemFlags_AutoClosePopups, false);
|
ImGui::PushItemFlag(ImGuiItemFlags_AutoClosePopups, false);
|
||||||
|
|
||||||
float fixed_width = 130.0f * dpi_scale_;
|
float fixed_width = title_bar_button_width_ * 3.8f;
|
||||||
ImGui::SetNextItemWidth(fixed_width);
|
ImGui::SetNextItemWidth(fixed_width);
|
||||||
ImGui::SetNextWindowSizeConstraints(ImVec2(fixed_width, 0),
|
ImGui::SetNextWindowSizeConstraints(ImVec2(fixed_width, 0),
|
||||||
ImVec2(fixed_width, 100.0f));
|
ImVec2(fixed_width, 100.0f));
|
||||||
@@ -121,33 +121,19 @@ int Render::ShowSimpleFileBrowser() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Render::SelfHostedServerWindow() {
|
int Render::SelfHostedServerWindow() {
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
if (show_self_hosted_server_config_window_) {
|
if (show_self_hosted_server_config_window_) {
|
||||||
if (self_hosted_server_config_window_pos_reset_) {
|
if (self_hosted_server_config_window_pos_reset_) {
|
||||||
const ImGuiViewport* viewport = ImGui::GetMainViewport();
|
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
ImGui::SetNextWindowPos(
|
ImGui::SetNextWindowPos(
|
||||||
ImVec2((viewport->WorkSize.x - viewport->WorkPos.x -
|
ImVec2(io.DisplaySize.x * 0.298f, io.DisplaySize.y * 0.25f));
|
||||||
SELF_HOSTED_SERVER_CONFIG_WINDOW_WIDTH_CN) /
|
|
||||||
2,
|
|
||||||
(viewport->WorkSize.y - viewport->WorkPos.y -
|
|
||||||
SELF_HOSTED_SERVER_CONFIG_WINDOW_HEIGHT_CN) /
|
|
||||||
2));
|
|
||||||
|
|
||||||
ImGui::SetNextWindowSize(
|
ImGui::SetNextWindowSize(
|
||||||
ImVec2(SELF_HOSTED_SERVER_CONFIG_WINDOW_WIDTH_CN,
|
ImVec2(io.DisplaySize.x * 0.407f, io.DisplaySize.y * 0.41f));
|
||||||
SELF_HOSTED_SERVER_CONFIG_WINDOW_HEIGHT_CN));
|
|
||||||
} else {
|
} else {
|
||||||
ImGui::SetNextWindowPos(
|
ImGui::SetNextWindowPos(
|
||||||
ImVec2((viewport->WorkSize.x - viewport->WorkPos.x -
|
ImVec2(io.DisplaySize.x * 0.27f, io.DisplaySize.y * 0.3f));
|
||||||
SELF_HOSTED_SERVER_CONFIG_WINDOW_WIDTH_EN) /
|
|
||||||
2,
|
|
||||||
(viewport->WorkSize.y - viewport->WorkPos.y -
|
|
||||||
SELF_HOSTED_SERVER_CONFIG_WINDOW_HEIGHT_EN) /
|
|
||||||
2));
|
|
||||||
|
|
||||||
ImGui::SetNextWindowSize(
|
ImGui::SetNextWindowSize(
|
||||||
ImVec2(SELF_HOSTED_SERVER_CONFIG_WINDOW_WIDTH_EN,
|
ImVec2(io.DisplaySize.x * 0.465f, io.DisplaySize.y * 0.41f));
|
||||||
SELF_HOSTED_SERVER_CONFIG_WINDOW_HEIGHT_EN));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self_hosted_server_config_window_pos_reset_ = false;
|
self_hosted_server_config_window_pos_reset_ = false;
|
||||||
@@ -155,9 +141,6 @@ int Render::SelfHostedServerWindow() {
|
|||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
{
|
{
|
||||||
static int settings_items_padding = 30 * dpi_scale_;
|
|
||||||
int settings_items_offset = 0;
|
|
||||||
|
|
||||||
ImGui::SetWindowFontScale(0.5f);
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 5.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 5.0f);
|
||||||
@@ -173,18 +156,17 @@ int Render::SelfHostedServerWindow() {
|
|||||||
ImGui::SetWindowFontScale(0.5f);
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
|
||||||
{
|
{
|
||||||
settings_items_offset += settings_items_padding;
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::SetCursorPosY(settings_items_offset + 2);
|
|
||||||
ImGui::Text("%s", localization::self_hosted_server_address
|
ImGui::Text("%s", localization::self_hosted_server_address
|
||||||
[localization_language_index_]
|
[localization_language_index_]
|
||||||
.c_str());
|
.c_str());
|
||||||
|
ImGui::SameLine();
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
ImGui::SetCursorPosX(SELF_HOSTED_SERVER_HOST_INPUT_BOX_PADDING_CN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 2.5f);
|
||||||
} else {
|
} else {
|
||||||
ImGui::SetCursorPosX(SELF_HOSTED_SERVER_HOST_INPUT_BOX_PADDING_EN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 3.43f);
|
||||||
}
|
}
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
ImGui::SetNextItemWidth(title_bar_button_width_ * 3.8f);
|
||||||
ImGui::SetNextItemWidth(SELF_HOSTED_SERVER_INPUT_WINDOW_WIDTH);
|
|
||||||
|
|
||||||
ImGui::InputText("##signal_server_ip_self_", signal_server_ip_self_,
|
ImGui::InputText("##signal_server_ip_self_", signal_server_ip_self_,
|
||||||
IM_ARRAYSIZE(signal_server_ip_self_),
|
IM_ARRAYSIZE(signal_server_ip_self_),
|
||||||
@@ -194,20 +176,18 @@ int Render::SelfHostedServerWindow() {
|
|||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
{
|
{
|
||||||
settings_items_offset += settings_items_padding;
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::SetCursorPosY(settings_items_offset + 2);
|
|
||||||
ImGui::Text(
|
ImGui::Text(
|
||||||
"%s",
|
"%s",
|
||||||
localization::self_hosted_server_port[localization_language_index_]
|
localization::self_hosted_server_port[localization_language_index_]
|
||||||
.c_str());
|
.c_str());
|
||||||
|
ImGui::SameLine();
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
ImGui::SetCursorPosX(SELF_HOSTED_SERVER_PORT_INPUT_BOX_PADDING_CN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 2.5f);
|
||||||
} else {
|
} else {
|
||||||
ImGui::SetCursorPosX(SELF_HOSTED_SERVER_PORT_INPUT_BOX_PADDING_EN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 3.43f);
|
||||||
}
|
}
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
ImGui::SetNextItemWidth(title_bar_button_width_ * 3.8f);
|
||||||
ImGui::SetNextItemWidth(SELF_HOSTED_SERVER_INPUT_WINDOW_WIDTH);
|
|
||||||
|
|
||||||
ImGui::InputText("##signal_server_port_self_", signal_server_port_self_,
|
ImGui::InputText("##signal_server_port_self_", signal_server_port_self_,
|
||||||
IM_ARRAYSIZE(signal_server_port_self_));
|
IM_ARRAYSIZE(signal_server_port_self_));
|
||||||
@@ -216,19 +196,17 @@ int Render::SelfHostedServerWindow() {
|
|||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
{
|
{
|
||||||
settings_items_offset += settings_items_padding;
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::SetCursorPosY(settings_items_offset + 2);
|
|
||||||
ImGui::Text("%s", localization::self_hosted_server_coturn_server_port
|
ImGui::Text("%s", localization::self_hosted_server_coturn_server_port
|
||||||
[localization_language_index_]
|
[localization_language_index_]
|
||||||
.c_str());
|
.c_str());
|
||||||
|
ImGui::SameLine();
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
ImGui::SetCursorPosX(SELF_HOSTED_SERVER_PORT_INPUT_BOX_PADDING_CN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 2.5f);
|
||||||
} else {
|
} else {
|
||||||
ImGui::SetCursorPosX(SELF_HOSTED_SERVER_PORT_INPUT_BOX_PADDING_EN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 3.43f);
|
||||||
}
|
}
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
ImGui::SetNextItemWidth(title_bar_button_width_ * 3.8f);
|
||||||
ImGui::SetNextItemWidth(SELF_HOSTED_SERVER_INPUT_WINDOW_WIDTH);
|
|
||||||
|
|
||||||
ImGui::InputText("##coturn_server_port_self_", coturn_server_port_self_,
|
ImGui::InputText("##coturn_server_port_self_", coturn_server_port_self_,
|
||||||
IM_ARRAYSIZE(coturn_server_port_self_));
|
IM_ARRAYSIZE(coturn_server_port_self_));
|
||||||
@@ -237,19 +215,17 @@ int Render::SelfHostedServerWindow() {
|
|||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
{
|
{
|
||||||
settings_items_offset += settings_items_padding;
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::SetCursorPosY(settings_items_offset + 2);
|
|
||||||
ImGui::Text("%s", localization::self_hosted_server_certificate_path
|
ImGui::Text("%s", localization::self_hosted_server_certificate_path
|
||||||
[localization_language_index_]
|
[localization_language_index_]
|
||||||
.c_str());
|
.c_str());
|
||||||
|
ImGui::SameLine();
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
ImGui::SetCursorPosX(SELF_HOSTED_SERVER_PORT_INPUT_BOX_PADDING_CN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 2.5f);
|
||||||
} else {
|
} else {
|
||||||
ImGui::SetCursorPosX(SELF_HOSTED_SERVER_PORT_INPUT_BOX_PADDING_EN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 3.43f);
|
||||||
}
|
}
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
ImGui::SetNextItemWidth(title_bar_button_width_ * 3.8f);
|
||||||
ImGui::SetNextItemWidth(SELF_HOSTED_SERVER_INPUT_WINDOW_WIDTH);
|
|
||||||
|
|
||||||
ShowSimpleFileBrowser();
|
ShowSimpleFileBrowser();
|
||||||
}
|
}
|
||||||
@@ -258,14 +234,14 @@ int Render::SelfHostedServerWindow() {
|
|||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::Dummy(ImVec2(0.0f, title_bar_button_width_ * 0.25f));
|
||||||
|
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
ImGui::SetCursorPosX(SELF_HOSTED_SERVER_CONFIG_OK_BUTTON_PADDING_CN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 2.32f);
|
||||||
} else {
|
} else {
|
||||||
ImGui::SetCursorPosX(SELF_HOSTED_SERVER_CONFIG_OK_BUTTON_PADDING_EN);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 2.7f);
|
||||||
}
|
}
|
||||||
|
|
||||||
settings_items_offset += settings_items_padding + 10;
|
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
|
|
||||||
// OK
|
// OK
|
||||||
@@ -299,16 +275,27 @@ int Render::SelfHostedServerWindow() {
|
|||||||
localization::cancel[localization_language_index_].c_str())) {
|
localization::cancel[localization_language_index_].c_str())) {
|
||||||
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_self_,
|
||||||
strncpy(signal_server_ip_self_, signal_server_ip_,
|
config_center_->GetSignalServerHost().c_str(),
|
||||||
sizeof(signal_server_ip_self_) - 1);
|
sizeof(signal_server_ip_self_) - 1);
|
||||||
signal_server_ip_self_[sizeof(signal_server_ip_self_) - 1] = '\0';
|
signal_server_ip_self_[sizeof(signal_server_ip_self_) - 1] = '\0';
|
||||||
strncpy(signal_server_port_self_, signal_server_port_,
|
int signal_port = config_center_->GetSignalServerPort();
|
||||||
sizeof(signal_server_port_self_) - 1);
|
if (signal_port > 0) {
|
||||||
signal_server_port_self_[sizeof(signal_server_port_self_) - 1] = '\0';
|
strncpy(signal_server_port_self_, std::to_string(signal_port).c_str(),
|
||||||
config_center_->SetServerHost(signal_server_ip_self_);
|
sizeof(signal_server_port_self_) - 1);
|
||||||
config_center_->SetServerPort(atoi(signal_server_port_self_));
|
signal_server_port_self_[sizeof(signal_server_port_self_) - 1] = '\0';
|
||||||
tls_cert_path_self_.clear();
|
} else {
|
||||||
|
signal_server_port_self_[0] = '\0';
|
||||||
|
}
|
||||||
|
int coturn_port = config_center_->GetCoturnServerPort();
|
||||||
|
if (coturn_port > 0) {
|
||||||
|
strncpy(coturn_server_port_self_, std::to_string(coturn_port).c_str(),
|
||||||
|
sizeof(coturn_server_port_self_) - 1);
|
||||||
|
coturn_server_port_self_[sizeof(coturn_server_port_self_) - 1] = '\0';
|
||||||
|
} else {
|
||||||
|
coturn_server_port_self_[0] = '\0';
|
||||||
|
}
|
||||||
|
tls_cert_path_self_ = config_center_->GetCertFilePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SetWindowFontScale(1.0f);
|
ImGui::SetWindowFontScale(1.0f);
|
||||||
|
|||||||
@@ -69,9 +69,12 @@ int Render::StreamWindow() {
|
|||||||
ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoMove;
|
ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoMove;
|
||||||
|
|
||||||
if (!fullscreen_button_pressed_) {
|
if (!fullscreen_button_pressed_) {
|
||||||
ImGui::SetNextWindowPos(ImVec2(20.0f * dpi_scale_, 0), ImGuiCond_Always);
|
ImGui::SetNextWindowPos(
|
||||||
ImGui::SetNextWindowSize(ImVec2(0, 30.0f * dpi_scale_), ImGuiCond_Always);
|
ImVec2(title_bar_button_width_ * 0.8f, title_bar_button_width_ * 0.1f),
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 8.0f));
|
ImGuiCond_Always);
|
||||||
|
ImGui::SetNextWindowSize(ImVec2(0, title_bar_button_width_ * 0.8f),
|
||||||
|
ImGuiCond_Always);
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0.0f));
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0.0f));
|
||||||
ImGui::Begin("TabBar", nullptr,
|
ImGui::Begin("TabBar", nullptr,
|
||||||
@@ -111,7 +114,7 @@ int Render::StreamWindow() {
|
|||||||
: props->remote_id_;
|
: props->remote_id_;
|
||||||
if (ImGui::BeginTabItem(tab_label.c_str(), &props->tab_opened_)) {
|
if (ImGui::BeginTabItem(tab_label.c_str(), &props->tab_opened_)) {
|
||||||
props->tab_selected_ = true;
|
props->tab_selected_ = true;
|
||||||
ImGui::SetWindowFontScale(0.6f * dpi_scale_);
|
ImGui::SetWindowFontScale(0.6f);
|
||||||
|
|
||||||
ImGui::SetNextWindowSize(
|
ImGui::SetNextWindowSize(
|
||||||
ImVec2(stream_window_width_, stream_window_height_),
|
ImVec2(stream_window_width_, stream_window_height_),
|
||||||
@@ -167,6 +170,20 @@ int Render::StreamWindow() {
|
|||||||
ImGui::EndTabItem();
|
ImGui::EndTabItem();
|
||||||
} else {
|
} else {
|
||||||
props->tab_selected_ = false;
|
props->tab_selected_ = false;
|
||||||
|
if (!props->tab_opened_) {
|
||||||
|
std::string remote_id_to_close = props->remote_id_;
|
||||||
|
// lock.unlock();
|
||||||
|
{
|
||||||
|
// std::unique_lock unique_lock(client_properties_mutex_);
|
||||||
|
auto close_it = client_properties_.find(remote_id_to_close);
|
||||||
|
if (close_it != client_properties_.end()) {
|
||||||
|
CloseTab(close_it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// lock.lock();
|
||||||
|
it = client_properties_.begin();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ int Render::UpdateNotificationWindow() {
|
|||||||
if (show_update_notification_window_ && update_available_) {
|
if (show_update_notification_window_ && update_available_) {
|
||||||
const ImGuiViewport* viewport = ImGui::GetMainViewport();
|
const ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||||
|
|
||||||
float window_width = update_notification_window_width_;
|
float update_notification_window_width = title_bar_button_width_ * 10.0f;
|
||||||
float window_height = update_notification_window_height_;
|
float update_notification_window_height = title_bar_button_width_ * 8.0f;
|
||||||
|
|
||||||
// #ifdef __APPLE__
|
// #ifdef __APPLE__
|
||||||
// float font_scale = 0.3f;
|
// float font_scale = 0.3f;
|
||||||
@@ -64,16 +64,16 @@ int Render::UpdateNotificationWindow() {
|
|||||||
// float font_scale = 0.5f;
|
// float font_scale = 0.5f;
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
float button_width = 35.0f * dpi_scale_;
|
ImGui::SetNextWindowPos(ImVec2((viewport->WorkSize.x - viewport->WorkPos.x -
|
||||||
float button_height = 25.0f * dpi_scale_;
|
update_notification_window_width) /
|
||||||
|
2,
|
||||||
|
(viewport->WorkSize.y - viewport->WorkPos.y -
|
||||||
|
update_notification_window_height) /
|
||||||
|
2),
|
||||||
|
ImGuiCond_FirstUseEver);
|
||||||
|
|
||||||
ImGui::SetNextWindowPos(
|
ImGui::SetNextWindowSize(ImVec2(update_notification_window_width,
|
||||||
ImVec2(
|
update_notification_window_height));
|
||||||
(viewport->WorkSize.x - viewport->WorkPos.x - window_width) / 2,
|
|
||||||
(viewport->WorkSize.y - viewport->WorkPos.y - window_height) / 2),
|
|
||||||
ImGuiCond_FirstUseEver);
|
|
||||||
|
|
||||||
ImGui::SetNextWindowSize(ImVec2(window_width, window_height));
|
|
||||||
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f);
|
||||||
@@ -85,11 +85,12 @@ int Render::UpdateNotificationWindow() {
|
|||||||
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse |
|
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse |
|
||||||
ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoTitleBar);
|
ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoTitleBar);
|
||||||
|
|
||||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + window_height * 0.05f);
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() +
|
||||||
|
update_notification_window_height * 0.05f);
|
||||||
|
|
||||||
// title: new version available
|
// title: new version available
|
||||||
ImGui::SetCursorPosX(window_width * 0.1f);
|
ImGui::SetCursorPosX(update_notification_window_width * 0.1f);
|
||||||
ImGui::SetWindowFontScale(0.6f);
|
ImGui::SetWindowFontScale(0.55f);
|
||||||
std::string title =
|
std::string title =
|
||||||
localization::new_version_available[localization_language_index_] +
|
localization::new_version_available[localization_language_index_] +
|
||||||
": v" + latest_version_;
|
": v" + latest_version_;
|
||||||
@@ -103,23 +104,25 @@ int Render::UpdateNotificationWindow() {
|
|||||||
localization::access_website[localization_language_index_] +
|
localization::access_website[localization_language_index_] +
|
||||||
"https://crossdesk.cn";
|
"https://crossdesk.cn";
|
||||||
ImGui::SetWindowFontScale(0.5f);
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
Hyperlink(download_text, "https://crossdesk.cn", window_width);
|
Hyperlink(download_text, "https://crossdesk.cn",
|
||||||
|
update_notification_window_width);
|
||||||
ImGui::SetWindowFontScale(1.0f);
|
ImGui::SetWindowFontScale(1.0f);
|
||||||
|
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
|
|
||||||
float scrollable_height =
|
float scrollable_height =
|
||||||
window_height - UPDATE_NOTIFICATION_RESERVED_HEIGHT;
|
update_notification_window_height - UPDATE_NOTIFICATION_RESERVED_HEIGHT;
|
||||||
|
|
||||||
if (main_windows_system_chinese_font_ != nullptr) {
|
if (main_windows_system_chinese_font_ != nullptr) {
|
||||||
ImGui::PushFont(main_windows_system_chinese_font_);
|
ImGui::PushFont(main_windows_system_chinese_font_);
|
||||||
}
|
}
|
||||||
// scrollable content area
|
// scrollable content area
|
||||||
ImGui::SetCursorPosX(window_width * 0.05f);
|
ImGui::SetCursorPosX(update_notification_window_width * 0.05f);
|
||||||
ImGui::BeginChild("ScrollableContent",
|
ImGui::BeginChild(
|
||||||
ImVec2(window_width * 0.9f, scrollable_height),
|
"ScrollableContent",
|
||||||
ImGuiChildFlags_Border, ImGuiWindowFlags_None);
|
ImVec2(update_notification_window_width * 0.9f, scrollable_height),
|
||||||
ImGui::SetWindowFontScale(0.6f);
|
ImGuiChildFlags_Border, ImGuiWindowFlags_None);
|
||||||
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
// set text wrap position to current available width (accounts for
|
// set text wrap position to current available width (accounts for
|
||||||
// scrollbar)
|
// scrollbar)
|
||||||
float wrap_pos = ImGui::GetContentRegionAvail().x;
|
float wrap_pos = ImGui::GetContentRegionAvail().x;
|
||||||
@@ -129,7 +132,7 @@ int Render::UpdateNotificationWindow() {
|
|||||||
if (latest_version_info_.contains("releaseName") &&
|
if (latest_version_info_.contains("releaseName") &&
|
||||||
latest_version_info_["releaseName"].is_string() &&
|
latest_version_info_["releaseName"].is_string() &&
|
||||||
!latest_version_info_["releaseName"].empty()) {
|
!latest_version_info_["releaseName"].empty()) {
|
||||||
ImGui::SetCursorPosX(window_width * 0.05f);
|
ImGui::SetCursorPosX(update_notification_window_width * 0.05f);
|
||||||
std::string release_name =
|
std::string release_name =
|
||||||
latest_version_info_["releaseName"].get<std::string>();
|
latest_version_info_["releaseName"].get<std::string>();
|
||||||
ImGui::TextWrapped("%s", release_name.c_str());
|
ImGui::TextWrapped("%s", release_name.c_str());
|
||||||
@@ -138,7 +141,7 @@ int Render::UpdateNotificationWindow() {
|
|||||||
|
|
||||||
// release notes
|
// release notes
|
||||||
if (!release_notes_.empty()) {
|
if (!release_notes_.empty()) {
|
||||||
ImGui::SetCursorPosX(window_width * 0.05f);
|
ImGui::SetCursorPosX(update_notification_window_width * 0.05f);
|
||||||
std::string cleaned_notes = CleanMarkdown(release_notes_);
|
std::string cleaned_notes = CleanMarkdown(release_notes_);
|
||||||
ImGui::TextWrapped("%s", cleaned_notes.c_str());
|
ImGui::TextWrapped("%s", cleaned_notes.c_str());
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
@@ -148,7 +151,7 @@ int Render::UpdateNotificationWindow() {
|
|||||||
if (latest_version_info_.contains("releaseDate") &&
|
if (latest_version_info_.contains("releaseDate") &&
|
||||||
latest_version_info_["releaseDate"].is_string() &&
|
latest_version_info_["releaseDate"].is_string() &&
|
||||||
!latest_version_info_["releaseDate"].empty()) {
|
!latest_version_info_["releaseDate"].empty()) {
|
||||||
ImGui::SetCursorPosX(window_width * 0.05f);
|
ImGui::SetCursorPosX(update_notification_window_width * 0.05f);
|
||||||
std::string date_label =
|
std::string date_label =
|
||||||
localization::release_date[localization_language_index_];
|
localization::release_date[localization_language_index_];
|
||||||
std::string release_date = latest_version_info_["releaseDate"];
|
std::string release_date = latest_version_info_["releaseDate"];
|
||||||
@@ -170,16 +173,15 @@ int Render::UpdateNotificationWindow() {
|
|||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
|
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
ImGui::SetCursorPosX(UPDATE_NOTIFICATION_OK_BUTTON_PADDING_CN);
|
ImGui::SetCursorPosX(update_notification_window_width * 0.407f);
|
||||||
} else {
|
} else {
|
||||||
ImGui::SetCursorPosX(UPDATE_NOTIFICATION_OK_BUTTON_PADDING_EN);
|
ImGui::SetCursorPosX(update_notification_window_width * 0.367f);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SetWindowFontScale(0.5f);
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
// update button
|
// update button
|
||||||
if (ImGui::Button(
|
if (ImGui::Button(
|
||||||
localization::update[localization_language_index_].c_str(),
|
localization::update[localization_language_index_].c_str())) {
|
||||||
ImVec2(button_width, button_height))) {
|
|
||||||
// open download page
|
// open download page
|
||||||
std::string url = "https://crossdesk.cn";
|
std::string url = "https://crossdesk.cn";
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
@@ -196,8 +198,7 @@ int Render::UpdateNotificationWindow() {
|
|||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
if (ImGui::Button(
|
if (ImGui::Button(
|
||||||
localization::cancel[localization_language_index_].c_str(),
|
localization::cancel[localization_language_index_].c_str())) {
|
||||||
ImVec2(button_width, button_height))) {
|
|
||||||
show_update_notification_window_ = false;
|
show_update_notification_window_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Submodule submodules/minirtc updated: 0008123221...9eebd7c4f3
Reference in New Issue
Block a user