mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-11-03 20:47:43 +08:00
[ui] unify floating logo hand cursors with arrow fallback
This commit is contained in:
@@ -71,6 +71,7 @@
|
|||||||
#elif (defined(__linux__) && !defined(__OHOS__))
|
#elif (defined(__linux__) && !defined(__OHOS__))
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
|
#include <X11/Xcursor/Xcursor.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@@ -100,6 +101,41 @@ namespace {
|
|||||||
|
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
|
bool SupportsControlHandCursor([[maybe_unused]] const slint::Window& window) {
|
||||||
|
#if defined(_WIN32)
|
||||||
|
return LoadCursorW(nullptr, IDC_HAND) != nullptr;
|
||||||
|
#elif defined(__linux__) && !defined(__OHOS__)
|
||||||
|
// Match winit's pointer aliases, without using any move/grab fallback.
|
||||||
|
constexpr const char* names[] = {"pointer", "hand2", "hand1", "hand",
|
||||||
|
"pointing_hand"};
|
||||||
|
if (window.wayland_surface()) {
|
||||||
|
const char* theme = std::getenv("XCURSOR_THEME");
|
||||||
|
for (const char* name : names) {
|
||||||
|
if (auto* images = XcursorLibraryLoadImages(name, theme, 24)) {
|
||||||
|
const bool available = images->nimage > 0;
|
||||||
|
XcursorImagesDestroy(images);
|
||||||
|
if (available) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::unique_ptr<Display, decltype(&XCloseDisplay)> display{
|
||||||
|
XOpenDisplay(nullptr), XCloseDisplay};
|
||||||
|
if (!display) return false;
|
||||||
|
for (const char* name : names) {
|
||||||
|
const Cursor cursor = XcursorLibraryLoadCursor(display.get(), name);
|
||||||
|
if (cursor != None) {
|
||||||
|
XFreeCursor(display.get(), cursor);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
// AppKit supplies pointingHandCursor; other adapters resolve pointer.
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<std::string> GenerateRandomPassword(std::string_view current) {
|
std::optional<std::string> GenerateRandomPassword(std::string_view current) {
|
||||||
constexpr std::string_view alphabet =
|
constexpr std::string_view alphabet =
|
||||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||||
@@ -3640,6 +3676,8 @@ void GuiApplication::SyncStreamWindow() {
|
|||||||
if (!has_sessions) need_to_create_stream_window_ = false;
|
if (!has_sessions) need_to_create_stream_window_ = false;
|
||||||
if (need_to_create_stream_window_ && !ui_->stream) {
|
if (need_to_create_stream_window_ && !ui_->stream) {
|
||||||
ui_->stream.emplace(ui::StreamWindow::create());
|
ui_->stream.emplace(ui::StreamWindow::create());
|
||||||
|
(*ui_->stream)->set_control_hand_cursor_supported(
|
||||||
|
SupportsControlHandCursor(ui_->main->window()));
|
||||||
#if (defined(__linux__) && !defined(__OHOS__))
|
#if (defined(__linux__) && !defined(__OHOS__))
|
||||||
(*ui_->stream)->set_custom_titlebar(use_xwayland_gui_);
|
(*ui_->stream)->set_custom_titlebar(use_xwayland_gui_);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ component ControlBarButton inherits Rectangle {
|
|||||||
in property <bool> show-logo: false;
|
in property <bool> show-logo: false;
|
||||||
in property <bool> logo-pressed: false;
|
in property <bool> logo-pressed: false;
|
||||||
in property <bool> logo-dragging: false;
|
in property <bool> logo-dragging: false;
|
||||||
|
in property <bool> hand-cursor-supported: true;
|
||||||
in property <float> reveal-progress: 1;
|
in property <float> reveal-progress: 1;
|
||||||
in property <string> badge: "";
|
in property <string> badge: "";
|
||||||
in property <string> tooltip: "";
|
in property <string> tooltip: "";
|
||||||
@@ -227,7 +228,7 @@ component ControlBarButton inherits Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
touch := TouchArea {
|
touch := TouchArea {
|
||||||
mouse-cursor: !root.action-enabled ? default : root.show-logo ? (root.logo-pressed ? grabbing : grab) : pointer;
|
mouse-cursor: root.action-enabled && root.hand-cursor-supported ? pointer : default;
|
||||||
scroll-event(event) => { accept }
|
scroll-event(event) => { accept }
|
||||||
pointer-event(event) => {
|
pointer-event(event) => {
|
||||||
root.pointer-input(event.button, event.kind, self.mouse-x, self.mouse-y);
|
root.pointer-input(event.button, event.kind, self.mouse-x, self.mouse-y);
|
||||||
@@ -285,6 +286,7 @@ export component StreamWindow inherits Window {
|
|||||||
default-font-size: ImGuiFontStyle.base;
|
default-font-size: ImGuiFontStyle.base;
|
||||||
|
|
||||||
in property <bool> custom-titlebar: false;
|
in property <bool> custom-titlebar: false;
|
||||||
|
in property <bool> control-hand-cursor-supported: true;
|
||||||
in property <bool> native-video-enabled: false;
|
in property <bool> native-video-enabled: false;
|
||||||
// Export the actual input surface in logical pixels. Native rendering and
|
// Export the actual input surface in logical pixels. Native rendering and
|
||||||
// input mapping must follow the same layout, including title and tab bars.
|
// input mapping must follow the same layout, including title and tab bars.
|
||||||
@@ -1073,7 +1075,8 @@ export component StreamWindow inherits Window {
|
|||||||
// The logo also retains a stable owner if another button is used.
|
// The logo also retains a stable owner if another button is used.
|
||||||
if root.remote-pointer-active || root.control-drag-pending: TouchArea {
|
if root.remote-pointer-active || root.control-drag-pending: TouchArea {
|
||||||
z: 15;
|
z: 15;
|
||||||
mouse-cursor: root.control-drag-pending ? MouseCursor.grabbing
|
mouse-cursor: root.control-drag-pending
|
||||||
|
? (root.control-hand-cursor-supported ? MouseCursor.pointer : MouseCursor.default)
|
||||||
: root.remote-cursor-active ? RemoteCursor.shape(root.remote-cursor-shape)
|
: root.remote-cursor-active ? RemoteCursor.shape(root.remote-cursor-shape)
|
||||||
: MouseCursor.default;
|
: MouseCursor.default;
|
||||||
pointer-event(event) => {
|
pointer-event(event) => {
|
||||||
@@ -1249,6 +1252,7 @@ export component StreamWindow inherits Window {
|
|||||||
width: root.control-toolbar-height;
|
width: root.control-toolbar-height;
|
||||||
height: root.control-toolbar-height;
|
height: root.control-toolbar-height;
|
||||||
show-logo: true;
|
show-logo: true;
|
||||||
|
hand-cursor-supported: root.control-hand-cursor-supported;
|
||||||
logo-pressed: root.control-drag-pending;
|
logo-pressed: root.control-drag-pending;
|
||||||
logo-dragging: self.logo-pressed && root.control-dragging;
|
logo-dragging: self.logo-pressed && root.control-dragging;
|
||||||
tooltip: root.control-expanded ? StreamStrings.collapse-control : StreamStrings.expand-control;
|
tooltip: root.control-expanded ? StreamStrings.collapse-control : StreamStrings.expand-control;
|
||||||
|
|||||||
Reference in New Issue
Block a user