diff --git a/apps/desktop/src/gui/application/gui_application.cpp b/apps/desktop/src/gui/application/gui_application.cpp index 7aa76d3a..deb65d32 100644 --- a/apps/desktop/src/gui/application/gui_application.cpp +++ b/apps/desktop/src/gui/application/gui_application.cpp @@ -1123,6 +1123,9 @@ void GuiApplication::InitializeUi() { } #endif #if defined(__linux__) && !defined(__APPLE__) + // Detect the desktop session before temporarily hiding Wayland variables + // for the XWayland GUI backend below. + const bool is_wayland_session = IsWaylandSession(); // Winit prefers Wayland whenever WAYLAND_DISPLAY/WAYLAND_SOCKET is present. // Hide them only while Slint selects its process-wide window backend, then // restore the environment before the rest of the application starts. @@ -1144,6 +1147,8 @@ void GuiApplication::InitializeUi() { #elif defined(__linux__) ui_->main->set_custom_titlebar(use_x11_custom_titlebar_); ui_->main->set_wayland_titlebar(use_xwayland_gui_); + // Set this only at startup so dismissing the notice lasts until exit. + ui_->main->set_wayland_notice_open(is_wayland_session); #endif ui_->main->set_release_note_blocks(ui_->release_note_blocks_model); RegisterFontAwesome(ui_->main->window()); diff --git a/apps/desktop/src/gui/assets/localization/localization_data.h b/apps/desktop/src/gui/assets/localization/localization_data.h index a8a2efdf..a5c86407 100644 --- a/apps/desktop/src/gui/assets/localization/localization_data.h +++ b/apps/desktop/src/gui/assets/localization/localization_data.h @@ -330,6 +330,34 @@ struct TranslationRow { X(permission_required_message, u8"该应用需要授权以下权限:", \ "The application requires the following permissions:", \ u8"Для работы приложения требуются следующие разрешения:") \ + X(wayland_notice_title, u8"Wayland 会话提示", "Wayland Session Notice", \ + u8"Уведомление о сеансе Wayland") \ + X(wayland_notice_subtitle, u8"检测到当前桌面会话使用 Wayland。", \ + "The current desktop session uses Wayland.", \ + u8"Текущий сеанс рабочего стола использует Wayland.") \ + X(wayland_permission_title, u8"每次共享均需本机授权", \ + "Local approval required each time", \ + u8"Разрешение требуется каждый раз") \ + X(wayland_notice_message, \ + u8"受 Wayland 安全机制限制,每次启动远程桌面共享时," \ + u8"均需在本机手动授权屏幕共享与远程控制,授权后方可正常使用。", \ + "Wayland security restrictions require you to authorize screen sharing " \ + "and remote control locally each time you start sharing this desktop. " \ + "Remote access is available only after authorization.", \ + u8"Из-за ограничений безопасности Wayland при каждом запуске общего " \ + u8"доступа к рабочему столу необходимо вручную разрешать на этом " \ + u8"компьютере показ экрана и удалённое управление. Удалённый доступ " \ + u8"возможен только после разрешения.") \ + X(wayland_recommendation_title, u8"建议使用 X11(Xorg)", \ + "X11 (Xorg) is recommended", u8"Рекомендуем X11 (Xorg)") \ + X(wayland_recommendation_message, \ + u8"为便于持续使用远程桌面,建议注销当前桌面会话," \ + u8"在登录界面选择 X11(Xorg)会话后重新登录。", \ + "For ongoing remote desktop access, we recommend logging out, selecting " \ + "an X11 (Xorg) session on the login screen, and logging in again.", \ + u8"Для постоянного удалённого доступа рекомендуем завершить сеанс, " \ + u8"выбрать X11 (Xorg) на экране входа и войти снова.") \ + X(wayland_notice_acknowledge, u8"我知道了", "Got it", u8"Понятно") \ X(show_main_window, u8"显示主界面", "Show Main Window", \ u8"Показать главное окно") \ X(privacy_screen_unlock_hint, u8"按下快捷键,解除隐私屏", \ diff --git a/apps/desktop/src/gui/ui/main_window.slint b/apps/desktop/src/gui/ui/main_window.slint index 751d3e43..ec9ba250 100644 --- a/apps/desktop/src/gui/ui/main_window.slint +++ b/apps/desktop/src/gui/ui/main_window.slint @@ -80,6 +80,13 @@ export global UiStrings { in-out property permission-required: "The application requires the following permissions:"; in-out property screen-recording-permission: "Screen recording permission"; in-out property accessibility-permission: "Accessibility permission"; + in-out property wayland-notice-title: "Wayland Session Notice"; + in-out property wayland-notice-subtitle; + in-out property wayland-permission-title; + in-out property wayland-notice-message; + in-out property wayland-recommendation-title; + in-out property wayland-recommendation-message; + in-out property wayland-notice-acknowledge: "Got it"; in-out property service-setup-title: "Install CrossDesk Service"; in-out property service-setup-message: "Administrator permission is required to control this device while it is locked."; in-out property service-settings-label: "Lock Screen Service:"; @@ -288,6 +295,7 @@ export component MainWindow inherits Window { in property permission-dialog-open: false; in property screen-recording-granted: true; in property accessibility-granted: true; + in-out property wayland-notice-open: false; in property portable-service-settings-visible: false; in property portable-service-dialog-open: false; in property portable-service-suppressed-notice-open: false; @@ -398,6 +406,10 @@ export component MainWindow inherits Window { } } + changed wayland-notice-open => { + if root.wayland-notice-open { focus-sink.focus(); } + } + reset-remote-id => { root.remote-id-input = ""; remote-id-editor.focus(); @@ -602,7 +614,18 @@ export component MainWindow inherits Window { border-width: 0px; border-radius: 0px; - focus-sink := FocusScope { x: 0px; y: 0px; width: 0px; height: 0px; } + focus-sink := FocusScope { + x: 0px; y: 0px; width: 0px; height: 0px; + key-pressed(event) => { + if root.wayland-notice-open { + if event.text == Key.Return || event.text == Key.Escape { + root.wayland-notice-open = false; + } + return accept; + } + return reject; + } + } TouchArea { clicked => { focus-sink.focus(); } } // Slint owns the client area below the native macOS title bar. Draw @@ -1810,6 +1833,105 @@ export component MainWindow inherits Window { } } + // Linux Wayland sessions show this advisory once per application launch. + if root.wayland-notice-open: Rectangle { + background: #14233b66; + z: 50; + TouchArea { clicked => { focus-sink.focus(); } } + DialogSurface { + x: (parent.width - self.width) / 2; + y: (parent.height - self.height) / 2; + width: 512px; + height: wayland-notice-content.preferred-height; + border-radius: 14px; + border-color: #dce3ee; + drop-shadow-color: #07142b30; + drop-shadow-blur: 28px; + drop-shadow-offset-y: 10px; + + wayland-notice-content := VerticalLayout { + padding: 24px; spacing: 18px; + VerticalLayout { + spacing: 7px; + Text { + text: UiStrings.wayland-notice-title; + color: #1c2b43; + font-size: 20px; + font-weight: 700; + wrap: word-wrap; + } + Text { + text: UiStrings.wayland-notice-subtitle; + color: #68758a; + font-size: ImGuiFontStyle.base; + wrap: word-wrap; + } + } + + Rectangle { + background: #fff8eb; + border-color: #f0dfba; + border-width: 1px; + border-radius: 9px; + VerticalLayout { + padding: 14px; spacing: 8px; + Text { + text: UiStrings.wayland-permission-title; + color: #805719; + font-size: 13px; + font-weight: 600; + wrap: word-wrap; + } + Text { + text: UiStrings.wayland-notice-message; + color: #6c5a3d; + font-size: ImGuiFontStyle.base; + wrap: word-wrap; + } + } + } + + Rectangle { + background: #f3f7fd; + border-color: #dfe8f5; + border-width: 1px; + border-radius: 9px; + VerticalLayout { + padding: 14px; spacing: 8px; + Text { + text: UiStrings.wayland-recommendation-title; + color: #244c87; + font-size: 13px; + font-weight: 600; + wrap: word-wrap; + } + Text { + text: UiStrings.wayland-recommendation-message; + color: #59677c; + font-size: ImGuiFontStyle.base; + wrap: word-wrap; + } + } + } + + Rectangle { height: 1px; background: #e9edf3; } + HorizontalLayout { + height: 34px; alignment: end; + PrimaryButton { + width: 104px; height: 34px; + border-radius: 7px; + text-size: ImGuiFontStyle.base; + text: UiStrings.wayland-notice-acknowledge; + accessible-role: button; + accessible-label: UiStrings.wayland-notice-acknowledge; + accessible-action-default => { root.wayland-notice-open = false; } + clicked => { root.wayland-notice-open = false; } + } + } + } + } + } + // Portable Windows builds prompt for the optional lock-screen service. if root.portable-service-dialog-open: Rectangle { background: #00000052; diff --git a/apps/desktop/src/gui/ui/ui_localization.h b/apps/desktop/src/gui/ui/ui_localization.h index ba247511..fdf660b4 100644 --- a/apps/desktop/src/gui/ui/ui_localization.h +++ b/apps/desktop/src/gui/ui/ui_localization.h @@ -104,6 +104,20 @@ inline int ApplyMainWindowStrings( Text(localization::screen_recording_permission[language])); strings.set_accessibility_permission( Text(localization::accessibility_permission[language])); + strings.set_wayland_notice_title( + Text(localization::wayland_notice_title[language])); + strings.set_wayland_notice_subtitle( + Text(localization::wayland_notice_subtitle[language])); + strings.set_wayland_permission_title( + Text(localization::wayland_permission_title[language])); + strings.set_wayland_notice_message( + Text(localization::wayland_notice_message[language])); + strings.set_wayland_recommendation_title( + Text(localization::wayland_recommendation_title[language])); + strings.set_wayland_recommendation_message( + Text(localization::wayland_recommendation_message[language])); + strings.set_wayland_notice_acknowledge( + Text(localization::wayland_notice_acknowledge[language])); strings.set_service_setup_title( Text(localization::windows_service_setup_title[language])); strings.set_service_setup_message( diff --git a/apps/desktop/tests/slint_ui_smoke_test.cpp b/apps/desktop/tests/slint_ui_smoke_test.cpp index 50439f3e..05d326f9 100644 --- a/apps/desktop/tests/slint_ui_smoke_test.cpp +++ b/apps/desktop/tests/slint_ui_smoke_test.cpp @@ -186,6 +186,7 @@ void ResetMainCaptureState( window->set_permission_dialog_open(false); window->set_screen_recording_granted(true); window->set_accessibility_granted(true); + window->set_wayland_notice_open(false); window->set_settings_session_active(false); window->set_portable_service_settings_visible(false); window->set_portable_service_dialog_open(false); @@ -277,6 +278,8 @@ void ConfigureMainCapturePage( window->set_permission_dialog_open(true); window->set_screen_recording_granted(false); window->set_accessibility_granted(false); + } else if (options.page == "wayland-notice") { + window->set_wayland_notice_open(true); } }