flutter_desktop: adjust window

Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
fufesou 2022-10-08 17:27:30 +08:00
parent 1719b4735d
commit 03439831a7
6 changed files with 112 additions and 21 deletions

View File

@ -179,3 +179,25 @@ class RemoteCursorMovedState {
static RxBool find(String id) => Get.find<RxBool>(tag: tag(id));
}
class RemoteCountState {
static String tag() => 'remote_count_';
static void init() {
final key = tag();
if (!Get.isRegistered(tag: key)) {
// Server side, default true
final RxInt state = 1.obs;
Get.put(state, tag: key);
}
}
static void delete() {
final key = tag();
if (Get.isRegistered(tag: key)) {
Get.delete(tag: key);
}
}
static RxInt find() => Get.find<RxInt>(tag: tag());
}

View File

@ -9,6 +9,8 @@ import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart';
import 'package:get/get.dart';
import 'package:window_manager/window_manager.dart';
import '../../common/shared_state.dart';
class DesktopTabPage extends StatefulWidget {
const DesktopTabPage({Key? key}) : super(key: key);
@ -40,6 +42,7 @@ class _DesktopTabPageState extends State<DesktopTabPage> {
void initState() {
super.initState();
Get.put<DesktopTabController>(tabController);
RemoteCountState.init();
tabController.add(TabInfo(
key: kTabLabelHomePage,
label: kTabLabelHomePage,

View File

@ -28,11 +28,13 @@ class RemotePage extends StatefulWidget {
const RemotePage({
Key? key,
required this.id,
required this.windowId,
required this.tabBarHeight,
required this.windowBorderWidth,
}) : super(key: key);
final String id;
final int windowId;
final double tabBarHeight;
final double windowBorderWidth;
@ -239,6 +241,7 @@ class _RemotePageState extends State<RemotePage>
paints.add(QualityMonitor(_ffi.qualityMonitorModel));
paints.add(RemoteMenubar(
id: widget.id,
windowId: widget.windowId,
ffi: _ffi,
onEnterOrLeaveImageSetter: (func) => _onEnterOrLeaveImage4Menubar = func,
onEnterOrLeaveImageCleaner: () => _onEnterOrLeaveImage4Menubar = null,

View File

@ -32,6 +32,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
var connectionMap = RxList<Widget>.empty(growable: true);
_ConnectionTabPageState(Map<String, dynamic> params) {
RemoteCountState.init();
final RxBool fullscreen = Get.find(tag: 'fullscreen');
final peerId = params['id'];
if (peerId != null) {
@ -45,10 +46,12 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
page: Obx(() => RemotePage(
key: ValueKey(peerId),
id: peerId,
windowId: windowId(),
tabBarHeight:
fullscreen.isTrue ? 0 : kDesktopRemoteTabBarHeight,
windowBorderWidth: fullscreen.isTrue ? 0 : kWindowBorderWidth,
))));
_update_remote_count();
}
}
@ -79,6 +82,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
page: Obx(() => RemotePage(
key: ValueKey(id),
id: id,
windowId: windowId(),
tabBarHeight:
fullscreen.isTrue ? 0 : kDesktopRemoteTabBarHeight,
windowBorderWidth: fullscreen.isTrue ? 0 : kWindowBorderWidth,
@ -86,6 +90,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
} else if (call.method == "onDestroy") {
tabController.clear();
}
_update_remote_count();
});
}
@ -161,6 +166,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
WindowController.fromWindowId(windowId()).hide();
}
ConnectionTypeState.delete(id);
_update_remote_count();
}
int windowId() {
@ -178,7 +184,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
}
Future<bool> handleWindowCloseButton() async {
final connLength = tabController.state.value.tabs.length;
final connLength = tabController.length;
if (connLength < 1) {
return true;
} else if (connLength == 1) {
@ -189,8 +195,12 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
final res = await closeConfirmDialog();
if (res) {
tabController.clear();
_update_remote_count();
}
return res;
}
}
_update_remote_count() =>
RemoteCountState.find().value = tabController.length;
}

View File

@ -8,6 +8,7 @@ import 'package:flutter_hbb/models/chat_model.dart';
import 'package:get/get.dart';
import 'package:provider/provider.dart';
import 'package:rxdart/rxdart.dart' as rxdart;
import 'package:desktop_multi_window/desktop_multi_window.dart';
import '../../common.dart';
import '../../mobile/widgets/dialog.dart';
@ -26,6 +27,7 @@ class _MenubarTheme {
class RemoteMenubar extends StatefulWidget {
final String id;
final int windowId;
final FFI ffi;
final Function(Function(bool)) onEnterOrLeaveImageSetter;
final Function() onEnterOrLeaveImageCleaner;
@ -33,6 +35,7 @@ class RemoteMenubar extends StatefulWidget {
const RemoteMenubar({
Key? key,
required this.id,
required this.windowId,
required this.ffi,
required this.onEnterOrLeaveImageSetter,
required this.onEnterOrLeaveImageCleaner,
@ -306,25 +309,29 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
return {'supportedHwcodec': supportedHwcodec};
}(), builder: (context, snapshot) {
if (snapshot.hasData) {
return mod_menu.PopupMenuButton(
padding: EdgeInsets.zero,
icon: const Icon(
Icons.tv,
color: _MenubarTheme.commonColor,
),
tooltip: translate('Display Settings'),
position: mod_menu.PopupMenuPosition.under,
itemBuilder: (BuildContext context) => _getDisplayMenu(snapshot.data!)
.map((entry) => entry.build(
context,
const MenuConfig(
commonColor: _MenubarTheme.commonColor,
height: _MenubarTheme.height,
dividerHeight: _MenubarTheme.dividerHeight,
)))
.expand((i) => i)
.toList(),
);
return Obx(() {
final remoteCount = RemoteCountState.find().value;
return mod_menu.PopupMenuButton(
padding: EdgeInsets.zero,
icon: const Icon(
Icons.tv,
color: _MenubarTheme.commonColor,
),
tooltip: translate('Display Settings'),
position: mod_menu.PopupMenuPosition.under,
itemBuilder: (BuildContext context) =>
_getDisplayMenu(snapshot.data!, remoteCount)
.map((entry) => entry.build(
context,
const MenuConfig(
commonColor: _MenubarTheme.commonColor,
height: _MenubarTheme.height,
dividerHeight: _MenubarTheme.dividerHeight,
)))
.expand((i) => i)
.toList(),
);
});
} else {
return const Offstage();
}
@ -586,7 +593,15 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
return displayMenu;
}
List<MenuEntryBase<String>> _getDisplayMenu(dynamic futureData) {
bool _isWindowCanBeAdjusted(int remoteCount) {
final RxBool fullscreen = Get.find(tag: 'fullscreen');
return remoteCount == 1 &&
fullscreen.isFalse &&
widget.ffi.canvasModel.scale > 1.0;
}
List<MenuEntryBase<String>> _getDisplayMenu(
dynamic futureData, int remoteCount) {
const EdgeInsets padding = EdgeInsets.only(left: 18.0, right: 8.0);
final displayMenu = [
MenuEntryRadios<String>(
@ -739,6 +754,42 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
MenuEntryDivider<String>(),
];
if (_isWindowCanBeAdjusted(remoteCount)) {
displayMenu.insert(
0,
MenuEntryDivider<String>(),
);
displayMenu.insert(
0,
MenuEntryButton<String>(
childBuilder: (TextStyle? style) => Container(
alignment: AlignmentDirectional.center,
height: _MenubarTheme.height,
child: Text(
translate('Adjust Window'),
style: style,
)),
proc: () {
() async {
final wndRect =
await WindowController.fromWindowId(widget.windowId)
.getFrame();
final canvasModel = widget.ffi.canvasModel;
final width =
canvasModel.size.width + canvasModel.windowBorderWidth * 2;
final height = canvasModel.size.height +
canvasModel.tabBarHeight +
canvasModel.windowBorderWidth * 2;
await WindowController.fromWindowId(widget.windowId).setFrame(
Rect.fromLTWH(wndRect.left, wndRect.top, width, height));
}();
},
padding: padding,
dismissOnClicked: true,
),
);
}
/// Show Codec Preference
if (bind.mainHasHwcodec()) {
final List<bool> codecs = [];

View File

@ -69,6 +69,8 @@ class DesktopTabController {
DesktopTabController({required this.tabType});
int get length => state.value.tabs.length;
void add(TabInfo tab, {bool authorized = false}) {
if (!isDesktop) return;
final index = state.value.tabs.indexWhere((e) => e.key == tab.key);