mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-11-11 19:07:33 +08:00
[fix] keep stream menus open while suspending remote input
This commit is contained in:
@@ -48,6 +48,7 @@
|
||||
#include "features/gallery/gallery_workspace.h"
|
||||
#include "features/gallery/preview_bandwidth.h"
|
||||
#include "features/gallery/preview_resolution.h"
|
||||
#include "features/input/stream_keyboard_focus.h"
|
||||
#include "filesystem_utf8.h"
|
||||
#include "localization.h"
|
||||
#include "platform.h"
|
||||
@@ -3803,19 +3804,10 @@ void GuiApplication::SyncXWaylandWindowActivation() {
|
||||
#endif
|
||||
|
||||
void GuiApplication::SetStreamKeyboardFocus(bool focused) {
|
||||
// Local dialogs own input even while the native window is active.
|
||||
if (focused && ui_ && ui_->stream &&
|
||||
(*ui_->stream)->get_modal_visible()) {
|
||||
focused = false;
|
||||
}
|
||||
if (focus_on_stream_window_ == focused) {
|
||||
return;
|
||||
}
|
||||
|
||||
focus_on_stream_window_ = focused;
|
||||
if (!focused) {
|
||||
ReleaseControl();
|
||||
}
|
||||
const bool local_input_active = ui_ && ui_->stream &&
|
||||
(*ui_->stream)->get_local_input_active();
|
||||
UpdateStreamKeyboardFocus(focused, local_input_active, focus_on_stream_window_,
|
||||
[this](bool preserve_local_ui) { ReleaseControl(preserve_local_ui); });
|
||||
}
|
||||
|
||||
void GuiApplication::SyncStreamKeyboardFocus() {
|
||||
@@ -5665,7 +5657,7 @@ void GuiApplication::SyncAudioPlayback() {
|
||||
}
|
||||
}
|
||||
|
||||
void GuiApplication::ReleasePressedInput() {
|
||||
void GuiApplication::ReleasePressedInput(bool preserve_local_ui) {
|
||||
keyboard_.ForceReleasePressedKeys();
|
||||
for (int button : ui_->pressed_mouse_buttons) {
|
||||
RemoteAction action{};
|
||||
@@ -5678,13 +5670,16 @@ void GuiApplication::ReleasePressedInput() {
|
||||
SendRemoteInput(action);
|
||||
}
|
||||
ui_->pressed_mouse_buttons.clear();
|
||||
if (ui_->stream) (*ui_->stream)->invoke_reset_input_state();
|
||||
if (ui_->stream) {
|
||||
if (preserve_local_ui) (*ui_->stream)->invoke_reset_pressed_input();
|
||||
else (*ui_->stream)->invoke_reset_input_state();
|
||||
}
|
||||
}
|
||||
|
||||
void GuiApplication::ReleaseControl() {
|
||||
void GuiApplication::ReleaseControl(bool preserve_local_ui) {
|
||||
const auto gallery_target = ui_->gallery_control_id;
|
||||
devices_.StopKeyboardCapturer();
|
||||
ReleasePressedInput();
|
||||
ReleasePressedInput(preserve_local_ui);
|
||||
gallery_group_control_id_.clear();
|
||||
ui_->wall->set_gallery_group_controlling(false);
|
||||
ui_->wall->set_gallery_remote_cursor_shape(
|
||||
|
||||
@@ -84,8 +84,8 @@ private:
|
||||
void DeviceGroupAction(const std::string& action, const std::string& value,
|
||||
bool gallery_window);
|
||||
bool SaveDeviceGroups(const std::string& new_group, bool gallery_window);
|
||||
void ReleasePressedInput();
|
||||
void ReleaseControl();
|
||||
void ReleasePressedInput(bool preserve_local_ui = false);
|
||||
void ReleaseControl(bool preserve_local_ui = false);
|
||||
void SyncAudioPlayback();
|
||||
void SaveGalleryWindowState();
|
||||
void SyncAnnouncements();
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* @Author: DI JUNKUN
|
||||
* @Date: 2026-11-11
|
||||
* Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _STREAM_KEYBOARD_FOCUS_H_
|
||||
#define _STREAM_KEYBOARD_FOCUS_H_
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
// Native window focus and ownership of keyboard input are different: a local
|
||||
// menu keeps the window active while temporarily suspending remote input.
|
||||
// Publish the new state before releasing input, since UI callbacks can reenter.
|
||||
template <typename Release>
|
||||
void UpdateStreamKeyboardFocus(bool focused, bool local_input_active,
|
||||
bool& remote_focused, Release release) {
|
||||
focused = focused && !local_input_active;
|
||||
if (remote_focused == focused) return;
|
||||
remote_focused = focused;
|
||||
if (!focused) release(local_input_active);
|
||||
}
|
||||
|
||||
} // namespace crossdesk
|
||||
|
||||
#endif
|
||||
@@ -423,6 +423,10 @@ export component StreamWindow inherits Window {
|
||||
private property <length> disconnect-menu-y: root.control-panel-y(root.disconnect-menu-height);
|
||||
private property <bool> control-menu-open:
|
||||
root.display-menu-open || root.shortcut-menu-open || root.video-menu-open || root.disconnect-menu-open;
|
||||
out property <bool> local-input-active: root.modal-visible || root.control-menu-open;
|
||||
changed control-menu-open => {
|
||||
root.keyboard-focus-changed(!root.control-menu-open && !root.modal-visible && input-focus.has-focus);
|
||||
}
|
||||
changed selected-tab => {
|
||||
root.close-control-menus();
|
||||
root.cancel-remote-pointer();
|
||||
@@ -589,10 +593,14 @@ export component StreamWindow inherits Window {
|
||||
|
||||
// Native focus/session changes release input in C++; clear the matching UI
|
||||
// ownership too, including when replacing the only tab (same tab index).
|
||||
public function reset-input-state() {
|
||||
public function reset-pressed-input() {
|
||||
root.remote-left-down = false;
|
||||
root.remote-right-down = false;
|
||||
root.remote-middle-down = false;
|
||||
}
|
||||
|
||||
public function reset-input-state() {
|
||||
root.reset-pressed-input();
|
||||
root.close-control-menus();
|
||||
root.control-drag-pending = false;
|
||||
root.end-control-drag();
|
||||
@@ -1039,10 +1047,10 @@ export component StreamWindow inherits Window {
|
||||
|
||||
input-focus := FocusScope {
|
||||
focus-on-click: true;
|
||||
focus-gained => { root.keyboard-focus-changed(true); }
|
||||
focus-gained => { root.keyboard-focus-changed(!root.control-menu-open && !root.modal-visible); }
|
||||
focus-lost => { root.keyboard-focus-changed(false); }
|
||||
key-pressed(event) => {
|
||||
if !root.modal-visible {
|
||||
if !root.modal-visible && !root.control-menu-open {
|
||||
root.key-input(event.text, true, event.modifiers.control, event.modifiers.alt, event.modifiers.shift, event.modifiers.meta);
|
||||
}
|
||||
accept
|
||||
@@ -1053,7 +1061,7 @@ export component StreamWindow inherits Window {
|
||||
if event.text == Key.Escape || event.text == Key.Return {
|
||||
if root.privacy-unlock-visible { root.dismiss-privacy-unlock(); } else { root.dismiss-remote-update(); }
|
||||
}
|
||||
} else {
|
||||
} else if !root.control-menu-open {
|
||||
root.key-input(event.text, false, event.modifiers.control, event.modifiers.alt, event.modifiers.shift, event.modifiers.meta);
|
||||
}
|
||||
accept
|
||||
|
||||
Reference in New Issue
Block a user