* 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>
		
			
				
	
	
		
			242 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			242 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
import 'package:debounce_throttle/debounce_throttle.dart';
 | 
						|
import 'package:flutter/material.dart';
 | 
						|
import 'package:flutter/services.dart';
 | 
						|
import 'package:flutter_hbb/common.dart';
 | 
						|
import 'package:flutter_hbb/consts.dart';
 | 
						|
import 'package:flutter_hbb/models/desktop_render_texture.dart';
 | 
						|
import 'package:flutter_hbb/models/platform_model.dart';
 | 
						|
import 'package:get/get.dart';
 | 
						|
 | 
						|
customImageQualityWidget(
 | 
						|
    {required double initQuality,
 | 
						|
    required double initFps,
 | 
						|
    required Function(double) setQuality,
 | 
						|
    required Function(double) setFps,
 | 
						|
    required bool showFps,
 | 
						|
    required bool showMoreQuality}) {
 | 
						|
  if (initQuality < kMinQuality ||
 | 
						|
      initQuality > (showMoreQuality ? kMaxMoreQuality : kMaxQuality)) {
 | 
						|
    initQuality = kDefaultQuality;
 | 
						|
  }
 | 
						|
  if (initFps < kMinFps || initFps > kMaxFps) {
 | 
						|
    initFps = kDefaultFps;
 | 
						|
  }
 | 
						|
  final qualityValue = initQuality.obs;
 | 
						|
  final fpsValue = initFps.obs;
 | 
						|
 | 
						|
  final RxBool moreQualityChecked = RxBool(qualityValue.value > kMaxQuality);
 | 
						|
  final debouncerQuality = Debouncer<double>(
 | 
						|
    Duration(milliseconds: 1000),
 | 
						|
    onChanged: (double v) {
 | 
						|
      setQuality(v);
 | 
						|
    },
 | 
						|
    initialValue: qualityValue.value,
 | 
						|
  );
 | 
						|
  final debouncerFps = Debouncer<double>(
 | 
						|
    Duration(milliseconds: 1000),
 | 
						|
    onChanged: (double v) {
 | 
						|
      setFps(v);
 | 
						|
    },
 | 
						|
    initialValue: fpsValue.value,
 | 
						|
  );
 | 
						|
 | 
						|
  onMoreChanged(bool? value) {
 | 
						|
    if (value == null) return;
 | 
						|
    moreQualityChecked.value = value;
 | 
						|
    if (!value && qualityValue.value > 100) {
 | 
						|
      qualityValue.value = 100;
 | 
						|
    }
 | 
						|
    debouncerQuality.value = qualityValue.value;
 | 
						|
  }
 | 
						|
 | 
						|
  return Column(
 | 
						|
    children: [
 | 
						|
      Obx(() => Row(
 | 
						|
            children: [
 | 
						|
              Expanded(
 | 
						|
                flex: 3,
 | 
						|
                child: Slider(
 | 
						|
                  value: qualityValue.value,
 | 
						|
                  min: kMinQuality,
 | 
						|
                  max: moreQualityChecked.value ? kMaxMoreQuality : kMaxQuality,
 | 
						|
                  divisions: moreQualityChecked.value
 | 
						|
                      ? ((kMaxMoreQuality - kMinQuality) / 10).round()
 | 
						|
                      : ((kMaxQuality - kMinQuality) / 5).round(),
 | 
						|
                  onChanged: (double value) async {
 | 
						|
                    qualityValue.value = value;
 | 
						|
                    debouncerQuality.value = value;
 | 
						|
                  },
 | 
						|
                ),
 | 
						|
              ),
 | 
						|
              Expanded(
 | 
						|
                  flex: 1,
 | 
						|
                  child: Text(
 | 
						|
                    '${qualityValue.value.round()}%',
 | 
						|
                    style: const TextStyle(fontSize: 15),
 | 
						|
                  )),
 | 
						|
              Expanded(
 | 
						|
                  flex: isMobile ? 2 : 1,
 | 
						|
                  child: Text(
 | 
						|
                    translate('Bitrate'),
 | 
						|
                    style: const TextStyle(fontSize: 15),
 | 
						|
                  )),
 | 
						|
              // mobile doesn't have enough space
 | 
						|
              if (showMoreQuality && !isMobile)
 | 
						|
                Expanded(
 | 
						|
                    flex: 1,
 | 
						|
                    child: Row(
 | 
						|
                      children: [
 | 
						|
                        Checkbox(
 | 
						|
                          value: moreQualityChecked.value,
 | 
						|
                          onChanged: onMoreChanged,
 | 
						|
                        ),
 | 
						|
                        Expanded(
 | 
						|
                          child: Text(translate('More')),
 | 
						|
                        )
 | 
						|
                      ],
 | 
						|
                    ))
 | 
						|
            ],
 | 
						|
          )),
 | 
						|
      if (showMoreQuality && isMobile)
 | 
						|
        Obx(() => Row(
 | 
						|
              children: [
 | 
						|
                Expanded(
 | 
						|
                  child: Align(
 | 
						|
                    alignment: Alignment.centerRight,
 | 
						|
                    child: Checkbox(
 | 
						|
                      value: moreQualityChecked.value,
 | 
						|
                      onChanged: onMoreChanged,
 | 
						|
                    ),
 | 
						|
                  ),
 | 
						|
                ),
 | 
						|
                Expanded(
 | 
						|
                  child: Text(translate('More')),
 | 
						|
                )
 | 
						|
              ],
 | 
						|
            )),
 | 
						|
      if (showFps)
 | 
						|
        Obx(() => Row(
 | 
						|
              children: [
 | 
						|
                Expanded(
 | 
						|
                  flex: 3,
 | 
						|
                  child: Slider(
 | 
						|
                    value: fpsValue.value,
 | 
						|
                    min: kMinFps,
 | 
						|
                    max: kMaxFps,
 | 
						|
                    divisions: ((kMaxFps - kMinFps) / 5).round(),
 | 
						|
                    onChanged: (double value) async {
 | 
						|
                      fpsValue.value = value;
 | 
						|
                      debouncerFps.value = value;
 | 
						|
                    },
 | 
						|
                  ),
 | 
						|
                ),
 | 
						|
                Expanded(
 | 
						|
                    flex: 1,
 | 
						|
                    child: Text(
 | 
						|
                      '${fpsValue.value.round()}',
 | 
						|
                      style: const TextStyle(fontSize: 15),
 | 
						|
                    )),
 | 
						|
                Expanded(
 | 
						|
                    flex: 2,
 | 
						|
                    child: Text(
 | 
						|
                      translate('FPS'),
 | 
						|
                      style: const TextStyle(fontSize: 15),
 | 
						|
                    ))
 | 
						|
              ],
 | 
						|
            )),
 | 
						|
    ],
 | 
						|
  );
 | 
						|
}
 | 
						|
 | 
						|
customImageQualitySetting() {
 | 
						|
  final qualityKey = 'custom_image_quality';
 | 
						|
  final fpsKey = 'custom-fps';
 | 
						|
 | 
						|
  var initQuality =
 | 
						|
      (double.tryParse(bind.mainGetUserDefaultOption(key: qualityKey)) ??
 | 
						|
          kDefaultQuality);
 | 
						|
  var initFps = (double.tryParse(bind.mainGetUserDefaultOption(key: fpsKey)) ??
 | 
						|
      kDefaultFps);
 | 
						|
 | 
						|
  return customImageQualityWidget(
 | 
						|
      initQuality: initQuality,
 | 
						|
      initFps: initFps,
 | 
						|
      setQuality: (v) {
 | 
						|
        bind.mainSetUserDefaultOption(key: qualityKey, value: v.toString());
 | 
						|
      },
 | 
						|
      setFps: (v) {
 | 
						|
        bind.mainSetUserDefaultOption(key: fpsKey, value: v.toString());
 | 
						|
      },
 | 
						|
      showFps: true,
 | 
						|
      showMoreQuality: true);
 | 
						|
}
 | 
						|
 | 
						|
List<Widget> ServerConfigImportExportWidgets(
 | 
						|
  List<TextEditingController> controllers,
 | 
						|
  List<RxString> errMsgs,
 | 
						|
) {
 | 
						|
  import() {
 | 
						|
    Clipboard.getData(Clipboard.kTextPlain).then((value) {
 | 
						|
      importConfig(controllers, errMsgs, value?.text);
 | 
						|
    });
 | 
						|
  }
 | 
						|
 | 
						|
  export() {
 | 
						|
    final text = ServerConfig(
 | 
						|
            idServer: controllers[0].text.trim(),
 | 
						|
            relayServer: controllers[1].text.trim(),
 | 
						|
            apiServer: controllers[2].text.trim(),
 | 
						|
            key: controllers[3].text.trim())
 | 
						|
        .encode();
 | 
						|
    debugPrint("ServerConfig export: $text");
 | 
						|
    Clipboard.setData(ClipboardData(text: text));
 | 
						|
    showToast(translate('Export server configuration successfully'));
 | 
						|
  }
 | 
						|
 | 
						|
  return [
 | 
						|
    Tooltip(
 | 
						|
      message: translate('Import server config'),
 | 
						|
      child: IconButton(
 | 
						|
          icon: Icon(Icons.paste, color: Colors.grey), onPressed: import),
 | 
						|
    ),
 | 
						|
    Tooltip(
 | 
						|
        message: translate('Export Server Config'),
 | 
						|
        child: IconButton(
 | 
						|
            icon: Icon(Icons.copy, color: Colors.grey), onPressed: export))
 | 
						|
  ];
 | 
						|
}
 | 
						|
 | 
						|
List<(String, String)> otherDefaultSettings() {
 | 
						|
  List<(String, String)> v = [
 | 
						|
    ('View Mode', 'view_only'),
 | 
						|
    if ((isDesktop || isWebDesktop)) ('show_monitors_tip', kKeyShowMonitorsToolbar),
 | 
						|
    if ((isDesktop || isWebDesktop)) ('Collapse toolbar', 'collapse_toolbar'),
 | 
						|
    ('Show remote cursor', 'show_remote_cursor'),
 | 
						|
    ('Follow remote cursor', 'follow_remote_cursor'),
 | 
						|
    ('Follow remote window focus', 'follow_remote_window'),
 | 
						|
    if ((isDesktop || isWebDesktop)) ('Zoom cursor', 'zoom-cursor'),
 | 
						|
    ('Show quality monitor', 'show_quality_monitor'),
 | 
						|
    ('Mute', 'disable_audio'),
 | 
						|
    if (isDesktop) ('Enable file copy and paste', 'enable_file_transfer'),
 | 
						|
    ('Disable clipboard', 'disable_clipboard'),
 | 
						|
    ('Lock after session end', 'lock_after_session_end'),
 | 
						|
    ('Privacy mode', 'privacy_mode'),
 | 
						|
    if (isMobile) ('Touch mode', 'touch-mode'),
 | 
						|
    ('True color (4:4:4)', 'i444'),
 | 
						|
    ('Reverse mouse wheel', kKeyReverseMouseWheel),
 | 
						|
    ('swap-left-right-mouse', 'swap-left-right-mouse'),
 | 
						|
    if (isDesktop && useTextureRender)
 | 
						|
      (
 | 
						|
        'Show displays as individual windows',
 | 
						|
        kKeyShowDisplaysAsIndividualWindows
 | 
						|
      ),
 | 
						|
    if (isDesktop && useTextureRender)
 | 
						|
      (
 | 
						|
        'Use all my displays for the remote session',
 | 
						|
        kKeyUseAllMyDisplaysForTheRemoteSession
 | 
						|
      )
 | 
						|
  ];
 | 
						|
 | 
						|
  return v;
 | 
						|
}
 |