* feat: auto switch display on follow remote cursor Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * feat: auto switch display on follow remote window focus Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * fix build and remove unused imports Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * fix build Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * fix build Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * fix linux get_focused_window_id Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * lock show remote cursor when follow remote cursor is enabled Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * fix config Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * prevent auto display switch on show all display and displays as individual windows Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * fix options Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * fix options Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * remove unused function Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * remove unwraps and improve iterations Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * set updateCursorPos to false to avoid interrupting remote cursor Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * update lang Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * fix web build Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * update checks for options and enable in view mode Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * use focused display index for window focus service Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * use window center for windows display focused Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * remove unused imports Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * fix build Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * use libxdo instead of xdotool Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * fix multi monitor check Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * enable show cursor when follow cursor is default Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * remove show_all_displays,use runtime state instead Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * fix show cursor lock state on default Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * remove view mode with follow options Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * fix build Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * use separate message for follow current display Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * fix options Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * sciter support for follow remote cursor and window Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * add check for ui session handlers count Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * use cached displays and remove peer info write Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * No follow options when show all displays Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * No follow options when multi ui session Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * turn off follow options when not used|prevent msgs Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * use window center for switch in linux Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * use subbed display count to prevent switch msgs Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * fix build Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * fix web build Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * move subbed displays count Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * fix build Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * add noperms for window focus Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * add subscribe for window focus Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * remove window_focus message and unsub on multi ui Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * add multi ui session field Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> --------- Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> Co-authored-by: RustDesk <71636191+rustdesk@users.noreply.github.com>
		
			
				
	
	
		
			362 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			362 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
| import 'package:flutter_hbb/common.dart';
 | |
| import 'package:get/get.dart';
 | |
| 
 | |
| import '../consts.dart';
 | |
| 
 | |
| // TODO: A lot of dup code.
 | |
| 
 | |
| class PrivacyModeState {
 | |
|   static String tag(String id) => 'privacy_mode_$id';
 | |
| 
 | |
|   static void init(String id) {
 | |
|     final key = tag(id);
 | |
|     if (!Get.isRegistered(tag: key)) {
 | |
|       final RxString state = ''.obs;
 | |
|       Get.put(state, tag: key);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static void delete(String id) {
 | |
|     final key = tag(id);
 | |
|     if (Get.isRegistered(tag: key)) {
 | |
|       Get.delete(tag: key);
 | |
|     } else {
 | |
|       Get.find<RxString>(tag: key).value = '';
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static RxString find(String id) => Get.find<RxString>(tag: tag(id));
 | |
| }
 | |
| 
 | |
| class BlockInputState {
 | |
|   static String tag(String id) => 'block_input_$id';
 | |
| 
 | |
|   static void init(String id) {
 | |
|     final key = tag(id);
 | |
|     if (!Get.isRegistered(tag: key)) {
 | |
|       final RxBool state = false.obs;
 | |
|       Get.put(state, tag: key);
 | |
|     } else {
 | |
|       Get.find<RxBool>(tag: key).value = false;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static void delete(String id) {
 | |
|     final key = tag(id);
 | |
|     if (Get.isRegistered(tag: key)) {
 | |
|       Get.delete(tag: key);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static RxBool find(String id) => Get.find<RxBool>(tag: tag(id));
 | |
| }
 | |
| 
 | |
| class CurrentDisplayState {
 | |
|   static String tag(String id) => 'current_display_$id';
 | |
| 
 | |
|   static void init(String id) {
 | |
|     final key = tag(id);
 | |
|     if (!Get.isRegistered(tag: key)) {
 | |
|       final RxInt state = RxInt(0);
 | |
|       Get.put(state, tag: key);
 | |
|     } else {
 | |
|       Get.find<RxInt>(tag: key).value = 0;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static void delete(String id) {
 | |
|     final key = tag(id);
 | |
|     if (Get.isRegistered(tag: key)) {
 | |
|       Get.delete(tag: key);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static RxInt find(String id) => Get.find<RxInt>(tag: tag(id));
 | |
| }
 | |
| 
 | |
| class ConnectionType {
 | |
|   final Rx<String> _secure = kInvalidValueStr.obs;
 | |
|   final Rx<String> _direct = kInvalidValueStr.obs;
 | |
| 
 | |
|   Rx<String> get secure => _secure;
 | |
|   Rx<String> get direct => _direct;
 | |
| 
 | |
|   static String get strSecure => 'secure';
 | |
|   static String get strInsecure => 'insecure';
 | |
|   static String get strDirect => '';
 | |
|   static String get strIndirect => '_relay';
 | |
| 
 | |
|   void setSecure(bool v) {
 | |
|     _secure.value = v ? strSecure : strInsecure;
 | |
|   }
 | |
| 
 | |
|   void setDirect(bool v) {
 | |
|     _direct.value = v ? strDirect : strIndirect;
 | |
|   }
 | |
| 
 | |
|   bool isValid() {
 | |
|     return _secure.value != kInvalidValueStr &&
 | |
|         _direct.value != kInvalidValueStr;
 | |
|   }
 | |
| }
 | |
| 
 | |
| class ConnectionTypeState {
 | |
|   static String tag(String id) => 'connection_type_$id';
 | |
| 
 | |
|   static void init(String id) {
 | |
|     final key = tag(id);
 | |
|     if (!Get.isRegistered(tag: key)) {
 | |
|       final ConnectionType collectionType = ConnectionType();
 | |
|       Get.put(collectionType, tag: key);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static void delete(String id) {
 | |
|     final key = tag(id);
 | |
|     if (Get.isRegistered(tag: key)) {
 | |
|       Get.delete(tag: key);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static ConnectionType find(String id) =>
 | |
|       Get.find<ConnectionType>(tag: tag(id));
 | |
| }
 | |
| 
 | |
| class FingerprintState {
 | |
|   static String tag(String id) => 'fingerprint_$id';
 | |
| 
 | |
|   static void init(String id) {
 | |
|     final key = tag(id);
 | |
|     if (!Get.isRegistered(tag: key)) {
 | |
|       final RxString state = ''.obs;
 | |
|       Get.put(state, tag: key);
 | |
|     } else {
 | |
|       Get.find<RxString>(tag: key).value = '';
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static void delete(String id) {
 | |
|     final key = tag(id);
 | |
|     if (Get.isRegistered(tag: key)) {
 | |
|       Get.delete(tag: key);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static RxString find(String id) => Get.find<RxString>(tag: tag(id));
 | |
| }
 | |
| 
 | |
| class ShowRemoteCursorState {
 | |
|   static String tag(String id) => 'show_remote_cursor_$id';
 | |
| 
 | |
|   static void init(String id) {
 | |
|     final key = tag(id);
 | |
|     if (!Get.isRegistered(tag: key)) {
 | |
|       final RxBool state = false.obs;
 | |
|       Get.put(state, tag: key);
 | |
|     } else {
 | |
|       Get.find<RxBool>(tag: key).value = false;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static void delete(String id) {
 | |
|     final key = tag(id);
 | |
|     if (Get.isRegistered(tag: key)) {
 | |
|       Get.delete(tag: key);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static RxBool find(String id) => Get.find<RxBool>(tag: tag(id));
 | |
| }
 | |
| 
 | |
| class ShowRemoteCursorLockState {
 | |
|   static String tag(String id) => 'show_remote_cursor_lock_$id';
 | |
| 
 | |
|   static void init(String id) {
 | |
|     final key = tag(id);
 | |
|     if (!Get.isRegistered(tag: key)) {
 | |
|       final RxBool state = false.obs;
 | |
|       Get.put(state, tag: key);
 | |
|     } else {
 | |
|       Get.find<RxBool>(tag: key).value = false;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static void delete(String id) {
 | |
|     final key = tag(id);
 | |
|     if (Get.isRegistered(tag: key)) {
 | |
|       Get.delete(tag: key);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static RxBool find(String id) => Get.find<RxBool>(tag: tag(id));
 | |
| }
 | |
| 
 | |
| class KeyboardEnabledState {
 | |
|   static String tag(String id) => 'keyboard_enabled_$id';
 | |
| 
 | |
|   static void init(String id) {
 | |
|     final key = tag(id);
 | |
|     if (!Get.isRegistered(tag: key)) {
 | |
|       // Server side, default true
 | |
|       final RxBool state = true.obs;
 | |
|       Get.put(state, tag: key);
 | |
|     } else {
 | |
|       Get.find<RxBool>(tag: key).value = true;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static void delete(String id) {
 | |
|     final key = tag(id);
 | |
|     if (Get.isRegistered(tag: key)) {
 | |
|       Get.delete(tag: key);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static RxBool find(String id) => Get.find<RxBool>(tag: tag(id));
 | |
| }
 | |
| 
 | |
| class RemoteCursorMovedState {
 | |
|   static String tag(String id) => 'remote_cursor_moved_$id';
 | |
| 
 | |
|   static void init(String id) {
 | |
|     final key = tag(id);
 | |
|     if (!Get.isRegistered(tag: key)) {
 | |
|       final RxBool state = false.obs;
 | |
|       Get.put(state, tag: key);
 | |
|     } else {
 | |
|       Get.find<RxBool>(tag: key).value = false;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static void delete(String id) {
 | |
|     final key = tag(id);
 | |
|     if (Get.isRegistered(tag: key)) {
 | |
|       Get.delete(tag: key);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   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)) {
 | |
|       final RxInt state = 1.obs;
 | |
|       Get.put(state, tag: key);
 | |
|     } else {
 | |
|       Get.find<RxInt>(tag: key).value = 1;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static void delete() {
 | |
|     final key = tag();
 | |
|     if (Get.isRegistered(tag: key)) {
 | |
|       Get.delete(tag: key);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static RxInt find() => Get.find<RxInt>(tag: tag());
 | |
| }
 | |
| 
 | |
| class PeerBoolOption {
 | |
|   static String tag(String id, String opt) => 'peer_{$opt}_$id';
 | |
| 
 | |
|   static void init(String id, String opt, bool Function() init_getter) {
 | |
|     final key = tag(id, opt);
 | |
|     if (!Get.isRegistered(tag: key)) {
 | |
|       final RxBool value = RxBool(init_getter());
 | |
|       Get.put(value, tag: key);
 | |
|     } else {
 | |
|       Get.find<RxBool>(tag: key).value = init_getter();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static void delete(String id, String opt) {
 | |
|     final key = tag(id, opt);
 | |
|     if (Get.isRegistered(tag: key)) {
 | |
|       Get.delete(tag: key);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static RxBool find(String id, String opt) =>
 | |
|       Get.find<RxBool>(tag: tag(id, opt));
 | |
| }
 | |
| 
 | |
| class PeerStringOption {
 | |
|   static String tag(String id, String opt) => 'peer_{$opt}_$id';
 | |
| 
 | |
|   static void init(String id, String opt, String Function() init_getter) {
 | |
|     final key = tag(id, opt);
 | |
|     if (!Get.isRegistered(tag: key)) {
 | |
|       final RxString value = RxString(init_getter());
 | |
|       Get.put(value, tag: key);
 | |
|     } else {
 | |
|       Get.find<RxString>(tag: key).value = init_getter();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static void delete(String id, String opt) {
 | |
|     final key = tag(id, opt);
 | |
|     if (Get.isRegistered(tag: key)) {
 | |
|       Get.delete(tag: key);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static RxString find(String id, String opt) =>
 | |
|       Get.find<RxString>(tag: tag(id, opt));
 | |
| }
 | |
| 
 | |
| class UnreadChatCountState {
 | |
|   static String tag(id) => 'unread_chat_count_$id';
 | |
| 
 | |
|   static void init(String id) {
 | |
|     final key = tag(id);
 | |
|     if (!Get.isRegistered(tag: key)) {
 | |
|       final RxInt state = RxInt(0);
 | |
|       Get.put(state, tag: key);
 | |
|     } else {
 | |
|       Get.find<RxInt>(tag: key).value = 0;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static void delete(String id) {
 | |
|     final key = tag(id);
 | |
|     if (Get.isRegistered(tag: key)) {
 | |
|       Get.delete(tag: key);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static RxInt find(String id) => Get.find<RxInt>(tag: tag(id));
 | |
| }
 | |
| 
 | |
| initSharedStates(String id) {
 | |
|   PrivacyModeState.init(id);
 | |
|   BlockInputState.init(id);
 | |
|   CurrentDisplayState.init(id);
 | |
|   KeyboardEnabledState.init(id);
 | |
|   ShowRemoteCursorState.init(id);
 | |
|   ShowRemoteCursorLockState.init(id);
 | |
|   RemoteCursorMovedState.init(id);
 | |
|   FingerprintState.init(id);
 | |
|   PeerBoolOption.init(id, 'zoom-cursor', () => false);
 | |
|   UnreadChatCountState.init(id);
 | |
|   if (isMobile) ConnectionTypeState.init(id); // desktop in other places
 | |
| }
 | |
| 
 | |
| removeSharedStates(String id) {
 | |
|   PrivacyModeState.delete(id);
 | |
|   BlockInputState.delete(id);
 | |
|   CurrentDisplayState.delete(id);
 | |
|   ShowRemoteCursorState.delete(id);
 | |
|   ShowRemoteCursorLockState.delete(id);
 | |
|   KeyboardEnabledState.delete(id);
 | |
|   RemoteCursorMovedState.delete(id);
 | |
|   FingerprintState.delete(id);
 | |
|   PeerBoolOption.delete(id, 'zoom-cursor');
 | |
|   UnreadChatCountState.delete(id);
 | |
|   if (isMobile) ConnectionTypeState.delete(id);
 | |
| }
 |