From d4c735bc3a2674160c801c6a730c91bbbe2ecf82 Mon Sep 17 00:00:00 2001 From: fufesou Date: Wed, 3 Aug 2022 15:31:19 +0800 Subject: [PATCH] flutter_desktop: fix canvas height - tabBarHeight Signed-off-by: fufesou --- flutter/lib/consts.dart | 1 + .../lib/desktop/pages/connection_page.dart | 2 + .../desktop/pages/connection_tab_page.dart | 76 ++++++++++--------- flutter/lib/desktop/pages/remote_page.dart | 36 +++++---- flutter/lib/desktop/widgets/peer_widget.dart | 28 ++++--- .../lib/desktop/widgets/peercard_widget.dart | 4 - .../lib/desktop/widgets/titlebar_widget.dart | 3 +- flutter/lib/mobile/pages/connection_page.dart | 10 +-- flutter/lib/models/model.dart | 61 +++++++++------ src/lan.rs | 5 +- 10 files changed, 130 insertions(+), 96 deletions(-) create mode 100644 flutter/lib/consts.dart diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart new file mode 100644 index 000000000..8f647837f --- /dev/null +++ b/flutter/lib/consts.dart @@ -0,0 +1 @@ +double kDesktopRemoteTabBarHeight = 48.0; diff --git a/flutter/lib/desktop/pages/connection_page.dart b/flutter/lib/desktop/pages/connection_page.dart index 628f962a2..b6a89a48c 100644 --- a/flutter/lib/desktop/pages/connection_page.dart +++ b/flutter/lib/desktop/pages/connection_page.dart @@ -906,8 +906,10 @@ class _PeerTabbedPageState extends State<_PeerTabbedPage> if (_tabController.indexIsChanging) { switch (_tabController.index) { case 0: + gFFI.bind.mainLoadRecentPeers(); break; case 1: + gFFI.bind.mainLoadFavPeers(); break; case 2: gFFI.bind.mainDiscover(); diff --git a/flutter/lib/desktop/pages/connection_tab_page.dart b/flutter/lib/desktop/pages/connection_tab_page.dart index 69c10ebff..9632fc1f0 100644 --- a/flutter/lib/desktop/pages/connection_tab_page.dart +++ b/flutter/lib/desktop/pages/connection_tab_page.dart @@ -3,9 +3,11 @@ import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter_hbb/common.dart'; +import 'package:flutter_hbb/consts.dart'; import 'package:flutter_hbb/desktop/pages/remote_page.dart'; import 'package:flutter_hbb/desktop/widgets/titlebar_widget.dart'; import 'package:flutter_hbb/utils/multi_window_manager.dart'; +import 'package:provider/provider.dart'; import 'package:get/get.dart'; import '../../models/model.dart'; @@ -70,6 +72,42 @@ class _ConnectionTabPageState extends State @override Widget build(BuildContext context) { + final tabBar = TabBar( + isScrollable: true, + labelColor: Colors.white, + physics: NeverScrollableScrollPhysics(), + indicatorColor: Colors.white, + tabs: connectionIds + .map((e) => Tab( + child: Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text(e), + SizedBox( + width: 4, + ), + InkWell( + onTap: () { + onRemoveId(e); + }, + child: Icon( + Icons.highlight_remove, + size: 20, + )) + ], + ), + )) + .toList()); + final tabBarView = TabBarView( + children: connectionIds + .map((e) => Container( + child: RemotePage( + key: ValueKey(e), + id: e, + tabBarHeight: kDesktopRemoteTabBarHeight, + ))) //RemotePage(key: ValueKey(e), id: e)) + .toList()); return Scaffold( body: DefaultTabController( initialIndex: initialIndex, @@ -78,43 +116,9 @@ class _ConnectionTabPageState extends State child: Column( children: [ DesktopTitleBar( - child: TabBar( - isScrollable: true, - labelColor: Colors.white, - physics: NeverScrollableScrollPhysics(), - indicatorColor: Colors.white, - tabs: connectionIds - .map((e) => Tab( - child: Row( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text(e), - SizedBox( - width: 4, - ), - InkWell( - onTap: () { - onRemoveId(e); - }, - child: Icon( - Icons.highlight_remove, - size: 20, - )) - ], - ), - )) - .toList()), + child: Container(height: kDesktopRemoteTabBarHeight, child: tabBar), ), - Expanded( - child: TabBarView( - children: connectionIds - .map((e) => Container( - child: RemotePage( - key: ValueKey(e), - id: e))) //RemotePage(key: ValueKey(e), id: e)) - .toList()), - ) + Expanded(child: tabBarView), ], ), ), diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index 3e4810c0e..ef5fb1c0b 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -16,6 +16,7 @@ import 'package:wakelock/wakelock.dart'; // import 'package:window_manager/window_manager.dart'; import '../../common.dart'; +import '../../consts.dart'; import '../../mobile/widgets/dialog.dart'; import '../../mobile/widgets/overlay.dart'; import '../../models/model.dart'; @@ -23,9 +24,11 @@ import '../../models/model.dart'; final initText = '\1' * 1024; class RemotePage extends StatefulWidget { - RemotePage({Key? key, required this.id}) : super(key: key); + RemotePage({Key? key, required this.id, required this.tabBarHeight}) + : super(key: key); final String id; + final double tabBarHeight; @override _RemotePageState createState() => _RemotePageState(); @@ -53,10 +56,12 @@ class _RemotePageState extends State @override void initState() { super.initState(); - final ffi = Get.put(FFI(), tag: widget.id); + var ffitmp = FFI(); + ffitmp.canvasModel.tabBarHeight = super.widget.tabBarHeight; + final ffi = Get.put(ffitmp, tag: widget.id); // note: a little trick ffi.ffiModel.platformFFI = gFFI.ffiModel.platformFFI; - ffi.connect(widget.id); + ffi.connect(widget.id, tabBarHeight: super.widget.tabBarHeight); WidgetsBinding.instance.addPostFrameCallback((_) { SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []); showLoading(translate('Connecting...')); @@ -236,11 +241,12 @@ class _RemotePageState extends State @override Widget build(BuildContext context) { super.build(context); + Provider.of(context, listen: false).tabBarHeight = + super.widget.tabBarHeight; final pi = Provider.of(context).pi; final hideKeyboard = isKeyboardShown() && _showEdit; final showActionButton = !_showBar || hideKeyboard; final keyboard = _ffi.ffiModel.permissions['keyboard'] != false; - return WillPopScope( onWillPop: () async { clientClose(); @@ -296,7 +302,6 @@ class _RemotePageState extends State Widget getRawPointerAndKeyBody(bool keyboard, Widget child) { return Listener( onPointerHover: (e) { - debugPrint("onPointerHover ${e}"); if (e.kind != ui.PointerDeviceKind.mouse) return; if (!_isPhysicalMouse) { setState(() { @@ -304,11 +309,11 @@ class _RemotePageState extends State }); } if (_isPhysicalMouse) { - _ffi.handleMouse(getEvent(e, 'mousemove')); + _ffi.handleMouse(getEvent(e, 'mousemove'), + tabBarHeight: super.widget.tabBarHeight); } }, onPointerDown: (e) { - debugPrint("onPointerDown ${e}"); if (e.kind != ui.PointerDeviceKind.mouse) { if (_isPhysicalMouse) { setState(() { @@ -317,25 +322,25 @@ class _RemotePageState extends State } } if (_isPhysicalMouse) { - _ffi.handleMouse(getEvent(e, 'mousedown')); + _ffi.handleMouse(getEvent(e, 'mousedown'), + tabBarHeight: super.widget.tabBarHeight); } }, onPointerUp: (e) { - debugPrint("onPointerUp ${e}"); if (e.kind != ui.PointerDeviceKind.mouse) return; if (_isPhysicalMouse) { - _ffi.handleMouse(getEvent(e, 'mouseup')); + _ffi.handleMouse(getEvent(e, 'mouseup'), + tabBarHeight: super.widget.tabBarHeight); } }, onPointerMove: (e) { - debugPrint("onPointerMove ${e}"); if (e.kind != ui.PointerDeviceKind.mouse) return; if (_isPhysicalMouse) { - _ffi.handleMouse(getEvent(e, 'mousemove')); + _ffi.handleMouse(getEvent(e, 'mousemove'), + tabBarHeight: super.widget.tabBarHeight); } }, onPointerSignal: (e) { - debugPrint("onPointerSignal ${e}"); if (e is PointerScrollEvent) { var dx = e.scrollDelta.dx; var dy = e.scrollDelta.dy; @@ -557,7 +562,7 @@ class _RemotePageState extends State void showActions(String id) async { final size = MediaQuery.of(context).size; final x = 120.0; - final y = size.height; + final y = size.height - super.widget.tabBarHeight; final more = >[]; final pi = _ffi.ffiModel.pi; final perms = _ffi.ffiModel.permissions; @@ -672,7 +677,6 @@ class _RemotePageState extends State if (!keyboard) { return SizedBox(); } - final size = MediaQuery.of(context).size; var wrap = (String text, void Function() onPressed, [bool? active, IconData? icon]) { return TextButton( @@ -788,7 +792,7 @@ class _RemotePageState extends State sendPrompt(widget.id, isMac, 'VK_S'); }), ]; - final space = size.width > 320 ? 4.0 : 2.0; + final space = MediaQuery.of(context).size.width > 320 ? 4.0 : 2.0; return Container( color: Color(0xAA000000), padding: EdgeInsets.only( diff --git a/flutter/lib/desktop/widgets/peer_widget.dart b/flutter/lib/desktop/widgets/peer_widget.dart index 45e2953eb..4705516f5 100644 --- a/flutter/lib/desktop/widgets/peer_widget.dart +++ b/flutter/lib/desktop/widgets/peer_widget.dart @@ -64,6 +64,11 @@ class _PeerWidgetState extends State<_PeerWidget> with WindowListener { _queryCoun = 0; } + @override + void onWindowMinimize() { + _queryCoun = _maxQueryCount; + } + @override Widget build(BuildContext context) { final space = 8.0; @@ -110,19 +115,23 @@ class _PeerWidgetState extends State<_PeerWidget> with WindowListener { final now = DateTime.now(); if (!setEquals(_curPeers, _lastQueryPeers)) { if (now.difference(_lastChangeTime) > Duration(seconds: 1)) { - gFFI.ffiModel.platformFFI.ffiBind - .queryOnlines(ids: _curPeers.toList(growable: false)); - _lastQueryPeers = {..._curPeers}; - _lastQueryTime = DateTime.now(); - _queryCoun = 0; + if (_curPeers.length > 0) { + gFFI.ffiModel.platformFFI.ffiBind + .queryOnlines(ids: _curPeers.toList(growable: false)); + _lastQueryPeers = {..._curPeers}; + _lastQueryTime = DateTime.now(); + _queryCoun = 0; + } } } else { if (_queryCoun < _maxQueryCount) { if (now.difference(_lastQueryTime) > Duration(seconds: 20)) { - gFFI.ffiModel.platformFFI.ffiBind - .queryOnlines(ids: _curPeers.toList(growable: false)); - _lastQueryTime = DateTime.now(); - _queryCoun += 1; + if (_curPeers.length > 0) { + gFFI.ffiModel.platformFFI.ffiBind + .queryOnlines(ids: _curPeers.toList(growable: false)); + _lastQueryTime = DateTime.now(); + _queryCoun += 1; + } } } } @@ -193,7 +202,6 @@ class DiscoveredPeerWidget extends BasePeerWidget { @override Widget build(BuildContext context) { - debugPrint("DiscoveredPeerWidget build"); final widget = super.build(context); gFFI.bind.mainLoadLanPeers(); return widget; diff --git a/flutter/lib/desktop/widgets/peercard_widget.dart b/flutter/lib/desktop/widgets/peercard_widget.dart index 39acd0bf2..3a4dbfada 100644 --- a/flutter/lib/desktop/widgets/peercard_widget.dart +++ b/flutter/lib/desktop/widgets/peercard_widget.dart @@ -405,7 +405,6 @@ class RecentPeerCard extends BasePeerCard { : super(peer: peer, key: key, type: PeerType.recent); Future>> _getPopupMenuItems() async { - debugPrint("call RecentPeerCard _getPopupMenuItems"); return [ PopupMenuItem( child: Text(translate('Connect')), value: 'connect'), @@ -427,7 +426,6 @@ class FavoritePeerCard extends BasePeerCard { : super(peer: peer, key: key, type: PeerType.fav); Future>> _getPopupMenuItems() async { - debugPrint("call FavoritePeerCard _getPopupMenuItems"); return [ PopupMenuItem( child: Text(translate('Connect')), value: 'connect'), @@ -451,7 +449,6 @@ class DiscoveredPeerCard extends BasePeerCard { : super(peer: peer, key: key, type: PeerType.discovered); Future>> _getPopupMenuItems() async { - debugPrint("call DiscoveredPeerCard _getPopupMenuItems"); return [ PopupMenuItem( child: Text(translate('Connect')), value: 'connect'), @@ -473,7 +470,6 @@ class AddressBookPeerCard extends BasePeerCard { : super(peer: peer, key: key, type: PeerType.ab); Future>> _getPopupMenuItems() async { - debugPrint("call AddressBookPeerCard _getPopupMenuItems"); return [ PopupMenuItem( child: Text(translate('Connect')), value: 'connect'), diff --git a/flutter/lib/desktop/widgets/titlebar_widget.dart b/flutter/lib/desktop/widgets/titlebar_widget.dart index 6e9b0bf6e..475b4cb86 100644 --- a/flutter/lib/desktop/widgets/titlebar_widget.dart +++ b/flutter/lib/desktop/widgets/titlebar_widget.dart @@ -22,7 +22,8 @@ class DesktopTitleBar extends StatelessWidget { child: Row( children: [ Expanded( - child: child ?? Offstage(),) + child: child ?? Offstage(), + ) // const WindowButtons() ], ), diff --git a/flutter/lib/mobile/pages/connection_page.dart b/flutter/lib/mobile/pages/connection_page.dart index 9ae0f3766..9722b1a47 100644 --- a/flutter/lib/mobile/pages/connection_page.dart +++ b/flutter/lib/mobile/pages/connection_page.dart @@ -213,13 +213,13 @@ class _ConnectionPageState extends State { /// Get all the saved peers. Widget getPeers() { - final size = MediaQuery.of(context).size; + final windowWidth = MediaQuery.of(context).size.width; final space = 8.0; - var width = size.width - 2 * space; + var width = windowWidth - 2 * space; final minWidth = 320.0; - if (size.width > minWidth + 2 * space) { - final n = (size.width / (minWidth + 2 * space)).floor(); - width = size.width / n - 2 * space; + if (windowWidth > minWidth + 2 * space) { + final n = (windowWidth / (minWidth + 2 * space)).floor(); + width = windowWidth / n - 2 * space; } final cards = []; var peers = gFFI.peers(); diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index e9367bd4c..11415eeef 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -349,7 +349,7 @@ class ImageModel with ChangeNotifier { ImageModel(this.parent); - void onRgba(Uint8List rgba) { + void onRgba(Uint8List rgba, double tabBarHeight) { if (_waitForImage) { _waitForImage = false; SmartDialog.dismiss(); @@ -363,22 +363,24 @@ class ImageModel with ChangeNotifier { if (parent.target?.id != pid) return; try { // my throw exception, because the listener maybe already dispose - update(image); + update(image, tabBarHeight); } catch (e) { print('update image: $e'); } }); } - void update(ui.Image? image) { + void update(ui.Image? image, double tabBarHeight) { if (_image == null && image != null) { if (isWebDesktop) { parent.target?.canvasModel.updateViewStyle(); } else { final size = MediaQueryData.fromWindow(ui.window).size; - final xscale = size.width / image.width; - final yscale = size.height / image.height; - parent.target?.canvasModel.scale = max(xscale, yscale); + final canvasWidth = size.width; + final canvasHeight = size.height - tabBarHeight; + final xscale = canvasWidth / image.width; + final yscale = canvasHeight / image.height; + parent.target?.canvasModel.scale = min(xscale, yscale); } if (parent.target != null) { initializeCursorAndCanvas(parent.target!); @@ -395,6 +397,8 @@ class ImageModel with ChangeNotifier { if (image != null) notifyListeners(); } + // mobile only + // for desktop, height should minus tabbar height double get maxScale { if (_image == null) return 1.5; final size = MediaQueryData.fromWindow(ui.window).size; @@ -403,6 +407,8 @@ class ImageModel with ChangeNotifier { return max(1.5, max(xscale, yscale)); } + // mobile only + // for desktop, height should minus tabbar height double get minScale { if (_image == null) return 1.5; final size = MediaQueryData.fromWindow(ui.window).size; @@ -416,6 +422,7 @@ class CanvasModel with ChangeNotifier { double _x = 0; double _y = 0; double _scale = 1.0; + double _tabBarHeight = 0.0; String id = ""; // TODO multi canvas model WeakReference parent; @@ -428,6 +435,9 @@ class CanvasModel with ChangeNotifier { double get scale => _scale; + set tabBarHeight(double h) => _tabBarHeight = h; + double get tabBarHeight => _tabBarHeight; + void updateViewStyle() async { final s = await parent.target?.bind.getSessionOption(id: id, arg: 'view-style'); @@ -435,8 +445,10 @@ class CanvasModel with ChangeNotifier { return; } final size = MediaQueryData.fromWindow(ui.window).size; - final s1 = size.width / (parent.target?.ffiModel.display.width ?? 720); - final s2 = size.height / (parent.target?.ffiModel.display.height ?? 1280); + final canvasWidth = size.width; + final canvasHeight = size.height - _tabBarHeight; + final s1 = canvasWidth / (parent.target?.ffiModel.display.width ?? 720); + final s2 = canvasHeight / (parent.target?.ffiModel.display.height ?? 1280); // Closure to perform shrink operation. final shrinkOp = () { final s = s1 < s2 ? s1 : s2; @@ -467,8 +479,8 @@ class CanvasModel with ChangeNotifier { defaultOp(); } } - _x = (size.width - getDisplayWidth() * _scale) / 2; - _y = (size.height - getDisplayHeight() * _scale) / 2; + _x = (canvasWidth - getDisplayWidth() * _scale) / 2; + _y = (canvasHeight - getDisplayHeight() * _scale) / 2; notifyListeners(); } @@ -491,15 +503,17 @@ class CanvasModel with ChangeNotifier { // On mobile platforms, move the canvas with the cursor. if (!isDesktop) { final size = MediaQueryData.fromWindow(ui.window).size; + final canvasWidth = size.width; + final canvasHeight = size.height - _tabBarHeight; final dw = getDisplayWidth() * _scale; final dh = getDisplayHeight() * _scale; var dxOffset = 0; var dyOffset = 0; - if (dw > size.width) { - dxOffset = (x - dw * (x / size.width) - _x).toInt(); + if (dw > canvasWidth) { + dxOffset = (x - dw * (x / canvasWidth) - _x).toInt(); } - if (dh > size.height) { - dyOffset = (y - dh * (y / size.height) - _y).toInt(); + if (dh > canvasHeight) { + dyOffset = (y - dh * (y / canvasHeight) - _y).toInt(); } _x += dxOffset; _y += dyOffset; @@ -524,8 +538,11 @@ class CanvasModel with ChangeNotifier { if (isWebDesktop) { updateViewStyle(); } else { - _x = 0; - _y = 0; + final size = MediaQueryData.fromWindow(ui.window).size; + final canvasWidth = size.width; + final canvasHeight = size.height - _tabBarHeight; + _x = (canvasWidth - getDisplayWidth() * _scale) / 2; + _y = (canvasHeight - getDisplayHeight() * _scale) / 2; } notifyListeners(); } @@ -933,7 +950,8 @@ class FFI { } /// Connect with the given [id]. Only transfer file if [isFileTransfer]. - void connect(String id, {bool isFileTransfer = false}) { + void connect(String id, + {bool isFileTransfer = false, double tabBarHeight = 0.0}) { if (!isFileTransfer) { chatModel.resetClientMode(); canvasModel.id = id; @@ -954,7 +972,7 @@ class FFI { print('json.decode fail(): $e'); } } else if (message is Rgba) { - imageModel.onRgba(message.field0); + imageModel.onRgba(message.field0, tabBarHeight); } } }(); @@ -979,7 +997,7 @@ class FFI { } bind.sessionClose(id: id); id = ""; - imageModel.update(null); + imageModel.update(null, 0.0); cursorModel.clear(); ffiModel.clear(); canvasModel.clear(); @@ -1027,8 +1045,7 @@ class FFI { RustdeskImpl get bind => ffiModel.platformFFI.ffiBind; - handleMouse(Map evt) { - debugPrint("mouse ${evt.toString()}"); + handleMouse(Map evt, {double tabBarHeight = 0.0}) { var type = ''; var isMove = false; switch (evt['type']) { @@ -1046,7 +1063,7 @@ class FFI { } evt['type'] = type; var x = evt['x']; - var y = max(0.0, (evt['y'] as double) - 50.0); + var y = max(0.0, (evt['y'] as double) - tabBarHeight); if (isMove) { canvasModel.moveDesktopMouse(x, y); } diff --git a/src/lan.rs b/src/lan.rs index f74492b8e..30af1de6b 100644 --- a/src/lan.rs +++ b/src/lan.rs @@ -276,10 +276,9 @@ async fn handle_received_peers(mut rx: UnboundedReceiver) peers.insert(0, peer); if last_write_time.elapsed().as_millis() > 300 { config::LanPeers::store(&peers); - last_write_time = Instant::now(); - #[cfg(feature = "flutter")] crate::flutter_ffi::main_load_lan_peers(); + last_write_time = Instant::now(); } } None => { @@ -290,5 +289,7 @@ async fn handle_received_peers(mut rx: UnboundedReceiver) } config::LanPeers::store(&peers); + #[cfg(feature = "flutter")] + crate::flutter_ffi::main_load_lan_peers(); Ok(()) }