mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-12-18 04:56:45 +08:00
Compare commits
11 Commits
757ca330b8
...
v1.1.3-202
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51409e16c8 | ||
|
|
6ca3b58ae2 | ||
|
|
692e176e34 | ||
|
|
4fb7acaa61 | ||
|
|
c0d6429a54 | ||
|
|
07c7c7f179 | ||
|
|
c5ceeb0d80 | ||
|
|
5ce0a891df | ||
|
|
f94ef49210 | ||
|
|
5d0a4d1385 | ||
|
|
dd482cee60 |
16
.github/workflows/build.yml
vendored
16
.github/workflows/build.yml
vendored
@@ -35,7 +35,7 @@ jobs:
|
|||||||
id: set_deb_version
|
id: set_deb_version
|
||||||
run: |
|
run: |
|
||||||
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7)
|
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7)
|
||||||
BUILD_DATE=$(date +%Y%m%d)
|
BUILD_DATE=$(TZ=Asia/Shanghai date +%Y%m%d)
|
||||||
if [[ ! "${VERSION_NUM}" =~ ^[0-9] ]]; then
|
if [[ ! "${VERSION_NUM}" =~ ^[0-9] ]]; then
|
||||||
LEGAL_VERSION="v0.0.0-${VERSION_NUM}-${BUILD_DATE}-${SHORT_SHA}"
|
LEGAL_VERSION="v0.0.0-${VERSION_NUM}-${BUILD_DATE}-${SHORT_SHA}"
|
||||||
else
|
else
|
||||||
@@ -101,7 +101,7 @@ jobs:
|
|||||||
id: set_deb_version
|
id: set_deb_version
|
||||||
run: |
|
run: |
|
||||||
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7)
|
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7)
|
||||||
BUILD_DATE=$(date +%Y%m%d)
|
BUILD_DATE=$(TZ=Asia/Shanghai date +%Y%m%d)
|
||||||
if [[ ! "${VERSION_NUM}" =~ ^[0-9] ]]; then
|
if [[ ! "${VERSION_NUM}" =~ ^[0-9] ]]; then
|
||||||
LEGAL_VERSION="v0.0.0-${VERSION_NUM}-${BUILD_DATE}-${SHORT_SHA}"
|
LEGAL_VERSION="v0.0.0-${VERSION_NUM}-${BUILD_DATE}-${SHORT_SHA}"
|
||||||
else
|
else
|
||||||
@@ -164,7 +164,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
VERSION="${GITHUB_REF##*/}"
|
VERSION="${GITHUB_REF##*/}"
|
||||||
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7)
|
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7)
|
||||||
BUILD_DATE=$(date +%Y%m%d)
|
BUILD_DATE=$(TZ=Asia/Shanghai date +%Y%m%d)
|
||||||
VERSION_NUM="v${VERSION#v}-${BUILD_DATE}-${SHORT_SHA}"
|
VERSION_NUM="v${VERSION#v}-${BUILD_DATE}-${SHORT_SHA}"
|
||||||
echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_ENV
|
echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_ENV
|
||||||
echo "VERSION_NUM=${VERSION_NUM}"
|
echo "VERSION_NUM=${VERSION_NUM}"
|
||||||
@@ -174,7 +174,7 @@ jobs:
|
|||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.xmake/packages
|
path: ~/.xmake/packages
|
||||||
key: ${{ runner.os }}-xmake-deps-${{ matrix.cache-key }}-${{ hashFiles('**/xmake.lua') }}
|
key: ${{ runner.os }}-xmake-deps-${{ matrix.cache-key }}-${{ github.sha }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-xmake-deps-${{ matrix.cache-key }}-
|
${{ runner.os }}-xmake-deps-${{ matrix.cache-key }}-
|
||||||
|
|
||||||
@@ -229,7 +229,7 @@ jobs:
|
|||||||
$version = $version -replace '^v', ''
|
$version = $version -replace '^v', ''
|
||||||
$version = $version -replace '/', '-'
|
$version = $version -replace '/', '-'
|
||||||
$SHORT_SHA = $env:GITHUB_SHA.Substring(0,7)
|
$SHORT_SHA = $env:GITHUB_SHA.Substring(0,7)
|
||||||
$BUILD_DATE = Get-Date -Format "yyyyMMdd"
|
$BUILD_DATE = ([System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId((Get-Date), "China Standard Time")).ToString("yyyyMMdd")
|
||||||
echo "VERSION_NUM=v$version-$BUILD_DATE-$SHORT_SHA" >> $env:GITHUB_ENV
|
echo "VERSION_NUM=v$version-$BUILD_DATE-$SHORT_SHA" >> $env:GITHUB_ENV
|
||||||
echo "BUILD_DATE=$BUILD_DATE" >> $env:GITHUB_ENV
|
echo "BUILD_DATE=$BUILD_DATE" >> $env:GITHUB_ENV
|
||||||
|
|
||||||
@@ -237,7 +237,7 @@ jobs:
|
|||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: D:\xmake_global\.xmake\packages
|
path: D:\xmake_global\.xmake\packages
|
||||||
key: ${{ runner.os }}-xmake-deps-intel-${{ hashFiles('**/xmake.lua') }}
|
key: ${{ runner.os }}-xmake-deps-intel-${{ github.sha }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-xmake-deps-intel-
|
${{ runner.os }}-xmake-deps-intel-
|
||||||
|
|
||||||
@@ -340,8 +340,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
VERSION="${GITHUB_REF##*/}"
|
VERSION="${GITHUB_REF##*/}"
|
||||||
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7)
|
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7)
|
||||||
BUILD_DATE=$(date +%Y%m%d)
|
BUILD_DATE=$(TZ=Asia/Shanghai date +%Y%m%d)
|
||||||
BUILD_DATE_ISO=$(date +%Y-%m-%d)
|
BUILD_DATE_ISO=$(TZ=Asia/Shanghai date +%Y-%m-%d)
|
||||||
VERSION_NUM="${VERSION#v}-${BUILD_DATE}-${SHORT_SHA}"
|
VERSION_NUM="${VERSION#v}-${BUILD_DATE}-${SHORT_SHA}"
|
||||||
VERSION_WITH_V="v${VERSION_NUM}"
|
VERSION_WITH_V="v${VERSION_NUM}"
|
||||||
VERSION_ONLY="${VERSION#v}"
|
VERSION_ONLY="${VERSION#v}"
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ CrossDesk 是 [MiniRTC](https://github.com/kunkundi/minirtc.git) 实时音视频
|
|||||||
Linux环境下需安装以下包:
|
Linux环境下需安装以下包:
|
||||||
|
|
||||||
```
|
```
|
||||||
sudo apt-get install -y software-properties-common git curl unzip build-essential libx11-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxcb-randr0-dev libxcb-xtest0-dev libxcb-xinerama0-dev libxcb-shape0-dev libxcb-xkb-dev libxcb-xfixes0-dev libxv-dev libxtst-dev libasound2-dev libsndio-dev libxcb-shm0-dev libasound2-dev libpulse-dev
|
sudo apt-get install -y software-properties-common git curl unzip build-essential libx11-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxcb-randr0-dev libxcb-xtest0-dev libxcb-xinerama0-dev libxcb-shape0-dev libxcb-xkb-dev libxcb-xfixes0-dev libxfixes-dev libxv-dev libxtst-dev libasound2-dev libsndio-dev libxcb-shm0-dev libasound2-dev libpulse-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
编译
|
编译
|
||||||
@@ -181,7 +181,7 @@ sudo docker run -d \
|
|||||||
-v /path/to/your/certs:/crossdesk-server/certs \
|
-v /path/to/your/certs:/crossdesk-server/certs \
|
||||||
-v /path/to/your/db:/crossdesk-server/db \
|
-v /path/to/your/db:/crossdesk-server/db \
|
||||||
-v /path/to/your/logs:/crossdesk-server/logs \
|
-v /path/to/your/logs:/crossdesk-server/logs \
|
||||||
crossdesk/crossdesk-server:latest
|
crossdesk/crossdesk-server:v1.1.1
|
||||||
```
|
```
|
||||||
|
|
||||||
上述命令中,用户需注意的参数如下:
|
上述命令中,用户需注意的参数如下:
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ Requirements:
|
|||||||
Following packages need to be installed on Linux:
|
Following packages need to be installed on Linux:
|
||||||
|
|
||||||
```
|
```
|
||||||
sudo apt-get install -y software-properties-common git curl unzip build-essential libx11-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxcb-randr0-dev libxcb-xtest0-dev libxcb-xinerama0-dev libxcb-shape0-dev libxcb-xkb-dev libxcb-xfixes0-dev libxv-dev libxtst-dev libasound2-dev libsndio-dev libxcb-shm0-dev libasound2-dev libpulse-dev
|
sudo apt-get install -y software-properties-common git curl unzip build-essential libx11-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxcb-randr0-dev libxcb-xtest0-dev libxcb-xinerama0-dev libxcb-shape0-dev libxcb-xkb-dev libxcb-xfixes0-dev libxfixes-dev libxv-dev libxtst-dev libasound2-dev libsndio-dev libxcb-shm0-dev libasound2-dev libpulse-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Build:
|
Build:
|
||||||
@@ -189,7 +189,7 @@ sudo docker run -d \
|
|||||||
-v /path/to/your/certs:/crossdesk-server/certs \
|
-v /path/to/your/certs:/crossdesk-server/certs \
|
||||||
-v /path/to/your/db:/crossdesk-server/db \
|
-v /path/to/your/db:/crossdesk-server/db \
|
||||||
-v /path/to/your/logs:/crossdesk-server/logs \
|
-v /path/to/your/logs:/crossdesk-server/logs \
|
||||||
crossdesk/crossdesk-server:v1.1.0
|
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:
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ class ConfigCenter {
|
|||||||
VIDEO_FRAME_RATE video_frame_rate_ = VIDEO_FRAME_RATE::FPS_60;
|
VIDEO_FRAME_RATE video_frame_rate_ = VIDEO_FRAME_RATE::FPS_60;
|
||||||
VIDEO_ENCODE_FORMAT video_encode_format_ = VIDEO_ENCODE_FORMAT::H264;
|
VIDEO_ENCODE_FORMAT video_encode_format_ = VIDEO_ENCODE_FORMAT::H264;
|
||||||
bool hardware_video_codec_ = false;
|
bool hardware_video_codec_ = false;
|
||||||
bool enable_turn_ = false;
|
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_ = "api.crossdesk.cn";
|
||||||
std::string signal_server_host_default_ = "api.crossdesk.cn";
|
std::string signal_server_host_default_ = "api.crossdesk.cn";
|
||||||
|
|||||||
@@ -51,7 +51,16 @@ int KeyboardCapturer::Hook(OnKeyAction on_key_action, void* user_ptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int KeyboardCapturer::Unhook() {
|
int KeyboardCapturer::Unhook() {
|
||||||
|
g_on_key_action = nullptr;
|
||||||
|
g_user_ptr = nullptr;
|
||||||
|
|
||||||
running_ = false;
|
running_ = false;
|
||||||
|
|
||||||
|
if (display_) {
|
||||||
|
XSelectInput(display_, DefaultRootWindow(display_), 0);
|
||||||
|
XFlush(display_);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ static void* g_user_ptr = nullptr;
|
|||||||
|
|
||||||
CGEventRef eventCallback(CGEventTapProxy proxy, CGEventType type,
|
CGEventRef eventCallback(CGEventTapProxy proxy, CGEventType type,
|
||||||
CGEventRef event, void* userInfo) {
|
CGEventRef event, void* userInfo) {
|
||||||
|
if (!g_on_key_action) {
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
KeyboardCapturer* keyboard_capturer = (KeyboardCapturer*)userInfo;
|
KeyboardCapturer* keyboard_capturer = (KeyboardCapturer*)userInfo;
|
||||||
if (!keyboard_capturer) {
|
if (!keyboard_capturer) {
|
||||||
LOG_ERROR("keyboard_capturer is nullptr");
|
LOG_ERROR("keyboard_capturer is nullptr");
|
||||||
@@ -120,12 +124,23 @@ int KeyboardCapturer::Hook(OnKeyAction on_key_action, void* user_ptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int KeyboardCapturer::Unhook() {
|
int KeyboardCapturer::Unhook() {
|
||||||
|
g_on_key_action = nullptr;
|
||||||
|
g_user_ptr = nullptr;
|
||||||
|
|
||||||
|
if (event_tap_) {
|
||||||
|
CGEventTapEnable(event_tap_, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (run_loop_source_) {
|
if (run_loop_source_) {
|
||||||
|
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), run_loop_source_,
|
||||||
|
kCFRunLoopCommonModes);
|
||||||
CFRelease(run_loop_source_);
|
CFRelease(run_loop_source_);
|
||||||
|
run_loop_source_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event_tap_) {
|
if (event_tap_) {
|
||||||
CFRelease(event_tap_);
|
CFRelease(event_tap_);
|
||||||
|
event_tap_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -39,7 +39,12 @@ int KeyboardCapturer::Hook(OnKeyAction on_key_action, void* user_ptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int KeyboardCapturer::Unhook() {
|
int KeyboardCapturer::Unhook() {
|
||||||
UnhookWindowsHookEx(keyboard_hook_);
|
if (keyboard_hook_) {
|
||||||
|
g_on_key_action = nullptr;
|
||||||
|
g_user_ptr = nullptr;
|
||||||
|
UnhookWindowsHookEx(keyboard_hook_);
|
||||||
|
keyboard_hook_ = nullptr;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1340,6 +1340,7 @@ void Render::ProcessSdlEvent(const SDL_Event& event) {
|
|||||||
is_client_mode_ = false;
|
is_client_mode_ = false;
|
||||||
reload_recent_connections_ = true;
|
reload_recent_connections_ = true;
|
||||||
fullscreen_button_pressed_ = false;
|
fullscreen_button_pressed_ = false;
|
||||||
|
start_keyboard_capturer_ = false;
|
||||||
just_created_ = false;
|
just_created_ = false;
|
||||||
recent_connection_image_save_time_ = SDL_GetTicks();
|
recent_connection_image_save_time_ = SDL_GetTicks();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -448,7 +448,7 @@ class Render {
|
|||||||
int video_frame_rate_button_value_ = 1;
|
int video_frame_rate_button_value_ = 1;
|
||||||
int video_encode_format_button_value_ = 0;
|
int video_encode_format_button_value_ = 0;
|
||||||
bool enable_hardware_video_codec_ = false;
|
bool enable_hardware_video_codec_ = false;
|
||||||
bool enable_turn_ = false;
|
bool enable_turn_ = true;
|
||||||
bool enable_srtp_ = false;
|
bool enable_srtp_ = false;
|
||||||
char signal_server_ip_[256] = "api.crossdesk.cn";
|
char signal_server_ip_[256] = "api.crossdesk.cn";
|
||||||
char signal_server_port_[6] = "9099";
|
char signal_server_port_[6] = "9099";
|
||||||
@@ -460,7 +460,7 @@ class Render {
|
|||||||
int video_frame_rate_button_value_last_ = 0;
|
int video_frame_rate_button_value_last_ = 0;
|
||||||
int video_encode_format_button_value_last_ = 0;
|
int video_encode_format_button_value_last_ = 0;
|
||||||
bool enable_hardware_video_codec_last_ = false;
|
bool enable_hardware_video_codec_last_ = false;
|
||||||
bool enable_turn_last_ = false;
|
bool enable_turn_last_ = true;
|
||||||
bool enable_srtp_last_ = false;
|
bool enable_srtp_last_ = false;
|
||||||
bool enable_self_hosted_last_ = false;
|
bool enable_self_hosted_last_ = false;
|
||||||
bool enable_autostart_ = false;
|
bool enable_autostart_ = false;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include <cmath>
|
||||||
|
|
||||||
#include "device_controller.h"
|
#include "device_controller.h"
|
||||||
#include "localization.h"
|
#include "localization.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
@@ -101,28 +103,39 @@ int Render::ProcessMouseEvent(const SDL_Event& event) {
|
|||||||
last_mouse_event.button.y >= props->stream_render_rect_.y &&
|
last_mouse_event.button.y >= props->stream_render_rect_.y &&
|
||||||
last_mouse_event.button.y <= props->stream_render_rect_.y +
|
last_mouse_event.button.y <= props->stream_render_rect_.y +
|
||||||
props->stream_render_rect_.h) {
|
props->stream_render_rect_.h) {
|
||||||
int scroll_x = event.wheel.x;
|
float scroll_x = event.wheel.x;
|
||||||
int scroll_y = event.wheel.y;
|
float scroll_y = event.wheel.y;
|
||||||
if (event.wheel.direction == SDL_MOUSEWHEEL_FLIPPED) {
|
if (event.wheel.direction == SDL_MOUSEWHEEL_FLIPPED) {
|
||||||
scroll_x = -scroll_x;
|
scroll_x = -scroll_x;
|
||||||
scroll_y = -scroll_y;
|
scroll_y = -scroll_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
remote_action.type = ControlType::mouse;
|
remote_action.type = ControlType::mouse;
|
||||||
if (scroll_x == 0) {
|
|
||||||
|
auto roundUp = [](float value) -> int {
|
||||||
|
if (value > 0) {
|
||||||
|
return static_cast<int>(std::ceil(value));
|
||||||
|
} else if (value < 0) {
|
||||||
|
return static_cast<int>(std::floor(value));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (std::abs(scroll_y) >= std::abs(scroll_x)) {
|
||||||
remote_action.m.flag = MouseFlag::wheel_vertical;
|
remote_action.m.flag = MouseFlag::wheel_vertical;
|
||||||
remote_action.m.s = scroll_y;
|
remote_action.m.s = roundUp(scroll_y);
|
||||||
} else if (scroll_y == 0) {
|
} else {
|
||||||
remote_action.m.flag = MouseFlag::wheel_horizontal;
|
remote_action.m.flag = MouseFlag::wheel_horizontal;
|
||||||
remote_action.m.s = scroll_x;
|
remote_action.m.s = roundUp(scroll_x);
|
||||||
}
|
}
|
||||||
|
|
||||||
render_width = props->stream_render_rect_.w;
|
render_width = props->stream_render_rect_.w;
|
||||||
render_height = props->stream_render_rect_.h;
|
render_height = props->stream_render_rect_.h;
|
||||||
remote_action.m.x =
|
remote_action.m.x =
|
||||||
(float)(event.button.x - props->stream_render_rect_.x) / render_width;
|
(float)(last_mouse_event.button.x - props->stream_render_rect_.x) /
|
||||||
|
render_width;
|
||||||
remote_action.m.y =
|
remote_action.m.y =
|
||||||
(float)(event.button.y - props->stream_render_rect_.y) /
|
(float)(last_mouse_event.button.y - props->stream_render_rect_.y) /
|
||||||
render_height;
|
render_height;
|
||||||
|
|
||||||
std::string msg = remote_action.to_json();
|
std::string msg = remote_action.to_json();
|
||||||
@@ -225,8 +238,6 @@ void Render::OnReceiveVideoBufferCb(const XVideoFrame* video_frame,
|
|||||||
props->video_height_ = video_frame->height;
|
props->video_height_ = video_frame->height;
|
||||||
props->video_size_ = video_frame->size;
|
props->video_size_ = video_frame->size;
|
||||||
|
|
||||||
LOG_ERROR("receive: {}x{}", props->video_width_, props->video_height_);
|
|
||||||
|
|
||||||
if (need_to_update_render_rect) {
|
if (need_to_update_render_rect) {
|
||||||
render->UpdateRenderRect();
|
render->UpdateRenderRect();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "screen_capturer_x11.h"
|
#include "screen_capturer_x11.h"
|
||||||
|
|
||||||
|
#include <X11/extensions/Xfixes.h>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
@@ -100,6 +102,7 @@ int ScreenCapturerX11::Destroy() {
|
|||||||
|
|
||||||
int ScreenCapturerX11::Start(bool show_cursor) {
|
int ScreenCapturerX11::Start(bool show_cursor) {
|
||||||
if (running_) return 0;
|
if (running_) return 0;
|
||||||
|
show_cursor_ = show_cursor;
|
||||||
running_ = true;
|
running_ = true;
|
||||||
paused_ = false;
|
paused_ = false;
|
||||||
thread_ = std::thread([this]() {
|
thread_ = std::thread([this]() {
|
||||||
@@ -156,6 +159,20 @@ void ScreenCapturerX11::OnFrame() {
|
|||||||
AllPlanes, ZPixmap);
|
AllPlanes, ZPixmap);
|
||||||
if (!image) return;
|
if (!image) return;
|
||||||
|
|
||||||
|
// if enable show cursor, draw cursor
|
||||||
|
if (show_cursor_) {
|
||||||
|
Window root_return, child_return;
|
||||||
|
int root_x, root_y, win_x, win_y;
|
||||||
|
unsigned int mask;
|
||||||
|
if (XQueryPointer(display_, root_, &root_return, &child_return, &root_x,
|
||||||
|
&root_y, &win_x, &win_y, &mask)) {
|
||||||
|
if (root_x >= left_ && root_x < left_ + width_ && root_y >= top_ &&
|
||||||
|
root_y < top_ + height_) {
|
||||||
|
DrawCursor(image, root_x - left_, root_y - top_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool needs_copy = image->bytes_per_line != width_ * 4;
|
bool needs_copy = image->bytes_per_line != width_ * 4;
|
||||||
std::vector<uint8_t> argb_buf;
|
std::vector<uint8_t> argb_buf;
|
||||||
uint8_t* src_argb = nullptr;
|
uint8_t* src_argb = nullptr;
|
||||||
@@ -186,4 +203,82 @@ void ScreenCapturerX11::OnFrame() {
|
|||||||
|
|
||||||
XDestroyImage(image);
|
XDestroyImage(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScreenCapturerX11::DrawCursor(XImage* image, int x, int y) {
|
||||||
|
if (!display_ || !image) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check XFixes extension
|
||||||
|
int event_base, error_base;
|
||||||
|
if (!XFixesQueryExtension(display_, &event_base, &error_base)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
XFixesCursorImage* cursor_image = XFixesGetCursorImage(display_);
|
||||||
|
if (!cursor_image) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cursor_width = cursor_image->width;
|
||||||
|
int cursor_height = cursor_image->height;
|
||||||
|
|
||||||
|
int draw_x = x - cursor_image->xhot;
|
||||||
|
int draw_y = y - cursor_image->yhot;
|
||||||
|
|
||||||
|
// draw cursor on image
|
||||||
|
for (int cy = 0; cy < cursor_height; ++cy) {
|
||||||
|
for (int cx = 0; cx < cursor_width; ++cx) {
|
||||||
|
int img_x = draw_x + cx;
|
||||||
|
int img_y = draw_y + cy;
|
||||||
|
|
||||||
|
if (img_x < 0 || img_x >= image->width || img_y < 0 ||
|
||||||
|
img_y >= image->height) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long cursor_pixel = cursor_image->pixels[cy * cursor_width + cx];
|
||||||
|
unsigned char a = (cursor_pixel >> 24) & 0xFF;
|
||||||
|
|
||||||
|
// if alpha is 0, skip
|
||||||
|
if (a == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long img_pixel = XGetPixel(image, img_x, img_y);
|
||||||
|
|
||||||
|
unsigned char img_r = (img_pixel >> 16) & 0xFF;
|
||||||
|
unsigned char img_g = (img_pixel >> 8) & 0xFF;
|
||||||
|
unsigned char img_b = img_pixel & 0xFF;
|
||||||
|
|
||||||
|
unsigned char cursor_r = (cursor_pixel >> 16) & 0xFF;
|
||||||
|
unsigned char cursor_g = (cursor_pixel >> 8) & 0xFF;
|
||||||
|
unsigned char cursor_b = cursor_pixel & 0xFF;
|
||||||
|
|
||||||
|
// alpha mix
|
||||||
|
unsigned char final_r, final_g, final_b;
|
||||||
|
if (a == 255) {
|
||||||
|
// if alpha is 255, use cursor color
|
||||||
|
final_r = cursor_r;
|
||||||
|
final_g = cursor_g;
|
||||||
|
final_b = cursor_b;
|
||||||
|
} else {
|
||||||
|
float alpha = a / 255.0f;
|
||||||
|
float inv_alpha = 1.0f - alpha;
|
||||||
|
final_r =
|
||||||
|
static_cast<unsigned char>(cursor_r * alpha + img_r * inv_alpha);
|
||||||
|
final_g =
|
||||||
|
static_cast<unsigned char>(cursor_g * alpha + img_g * inv_alpha);
|
||||||
|
final_b =
|
||||||
|
static_cast<unsigned char>(cursor_b * alpha + img_b * inv_alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set pixel
|
||||||
|
unsigned long new_pixel = (final_r << 16) | (final_g << 8) | final_b;
|
||||||
|
XPutPixel(image, img_x, img_y, new_pixel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XFree(cursor_image);
|
||||||
|
}
|
||||||
} // namespace crossdesk
|
} // namespace crossdesk
|
||||||
Submodule submodules/minirtc updated: 0461314f9b...0008123221
@@ -45,7 +45,7 @@ elseif is_os("linux") then
|
|||||||
add_links("pulse-simple", "pulse")
|
add_links("pulse-simple", "pulse")
|
||||||
add_requires("libyuv")
|
add_requires("libyuv")
|
||||||
add_syslinks("pthread", "dl")
|
add_syslinks("pthread", "dl")
|
||||||
add_links("SDL3", "asound", "X11", "Xtst", "Xrandr")
|
add_links("SDL3", "asound", "X11", "Xtst", "Xrandr", "Xfixes")
|
||||||
add_cxflags("-Wno-unused-variable")
|
add_cxflags("-Wno-unused-variable")
|
||||||
elseif is_os("macosx") then
|
elseif is_os("macosx") then
|
||||||
add_links("SDL3")
|
add_links("SDL3")
|
||||||
|
|||||||
Reference in New Issue
Block a user