Add peer option: zoom cursor & show menubar on conn

Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
fufesou 2022-11-16 18:07:58 +08:00
parent 46423614c8
commit 9a70725090
28 changed files with 121 additions and 23 deletions

View File

@ -202,6 +202,28 @@ class RemoteCountState {
static RxInt find() => Get.find<RxInt>(tag: tag()); 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);
}
}
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 { class PeerStringOption {
static String tag(String id, String opt) => 'peer_{$opt}_$id'; static String tag(String id, String opt) => 'peer_{$opt}_$id';

View File

@ -51,6 +51,7 @@ class _RemotePageState extends State<RemotePage>
String keyboardMode = "legacy"; String keyboardMode = "legacy";
final _cursorOverImage = false.obs; final _cursorOverImage = false.obs;
late RxBool _showRemoteCursor; late RxBool _showRemoteCursor;
late RxBool _zoomCursor;
late RxBool _remoteCursorMoved; late RxBool _remoteCursorMoved;
late RxBool _keyboardEnabled; late RxBool _keyboardEnabled;
@ -68,6 +69,10 @@ class _RemotePageState extends State<RemotePage>
KeyboardEnabledState.init(id); KeyboardEnabledState.init(id);
ShowRemoteCursorState.init(id); ShowRemoteCursorState.init(id);
RemoteCursorMovedState.init(id); RemoteCursorMovedState.init(id);
final optZoomCursor = 'zoom-cursor';
PeerBoolOption.init(id, optZoomCursor,
() => bind.sessionGetToggleOptionSync(id: id, arg: optZoomCursor));
_zoomCursor = PeerBoolOption.find(id, optZoomCursor);
_showRemoteCursor = ShowRemoteCursorState.find(id); _showRemoteCursor = ShowRemoteCursorState.find(id);
_keyboardEnabled = KeyboardEnabledState.find(id); _keyboardEnabled = KeyboardEnabledState.find(id);
_remoteCursorMoved = RemoteCursorMovedState.find(id); _remoteCursorMoved = RemoteCursorMovedState.find(id);
@ -216,6 +221,7 @@ class _RemotePageState extends State<RemotePage>
}); });
return ImagePaint( return ImagePaint(
id: widget.id, id: widget.id,
zoomCursor: _zoomCursor,
cursorOverImage: _cursorOverImage, cursorOverImage: _cursorOverImage,
keyboardEnabled: _keyboardEnabled, keyboardEnabled: _keyboardEnabled,
remoteCursorMoved: _remoteCursorMoved, remoteCursorMoved: _remoteCursorMoved,
@ -233,6 +239,7 @@ class _RemotePageState extends State<RemotePage>
visible: _showRemoteCursor.isTrue && _remoteCursorMoved.isTrue, visible: _showRemoteCursor.isTrue && _remoteCursorMoved.isTrue,
child: CursorPaint( child: CursorPaint(
id: widget.id, id: widget.id,
zoomCursor: _zoomCursor,
)))); ))));
paints.add(QualityMonitor(_ffi.qualityMonitorModel)); paints.add(QualityMonitor(_ffi.qualityMonitorModel));
paints.add(RemoteMenubar( paints.add(RemoteMenubar(
@ -253,6 +260,7 @@ class _RemotePageState extends State<RemotePage>
class ImagePaint extends StatefulWidget { class ImagePaint extends StatefulWidget {
final String id; final String id;
final Rx<bool> zoomCursor;
final Rx<bool> cursorOverImage; final Rx<bool> cursorOverImage;
final Rx<bool> keyboardEnabled; final Rx<bool> keyboardEnabled;
final Rx<bool> remoteCursorMoved; final Rx<bool> remoteCursorMoved;
@ -261,6 +269,7 @@ class ImagePaint extends StatefulWidget {
ImagePaint( ImagePaint(
{Key? key, {Key? key,
required this.id, required this.id,
required this.zoomCursor,
required this.cursorOverImage, required this.cursorOverImage,
required this.keyboardEnabled, required this.keyboardEnabled,
required this.remoteCursorMoved, required this.remoteCursorMoved,
@ -277,6 +286,7 @@ class _ImagePaintState extends State<ImagePaint> {
final ScrollController _vertical = ScrollController(); final ScrollController _vertical = ScrollController();
String get id => widget.id; String get id => widget.id;
Rx<bool> get zoomCursor => widget.zoomCursor;
Rx<bool> get cursorOverImage => widget.cursorOverImage; Rx<bool> get cursorOverImage => widget.cursorOverImage;
Rx<bool> get keyboardEnabled => widget.keyboardEnabled; Rx<bool> get keyboardEnabled => widget.keyboardEnabled;
Rx<bool> get remoteCursorMoved => widget.remoteCursorMoved; Rx<bool> get remoteCursorMoved => widget.remoteCursorMoved;
@ -357,7 +367,7 @@ class _ImagePaintState extends State<ImagePaint> {
if (cache == null) { if (cache == null) {
return MouseCursor.defer; return MouseCursor.defer;
} else { } else {
final key = cache.updateGetKey(scale); final key = cache.updateGetKey(scale, zoomCursor.value);
cursor.addKey(key); cursor.addKey(key);
return FlutterCustomMemoryImageCursor( return FlutterCustomMemoryImageCursor(
pixbuf: cache.data, pixbuf: cache.data,
@ -500,8 +510,13 @@ class _ImagePaintState extends State<ImagePaint> {
class CursorPaint extends StatelessWidget { class CursorPaint extends StatelessWidget {
final String id; final String id;
final RxBool zoomCursor;
const CursorPaint({Key? key, required this.id}) : super(key: key); const CursorPaint({
Key? key,
required this.id,
required this.zoomCursor,
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -516,13 +531,21 @@ class CursorPaint extends StatelessWidget {
hoty = m.defaultImage!.height / 2; hoty = m.defaultImage!.height / 2;
} }
} }
return CustomPaint( return zoomCursor.isTrue
painter: ImagePainter( ? CustomPaint(
image: m.image ?? m.defaultImage, painter: ImagePainter(
x: m.x - hotx + c.x / c.scale, image: m.image ?? m.defaultImage,
y: m.y - hoty + c.y / c.scale, x: m.x - hotx + c.x / c.scale,
scale: c.scale), y: m.y - hoty + c.y / c.scale,
); scale: c.scale),
)
: CustomPaint(
painter: ImagePainter(
image: m.image ?? m.defaultImage,
x: (m.x - hotx) * c.scale + c.x,
y: (m.y - hoty) * c.scale + c.y,
scale: 1.0),
);
} }
} }

View File

@ -47,7 +47,8 @@ class MenubarState {
} }
_initSet(bool s, bool p) { _initSet(bool s, bool p) {
show = RxBool(s); // Show remubar when connection is established.
show = RxBool(true);
_pin = RxBool(p); _pin = RxBool(p);
} }
@ -1109,6 +1110,25 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
); );
}()); }());
/// Show remote cursor
displayMenu.add(() {
final opt = 'zoom-cursor';
final state = PeerBoolOption.find(widget.id, opt);
return MenuEntrySwitch2<String>(
switchType: SwitchType.scheckbox,
text: translate('Zoom cursor'),
getter: () {
return state;
},
setter: (bool v) async {
state.value = v;
await bind.sessionToggleOption(id: widget.id, value: opt);
},
padding: padding,
dismissOnClicked: true,
);
}());
/// Show quality monitor /// Show quality monitor
displayMenu.add(MenuEntrySwitch<String>( displayMenu.add(MenuEntrySwitch<String>(
switchType: SwitchType.scheckbox, switchType: SwitchType.scheckbox,

View File

@ -718,35 +718,44 @@ class CursorData {
int _doubleToInt(double v) => (v * 10e6).round().toInt(); int _doubleToInt(double v) => (v * 10e6).round().toInt();
double _checkUpdateScale(double scale) { double _checkUpdateScale(double scale, bool shouldScale) {
// Update data if scale changed. double oldScale = this.scale;
if (Platform.isWindows) { if (!shouldScale) {
final tgtWidth = (width * scale).toInt(); scale = 1.0;
final tgtHeight = (width * scale).toInt(); } else {
if (tgtWidth < kMinCursorSize || tgtHeight < kMinCursorSize) { // Update data if scale changed.
double sw = kMinCursorSize.toDouble() / width; if (Platform.isWindows) {
double sh = kMinCursorSize.toDouble() / height; final tgtWidth = (width * scale).toInt();
scale = sw < sh ? sh : sw; final tgtHeight = (width * scale).toInt();
if (tgtWidth < kMinCursorSize || tgtHeight < kMinCursorSize) {
double sw = kMinCursorSize.toDouble() / width;
double sh = kMinCursorSize.toDouble() / height;
scale = sw < sh ? sh : sw;
}
} }
if (_doubleToInt(this.scale) != _doubleToInt(scale)) { }
if (Platform.isWindows) {
if (_doubleToInt(oldScale) != _doubleToInt(scale)) {
data = img2 data = img2
.copyResize( .copyResize(
image!, image!,
width: (width * scale).toInt(), width: (width * scale).toInt(),
height: (height * scale).toInt(), height: (height * scale).toInt(),
interpolation: img2.Interpolation.linear, interpolation: img2.Interpolation.average,
) )
.getBytes(format: img2.Format.bgra); .getBytes(format: img2.Format.bgra);
} }
} }
this.scale = scale; this.scale = scale;
hotx = hotxOrigin * scale; hotx = hotxOrigin * scale;
hoty = hotyOrigin * scale; hoty = hotyOrigin * scale;
return scale; return scale;
} }
String updateGetKey(double scale) { String updateGetKey(double scale, bool shouldScale) {
scale = _checkUpdateScale(scale); scale = _checkUpdateScale(scale, shouldScale);
return '${peerId}_${id}_${_doubleToInt(width * scale)}_${_doubleToInt(height * scale)}'; return '${peerId}_${id}_${_doubleToInt(width * scale)}_${_doubleToInt(height * scale)}';
} }
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", ""), ("or", ""),
("Continue with", "使用"), ("Continue with", "使用"),
("Elevate", "提权"), ("Elevate", "提权"),
("Zoom cursor", "缩放鼠标"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", ""), ("or", ""),
("Continue with", ""), ("Continue with", ""),
("Elevate", ""), ("Elevate", ""),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", ""), ("or", ""),
("Continue with", ""), ("Continue with", ""),
("Elevate", ""), ("Elevate", ""),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", ""), ("or", ""),
("Continue with", ""), ("Continue with", ""),
("Elevate", ""), ("Elevate", ""),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", ""), ("or", ""),
("Continue with", ""), ("Continue with", ""),
("Elevate", ""), ("Elevate", ""),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", "o"), ("or", "o"),
("Continue with", "Continuar con"), ("Continue with", "Continuar con"),
("Elevate", ""), ("Elevate", ""),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -388,5 +388,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("This PC", "This PC"), ("This PC", "This PC"),
("or", "یا"), ("or", "یا"),
("Continue with", "ادامه با"), ("Continue with", "ادامه با"),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", "ou"), ("or", "ou"),
("Continue with", "Continuer avec"), ("Continue with", "Continuer avec"),
("Elevate", ""), ("Elevate", ""),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", "vagy"), ("or", "vagy"),
("Continue with", "Folytatás a következővel"), ("Continue with", "Folytatás a következővel"),
("Elevate", ""), ("Elevate", ""),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", ""), ("or", ""),
("Continue with", ""), ("Continue with", ""),
("Elevate", ""), ("Elevate", ""),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", ""), ("or", ""),
("Continue with", ""), ("Continue with", ""),
("Elevate", ""), ("Elevate", ""),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", ""), ("or", ""),
("Continue with", ""), ("Continue with", ""),
("Elevate", ""), ("Elevate", ""),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", ""), ("or", ""),
("Continue with", ""), ("Continue with", ""),
("Elevate", ""), ("Elevate", ""),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", ""), ("or", ""),
("Continue with", ""), ("Continue with", ""),
("Elevate", ""), ("Elevate", ""),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", "albo"), ("or", "albo"),
("Continue with", "Kontynuuj z"), ("Continue with", "Kontynuuj z"),
("Elevate", ""), ("Elevate", ""),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", ""), ("or", ""),
("Continue with", ""), ("Continue with", ""),
("Elevate", ""), ("Elevate", ""),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", "ou"), ("or", "ou"),
("Continue with", "Continuar com"), ("Continue with", "Continuar com"),
("Elevate", ""), ("Elevate", ""),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", "или"), ("or", "или"),
("Continue with", "Продолжить с"), ("Continue with", "Продолжить с"),
("Elevate", ""), ("Elevate", ""),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", ""), ("or", ""),
("Continue with", ""), ("Continue with", ""),
("Elevate", ""), ("Elevate", ""),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", ""), ("or", ""),
("Continue with", ""), ("Continue with", ""),
("Elevate", ""), ("Elevate", ""),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", ""), ("or", ""),
("Continue with", ""), ("Continue with", ""),
("Elevate", ""), ("Elevate", ""),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", ""), ("or", ""),
("Continue with", ""), ("Continue with", ""),
("Elevate", "提權"), ("Elevate", "提權"),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", ""), ("or", ""),
("Continue with", ""), ("Continue with", ""),
("Elevate", ""), ("Elevate", ""),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -389,5 +389,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("or", ""), ("or", ""),
("Continue with", ""), ("Continue with", ""),
("Elevate", ""), ("Elevate", ""),
("Zoom cursor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }