| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | import 'dart:convert'; | 
					
						
							| 
									
										
										
										
											2022-09-19 10:14:14 +08:00
										 |  |  | import 'dart:io'; | 
					
						
							| 
									
										
										
										
											2022-11-03 21:58:25 +08:00
										 |  |  | import 'dart:ui' as ui; | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-09 16:37:11 +08:00
										 |  |  | import 'package:desktop_multi_window/desktop_multi_window.dart'; | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | import 'package:flutter/material.dart'; | 
					
						
							| 
									
										
										
										
											2022-06-28 22:04:10 +08:00
										 |  |  | import 'package:flutter_hbb/common.dart'; | 
					
						
							| 
									
										
										
										
											2022-08-29 18:48:12 +08:00
										 |  |  | import 'package:flutter_hbb/common/shared_state.dart'; | 
					
						
							| 
									
										
										
										
											2022-08-03 15:31:19 +08:00
										 |  |  | import 'package:flutter_hbb/consts.dart'; | 
					
						
							| 
									
										
										
										
											2022-11-01 18:16:52 +08:00
										 |  |  | import 'package:flutter_hbb/models/state_model.dart'; | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | import 'package:flutter_hbb/desktop/pages/remote_page.dart'; | 
					
						
							| 
									
										
										
										
											2022-11-10 14:32:22 +08:00
										 |  |  | import 'package:flutter_hbb/desktop/widgets/remote_menubar.dart'; | 
					
						
							| 
									
										
										
										
											2022-08-06 17:08:48 +08:00
										 |  |  | import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart'; | 
					
						
							| 
									
										
										
										
											2022-11-03 21:58:25 +08:00
										 |  |  | import 'package:flutter_hbb/desktop/widgets/material_mod_popup_menu.dart' | 
					
						
							|  |  |  |     as mod_menu; | 
					
						
							|  |  |  | import 'package:flutter_hbb/desktop/widgets/popup_menu.dart'; | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | import 'package:flutter_hbb/utils/multi_window_manager.dart'; | 
					
						
							| 
									
										
										
										
											2022-09-27 19:42:05 +08:00
										 |  |  | import 'package:flutter_svg/flutter_svg.dart'; | 
					
						
							| 
									
										
										
										
											2022-06-28 22:04:10 +08:00
										 |  |  | import 'package:get/get.dart'; | 
					
						
							| 
									
										
										
										
											2022-11-03 21:58:25 +08:00
										 |  |  | import 'package:bot_toast/bot_toast.dart'; | 
					
						
							| 
									
										
										
										
											2022-06-28 22:04:10 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-13 21:19:05 +09:00
										 |  |  | import '../../models/platform_model.dart'; | 
					
						
							| 
									
										
										
										
											2022-09-08 19:26:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-03 21:58:25 +08:00
										 |  |  | class _MenuTheme { | 
					
						
							|  |  |  |   static const Color commonColor = MyTheme.accent; | 
					
						
							|  |  |  |   // kMinInteractiveDimension
 | 
					
						
							|  |  |  |   static const double height = 20.0; | 
					
						
							|  |  |  |   static const double dividerHeight = 12.0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | class ConnectionTabPage extends StatefulWidget { | 
					
						
							|  |  |  |   final Map<String, dynamic> params; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const ConnectionTabPage({Key? key, required this.params}) : super(key: key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   State<ConnectionTabPage> createState() => _ConnectionTabPageState(params); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 10:54:09 +08:00
										 |  |  | class _ConnectionTabPageState extends State<ConnectionTabPage> { | 
					
						
							| 
									
										
										
										
											2022-10-27 15:52:40 +08:00
										 |  |  |   final tabController = Get.put(DesktopTabController( | 
					
						
							| 
									
										
										
										
											2023-01-23 22:07:50 +08:00
										 |  |  |       tabType: DesktopTabType.remoteScreen)); | 
					
						
							| 
									
										
										
										
											2022-08-29 18:48:12 +08:00
										 |  |  |   static const IconData selectedIcon = Icons.desktop_windows_sharp; | 
					
						
							|  |  |  |   static const IconData unselectedIcon = Icons.desktop_windows_outlined; | 
					
						
							| 
									
										
										
										
											2022-08-05 10:27:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-10 14:32:22 +08:00
										 |  |  |   late MenubarState _menubarState; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-05 10:27:06 +08:00
										 |  |  |   var connectionMap = RxList<Widget>.empty(growable: true); | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   _ConnectionTabPageState(Map<String, dynamic> params) { | 
					
						
							| 
									
										
										
										
											2022-11-10 14:32:22 +08:00
										 |  |  |     _menubarState = MenubarState(); | 
					
						
							| 
									
										
										
										
											2022-10-08 17:27:30 +08:00
										 |  |  |     RemoteCountState.init(); | 
					
						
							| 
									
										
										
										
											2022-08-29 22:46:19 +08:00
										 |  |  |     final peerId = params['id']; | 
					
						
							|  |  |  |     if (peerId != null) { | 
					
						
							|  |  |  |       ConnectionTypeState.init(peerId); | 
					
						
							| 
									
										
										
										
											2023-01-23 22:07:50 +08:00
										 |  |  |       tabController.onSelected = (_, id) { | 
					
						
							|  |  |  |         bind.setCurSessionId(id: id); | 
					
						
							|  |  |  |         WindowController.fromWindowId(windowId()) | 
					
						
							|  |  |  |             .setTitle(getWindowNameWithId(id)); | 
					
						
							|  |  |  |       }; | 
					
						
							| 
									
										
										
										
											2022-08-26 12:14:14 +08:00
										 |  |  |       tabController.add(TabInfo( | 
					
						
							| 
									
										
										
										
											2022-11-01 17:01:43 +08:00
										 |  |  |         key: peerId, | 
					
						
							|  |  |  |         label: peerId, | 
					
						
							|  |  |  |         selectedIcon: selectedIcon, | 
					
						
							|  |  |  |         unselectedIcon: unselectedIcon, | 
					
						
							|  |  |  |         onTabCloseButton: () => tabController.closeBy(peerId), | 
					
						
							|  |  |  |         page: RemotePage( | 
					
						
							|  |  |  |           key: ValueKey(peerId), | 
					
						
							|  |  |  |           id: peerId, | 
					
						
							| 
									
										
										
										
											2022-11-10 14:32:22 +08:00
										 |  |  |           menubarState: _menubarState, | 
					
						
							| 
									
										
										
										
											2023-01-17 13:28:33 +08:00
										 |  |  |           switchUuid: params['switch_uuid'], | 
					
						
							| 
									
										
										
										
											2022-11-01 17:01:43 +08:00
										 |  |  |         ), | 
					
						
							|  |  |  |       )); | 
					
						
							| 
									
										
										
										
											2022-10-08 17:27:30 +08:00
										 |  |  |       _update_remote_count(); | 
					
						
							| 
									
										
										
										
											2022-05-31 16:27:54 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   void initState() { | 
					
						
							|  |  |  |     super.initState(); | 
					
						
							| 
									
										
										
										
											2022-08-24 20:56:42 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-27 10:56:14 +08:00
										 |  |  |     tabController.onRemoved = (_, id) => onRemoveId(id); | 
					
						
							| 
									
										
										
										
											2023-01-23 22:07:50 +08:00
										 |  |  |     | 
					
						
							| 
									
										
										
										
											2022-08-24 20:56:42 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  |     rustDeskWinManager.setMethodHandler((call, fromWindowId) async { | 
					
						
							|  |  |  |       print( | 
					
						
							| 
									
										
										
										
											2022-11-05 23:41:22 +08:00
										 |  |  |           "[Remote Page] call ${call.method} with args ${call.arguments} from window $fromWindowId"); | 
					
						
							| 
									
										
										
										
											2022-08-26 23:28:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  |       // for simplify, just replace connectionId
 | 
					
						
							|  |  |  |       if (call.method == "new_remote_desktop") { | 
					
						
							| 
									
										
										
										
											2022-08-05 10:27:06 +08:00
										 |  |  |         final args = jsonDecode(call.arguments); | 
					
						
							|  |  |  |         final id = args['id']; | 
					
						
							| 
									
										
										
										
											2023-01-17 13:28:33 +08:00
										 |  |  |         final switchUuid = args['switch_uuid']; | 
					
						
							| 
									
										
										
										
											2022-08-09 19:32:19 +08:00
										 |  |  |         window_on_top(windowId()); | 
					
						
							| 
									
										
										
										
											2022-08-31 18:41:55 +08:00
										 |  |  |         ConnectionTypeState.init(id); | 
					
						
							| 
									
										
										
										
											2022-08-24 20:56:42 +08:00
										 |  |  |         tabController.add(TabInfo( | 
					
						
							| 
									
										
										
										
											2022-11-01 17:01:43 +08:00
										 |  |  |           key: id, | 
					
						
							|  |  |  |           label: id, | 
					
						
							|  |  |  |           selectedIcon: selectedIcon, | 
					
						
							|  |  |  |           unselectedIcon: unselectedIcon, | 
					
						
							|  |  |  |           onTabCloseButton: () => tabController.closeBy(id), | 
					
						
							| 
									
										
										
										
											2022-11-10 14:32:22 +08:00
										 |  |  |           page: RemotePage( | 
					
						
							|  |  |  |             key: ValueKey(id), | 
					
						
							|  |  |  |             id: id, | 
					
						
							|  |  |  |             menubarState: _menubarState, | 
					
						
							| 
									
										
										
										
											2023-01-17 13:28:33 +08:00
										 |  |  |             switchUuid: switchUuid, | 
					
						
							| 
									
										
										
										
											2022-11-10 14:32:22 +08:00
										 |  |  |           ), | 
					
						
							| 
									
										
										
										
											2022-11-01 17:01:43 +08:00
										 |  |  |         )); | 
					
						
							| 
									
										
										
										
											2022-06-28 22:04:10 +08:00
										 |  |  |       } else if (call.method == "onDestroy") { | 
					
						
							| 
									
										
										
										
											2022-08-30 20:48:03 +08:00
										 |  |  |         tabController.clear(); | 
					
						
							| 
									
										
										
										
											2022-10-26 14:39:13 +08:00
										 |  |  |       } else if (call.method == kWindowActionRebuild) { | 
					
						
							|  |  |  |         reloadCurrentWindow(); | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2022-10-08 17:27:30 +08:00
										 |  |  |       _update_remote_count(); | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-10 14:32:22 +08:00
										 |  |  |   @override | 
					
						
							|  |  |  |   void dispose() { | 
					
						
							|  |  |  |     super.dispose(); | 
					
						
							|  |  |  |     _menubarState.save(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							| 
									
										
										
										
											2022-11-16 19:49:52 +08:00
										 |  |  |     final tabWidget = Obx( | 
					
						
							|  |  |  |       () => Container( | 
					
						
							|  |  |  |         decoration: BoxDecoration( | 
					
						
							| 
									
										
										
										
											2022-10-04 21:19:31 +08:00
										 |  |  |           border: Border.all( | 
					
						
							|  |  |  |               color: MyTheme.color(context).border!, | 
					
						
							| 
									
										
										
										
											2022-11-16 19:49:52 +08:00
										 |  |  |               width: stateGlobal.windowBorderWidth.value), | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |         child: Scaffold( | 
					
						
							| 
									
										
										
										
											2022-09-23 16:31:50 +08:00
										 |  |  |           backgroundColor: Theme.of(context).backgroundColor, | 
					
						
							| 
									
										
										
										
											2022-11-01 17:01:43 +08:00
										 |  |  |           body: DesktopTab( | 
					
						
							|  |  |  |             controller: tabController, | 
					
						
							|  |  |  |             onWindowCloseButton: handleWindowCloseButton, | 
					
						
							|  |  |  |             tail: const AddButton().paddingOnly(left: 10), | 
					
						
							|  |  |  |             pageViewBuilder: (pageView) => pageView, | 
					
						
							| 
									
										
										
										
											2022-11-12 22:33:10 +08:00
										 |  |  |             labelGetter: DesktopTab.labelGetterAlias, | 
					
						
							| 
									
										
										
										
											2022-11-01 17:01:43 +08:00
										 |  |  |             tabBuilder: (key, icon, label, themeConf) => Obx(() { | 
					
						
							|  |  |  |               final connectionType = ConnectionTypeState.find(key); | 
					
						
							|  |  |  |               if (!connectionType.isValid()) { | 
					
						
							|  |  |  |                 return Row( | 
					
						
							|  |  |  |                   mainAxisAlignment: MainAxisAlignment.center, | 
					
						
							|  |  |  |                   children: [ | 
					
						
							|  |  |  |                     icon, | 
					
						
							|  |  |  |                     label, | 
					
						
							|  |  |  |                   ], | 
					
						
							|  |  |  |                 ); | 
					
						
							|  |  |  |               } else { | 
					
						
							|  |  |  |                 final msgDirect = translate( | 
					
						
							|  |  |  |                     connectionType.direct.value == ConnectionType.strDirect | 
					
						
							|  |  |  |                         ? 'Direct Connection' | 
					
						
							|  |  |  |                         : 'Relay Connection'); | 
					
						
							|  |  |  |                 final msgSecure = translate( | 
					
						
							|  |  |  |                     connectionType.secure.value == ConnectionType.strSecure | 
					
						
							|  |  |  |                         ? 'Secure Connection' | 
					
						
							|  |  |  |                         : 'Insecure Connection'); | 
					
						
							| 
									
										
										
										
											2022-11-03 21:58:25 +08:00
										 |  |  |                 final tab = Row( | 
					
						
							| 
									
										
										
										
											2022-11-01 17:01:43 +08:00
										 |  |  |                   mainAxisAlignment: MainAxisAlignment.center, | 
					
						
							|  |  |  |                   children: [ | 
					
						
							|  |  |  |                     icon, | 
					
						
							|  |  |  |                     Tooltip( | 
					
						
							|  |  |  |                       message: '$msgDirect\n$msgSecure', | 
					
						
							|  |  |  |                       child: SvgPicture.asset( | 
					
						
							|  |  |  |                         'assets/${connectionType.secure.value}${connectionType.direct.value}.svg', | 
					
						
							|  |  |  |                         width: themeConf.iconSize, | 
					
						
							|  |  |  |                         height: themeConf.iconSize, | 
					
						
							|  |  |  |                       ).paddingOnly(right: 5), | 
					
						
							|  |  |  |                     ), | 
					
						
							|  |  |  |                     label, | 
					
						
							|  |  |  |                   ], | 
					
						
							|  |  |  |                 ); | 
					
						
							| 
									
										
										
										
											2022-11-03 21:58:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 return Listener( | 
					
						
							|  |  |  |                   onPointerDown: (e) { | 
					
						
							|  |  |  |                     if (e.kind != ui.PointerDeviceKind.mouse) { | 
					
						
							|  |  |  |                       return; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     if (e.buttons == 2) { | 
					
						
							|  |  |  |                       showRightMenu( | 
					
						
							|  |  |  |                         (CancelFunc cancelFunc) { | 
					
						
							|  |  |  |                           return _tabMenuBuilder(key, cancelFunc); | 
					
						
							|  |  |  |                         }, | 
					
						
							|  |  |  |                         target: e.position, | 
					
						
							|  |  |  |                       ); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                   }, | 
					
						
							|  |  |  |                   child: tab, | 
					
						
							|  |  |  |                 ); | 
					
						
							| 
									
										
										
										
											2022-11-01 17:01:43 +08:00
										 |  |  |               } | 
					
						
							|  |  |  |             }), | 
					
						
							| 
									
										
										
										
											2022-11-16 19:49:52 +08:00
										 |  |  |           ), | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |       ), | 
					
						
							| 
									
										
										
										
											2022-09-19 10:14:14 +08:00
										 |  |  |     ); | 
					
						
							| 
									
										
										
										
											2022-09-19 11:09:29 +08:00
										 |  |  |     return Platform.isMacOS | 
					
						
							| 
									
										
										
										
											2022-09-19 10:14:14 +08:00
										 |  |  |         ? tabWidget | 
					
						
							| 
									
										
										
										
											2022-11-01 18:16:52 +08:00
										 |  |  |         : SubWindowDragToResizeArea( | 
					
						
							|  |  |  |             child: tabWidget, | 
					
						
							|  |  |  |             resizeEdgeSize: stateGlobal.resizeEdgeSize.value, | 
					
						
							|  |  |  |             windowId: stateGlobal.windowId, | 
					
						
							|  |  |  |           ); | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-05-31 16:27:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-10 14:32:22 +08:00
										 |  |  |   // Note: Some dup code to ../widgets/remote_menubar
 | 
					
						
							| 
									
										
										
										
											2022-11-03 21:58:25 +08:00
										 |  |  |   Widget _tabMenuBuilder(String key, CancelFunc cancelFunc) { | 
					
						
							|  |  |  |     final List<MenuEntryBase<String>> menu = []; | 
					
						
							|  |  |  |     const EdgeInsets padding = EdgeInsets.only(left: 8.0, right: 5.0); | 
					
						
							|  |  |  |     final remotePage = tabController.state.value.tabs | 
					
						
							|  |  |  |         .firstWhere((tab) => tab.key == key) | 
					
						
							|  |  |  |         .page as RemotePage; | 
					
						
							|  |  |  |     final ffi = remotePage.ffi; | 
					
						
							|  |  |  |     final pi = ffi.ffiModel.pi; | 
					
						
							|  |  |  |     final perms = ffi.ffiModel.permissions; | 
					
						
							|  |  |  |     menu.addAll([ | 
					
						
							|  |  |  |       MenuEntryButton<String>( | 
					
						
							|  |  |  |         childBuilder: (TextStyle? style) => Text( | 
					
						
							|  |  |  |           translate('Close'), | 
					
						
							|  |  |  |           style: style, | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |         proc: () { | 
					
						
							|  |  |  |           tabController.closeBy(key); | 
					
						
							|  |  |  |           cancelFunc(); | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         padding: padding, | 
					
						
							|  |  |  |       ), | 
					
						
							|  |  |  |       MenuEntryButton<String>( | 
					
						
							|  |  |  |         childBuilder: (TextStyle? style) => Obx(() => Text( | 
					
						
							| 
									
										
										
										
											2022-11-10 14:32:22 +08:00
										 |  |  |               translate( | 
					
						
							|  |  |  |                   _menubarState.show.isTrue ? 'Hide Menubar' : 'Show Menubar'), | 
					
						
							| 
									
										
										
										
											2022-11-03 21:58:25 +08:00
										 |  |  |               style: style, | 
					
						
							|  |  |  |             )), | 
					
						
							|  |  |  |         proc: () { | 
					
						
							| 
									
										
										
										
											2022-11-10 14:32:22 +08:00
										 |  |  |           _menubarState.switchShow(); | 
					
						
							| 
									
										
										
										
											2022-11-03 21:58:25 +08:00
										 |  |  |           cancelFunc(); | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         padding: padding, | 
					
						
							|  |  |  |       ), | 
					
						
							|  |  |  |       MenuEntryDivider<String>(), | 
					
						
							|  |  |  |       MenuEntryRadios<String>( | 
					
						
							|  |  |  |         text: translate('Ratio'), | 
					
						
							|  |  |  |         optionsGetter: () => [ | 
					
						
							|  |  |  |           MenuEntryRadioOption( | 
					
						
							|  |  |  |             text: translate('Scale original'), | 
					
						
							| 
									
										
										
										
											2022-11-24 11:19:16 +08:00
										 |  |  |             value: kRemoteViewStyleOriginal, | 
					
						
							| 
									
										
										
										
											2022-11-03 21:58:25 +08:00
										 |  |  |             dismissOnClicked: true, | 
					
						
							|  |  |  |           ), | 
					
						
							|  |  |  |           MenuEntryRadioOption( | 
					
						
							|  |  |  |             text: translate('Scale adaptive'), | 
					
						
							| 
									
										
										
										
											2022-11-24 11:19:16 +08:00
										 |  |  |             value: kRemoteViewStyleAdaptive, | 
					
						
							| 
									
										
										
										
											2022-11-03 21:58:25 +08:00
										 |  |  |             dismissOnClicked: true, | 
					
						
							|  |  |  |           ), | 
					
						
							|  |  |  |         ], | 
					
						
							| 
									
										
										
										
											2022-11-17 18:52:27 +08:00
										 |  |  |         curOptionGetter: () async => | 
					
						
							|  |  |  |             // null means peer id is not found, which there's no need to care about
 | 
					
						
							|  |  |  |             await bind.sessionGetViewStyle(id: key) ?? '', | 
					
						
							| 
									
										
										
										
											2022-11-03 21:58:25 +08:00
										 |  |  |         optionSetter: (String oldValue, String newValue) async { | 
					
						
							| 
									
										
										
										
											2022-11-24 11:19:16 +08:00
										 |  |  |           await bind.sessionSetViewStyle(id: key, value: newValue); | 
					
						
							| 
									
										
										
										
											2022-11-03 21:58:25 +08:00
										 |  |  |           ffi.canvasModel.updateViewStyle(); | 
					
						
							|  |  |  |           cancelFunc(); | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         padding: padding, | 
					
						
							|  |  |  |       ), | 
					
						
							| 
									
										
										
										
											2022-11-29 16:36:35 +08:00
										 |  |  |     ]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-31 21:41:16 +08:00
										 |  |  |     if (!ffi.canvasModel.cursorEmbedded) { | 
					
						
							| 
									
										
										
										
											2022-11-29 16:36:35 +08:00
										 |  |  |       menu.add(MenuEntryDivider<String>()); | 
					
						
							|  |  |  |       menu.add(() { | 
					
						
							| 
									
										
										
										
											2022-11-03 21:58:25 +08:00
										 |  |  |         final state = ShowRemoteCursorState.find(key); | 
					
						
							|  |  |  |         return MenuEntrySwitch2<String>( | 
					
						
							|  |  |  |           switchType: SwitchType.scheckbox, | 
					
						
							|  |  |  |           text: translate('Show remote cursor'), | 
					
						
							|  |  |  |           getter: () { | 
					
						
							|  |  |  |             return state; | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |           setter: (bool v) async { | 
					
						
							|  |  |  |             state.value = v; | 
					
						
							|  |  |  |             await bind.sessionToggleOption( | 
					
						
							|  |  |  |                 id: key, value: 'show-remote-cursor'); | 
					
						
							|  |  |  |             cancelFunc(); | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |           padding: padding, | 
					
						
							|  |  |  |         ); | 
					
						
							| 
									
										
										
										
											2022-11-29 16:36:35 +08:00
										 |  |  |       }()); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-11-03 21:58:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (perms['keyboard'] != false) { | 
					
						
							| 
									
										
										
										
											2022-11-04 11:09:48 +08:00
										 |  |  |       if (perms['clipboard'] != false) { | 
					
						
							|  |  |  |         menu.add(MenuEntrySwitch<String>( | 
					
						
							|  |  |  |           switchType: SwitchType.scheckbox, | 
					
						
							|  |  |  |           text: translate('Disable clipboard'), | 
					
						
							|  |  |  |           getter: () async { | 
					
						
							|  |  |  |             return bind.sessionGetToggleOptionSync( | 
					
						
							|  |  |  |                 id: key, arg: 'disable-clipboard'); | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |           setter: (bool v) async { | 
					
						
							|  |  |  |             await bind.sessionToggleOption(id: key, value: 'disable-clipboard'); | 
					
						
							|  |  |  |             cancelFunc(); | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |           padding: padding, | 
					
						
							|  |  |  |         )); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       menu.add(MenuEntryButton<String>( | 
					
						
							|  |  |  |         childBuilder: (TextStyle? style) => Text( | 
					
						
							|  |  |  |           translate('Insert Lock'), | 
					
						
							|  |  |  |           style: style, | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |         proc: () { | 
					
						
							|  |  |  |           bind.sessionLockScreen(id: key); | 
					
						
							|  |  |  |           cancelFunc(); | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         padding: padding, | 
					
						
							|  |  |  |         dismissOnClicked: true, | 
					
						
							|  |  |  |       )); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-10 17:13:40 +08:00
										 |  |  |       if (pi.platform == kPeerPlatformLinux || pi.sasEnabled) { | 
					
						
							| 
									
										
										
										
											2022-11-03 21:58:25 +08:00
										 |  |  |         menu.add(MenuEntryButton<String>( | 
					
						
							|  |  |  |           childBuilder: (TextStyle? style) => Text( | 
					
						
							|  |  |  |             '${translate("Insert")} Ctrl + Alt + Del', | 
					
						
							|  |  |  |             style: style, | 
					
						
							|  |  |  |           ), | 
					
						
							|  |  |  |           proc: () { | 
					
						
							|  |  |  |             bind.sessionCtrlAltDel(id: key); | 
					
						
							|  |  |  |             cancelFunc(); | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |           padding: padding, | 
					
						
							|  |  |  |           dismissOnClicked: true, | 
					
						
							|  |  |  |         )); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return mod_menu.PopupMenu<String>( | 
					
						
							|  |  |  |       items: menu | 
					
						
							|  |  |  |           .map((entry) => entry.build( | 
					
						
							|  |  |  |               context, | 
					
						
							|  |  |  |               const MenuConfig( | 
					
						
							|  |  |  |                 commonColor: _MenuTheme.commonColor, | 
					
						
							|  |  |  |                 height: _MenuTheme.height, | 
					
						
							|  |  |  |                 dividerHeight: _MenuTheme.dividerHeight, | 
					
						
							|  |  |  |               ))) | 
					
						
							|  |  |  |           .expand((i) => i) | 
					
						
							|  |  |  |           .toList(), | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-09 15:14:11 +08:00
										 |  |  |   void onRemoveId(String id) async { | 
					
						
							| 
									
										
										
										
											2022-08-30 16:45:47 +08:00
										 |  |  |     if (tabController.state.value.tabs.isEmpty) { | 
					
						
							| 
									
										
										
										
											2022-11-09 15:14:11 +08:00
										 |  |  |       await WindowController.fromWindowId(windowId()).close(); | 
					
						
							| 
									
										
										
										
											2022-08-09 09:01:06 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-08-29 22:46:19 +08:00
										 |  |  |     ConnectionTypeState.delete(id); | 
					
						
							| 
									
										
										
										
											2022-10-08 17:27:30 +08:00
										 |  |  |     _update_remote_count(); | 
					
						
							| 
									
										
										
										
											2022-05-31 16:27:54 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-08-09 16:37:11 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   int windowId() { | 
					
						
							|  |  |  |     return widget.params["windowId"]; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:03:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-09 19:29:19 +08:00
										 |  |  |   Future<bool> handleWindowCloseButton() async { | 
					
						
							| 
									
										
										
										
											2022-10-08 17:27:30 +08:00
										 |  |  |     final connLength = tabController.length; | 
					
						
							| 
									
										
										
										
											2022-10-13 21:19:05 +09:00
										 |  |  |     if (connLength <= 1) { | 
					
						
							|  |  |  |       tabController.clear(); | 
					
						
							| 
									
										
										
										
											2022-09-09 19:29:19 +08:00
										 |  |  |       return true; | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2022-10-13 21:19:05 +09:00
										 |  |  |       final opt = "enable-confirm-closing-tabs"; | 
					
						
							|  |  |  |       final bool res; | 
					
						
							|  |  |  |       if (!option2bool(opt, await bind.mainGetOption(key: opt))) { | 
					
						
							|  |  |  |         res = true; | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         res = await closeConfirmDialog(); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2022-09-09 19:29:19 +08:00
										 |  |  |       if (res) { | 
					
						
							|  |  |  |         tabController.clear(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return res; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-10-08 17:27:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   _update_remote_count() => | 
					
						
							|  |  |  |       RemoteCountState.find().value = tabController.length; | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | } |