From a075385a114530314d1f8d133de73494e31a16ec Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 13 Sep 2022 06:59:06 -0700 Subject: [PATCH] flutter_desktop: fix resize scale && Pin peer menu bar Signed-off-by: fufesou --- .../lib/desktop/pages/desktop_home_page.dart | 100 +----------------- flutter/lib/desktop/pages/remote_page.dart | 13 ++- .../lib/desktop/widgets/remote_menubar.dart | 48 ++++++++- flutter/lib/models/model.dart | 80 ++++++++++++-- src/lang/cn.rs | 1 + src/lang/cs.rs | 1 + src/lang/da.rs | 1 + src/lang/de.rs | 1 + src/lang/eo.rs | 1 + src/lang/es.rs | 1 + src/lang/fr.rs | 1 + src/lang/hu.rs | 1 + src/lang/id.rs | 1 + src/lang/it.rs | 1 + src/lang/ja.rs | 1 + src/lang/ko.rs | 1 + src/lang/pl.rs | 1 + src/lang/pt_PT.rs | 1 + src/lang/ptbr.rs | 1 + src/lang/ru.rs | 1 + src/lang/sk.rs | 1 + src/lang/template.rs | 1 + src/lang/tr.rs | 1 + src/lang/tw.rs | 1 + src/lang/vn.rs | 1 + 25 files changed, 146 insertions(+), 116 deletions(-) diff --git a/flutter/lib/desktop/pages/desktop_home_page.dart b/flutter/lib/desktop/pages/desktop_home_page.dart index 47f1cc026..25d1ae66d 100644 --- a/flutter/lib/desktop/pages/desktop_home_page.dart +++ b/flutter/lib/desktop/pages/desktop_home_page.dart @@ -330,18 +330,6 @@ class _DesktopHomePageState extends State onHover: (value) => refreshHover.value = value, ), const _PasswordPopupMenu(), - // FutureBuilder( - // future: buildPasswordPopupMenu(context), - // builder: (context, snapshot) { - // if (snapshot.hasError) { - // print("${snapshot.error}"); - // } - // if (snapshot.hasData) { - // return snapshot.data!; - // } else { - // return Offstage(); - // } - // }) ], ), ], @@ -353,92 +341,6 @@ class _DesktopHomePageState extends State ); } - Future buildPasswordPopupMenu(BuildContext context) async { - var position; - RxBool editHover = false.obs; - return InkWell( - onTapDown: (detail) { - final x = detail.globalPosition.dx; - final y = detail.globalPosition.dy; - position = RelativeRect.fromLTRB(x, y, x, y); - }, - onTap: () async { - var method = (String text, String value) => PopupMenuItem( - child: Row( - children: [ - Offstage( - offstage: gFFI.serverModel.verificationMethod != value, - child: Icon(Icons.check)), - Text( - text, - ), - ], - ), - onTap: () => gFFI.serverModel.setVerificationMethod(value), - ); - final temporary_enabled = - gFFI.serverModel.verificationMethod != kUsePermanentPassword; - var menu = [ - method(translate("Use temporary password"), kUseTemporaryPassword), - method(translate("Use permanent password"), kUsePermanentPassword), - method(translate("Use both passwords"), kUseBothPasswords), - PopupMenuDivider(), - PopupMenuItem( - child: Text(translate("Set permanent password")), - value: 'set-permanent-password', - enabled: gFFI.serverModel.verificationMethod != - kUseTemporaryPassword), - PopupMenuItem( - child: PopupMenuButton( - padding: EdgeInsets.zero, - child: Text( - translate("Set temporary password length"), - ), - itemBuilder: (context) => ["6", "8", "10"] - .map((e) => PopupMenuItem( - child: Row( - children: [ - Offstage( - offstage: gFFI.serverModel - .temporaryPasswordLength != - e, - child: Icon(Icons.check)), - Text( - e, - ), - ], - ), - onTap: () { - if (gFFI.serverModel.temporaryPasswordLength != - e) { - () async { - await gFFI.serverModel - .setTemporaryPasswordLength(e); - await bind.mainUpdateTemporaryPassword(); - }(); - } - }, - )) - .toList(), - enabled: temporary_enabled, - ), - enabled: temporary_enabled), - ]; - final v = - await showMenu(context: context, position: position, items: menu); - if (v == "set-permanent-password") { - setPasswordDialog(); - } - }, - onHover: (value) => editHover.value = value, - child: Obx(() => Icon(Icons.edit, - size: 22, - color: editHover.value - ? MyTheme.color(context).text - : Color(0xFFDDDDDD)) - .marginOnly(bottom: 2))); - } - buildTip(BuildContext context) { return Padding( padding: @@ -469,7 +371,7 @@ class _DesktopHomePageState extends State @override void onTrayMenuItemClick(MenuItem menuItem) { - print("click ${menuItem.key}"); + print('click ${menuItem.key}'); switch (menuItem.key) { case "quit": exit(0); diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index 29e99e6a7..35ab548c3 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -50,6 +50,8 @@ class _RemotePageState extends State var _isPhysicalMouse = false; var _imageFocused = false; + final _onEnterOrLeaveImage = []; + late FFI _ffi; void _updateTabBarHeight() { @@ -421,11 +423,17 @@ class _RemotePageState extends State _physicalFocusNode.requestFocus(); } _cursorOverImage.value = true; + for (var f in _onEnterOrLeaveImage) { + f(true); + } _ffi.enterOrLeave(true); } void leaveView(PointerExitEvent evt) { _cursorOverImage.value = false; + for (var f in _onEnterOrLeaveImage) { + f(false); + } _ffi.enterOrLeave(false); } @@ -469,6 +477,7 @@ class _RemotePageState extends State paints.add(RemoteMenubar( id: widget.id, ffi: _ffi, + onEnterOrLeaveImage: _onEnterOrLeaveImage, )); return Stack( children: paints, @@ -597,8 +606,8 @@ class ImagePaint extends StatelessWidget { return FlutterCustomMemoryImageCursor( pixbuf: cacheLinux.data, key: key, - hotx: 0.0, - hoty: 0.0, + hotx: cacheLinux.hotx, + hoty: cacheLinux.hoty, imageWidth: (cacheLinux.width * scale).toInt(), imageHeight: (cacheLinux.height * scale).toInt(), ); diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 327da889f..47ac2094b 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -25,11 +25,13 @@ class _MenubarTheme { class RemoteMenubar extends StatefulWidget { final String id; final FFI ffi; + final List onEnterOrLeaveImage; const RemoteMenubar({ Key? key, required this.id, required this.ffi, + required this.onEnterOrLeaveImage, }) : super(key: key); @override @@ -39,12 +41,38 @@ class RemoteMenubar extends StatefulWidget { class _RemoteMenubarState extends State { final RxBool _show = false.obs; final Rx _hideColor = Colors.white12.obs; + final _rxHideReplay = rxdart.ReplaySubject(); + final _pinMenubar = false.obs; + bool _isCursorOverImage = false; bool get isFullscreen => Get.find(tag: 'fullscreen').isTrue; - void setFullscreen(bool v) { + void _setFullscreen(bool v) { Get.find(tag: 'fullscreen').value = v; } + @override + void initState() { + super.initState(); + + widget.onEnterOrLeaveImage.add((enter) { + if (enter) { + _rxHideReplay.add(0); + _isCursorOverImage = true; + } else { + _isCursorOverImage = false; + } + }); + + _rxHideReplay + .throttleTime(const Duration(milliseconds: 5000), + trailing: true, leading: false) + .listen((int v) { + if (_pinMenubar.isFalse && _show.isTrue && _isCursorOverImage) { + _show.value = false; + } + }); + } + @override Widget build(BuildContext context) { return Align( @@ -76,6 +104,7 @@ class _RemoteMenubarState extends State { Widget _buildMenubar(BuildContext context) { final List menubarItems = []; if (!isWebDesktop) { + menubarItems.add(_buildPinMenubar(context)); menubarItems.add(_buildFullscreen(context)); if (widget.ffi.ffiModel.isPeerAndroid) { menubarItems.add(IconButton( @@ -111,11 +140,24 @@ class _RemoteMenubarState extends State { ])); } + Widget _buildPinMenubar(BuildContext context) { + return IconButton( + tooltip: translate('Pin menubar'), + onPressed: () { + _pinMenubar.value = !_pinMenubar.value; + }, + icon: Obx(() => Icon( + Icons.push_pin, + color: _pinMenubar.isTrue ? _MenubarTheme.commonColor : Colors.grey, + )), + ); + } + Widget _buildFullscreen(BuildContext context) { return IconButton( tooltip: translate(isFullscreen ? 'Exit Fullscreen' : 'Fullscreen'), onPressed: () { - setFullscreen(!isFullscreen); + _setFullscreen(!isFullscreen); }, icon: Obx(() => isFullscreen ? const Icon( @@ -250,7 +292,6 @@ class _RemoteMenubarState extends State { ), tooltip: translate('Display Settings'), position: mod_menu.PopupMenuPosition.under, - onSelected: (String item) {}, itemBuilder: (BuildContext context) => _getDisplayMenu() .map((entry) => entry.build( context, @@ -273,7 +314,6 @@ class _RemoteMenubarState extends State { ), tooltip: translate('Keyboard Settings'), position: mod_menu.PopupMenuPosition.under, - onSelected: (String item) {}, itemBuilder: (BuildContext context) => _getKeyboardMenu() .map((entry) => entry.build( context, diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 7fe2b6767..c37ae1046 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -409,6 +409,56 @@ enum ScrollStyle { scrollauto, } +class ViewStyle { + final String style; + final double width; + final double height; + final int displayWidth; + final int displayHeight; + ViewStyle({ + this.style = '', + this.width = 0.0, + this.height = 0.0, + this.displayWidth = 0, + this.displayHeight = 0, + }); + + static int _double2Int(double v) => (v * 100).round().toInt(); + + @override + bool operator ==(Object other) => + other is ViewStyle && + other.runtimeType == runtimeType && + _innerEqual(other); + + bool _innerEqual(ViewStyle other) { + return style == other.style && + ViewStyle._double2Int(other.width) == ViewStyle._double2Int(width) && + ViewStyle._double2Int(other.height) == ViewStyle._double2Int(height) && + other.displayWidth == displayWidth && + other.displayHeight == displayHeight; + } + + @override + int get hashCode => Object.hash( + style, + ViewStyle._double2Int(width), + ViewStyle._double2Int(height), + displayWidth, + displayHeight, + ).hashCode; + + double get scale { + double s = 1.0; + if (style == 'adaptive') { + final s1 = width / displayWidth; + final s2 = height / displayHeight; + s = s1 < s2 ? s1 : s2; + } + return s; + } +} + class CanvasModel with ChangeNotifier { // image offset of canvas double _x = 0; @@ -425,7 +475,7 @@ class CanvasModel with ChangeNotifier { // scroll offset y percent double _scrollY = 0.0; ScrollStyle _scrollStyle = ScrollStyle.scrollauto; - String? _viewStyle; + ViewStyle _lastViewStyle = ViewStyle(); WeakReference parent; @@ -446,19 +496,27 @@ class CanvasModel with ChangeNotifier { updateViewStyle() async { final style = await bind.sessionGetOption(id: id, arg: 'view-style'); - if (style == null || _viewStyle == style) { + if (style == null) { return; } - - _scale = 1.0; - if (style == 'adaptive') { - final s1 = size.width / getDisplayWidth(); - final s2 = size.height / getDisplayHeight(); - _scale = s1 < s2 ? s1 : s2; + final sizeWidth = size.width; + final sizeHeight = size.height; + final displayWidth = getDisplayWidth(); + final displayHeight = getDisplayHeight(); + final viewStyle = ViewStyle( + style: style, + width: sizeWidth, + height: sizeHeight, + displayWidth: displayWidth, + displayHeight: displayHeight, + ); + if (_lastViewStyle == viewStyle) { + return; } - _viewStyle = style; - _x = (size.width - getDisplayWidth() * _scale) / 2; - _y = (size.height - getDisplayHeight() * _scale) / 2; + _lastViewStyle = viewStyle; + _scale = viewStyle.scale; + _x = (sizeWidth - displayWidth * _scale) / 2; + _y = (sizeHeight - displayHeight * _scale) / 2; notifyListeners(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index abb772d51..62d2cce23 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -344,5 +344,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use IP Whitelisting", "只允许白名单上的IP访问"), ("Network", "网络"), ("Enable RDP", "允许RDP访问"), + ("Pin menubar", "固定菜单栏"), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 5061fbb88..3b317f864 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -344,5 +344,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use IP Whitelisting", ""), ("Network", ""), ("Enable RDP", ""), + ("Pin menubar", "Připnout panel nabídek"), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index ed5e3425b..1180a43d4 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -344,5 +344,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use IP Whitelisting", ""), ("Network", ""), ("Enable RDP", ""), + ("Pin menubar", "Fastgør menulinjen"), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 43f0b2f8e..f5278d2d0 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -344,5 +344,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use IP Whitelisting", ""), ("Network", ""), ("Enable RDP", ""), + ("Pin menubar", "Pin-Menüleiste"), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index d7f038b41..58143d80d 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -344,5 +344,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use IP Whitelisting", ""), ("Network", ""), ("Enable RDP", ""), + ("Pin menubar", "Alpingla menubreto"), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index 7c13e849c..0674840c7 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -357,5 +357,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use IP Whitelisting", ""), ("Network", ""), ("Enable RDP", ""), + ("Pin menubar", "Pin barra de menú"), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 3e46a6b40..e4387d773 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -344,5 +344,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use IP Whitelisting", ""), ("Network", ""), ("Enable RDP", ""), + ("Pin menubar", "Épingler la barre de menus"), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 78089075c..8830bdfc0 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -344,5 +344,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use IP Whitelisting", ""), ("Network", ""), ("Enable RDP", ""), + ("Pin menubar", "Menüsor rögzítése"), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index a9cc27767..16fa641f2 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -357,5 +357,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use IP Whitelisting", ""), ("Network", ""), ("Enable RDP", ""), + ("Pin menubar", "Pin menubar"), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 8749e2976..c5a3a3330 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -343,5 +343,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use IP Whitelisting", ""), ("Network", ""), ("Enable RDP", ""), + ("Pin menubar", "Aggiungi barra dei menu"), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 30181b7a5..2a160f744 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -341,5 +341,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use IP Whitelisting", ""), ("Network", ""), ("Enable RDP", ""), + ("Pin menubar", "メニューバーを固定する"), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 7b8377206..6b866a1ee 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -338,5 +338,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use IP Whitelisting", ""), ("Network", ""), ("Enable RDP", ""), + ("Pin menubar", "핀 메뉴 바"), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 1088cfa72..3f8f81e2b 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -342,5 +342,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use IP Whitelisting", ""), ("Network", ""), ("Enable RDP", ""), + ("Pin menubar", "Przypnij pasek menu"), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index cb6fcf548..aeceec759 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -338,5 +338,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use IP Whitelisting", ""), ("Network", ""), ("Enable RDP", ""), + ("Pin menubar", "Fixar barra de menu"), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index cba544380..3dc651743 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -344,5 +344,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use IP Whitelisting", ""), ("Network", ""), ("Enable RDP", ""), + ("Pin menubar", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 6fb7078ac..9e890e7d8 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -344,5 +344,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use IP Whitelisting", ""), ("Network", ""), ("Enable RDP", ""), + ("Pin menubar", "Закрепить строку меню"), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index ebc9571af..74bc27b26 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -344,5 +344,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use IP Whitelisting", ""), ("Network", ""), ("Enable RDP", ""), + ("Pin menubar", "Pripnúť panel s ponukami"), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 5d3061a05..9a6dc431f 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -344,5 +344,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use IP Whitelisting", ""), ("Network", ""), ("Enable RDP", ""), + ("Pin menubar", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 6cf6c1298..823d31043 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -357,5 +357,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use IP Whitelisting", ""), ("Network", ""), ("Enable RDP", ""), + ("Pin menubar", "Menü çubuğunu sabitle"), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index f312c7f47..dd7178122 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -344,5 +344,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use IP Whitelisting", "只允許白名單上的IP訪問"), ("Network", "網絡"), ("Enable RDP", "允許RDP訪問"), + ("Pin menubar", "固定菜單欄"), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 94beafb67..5d11ca6b9 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -344,5 +344,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Use IP Whitelisting", ""), ("Network", ""), ("Enable RDP", ""), + ("Pin menubar", "Ghim thanh menu"), ].iter().cloned().collect(); }