Merge pull request #5489 from fufesou/fix/enable_menu_before_image
Fix/enable menu before image
This commit is contained in:
commit
c450b41e8f
@ -228,49 +228,67 @@ class _RemotePageState extends State<RemotePage>
|
|||||||
removeSharedStates(widget.id);
|
removeSharedStates(widget.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildBody(BuildContext context) {
|
Widget emptyOverlay() => BlockableOverlay(
|
||||||
return Scaffold(
|
/// the Overlay key will be set with _blockableOverlayState in BlockableOverlay
|
||||||
backgroundColor: Theme.of(context).colorScheme.background,
|
/// see override build() in [BlockableOverlay]
|
||||||
|
|
||||||
/// the Overlay key will be set with _blockableOverlayState in BlockableOverlay
|
|
||||||
/// see override build() in [BlockableOverlay]
|
|
||||||
body: BlockableOverlay(
|
|
||||||
state: _blockableOverlayState,
|
state: _blockableOverlayState,
|
||||||
underlying: Container(
|
underlying: Container(
|
||||||
color: Colors.black,
|
color: Colors.transparent,
|
||||||
child: RawKeyFocusScope(
|
),
|
||||||
focusNode: _rawKeyFocusNode,
|
);
|
||||||
onFocusChange: (bool imageFocused) {
|
|
||||||
debugPrint(
|
Widget buildBody(BuildContext context) {
|
||||||
"onFocusChange(window active:${!_isWindowBlur}) $imageFocused");
|
remoteToolbar(BuildContext context) => RemoteToolbar(
|
||||||
// See [onWindowBlur].
|
id: widget.id,
|
||||||
if (Platform.isWindows) {
|
ffi: _ffi,
|
||||||
if (_isWindowBlur) {
|
state: widget.toolbarState,
|
||||||
imageFocused = false;
|
onEnterOrLeaveImageSetter: (func) =>
|
||||||
Future.delayed(Duration.zero, () {
|
_onEnterOrLeaveImage4Toolbar = func,
|
||||||
_rawKeyFocusNode.unfocus();
|
onEnterOrLeaveImageCleaner: () => _onEnterOrLeaveImage4Toolbar = null,
|
||||||
});
|
);
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Theme.of(context).colorScheme.background,
|
||||||
|
body: Stack(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
color: Colors.black,
|
||||||
|
child: RawKeyFocusScope(
|
||||||
|
focusNode: _rawKeyFocusNode,
|
||||||
|
onFocusChange: (bool imageFocused) {
|
||||||
|
debugPrint(
|
||||||
|
"onFocusChange(window active:${!_isWindowBlur}) $imageFocused");
|
||||||
|
// See [onWindowBlur].
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
if (_isWindowBlur) {
|
||||||
|
imageFocused = false;
|
||||||
|
Future.delayed(Duration.zero, () {
|
||||||
|
_rawKeyFocusNode.unfocus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (imageFocused) {
|
||||||
|
_ffi.inputModel.enterOrLeave(true);
|
||||||
|
} else {
|
||||||
|
_ffi.inputModel.enterOrLeave(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (imageFocused) {
|
},
|
||||||
_ffi.inputModel.enterOrLeave(true);
|
inputModel: _ffi.inputModel,
|
||||||
} else {
|
child: getBodyForDesktop(context))),
|
||||||
_ffi.inputModel.enterOrLeave(false);
|
Obx(() => Stack(
|
||||||
}
|
children: [
|
||||||
}
|
_ffi.ffiModel.pi.isSet.isTrue &&
|
||||||
},
|
_ffi.ffiModel.waitForFirstImage.isTrue
|
||||||
inputModel: _ffi.inputModel,
|
? emptyOverlay()
|
||||||
child: getBodyForDesktop(context))),
|
: Offstage(),
|
||||||
upperLayer: [
|
// Use Overlay to enable rebuild every time on menu button click.
|
||||||
OverlayEntry(
|
_ffi.ffiModel.pi.isSet.isTrue
|
||||||
builder: (context) => RemoteToolbar(
|
? Overlay(initialEntries: [
|
||||||
id: widget.id,
|
OverlayEntry(builder: remoteToolbar)
|
||||||
ffi: _ffi,
|
])
|
||||||
state: widget.toolbarState,
|
: remoteToolbar(context),
|
||||||
onEnterOrLeaveImageSetter: (func) =>
|
_ffi.ffiModel.pi.isSet.isFalse ? emptyOverlay() : Offstage(),
|
||||||
_onEnterOrLeaveImage4Toolbar = func,
|
],
|
||||||
onEnterOrLeaveImageCleaner: () =>
|
)),
|
||||||
_onEnterOrLeaveImage4Toolbar = null,
|
|
||||||
))
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -266,7 +266,11 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
|
|||||||
if (e.kind != ui.PointerDeviceKind.mouse) {
|
if (e.kind != ui.PointerDeviceKind.mouse) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (e.buttons == 2) {
|
final remotePage = tabController.state.value.tabs
|
||||||
|
.firstWhere((tab) => tab.key == key)
|
||||||
|
.page as RemotePage;
|
||||||
|
if (remotePage.ffi.ffiModel.pi.isSet.isTrue &&
|
||||||
|
e.buttons == 2) {
|
||||||
showRightMenu(
|
showRightMenu(
|
||||||
(CancelFunc cancelFunc) {
|
(CancelFunc cancelFunc) {
|
||||||
return _tabMenuBuilder(key, cancelFunc);
|
return _tabMenuBuilder(key, cancelFunc);
|
||||||
|
@ -77,7 +77,7 @@ CancelFunc showRightMenu(ToastBuilder builder,
|
|||||||
targetContext: context,
|
targetContext: context,
|
||||||
verticalOffset: 0,
|
verticalOffset: 0,
|
||||||
horizontalOffset: 0,
|
horizontalOffset: 0,
|
||||||
duration: Duration(seconds: 4),
|
duration: Duration(seconds: 300),
|
||||||
animationDuration: Duration(milliseconds: 0),
|
animationDuration: Duration(milliseconds: 0),
|
||||||
animationReverseDuration: Duration(milliseconds: 0),
|
animationReverseDuration: Duration(milliseconds: 0),
|
||||||
preferDirection: PreferDirection.rightTop,
|
preferDirection: PreferDirection.rightTop,
|
||||||
|
@ -38,8 +38,6 @@ import 'platform_model.dart';
|
|||||||
|
|
||||||
typedef HandleMsgBox = Function(Map<String, dynamic> evt, String id);
|
typedef HandleMsgBox = Function(Map<String, dynamic> evt, String id);
|
||||||
typedef ReconnectHandle = Function(OverlayDialogManager, SessionID, bool);
|
typedef ReconnectHandle = Function(OverlayDialogManager, SessionID, bool);
|
||||||
final _waitForImageDialogShow = <UuidValue, bool>{};
|
|
||||||
final _waitForFirstImage = <UuidValue, bool>{};
|
|
||||||
final _constSessionId = Uuid().v4obj();
|
final _constSessionId = Uuid().v4obj();
|
||||||
|
|
||||||
class CachedPeerData {
|
class CachedPeerData {
|
||||||
@ -100,6 +98,10 @@ class FfiModel with ChangeNotifier {
|
|||||||
WeakReference<FFI> parent;
|
WeakReference<FFI> parent;
|
||||||
late final SessionID sessionId;
|
late final SessionID sessionId;
|
||||||
|
|
||||||
|
RxBool waitForImageDialogShow = true.obs;
|
||||||
|
Timer? waitForImageTimer;
|
||||||
|
RxBool waitForFirstImage = true.obs;
|
||||||
|
|
||||||
Map<String, bool> get permissions => _permissions;
|
Map<String, bool> get permissions => _permissions;
|
||||||
|
|
||||||
Display get display => _display;
|
Display get display => _display;
|
||||||
@ -158,6 +160,7 @@ class FfiModel with ChangeNotifier {
|
|||||||
_timer?.cancel();
|
_timer?.cancel();
|
||||||
_timer = null;
|
_timer = null;
|
||||||
clearPermissions();
|
clearPermissions();
|
||||||
|
waitForImageTimer?.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
setConnectionType(String peerId, bool secure, bool direct) {
|
setConnectionType(String peerId, bool secure, bool direct) {
|
||||||
@ -498,7 +501,7 @@ class FfiModel with ChangeNotifier {
|
|||||||
closeConnection();
|
closeConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_waitForFirstImage[sessionId] == false) return;
|
if (waitForFirstImage.isFalse) return;
|
||||||
dialogManager.show(
|
dialogManager.show(
|
||||||
(setState, close, context) => CustomAlertDialog(
|
(setState, close, context) => CustomAlertDialog(
|
||||||
title: null,
|
title: null,
|
||||||
@ -509,7 +512,12 @@ class FfiModel with ChangeNotifier {
|
|||||||
onCancel: onClose),
|
onCancel: onClose),
|
||||||
tag: '$sessionId-waiting-for-image',
|
tag: '$sessionId-waiting-for-image',
|
||||||
);
|
);
|
||||||
_waitForImageDialogShow[sessionId] = true;
|
waitForImageDialogShow.value = true;
|
||||||
|
waitForImageTimer = Timer(Duration(milliseconds: 1500), () {
|
||||||
|
if (waitForFirstImage.isTrue) {
|
||||||
|
bind.sessionInputOsPassword(sessionId: sessionId, value: '');
|
||||||
|
}
|
||||||
|
});
|
||||||
bind.sessionOnWaitingForImageDialogShow(sessionId: sessionId);
|
bind.sessionOnWaitingForImageDialogShow(sessionId: sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -578,7 +586,7 @@ class FfiModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
if (displays.isNotEmpty) {
|
if (displays.isNotEmpty) {
|
||||||
_reconnects = 1;
|
_reconnects = 1;
|
||||||
_waitForFirstImage[sessionId] = true;
|
waitForFirstImage.value = true;
|
||||||
}
|
}
|
||||||
Map<String, dynamic> features = json.decode(evt['features']);
|
Map<String, dynamic> features = json.decode(evt['features']);
|
||||||
_pi.features.privacyMode = features['privacy_mode'] == 1;
|
_pi.features.privacyMode = features['privacy_mode'] == 1;
|
||||||
@ -602,6 +610,7 @@ class FfiModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_pi.isSet.value = true;
|
||||||
stateGlobal.resetLastResolutionGroupValues(peerId);
|
stateGlobal.resetLastResolutionGroupValues(peerId);
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@ -1814,12 +1823,13 @@ class FFI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void onEvent2UIRgba() async {
|
void onEvent2UIRgba() async {
|
||||||
if (_waitForImageDialogShow[sessionId] == true) {
|
if (ffiModel.waitForImageDialogShow.isTrue) {
|
||||||
_waitForImageDialogShow[sessionId] = false;
|
ffiModel.waitForImageDialogShow.value = false;
|
||||||
|
ffiModel.waitForImageTimer?.cancel();
|
||||||
clearWaitingForImage(dialogManager, sessionId);
|
clearWaitingForImage(dialogManager, sessionId);
|
||||||
}
|
}
|
||||||
if (_waitForFirstImage[sessionId] == true) {
|
if (ffiModel.waitForFirstImage.value == true) {
|
||||||
_waitForFirstImage[sessionId] = false;
|
ffiModel.waitForFirstImage.value = false;
|
||||||
dialogManager.dismissAll();
|
dialogManager.dismissAll();
|
||||||
await canvasModel.updateViewStyle();
|
await canvasModel.updateViewStyle();
|
||||||
await canvasModel.updateScrollStyle();
|
await canvasModel.updateScrollStyle();
|
||||||
@ -1934,7 +1944,7 @@ class Features {
|
|||||||
bool privacyMode = false;
|
bool privacyMode = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
class PeerInfo {
|
class PeerInfo with ChangeNotifier {
|
||||||
String version = '';
|
String version = '';
|
||||||
String username = '';
|
String username = '';
|
||||||
String hostname = '';
|
String hostname = '';
|
||||||
@ -1946,6 +1956,8 @@ class PeerInfo {
|
|||||||
List<Resolution> resolutions = [];
|
List<Resolution> resolutions = [];
|
||||||
Map<String, dynamic> platform_additions = {};
|
Map<String, dynamic> platform_additions = {};
|
||||||
|
|
||||||
|
RxBool isSet = false.obs;
|
||||||
|
|
||||||
bool get is_wayland => platform_additions['is_wayland'] == true;
|
bool get is_wayland => platform_additions['is_wayland'] == true;
|
||||||
bool get is_headless => platform_additions['headless'] == true;
|
bool get is_headless => platform_additions['headless'] == true;
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,10 @@ use scrap::{
|
|||||||
ImageFormat, ImageRgb,
|
ImageFormat, ImageRgb,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::is_keyboard_mode_supported;
|
use crate::{
|
||||||
|
common::input::{MOUSE_BUTTON_LEFT, MOUSE_TYPE_DOWN, MOUSE_TYPE_UP},
|
||||||
|
is_keyboard_mode_supported,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(not(feature = "flutter"))]
|
#[cfg(not(feature = "flutter"))]
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
@ -2057,13 +2060,20 @@ pub fn send_pointer_device_event(
|
|||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `interface` - The interface for sending data.
|
/// * `interface` - The interface for sending data.
|
||||||
fn activate_os(interface: &impl Interface) {
|
/// * `send_click` - Whether to send a click event.
|
||||||
|
fn activate_os(interface: &impl Interface, send_click: bool) {
|
||||||
|
let left_down = MOUSE_BUTTON_LEFT << 3 | MOUSE_TYPE_DOWN;
|
||||||
|
let left_up = MOUSE_BUTTON_LEFT << 3 | MOUSE_TYPE_UP;
|
||||||
|
send_mouse(left_up, 0, 0, false, false, false, false, interface);
|
||||||
|
std::thread::sleep(Duration::from_millis(50));
|
||||||
send_mouse(0, 0, 0, false, false, false, false, interface);
|
send_mouse(0, 0, 0, false, false, false, false, interface);
|
||||||
std::thread::sleep(Duration::from_millis(50));
|
std::thread::sleep(Duration::from_millis(50));
|
||||||
send_mouse(0, 3, 3, false, false, false, false, interface);
|
send_mouse(0, 3, 3, false, false, false, false, interface);
|
||||||
std::thread::sleep(Duration::from_millis(50));
|
if send_click {
|
||||||
send_mouse(1 | 1 << 3, 0, 0, false, false, false, false, interface);
|
std::thread::sleep(Duration::from_millis(50));
|
||||||
send_mouse(2 | 1 << 3, 0, 0, false, false, false, false, interface);
|
send_mouse(left_down, 0, 0, false, false, false, false, interface);
|
||||||
|
send_mouse(left_up, 0, 0, false, false, false, false, interface);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
let mut key_event = KeyEvent::new();
|
let mut key_event = KeyEvent::new();
|
||||||
// do not use Esc, which has problem with Linux
|
// do not use Esc, which has problem with Linux
|
||||||
@ -2096,10 +2106,15 @@ pub fn input_os_password(p: String, activate: bool, interface: impl Interface) {
|
|||||||
/// * `activate` - Whether to activate OS.
|
/// * `activate` - Whether to activate OS.
|
||||||
/// * `interface` - The interface for sending data.
|
/// * `interface` - The interface for sending data.
|
||||||
fn _input_os_password(p: String, activate: bool, interface: impl Interface) {
|
fn _input_os_password(p: String, activate: bool, interface: impl Interface) {
|
||||||
|
let input_password = !p.is_empty();
|
||||||
if activate {
|
if activate {
|
||||||
activate_os(&interface);
|
// Click event is used to bring up the password input box.
|
||||||
|
activate_os(&interface, input_password);
|
||||||
std::thread::sleep(Duration::from_millis(1200));
|
std::thread::sleep(Duration::from_millis(1200));
|
||||||
}
|
}
|
||||||
|
if !input_password {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let mut key_event = KeyEvent::new();
|
let mut key_event = KeyEvent::new();
|
||||||
key_event.press = true;
|
key_event.press = true;
|
||||||
let mut msg_out = Message::new();
|
let mut msg_out = Message::new();
|
||||||
|
@ -25,7 +25,7 @@ use hbb_common::{
|
|||||||
protobuf::Enum,
|
protobuf::Enum,
|
||||||
protobuf::Message as _,
|
protobuf::Message as _,
|
||||||
rendezvous_proto::*,
|
rendezvous_proto::*,
|
||||||
sleep, socket_client,
|
socket_client,
|
||||||
tcp::FramedStream,
|
tcp::FramedStream,
|
||||||
tokio, ResultType,
|
tokio, ResultType,
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user