Merge pull request #1167 from fufesou/flutter_desktop_connection_3

flutter_desktop: fix canvas height - tabBarHeight
This commit is contained in:
RustDesk 2022-08-03 15:46:08 +08:00 committed by GitHub
commit d3bc0ca073
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 130 additions and 96 deletions

1
flutter/lib/consts.dart Normal file
View File

@ -0,0 +1 @@
double kDesktopRemoteTabBarHeight = 48.0;

View File

@ -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();

View File

@ -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<ConnectionTabPage>
@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<ConnectionTabPage>
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),
],
),
),

View File

@ -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<RemotePage>
@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<RemotePage>
@override
Widget build(BuildContext context) {
super.build(context);
Provider.of<CanvasModel>(context, listen: false).tabBarHeight =
super.widget.tabBarHeight;
final pi = Provider.of<FfiModel>(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<RemotePage>
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<RemotePage>
});
}
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<RemotePage>
}
}
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<RemotePage>
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 = <PopupMenuItem<String>>[];
final pi = _ffi.ffiModel.pi;
final perms = _ffi.ffiModel.permissions;
@ -672,7 +677,6 @@ class _RemotePageState extends State<RemotePage>
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<RemotePage>
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(

View File

@ -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;

View File

@ -405,7 +405,6 @@ class RecentPeerCard extends BasePeerCard {
: super(peer: peer, key: key, type: PeerType.recent);
Future<List<PopupMenuItem<String>>> _getPopupMenuItems() async {
debugPrint("call RecentPeerCard _getPopupMenuItems");
return [
PopupMenuItem<String>(
child: Text(translate('Connect')), value: 'connect'),
@ -427,7 +426,6 @@ class FavoritePeerCard extends BasePeerCard {
: super(peer: peer, key: key, type: PeerType.fav);
Future<List<PopupMenuItem<String>>> _getPopupMenuItems() async {
debugPrint("call FavoritePeerCard _getPopupMenuItems");
return [
PopupMenuItem<String>(
child: Text(translate('Connect')), value: 'connect'),
@ -451,7 +449,6 @@ class DiscoveredPeerCard extends BasePeerCard {
: super(peer: peer, key: key, type: PeerType.discovered);
Future<List<PopupMenuItem<String>>> _getPopupMenuItems() async {
debugPrint("call DiscoveredPeerCard _getPopupMenuItems");
return [
PopupMenuItem<String>(
child: Text(translate('Connect')), value: 'connect'),
@ -473,7 +470,6 @@ class AddressBookPeerCard extends BasePeerCard {
: super(peer: peer, key: key, type: PeerType.ab);
Future<List<PopupMenuItem<String>>> _getPopupMenuItems() async {
debugPrint("call AddressBookPeerCard _getPopupMenuItems");
return [
PopupMenuItem<String>(
child: Text(translate('Connect')), value: 'connect'),

View File

@ -22,7 +22,8 @@ class DesktopTitleBar extends StatelessWidget {
child: Row(
children: [
Expanded(
child: child ?? Offstage(),)
child: child ?? Offstage(),
)
// const WindowButtons()
],
),

View File

@ -213,13 +213,13 @@ class _ConnectionPageState extends State<ConnectionPage> {
/// 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 = <Widget>[];
var peers = gFFI.peers();

View File

@ -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<FFI> 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<String, dynamic> evt) {
debugPrint("mouse ${evt.toString()}");
handleMouse(Map<String, dynamic> 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);
}

View File

@ -276,10 +276,9 @@ async fn handle_received_peers(mut rx: UnboundedReceiver<config::DiscoveryPeer>)
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::DiscoveryPeer>)
}
config::LanPeers::store(&peers);
#[cfg(feature = "flutter")]
crate::flutter_ffi::main_load_lan_peers();
Ok(())
}