mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-08-19 17:46:27 +08:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7897a003d | ||
|
|
d2478006ba | ||
|
|
7ff6c8a4ad |
@@ -80,7 +80,7 @@ Windows 安装包会自动打包 `crossdesk_service.exe` 和 `crossdesk_session_
|
|||||||
|
|
||||||
依赖:
|
依赖:
|
||||||
- [xmake](https://xmake.io/#/guide/installation)
|
- [xmake](https://xmake.io/#/guide/installation)
|
||||||
- [cmake](https://cmake.org/download/) 3.21 及以上(系统版本过低时由 xmake 自动安装)
|
- [cmake](https://cmake.org/download/) 3.21 及以上
|
||||||
|
|
||||||
### Linux
|
### Linux
|
||||||
|
|
||||||
@@ -97,10 +97,11 @@ sudo apt-get install -y \
|
|||||||
libxtst-dev libxcb-randr0-dev libxcb-xtest0-dev libxcb-xinerama0-dev \
|
libxtst-dev libxcb-randr0-dev libxcb-xtest0-dev libxcb-xinerama0-dev \
|
||||||
libxcb-shape0-dev libxcb-xkb-dev libxcb-xfixes0-dev libxcb-shm0-dev \
|
libxcb-shape0-dev libxcb-xkb-dev libxcb-xfixes0-dev libxcb-shm0-dev \
|
||||||
libasound2-dev libsndio-dev libpulse-dev
|
libasound2-dev libsndio-dev libpulse-dev
|
||||||
```
|
|
||||||
|
|
||||||
Ubuntu 20.04 自带的 CMake 3.16 不满足要求时,xmake 会自动下载并使用
|
# Ubuntu 20.04 自带的 CMake 3.16 不满足 Slint 1.17 的要求
|
||||||
CMake 3.21 或更高版本,无需手动替换系统 CMake。
|
python3 -m pip install --user cmake==3.31.6
|
||||||
|
export PATH="$HOME/.local/bin:$PATH"
|
||||||
|
```
|
||||||
|
|
||||||
Ubuntu 20.04 默认的 GCC 9 缺少 Slint C++ API 所需的部分 C++20 标准库,
|
Ubuntu 20.04 默认的 GCC 9 缺少 Slint C++ API 所需的部分 C++20 标准库,
|
||||||
因此上述命令同时安装并在后续配置中指定 GCC 10。
|
因此上述命令同时安装并在后续配置中指定 GCC 10。
|
||||||
@@ -127,21 +128,17 @@ git submodule update --init --recursive
|
|||||||
# 已安装发行版 PipeWire 0.3 开发包时可跳过此步骤。
|
# 已安装发行版 PipeWire 0.3 开发包时可跳过此步骤。
|
||||||
sudo ./docker/linux-build/install-pipewire-sdk.sh
|
sudo ./docker/linux-build/install-pipewire-sdk.sh
|
||||||
|
|
||||||
xmake f -c -m release --USE_CUDA=false --toolchain=gcc-10 -y
|
xmake f -m release --USE_CUDA=false --cc=gcc-10 --cxx=g++-10 -y
|
||||||
xmake b -vy crossdesk
|
xmake b -vy crossdesk
|
||||||
```
|
```
|
||||||
|
|
||||||
这里应使用 `--toolchain=gcc-10`,以确保 CrossDesk 及 xmake 在配置阶段构建的
|
|
||||||
libyuv 等第三方包都使用 GCC 10。只指定 `--cc`/`--cxx` 时,依赖安装可能仍回退到
|
|
||||||
系统默认的 `/bin/cc` 和 `/bin/c++`。`-c` 会清除旧配置,切换编译器时必须保留。
|
|
||||||
|
|
||||||
amd64 构建结果位于 `build/linux/x86_64/release/crossdesk`,arm64 构建结果位于 `build/linux/arm64/release/crossdesk`。
|
amd64 构建结果位于 `build/linux/x86_64/release/crossdesk`,arm64 构建结果位于 `build/linux/arm64/release/crossdesk`。
|
||||||
|
|
||||||
启用 Wayland 和 DRM 的配置示例:
|
启用 Wayland 和 DRM 的配置示例:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
xmake f -c -m release --USE_WAYLAND=true --USE_DRM=true --USE_CUDA=false \
|
xmake f -m release --USE_WAYLAND=true --USE_DRM=true --USE_CUDA=false \
|
||||||
--toolchain=gcc-10 -y
|
--cc=gcc-10 --cxx=g++-10 -y
|
||||||
xmake b -vy crossdesk
|
xmake b -vy crossdesk
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
+8
-14
@@ -85,7 +85,7 @@ If the remote Windows service is not installed, not running, or temporarily unav
|
|||||||
|
|
||||||
Requirements:
|
Requirements:
|
||||||
- [xmake](https://xmake.io/#/guide/installation)
|
- [xmake](https://xmake.io/#/guide/installation)
|
||||||
- [cmake](https://cmake.org/download/) 3.21 or later (installed automatically by xmake when the system version is too old)
|
- [cmake](https://cmake.org/download/) 3.21 or later
|
||||||
|
|
||||||
### Linux
|
### Linux
|
||||||
|
|
||||||
@@ -103,11 +103,11 @@ sudo apt-get install -y \
|
|||||||
libxtst-dev libxcb-randr0-dev libxcb-xtest0-dev libxcb-xinerama0-dev \
|
libxtst-dev libxcb-randr0-dev libxcb-xtest0-dev libxcb-xinerama0-dev \
|
||||||
libxcb-shape0-dev libxcb-xkb-dev libxcb-xfixes0-dev libxcb-shm0-dev \
|
libxcb-shape0-dev libxcb-xkb-dev libxcb-xfixes0-dev libxcb-shm0-dev \
|
||||||
libasound2-dev libsndio-dev libpulse-dev
|
libasound2-dev libsndio-dev libpulse-dev
|
||||||
```
|
|
||||||
|
|
||||||
When Ubuntu 20.04's bundled CMake 3.16 is too old, xmake automatically
|
# Ubuntu 20.04's CMake 3.16 is too old for Slint 1.17.
|
||||||
downloads and uses CMake 3.21 or later; replacing the system CMake manually is
|
python3 -m pip install --user cmake==3.31.6
|
||||||
not required.
|
export PATH="$HOME/.local/bin:$PATH"
|
||||||
|
```
|
||||||
|
|
||||||
Ubuntu 20.04's default GCC 9 lacks parts of the C++20 standard library needed
|
Ubuntu 20.04's default GCC 9 lacks parts of the C++20 standard library needed
|
||||||
by Slint's C++ API, so the commands above install GCC 10 and the configuration
|
by Slint's C++ API, so the commands above install GCC 10 and the configuration
|
||||||
@@ -136,23 +136,17 @@ git submodule update --init --recursive
|
|||||||
# PipeWire 0.3 development packages are already installed.
|
# PipeWire 0.3 development packages are already installed.
|
||||||
sudo ./docker/linux-build/install-pipewire-sdk.sh
|
sudo ./docker/linux-build/install-pipewire-sdk.sh
|
||||||
|
|
||||||
xmake f -c -m release --USE_CUDA=false --toolchain=gcc-10 -y
|
xmake f -m release --USE_CUDA=false --cc=gcc-10 --cxx=g++-10 -y
|
||||||
xmake b -vy crossdesk
|
xmake b -vy crossdesk
|
||||||
```
|
```
|
||||||
|
|
||||||
Use `--toolchain=gcc-10` so that both CrossDesk and third-party packages such
|
|
||||||
as libyuv, which xmake builds during configuration, use GCC 10. Specifying only
|
|
||||||
`--cc`/`--cxx` may still let dependency builds fall back to the system
|
|
||||||
`/bin/cc` and `/bin/c++`. Keep `-c` when switching compilers to clear the old
|
|
||||||
configuration.
|
|
||||||
|
|
||||||
The amd64 binary is written to `build/linux/x86_64/release/crossdesk`; the arm64 binary is written to `build/linux/arm64/release/crossdesk`.
|
The amd64 binary is written to `build/linux/x86_64/release/crossdesk`; the arm64 binary is written to `build/linux/arm64/release/crossdesk`.
|
||||||
|
|
||||||
Example configuration with Wayland and DRM capture enabled:
|
Example configuration with Wayland and DRM capture enabled:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
xmake f -c -m release --USE_WAYLAND=true --USE_DRM=true --USE_CUDA=false \
|
xmake f -m release --USE_WAYLAND=true --USE_DRM=true --USE_CUDA=false \
|
||||||
--toolchain=gcc-10 -y
|
--cc=gcc-10 --cxx=g++-10 -y
|
||||||
xmake b -vy crossdesk
|
xmake b -vy crossdesk
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
|
||||||
#include "keyboard_converter.h"
|
#include "keyboard_converter.h"
|
||||||
#include "linux_evdev_keycode.h"
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
#include "windows_key_metadata.h"
|
#include "windows_key_metadata.h"
|
||||||
@@ -18,40 +17,6 @@ namespace crossdesk {
|
|||||||
static OnKeyAction g_on_key_action = nullptr;
|
static OnKeyAction g_on_key_action = nullptr;
|
||||||
static void* g_user_ptr = nullptr;
|
static void* g_user_ptr = nullptr;
|
||||||
|
|
||||||
static KeyCode ResolveX11Keycode(Display* display, int key_code,
|
|
||||||
uint32_t scan_code, bool extended) {
|
|
||||||
if (!display) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto key_it = vkCodeToX11KeySym.find(key_code);
|
|
||||||
if (key_it != vkCodeToX11KeySym.end()) {
|
|
||||||
const KeyCode x11_keycode =
|
|
||||||
XKeysymToKeycode(display, static_cast<KeySym>(key_it->second));
|
|
||||||
if (x11_keycode != 0) {
|
|
||||||
return x11_keycode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Some controllers can preserve the physical Windows scan code even when
|
|
||||||
// they cannot resolve a Windows virtual-key value. Xorg's evdev keycodes use
|
|
||||||
// the Linux input code plus the protocol-reserved offset of 8.
|
|
||||||
const int evdev_keycode =
|
|
||||||
ResolveLinuxEvdevKeycodeFromWindowsKey(key_code, scan_code, extended);
|
|
||||||
if (evdev_keycode < 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int min_keycode = 0;
|
|
||||||
int max_keycode = 0;
|
|
||||||
XDisplayKeycodes(display, &min_keycode, &max_keycode);
|
|
||||||
const int x11_keycode = evdev_keycode + 8;
|
|
||||||
if (x11_keycode < min_keycode || x11_keycode > max_keycode) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return static_cast<KeyCode>(x11_keycode);
|
|
||||||
}
|
|
||||||
|
|
||||||
static KeySym NormalizeKeySym(KeySym key_sym) {
|
static KeySym NormalizeKeySym(KeySym key_sym) {
|
||||||
if (key_sym >= XK_a && key_sym <= XK_z) {
|
if (key_sym >= XK_a && key_sym <= XK_z) {
|
||||||
return key_sym - XK_a + XK_A;
|
return key_sym - XK_a + XK_A;
|
||||||
@@ -97,16 +62,7 @@ KeyboardCapturer::KeyboardCapturer()
|
|||||||
display_ = XOpenDisplay(nullptr);
|
display_ = XOpenDisplay(nullptr);
|
||||||
if (!display_) {
|
if (!display_) {
|
||||||
LOG_ERROR("Failed to open X display.");
|
LOG_ERROR("Failed to open X display.");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int event_base = 0;
|
|
||||||
int error_base = 0;
|
|
||||||
int major_version = 0;
|
|
||||||
int minor_version = 0;
|
|
||||||
x11_xtest_available_ =
|
|
||||||
XTestQueryExtension(display_, &event_base, &error_base, &major_version,
|
|
||||||
&minor_version) != 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyboardCapturer::~KeyboardCapturer() {
|
KeyboardCapturer::~KeyboardCapturer() {
|
||||||
@@ -114,10 +70,8 @@ KeyboardCapturer::~KeyboardCapturer() {
|
|||||||
CleanupWaylandPortal();
|
CleanupWaylandPortal();
|
||||||
|
|
||||||
if (display_) {
|
if (display_) {
|
||||||
std::lock_guard<std::mutex> lock(x11_injection_mutex_);
|
|
||||||
XCloseDisplay(display_);
|
XCloseDisplay(display_);
|
||||||
display_ = nullptr;
|
display_ = nullptr;
|
||||||
x11_xtest_available_ = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,6 +156,8 @@ int KeyboardCapturer::Unhook() {
|
|||||||
|
|
||||||
int KeyboardCapturer::SendKeyboardCommand(int key_code, bool is_down,
|
int KeyboardCapturer::SendKeyboardCommand(int key_code, bool is_down,
|
||||||
uint32_t scan_code, bool extended) {
|
uint32_t scan_code, bool extended) {
|
||||||
|
(void)scan_code;
|
||||||
|
(void)extended;
|
||||||
if (IsWaylandSession()) {
|
if (IsWaylandSession()) {
|
||||||
if (!use_wayland_portal_ && !wayland_init_attempted_) {
|
if (!use_wayland_portal_ && !wayland_init_attempted_) {
|
||||||
wayland_init_attempted_ = true;
|
wayland_init_attempted_ = true;
|
||||||
@@ -225,33 +181,12 @@ int KeyboardCapturer::SendKeyboardCommand(int key_code, bool is_down,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(x11_injection_mutex_);
|
if (vkCodeToX11KeySym.find(key_code) != vkCodeToX11KeySym.end()) {
|
||||||
if (!x11_xtest_available_) {
|
int x11_key_code = vkCodeToX11KeySym[key_code];
|
||||||
LOG_ERROR("XTest extension not available for keyboard injection");
|
KeyCode keycode = XKeysymToKeycode(display_, x11_key_code);
|
||||||
return -2;
|
XTestFakeKeyEvent(display_, keycode, is_down, CurrentTime);
|
||||||
|
XFlush(display_);
|
||||||
}
|
}
|
||||||
|
|
||||||
const KeyCode x11_keycode =
|
|
||||||
ResolveX11Keycode(display_, key_code, scan_code, extended);
|
|
||||||
if (x11_keycode == 0) {
|
|
||||||
LOG_WARN(
|
|
||||||
"Cannot map remote keyboard event to X11 keycode, vk_code={}, "
|
|
||||||
"scan_code={}, extended={}",
|
|
||||||
key_code, scan_code, extended);
|
|
||||||
return -3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!XTestFakeKeyEvent(display_, x11_keycode, is_down, CurrentTime)) {
|
|
||||||
LOG_ERROR(
|
|
||||||
"XTest keyboard injection failed, vk_code={}, scan_code={}, "
|
|
||||||
"extended={}, x11_keycode={}, is_down={}",
|
|
||||||
key_code, scan_code, extended, static_cast<int>(x11_keycode), is_down);
|
|
||||||
return -4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Complete the request before reporting success to the keyboard-state
|
|
||||||
// reconciler. This also makes X11 protocol errors observable immediately.
|
|
||||||
XSync(display_, False);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} // namespace crossdesk
|
} // namespace crossdesk
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <mutex>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
@@ -50,8 +49,6 @@ class KeyboardCapturer : public DeviceController {
|
|||||||
unsigned long root_;
|
unsigned long root_;
|
||||||
std::atomic<bool> running_;
|
std::atomic<bool> running_;
|
||||||
std::thread event_thread_;
|
std::thread event_thread_;
|
||||||
std::mutex x11_injection_mutex_;
|
|
||||||
bool x11_xtest_available_ = false;
|
|
||||||
bool use_wayland_portal_ = false;
|
bool use_wayland_portal_ = false;
|
||||||
bool wayland_init_attempted_ = false;
|
bool wayland_init_attempted_ = false;
|
||||||
DBusConnection* dbus_connection_ = nullptr;
|
DBusConnection* dbus_connection_ = nullptr;
|
||||||
|
|||||||
@@ -611,7 +611,6 @@ int KeyboardCapturer::SendWaylandKeyboardCommand(int key_code, bool is_down,
|
|||||||
// Prefer keycode injection to preserve physical-key semantics and avoid
|
// Prefer keycode injection to preserve physical-key semantics and avoid
|
||||||
// implicit Shift interpretation for uppercase keysyms.
|
// implicit Shift interpretation for uppercase keysyms.
|
||||||
if (display_) {
|
if (display_) {
|
||||||
std::lock_guard<std::mutex> lock(x11_injection_mutex_);
|
|
||||||
const int keysym = key_it->second;
|
const int keysym = key_it->second;
|
||||||
const KeyCode x11_keycode =
|
const KeyCode x11_keycode =
|
||||||
XKeysymToKeycode(display_, static_cast<KeySym>(keysym));
|
XKeysymToKeycode(display_, static_cast<KeySym>(keysym));
|
||||||
|
|||||||
@@ -943,6 +943,10 @@ void GuiApplication::InitializeSettings() {
|
|||||||
|
|
||||||
bool GuiApplication::InitializeSDL() {
|
bool GuiApplication::InitializeSDL() {
|
||||||
#if defined(__linux__) && !defined(__APPLE__)
|
#if defined(__linux__) && !defined(__APPLE__)
|
||||||
|
if (!getenv("SDL_AUDIODRIVER")) {
|
||||||
|
setenv("SDL_AUDIODRIVER", "pulseaudio", 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Standard Wayland top-level windows cannot choose an absolute screen
|
// Standard Wayland top-level windows cannot choose an absolute screen
|
||||||
// position. Use the session's XWayland compatibility server for the GUI so
|
// position. Use the session's XWayland compatibility server for the GUI so
|
||||||
// auxiliary windows such as the controlled-side status window can be
|
// auxiliary windows such as the controlled-side status window can be
|
||||||
@@ -966,14 +970,6 @@ bool GuiApplication::InitializeSDL() {
|
|||||||
LOG_ERROR("SDL initialization failed: {}", SDL_GetError());
|
LOG_ERROR("SDL initialization failed: {}", SDL_GetError());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#if defined(__linux__) && !defined(__APPLE__)
|
|
||||||
const char* active_video_driver = SDL_GetCurrentVideoDriver();
|
|
||||||
// X11 permits the manual move/position operations used by the frameless
|
|
||||||
// main window. Keep native Wayland decorations as a compatibility fallback.
|
|
||||||
use_x11_custom_titlebar_ =
|
|
||||||
active_video_driver != nullptr &&
|
|
||||||
std::strcmp(active_video_driver, "x11") == 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (const SDL_DisplayMode* mode = SDL_GetCurrentDisplayMode(0)) {
|
if (const SDL_DisplayMode* mode = SDL_GetCurrentDisplayMode(0)) {
|
||||||
screen_width_ = mode->w;
|
screen_width_ = mode->w;
|
||||||
@@ -1008,8 +1004,10 @@ void GuiApplication::InitializeUi() {
|
|||||||
#if _WIN32
|
#if _WIN32
|
||||||
ui_->main->set_custom_titlebar(true);
|
ui_->main->set_custom_titlebar(true);
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
ui_->main->set_custom_titlebar(use_x11_custom_titlebar_);
|
if (use_xwayland_gui_) {
|
||||||
ui_->main->set_wayland_titlebar(use_xwayland_gui_);
|
ui_->main->set_custom_titlebar(true);
|
||||||
|
ui_->main->set_wayland_titlebar(true);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
std::vector<ui::ReleaseNoteBlock> release_note_blocks;
|
std::vector<ui::ReleaseNoteBlock> release_note_blocks;
|
||||||
for (const auto& parsed : ParseReleaseNotesMarkdownForSlint(release_notes_)) {
|
for (const auto& parsed : ParseReleaseNotesMarkdownForSlint(release_notes_)) {
|
||||||
|
|||||||
@@ -66,7 +66,6 @@ private:
|
|||||||
std::unique_ptr<SlintUi> ui_;
|
std::unique_ptr<SlintUi> ui_;
|
||||||
#if defined(__linux__) && !defined(__APPLE__)
|
#if defined(__linux__) && !defined(__APPLE__)
|
||||||
bool use_xwayland_gui_ = false;
|
bool use_xwayland_gui_ = false;
|
||||||
bool use_x11_custom_titlebar_ = false;
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -601,15 +601,6 @@ export component MainWindow inherits Window {
|
|||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
border-color: ImGuiLineStyle.border;
|
border-color: ImGuiLineStyle.border;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
// Measure the ID using the preferred field size.
|
|
||||||
// The visible text can then scale only on systems
|
|
||||||
// whose font metrics would otherwise clip it.
|
|
||||||
local-id-width-probe := Text {
|
|
||||||
visible: false;
|
|
||||||
text: root.local-id;
|
|
||||||
font-size: ImGuiFontStyle.field-value;
|
|
||||||
letter-spacing: 1px;
|
|
||||||
}
|
|
||||||
Text {
|
Text {
|
||||||
x: 8px;
|
x: 8px;
|
||||||
// Compensate for the font's ascender-heavy
|
// Compensate for the font's ascender-heavy
|
||||||
@@ -619,9 +610,7 @@ export component MainWindow inherits Window {
|
|||||||
height: parent.height - 4px;
|
height: parent.height - 4px;
|
||||||
text: root.local-id;
|
text: root.local-id;
|
||||||
color: #20242a;
|
color: #20242a;
|
||||||
font-size: max(18px,
|
font-size: ImGuiFontStyle.field-value;
|
||||||
ImGuiFontStyle.field-value *
|
|
||||||
(self.width / max(self.width, local-id-width-probe.preferred-width)));
|
|
||||||
letter-spacing: 1px;
|
letter-spacing: 1px;
|
||||||
horizontal-alignment: left;
|
horizontal-alignment: left;
|
||||||
vertical-alignment: center;
|
vertical-alignment: center;
|
||||||
|
|||||||
+1
-1
Submodule submodules/minirtc updated: 50ca51ecc1...00aad6aa37
@@ -1,52 +0,0 @@
|
|||||||
#include <X11/Xlib.h>
|
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
#include "keyboard_capturer.h"
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
Display* receiver = XOpenDisplay(nullptr);
|
|
||||||
if (!receiver) {
|
|
||||||
std::fprintf(stderr, "open display failed\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int screen = DefaultScreen(receiver);
|
|
||||||
Window window = XCreateSimpleWindow(receiver, RootWindow(receiver, screen),
|
|
||||||
0, 0, 100, 100, 0, 0, 0);
|
|
||||||
XSelectInput(receiver, window, KeyPressMask | KeyReleaseMask);
|
|
||||||
XMapWindow(receiver, window);
|
|
||||||
XSync(receiver, False);
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
||||||
XSetInputFocus(receiver, window, RevertToParent, CurrentTime);
|
|
||||||
XSync(receiver, False);
|
|
||||||
|
|
||||||
crossdesk::KeyboardCapturer keyboard;
|
|
||||||
// Exercise the scan-code fallback: the controller supplied no usable VK,
|
|
||||||
// but did preserve the set-1 scan code for the A key.
|
|
||||||
const int down = keyboard.SendKeyboardCommand(0, true, 0x1E, false);
|
|
||||||
const int up = keyboard.SendKeyboardCommand(0, false, 0x1E, false);
|
|
||||||
|
|
||||||
bool saw_down = false;
|
|
||||||
bool saw_up = false;
|
|
||||||
const auto deadline = std::chrono::steady_clock::now() +
|
|
||||||
std::chrono::seconds(2);
|
|
||||||
while (std::chrono::steady_clock::now() < deadline &&
|
|
||||||
(!saw_down || !saw_up)) {
|
|
||||||
while (XPending(receiver) > 0) {
|
|
||||||
XEvent event{};
|
|
||||||
XNextEvent(receiver, &event);
|
|
||||||
saw_down = saw_down || event.type == KeyPress;
|
|
||||||
saw_up = saw_up || event.type == KeyRelease;
|
|
||||||
}
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
||||||
}
|
|
||||||
|
|
||||||
XDestroyWindow(receiver, window);
|
|
||||||
XCloseDisplay(receiver);
|
|
||||||
std::printf("down_ret=%d up_ret=%d saw_down=%d saw_up=%d\n", down, up,
|
|
||||||
saw_down, saw_up);
|
|
||||||
return down == 0 && up == 0 && saw_down && saw_up ? 0 : 2;
|
|
||||||
}
|
|
||||||
Vendored
+1
-17
@@ -9,13 +9,10 @@ package("slint")
|
|||||||
|
|
||||||
add_configs("shared", {description = "Build the Slint runtime as a shared library", default = true, type = "boolean", readonly = true})
|
add_configs("shared", {description = "Build the Slint runtime as a shared library", default = true, type = "boolean", readonly = true})
|
||||||
|
|
||||||
add_deps("cmake~slint >=3.21 <4.0", {host = true, private = true, system = false})
|
add_deps("cmake")
|
||||||
add_deps("rust 1.92.0", {host = true, private = true, system = false})
|
add_deps("rust 1.92.0", {host = true, private = true, system = false})
|
||||||
|
|
||||||
on_load(function(package)
|
on_load(function(package)
|
||||||
if package:is_plat("linux") then
|
|
||||||
package:add("deps", "fontconfig", {private = true, system = false})
|
|
||||||
end
|
|
||||||
package:add("includedirs", "include/slint")
|
package:add("includedirs", "include/slint")
|
||||||
if package:is_plat("windows") then
|
if package:is_plat("windows") then
|
||||||
package:add("links", "slint_cpp.dll")
|
package:add("links", "slint_cpp.dll")
|
||||||
@@ -25,13 +22,6 @@ package("slint")
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
on_install("windows", "linux", "macosx", function(package)
|
on_install("windows", "linux", "macosx", function(package)
|
||||||
for _, dep in ipairs(package:orderdeps()) do
|
|
||||||
if dep:name() == "cmake" and dep:label() == "slint" then
|
|
||||||
os.addenv("PATH", dep:installdir("bin"))
|
|
||||||
import("core.cache.detectcache"):set2("find_program", "cmake", nil)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local configs = {
|
local configs = {
|
||||||
"-DSLINT_BUILD_TESTING=OFF",
|
"-DSLINT_BUILD_TESTING=OFF",
|
||||||
"-DSLINT_BUILD_EXAMPLES=OFF",
|
"-DSLINT_BUILD_EXAMPLES=OFF",
|
||||||
@@ -49,12 +39,6 @@ package("slint")
|
|||||||
"-DSLINT_STYLE=fluent",
|
"-DSLINT_STYLE=fluent",
|
||||||
"-DBUILD_SHARED_LIBS=ON"
|
"-DBUILD_SHARED_LIBS=ON"
|
||||||
}
|
}
|
||||||
if package:is_plat("windows") then
|
|
||||||
local rc = assert(package:build_getenv("mrc"),
|
|
||||||
"failed to find the Windows resource compiler")
|
|
||||||
rc = rc:gsub("\\", "/")
|
|
||||||
table.insert(configs, "-DCMAKE_RC_COMPILER=" .. rc)
|
|
||||||
end
|
|
||||||
import("package.tools.cmake").install(package, configs)
|
import("package.tools.cmake").install(package, configs)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -51,7 +51,7 @@ function setup_options_and_dependencies()
|
|||||||
add_defines("CROSSDESK_DEBUG")
|
add_defines("CROSSDESK_DEBUG")
|
||||||
end
|
end
|
||||||
|
|
||||||
add_requireconfs("**.python", {version = "3.12", override = true, configs = {pgo = false}})
|
add_requireconfs("*.python", {version = "3.12", override = true, configs = {pgo = false}})
|
||||||
add_requires("spdlog 1.14.1", {system = false})
|
add_requires("spdlog 1.14.1", {system = false})
|
||||||
add_requires("slint 1.17.1", {configs = {shared = true}})
|
add_requires("slint 1.17.1", {configs = {shared = true}})
|
||||||
add_requires("libsdl3 3.2.26", {configs = {shared = false}})
|
add_requires("libsdl3 3.2.26", {configs = {shared = false}})
|
||||||
|
|||||||
@@ -197,14 +197,6 @@ function setup_targets()
|
|||||||
"src/device_controller/keyboard/linux", {public = true})
|
"src/device_controller/keyboard/linux", {public = true})
|
||||||
end
|
end
|
||||||
|
|
||||||
if is_os("linux") then
|
|
||||||
target("linux_keyboard_x11_integration_test")
|
|
||||||
set_kind("binary")
|
|
||||||
set_default(false)
|
|
||||||
add_deps("device_controller")
|
|
||||||
add_files("tests/linux_keyboard_x11_integration_test.cpp")
|
|
||||||
end
|
|
||||||
|
|
||||||
target("thumbnail")
|
target("thumbnail")
|
||||||
set_kind("object")
|
set_kind("object")
|
||||||
add_packages("libyuv", "openssl3")
|
add_packages("libyuv", "openssl3")
|
||||||
|
|||||||
Reference in New Issue
Block a user