feat, trackpad speed (#11680)

* feat, trackpad speed

Signed-off-by: fufesou <linlong1266@gmail.com>

* comments

Signed-off-by: fufesou <linlong1266@gmail.com>

* Trackpad speed, user default value

Signed-off-by: fufesou <linlong1266@gmail.com>

---------

Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
fufesou 2025-05-09 15:36:45 +08:00 committed by GitHub
parent 9475743b4e
commit ca7b4872d9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
57 changed files with 325 additions and 9 deletions

View file

@ -1623,6 +1623,28 @@ customImageQualityDialog(SessionID sessionId, String id, FFI ffi) async {
msgBoxCommon(ffi.dialogManager, 'Custom Image Quality', content, [btnClose]); msgBoxCommon(ffi.dialogManager, 'Custom Image Quality', content, [btnClose]);
} }
trackpadSpeedDialog(SessionID sessionId, FFI ffi) async {
int initSpeed = ffi.inputModel.trackpadSpeed;
final curSpeed = SimpleWrapper(initSpeed);
final btnClose = dialogButton('Close', onPressed: () async {
if (curSpeed.value <= kMaxTrackpadSpeed &&
curSpeed.value >= kMinTrackpadSpeed &&
curSpeed.value != initSpeed) {
await bind.sessionSetTrackpadSpeed(
sessionId: sessionId, value: curSpeed.value);
await ffi.inputModel.updateTrackpadSpeed();
}
ffi.dialogManager.dismissAll();
});
msgBoxCommon(
ffi.dialogManager,
'Trackpad speed',
TrackpadSpeedWidget(
value: curSpeed,
),
[btnClose]);
}
void deleteConfirmDialog(Function onSubmit, String title) async { void deleteConfirmDialog(Function onSubmit, String title) async {
gFFI.dialogManager.show( gFFI.dialogManager.show(
(setState, close, context) { (setState, close, context) {

View file

@ -248,3 +248,93 @@ List<(String, String)> otherDefaultSettings() {
return v; return v;
} }
class TrackpadSpeedWidget extends StatefulWidget {
final SimpleWrapper<int> value;
// If null, no debouncer will be applied.
final Function(int)? onDebouncer;
TrackpadSpeedWidget({Key? key, required this.value, this.onDebouncer});
@override
TrackpadSpeedWidgetState createState() => TrackpadSpeedWidgetState();
}
class TrackpadSpeedWidgetState extends State<TrackpadSpeedWidget> {
final TextEditingController _controller = TextEditingController();
late final Debouncer<int> debouncerSpeed;
set value(int v) => widget.value.value = v;
int get value => widget.value.value;
void updateValue(int newValue) {
setState(() {
value = newValue.clamp(kMinTrackpadSpeed, kMaxTrackpadSpeed);
// Scale the trackpad speed value to a percentage for display purposes.
_controller.text = value.toString();
if (widget.onDebouncer != null) {
debouncerSpeed.setValue(value);
}
});
}
@override
void initState() {
super.initState();
debouncerSpeed = Debouncer<int>(
Duration(milliseconds: 1000),
onChanged: widget.onDebouncer,
initialValue: widget.value.value,
);
}
@override
Widget build(BuildContext context) {
if (_controller.text.isEmpty) {
_controller.text = value.toString();
}
return Row(
children: [
Expanded(
flex: 3,
child: Slider(
value: value.toDouble(),
min: kMinTrackpadSpeed.toDouble(),
max: kMaxTrackpadSpeed.toDouble(),
divisions: ((kMaxTrackpadSpeed - kMinTrackpadSpeed) / 10).round(),
onChanged: (double v) => updateValue(v.round()),
),
),
Expanded(
flex: 1,
child: Row(
children: [
SizedBox(
width: 56,
child: TextField(
controller: _controller,
keyboardType: TextInputType.number,
textAlign: TextAlign.center,
onSubmitted: (text) {
int? v = int.tryParse(text);
if (v != null) {
updateValue(v);
}
},
style: const TextStyle(fontSize: 13),
decoration: InputDecoration(
contentPadding:
EdgeInsets.symmetric(vertical: 8.0, horizontal: 12.0),
),
),
).marginOnly(right: 8.0),
Text(
'%',
style: const TextStyle(fontSize: 15),
)
],
)),
],
);
}
}

View file

@ -226,6 +226,12 @@ const double kDefaultQuality = 50;
const double kMaxQuality = 100; const double kMaxQuality = 100;
const double kMaxMoreQuality = 2000; const double kMaxMoreQuality = 2000;
// trackpad speed
const String kKeyTrackpadSpeed = 'trackpad-speed';
const int kMinTrackpadSpeed = 10;
const int kDefaultTrackpadSpeed = 100;
const int kMaxTrackpadSpeed = 1000;
// incomming (should be incoming) is kept, because change it will break the previous setting. // incomming (should be incoming) is kept, because change it will break the previous setting.
const String kKeyPrinterIncomingJobAction = 'printer-incomming-job-action'; const String kKeyPrinterIncomingJobAction = 'printer-incomming-job-action';
const String kValuePrinterIncomingJobDismiss = 'dismiss'; const String kValuePrinterIncomingJobDismiss = 'dismiss';

View file

@ -76,7 +76,9 @@ class DesktopSettingPage extends StatefulWidget {
if (!isWeb && !bind.isIncomingOnly() && bind.pluginFeatureIsEnabled()) if (!isWeb && !bind.isIncomingOnly() && bind.pluginFeatureIsEnabled())
SettingsTabKey.plugin, SettingsTabKey.plugin,
if (!bind.isDisableAccount()) SettingsTabKey.account, if (!bind.isDisableAccount()) SettingsTabKey.account,
if (isWindows && bind.mainGetBuildinOption(key: kOptionHideRemotePrinterSetting) != 'Y') SettingsTabKey.printer, if (isWindows &&
bind.mainGetBuildinOption(key: kOptionHideRemotePrinterSetting) != 'Y')
SettingsTabKey.printer,
SettingsTabKey.about, SettingsTabKey.about,
]; ];
@ -1602,6 +1604,7 @@ class _DisplayState extends State<_Display> {
scrollStyle(context), scrollStyle(context),
imageQuality(context), imageQuality(context),
codec(context), codec(context),
if (isDesktop) trackpadSpeed(context),
if (!isWeb) privacyModeImpl(context), if (!isWeb) privacyModeImpl(context),
other(context), other(context),
]).marginOnly(bottom: _kListViewBottomMargin); ]).marginOnly(bottom: _kListViewBottomMargin);
@ -1689,6 +1692,26 @@ class _DisplayState extends State<_Display> {
]); ]);
} }
Widget trackpadSpeed(BuildContext context) {
final initSpeed = (int.tryParse(
bind.mainGetUserDefaultOption(key: kKeyTrackpadSpeed)) ??
kDefaultTrackpadSpeed);
final curSpeed = SimpleWrapper(initSpeed);
void onDebouncer(int v) {
bind.mainSetUserDefaultOption(
key: kKeyTrackpadSpeed, value: v.toString());
// It's better to notify all sessions that the default speed is changed.
// But it may also be ok to take effect in the next connection.
}
return _Card(title: 'Default trackpad speed', children: [
TrackpadSpeedWidget(
value: curSpeed,
onDebouncer: onDebouncer,
),
]);
}
Widget codec(BuildContext context) { Widget codec(BuildContext context) {
onChanged(String value) async { onChanged(String value) async {
await bind.mainSetUserDefaultOption( await bind.mainSetUserDefaultOption(

View file

@ -4,6 +4,7 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_hbb/common/widgets/audio_input.dart'; import 'package:flutter_hbb/common/widgets/audio_input.dart';
import 'package:flutter_hbb/common/widgets/dialog.dart';
import 'package:flutter_hbb/common/widgets/toolbar.dart'; import 'package:flutter_hbb/common/widgets/toolbar.dart';
import 'package:flutter_hbb/models/chat_model.dart'; import 'package:flutter_hbb/models/chat_model.dart';
import 'package:flutter_hbb/models/state_model.dart'; import 'package:flutter_hbb/models/state_model.dart';
@ -1594,10 +1595,28 @@ class _KeyboardMenu extends StatelessWidget {
viewMode(), viewMode(),
Divider(), Divider(),
...toolbarToggles(), ...toolbarToggles(),
...mouseSpeed(),
...mobileActions(), ...mobileActions(),
]); ]);
} }
mouseSpeed() {
final speedWidgets = [];
final sessionId = ffi.sessionId;
if (isDesktop) {
if (ffi.ffiModel.keyboard) {
final enabled = !ffi.ffiModel.viewOnly;
final trackpad = MenuButton(
child: Text(translate('Trackpad speed')).paddingOnly(left: 26.0),
onPressed: enabled ? () => trackpadSpeedDialog(sessionId, ffi) : null,
ffi: ffi,
);
speedWidgets.add(trackpad);
}
}
return speedWidgets;
}
keyboardMode() { keyboardMode() {
return futureBuilder(future: () async { return futureBuilder(future: () async {
return await bind.sessionGetKeyboardMode(sessionId: ffi.sessionId) ?? return await bind.sessionGetKeyboardMode(sessionId: ffi.sessionId) ??

View file

@ -345,8 +345,11 @@ class InputModel {
var _fling = false; var _fling = false;
Timer? _flingTimer; Timer? _flingTimer;
final _flingBaseDelay = 30; final _flingBaseDelay = 30;
// trackpad, peer linux final _trackpadAdjustPeerLinux = 0.06;
final _trackpadSpeed = 0.06; // This is an experience value.
final _trackpadAdjustMacToWin = 2.50;
int _trackpadSpeed = kDefaultTrackpadSpeed;
double _trackpadSpeedInner = kDefaultTrackpadSpeed / 100.0;
var _trackpadScrollUnsent = Offset.zero; var _trackpadScrollUnsent = Offset.zero;
var _lastScale = 1.0; var _lastScale = 1.0;
@ -370,6 +373,7 @@ class InputModel {
bool get isViewOnly => parent.target!.ffiModel.viewOnly; bool get isViewOnly => parent.target!.ffiModel.viewOnly;
double get devicePixelRatio => parent.target!.canvasModel.devicePixelRatio; double get devicePixelRatio => parent.target!.canvasModel.devicePixelRatio;
bool get isViewCamera => parent.target!.connType == ConnType.viewCamera; bool get isViewCamera => parent.target!.connType == ConnType.viewCamera;
int get trackpadSpeed => _trackpadSpeed;
InputModel(this.parent) { InputModel(this.parent) {
sessionId = parent.target!.sessionId; sessionId = parent.target!.sessionId;
@ -385,6 +389,28 @@ class InputModel {
} }
} }
/// Updates the trackpad speed based on the session value.
///
/// The expected format of the retrieved value is a string that can be parsed into a double.
/// If parsing fails or the value is out of bounds (less than `kMinTrackpadSpeed` or greater
/// than `kMaxTrackpadSpeed`), the trackpad speed is reset to the default
/// value (`kDefaultTrackpadSpeed`).
///
/// Bounds:
/// - Minimum: `kMinTrackpadSpeed`
/// - Maximum: `kMaxTrackpadSpeed`
/// - Default: `kDefaultTrackpadSpeed`
Future<void> updateTrackpadSpeed() async {
_trackpadSpeed =
(await bind.sessionGetTrackpadSpeed(sessionId: sessionId) ??
kDefaultTrackpadSpeed);
if (_trackpadSpeed < kMinTrackpadSpeed ||
_trackpadSpeed > kMaxTrackpadSpeed) {
_trackpadSpeed = kDefaultTrackpadSpeed;
}
_trackpadSpeedInner = _trackpadSpeed / 100.0;
}
void handleKeyDownEventModifiers(KeyEvent e) { void handleKeyDownEventModifiers(KeyEvent e) {
KeyUpEvent upEvent(e) => KeyUpEvent( KeyUpEvent upEvent(e) => KeyUpEvent(
physicalKey: e.physicalKey, physicalKey: e.physicalKey,
@ -888,13 +914,16 @@ class InputModel {
} }
} }
final delta = e.panDelta; var delta = e.panDelta * _trackpadSpeedInner;
if (isMacOS && peerPlatform == kPeerPlatformWindows) {
delta *= _trackpadAdjustMacToWin;
}
_trackpadLastDelta = delta; _trackpadLastDelta = delta;
var x = delta.dx.toInt(); var x = delta.dx.toInt();
var y = delta.dy.toInt(); var y = delta.dy.toInt();
if (peerPlatform == kPeerPlatformLinux) { if (peerPlatform == kPeerPlatformLinux) {
_trackpadScrollUnsent += (delta * _trackpadSpeed); _trackpadScrollUnsent += (delta * _trackpadAdjustPeerLinux);
x = _trackpadScrollUnsent.dx.truncate(); x = _trackpadScrollUnsent.dx.truncate();
y = _trackpadScrollUnsent.dy.truncate(); y = _trackpadScrollUnsent.dy.truncate();
_trackpadScrollUnsent -= Offset(x.toDouble(), y.toDouble()); _trackpadScrollUnsent -= Offset(x.toDouble(), y.toDouble());
@ -942,8 +971,8 @@ class InputModel {
var dx = x.toInt(); var dx = x.toInt();
var dy = y.toInt(); var dy = y.toInt();
if (parent.target?.ffiModel.pi.platform == kPeerPlatformLinux) { if (parent.target?.ffiModel.pi.platform == kPeerPlatformLinux) {
dx = (x * _trackpadSpeed).toInt(); dx = (x * _trackpadAdjustPeerLinux).toInt();
dy = (y * _trackpadSpeed).toInt(); dy = (y * _trackpadAdjustPeerLinux).toInt();
} }
var delay = _flingBaseDelay; var delay = _flingBaseDelay;
@ -989,7 +1018,10 @@ class InputModel {
_stopFling = false; _stopFling = false;
// 2.0 is an experience value // 2.0 is an experience value
double minFlingValue = 2.0; double minFlingValue = 2.0 * _trackpadSpeedInner;
if (isMacOS && peerPlatform == kPeerPlatformWindows) {
minFlingValue *= _trackpadAdjustMacToWin;
}
if (_trackpadLastDelta.dx.abs() > minFlingValue || if (_trackpadLastDelta.dx.abs() > minFlingValue ||
_trackpadLastDelta.dy.abs() > minFlingValue) { _trackpadLastDelta.dy.abs() > minFlingValue) {
_fling = true; _fling = true;

View file

@ -2991,6 +2991,10 @@ class FFI {
textureModel.updateCurrentDisplay(display ?? 0); textureModel.updateCurrentDisplay(display ?? 0);
} }
if (isDesktop) {
inputModel.updateTrackpadSpeed();
}
// CAUTION: `sessionStart()` and `sessionStartWithDisplays()` are an async functions. // CAUTION: `sessionStart()` and `sessionStartWithDisplays()` are an async functions.
// Though the stream is returned immediately, the stream may not be ready. // Though the stream is returned immediately, the stream may not be ready.
// Any operations that depend on the stream should be carefully handled. // Any operations that depend on the stream should be carefully handled.

@ -1 +1 @@
Subproject commit 7839dcf4e4ddc3feab9b52b0ae1903d443bc084d Subproject commit 6e556f7e1751a3a709cd5cca0df7268ba3cb1c48

View file

@ -2105,6 +2105,12 @@ impl LoginConfigHandler {
res res
} }
pub fn save_trackpad_speed(&mut self, speed: i32) {
let mut config = self.load_config();
config.trackpad_speed = speed;
self.save_config(config);
}
/// Create a [`Message`] for saving custom fps. /// Create a [`Message`] for saving custom fps.
/// ///
/// # Arguments /// # Arguments

View file

@ -492,6 +492,20 @@ pub fn session_set_custom_fps(session_id: SessionID, fps: i32) {
} }
} }
pub fn session_get_trackpad_speed(session_id: SessionID) -> Option<i32> {
if let Some(session) = sessions::get_session_by_session_id(&session_id) {
Some(session.get_trackpad_speed())
} else {
None
}
}
pub fn session_set_trackpad_speed(session_id: SessionID, value: i32) {
if let Some(session) = sessions::get_session_by_session_id(&session_id) {
session.save_trackpad_speed(value);
}
}
pub fn session_lock_screen(session_id: SessionID) { pub fn session_lock_screen(session_id: SessionID) {
if let Some(session) = sessions::get_session_by_session_id(&session_id) { if let Some(session) = sessions::get_session_by_session_id(&session_id) {
session.lock_screen(); session.lock_screen();

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", "安装方式检测失败。请点击\"下载\"按钮,从发布网址下载,并手动升级。"), ("update-failed-check-msi-tip", "安装方式检测失败。请点击\"下载\"按钮,从发布网址下载,并手动升级。"),
("websocket_tip", "使用 WebSocket 时,仅支持中继连接。"), ("websocket_tip", "使用 WebSocket 时,仅支持中继连接。"),
("Use WebSocket", "使用 WebSocket"), ("Use WebSocket", "使用 WebSocket"),
("Trackpad speed", "触控板速度"),
("Default trackpad speed", "默认触控板速度"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", "Prüfung der Installationsmethode fehlgeschlagen. Bitte klicken Sie auf die Schaltfläche \"Herunterladen\", um von der Versionsseite herunterzuladen und manuell zu aktualisieren."), ("update-failed-check-msi-tip", "Prüfung der Installationsmethode fehlgeschlagen. Bitte klicken Sie auf die Schaltfläche \"Herunterladen\", um von der Versionsseite herunterzuladen und manuell zu aktualisieren."),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", "Controllo metodo installazione non riuscito.\nSeleziona 'Download' per scaricare il programma e aggiornarlo manualmente."), ("update-failed-check-msi-tip", "Controllo metodo installazione non riuscito.\nSeleziona 'Download' per scaricare il programma e aggiornarlo manualmente."),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", "업데이트에 실패했습니다. .msi 설치 파일을 확인하세요."), ("update-failed-check-msi-tip", "업데이트에 실패했습니다. .msi 설치 파일을 확인하세요."),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", "Kan de installatiemethode niet bepalen. Klik op “Downloaden” om de applicatie van de officiële website te downloaden en handmatig bij te werken."), ("update-failed-check-msi-tip", "Kan de installatiemethode niet bepalen. Klik op “Downloaden” om de applicatie van de officiële website te downloaden en handmatig bij te werken."),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", "Sprawdzenie metody instalacji nie powiodło się. Kliknij przycisk \"Pobierz\", aby pobrać ze strony wydania i uaktualnić ręcznie."), ("update-failed-check-msi-tip", "Sprawdzenie metody instalacji nie powiodło się. Kliknij przycisk \"Pobierz\", aby pobrać ze strony wydania i uaktualnić ręcznie."),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", "Невозможно определить метод установки. Нажмите кнопку \"Скачать\", чтобы скачать приложение с официального сайта и обновить его вручную."), ("update-failed-check-msi-tip", "Невозможно определить метод установки. Нажмите кнопку \"Скачать\", чтобы скачать приложение с официального сайта и обновить его вручную."),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -696,5 +696,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("update-failed-check-msi-tip", ""), ("update-failed-check-msi-tip", ""),
("websocket_tip", ""), ("websocket_tip", ""),
("Use WebSocket", ""), ("Use WebSocket", ""),
("Trackpad speed", ""),
("Default trackpad speed", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View file

@ -230,6 +230,10 @@ impl<T: InvokeUiSession> Session<T> {
self.lc.read().unwrap().version.clone() self.lc.read().unwrap().version.clone()
} }
pub fn get_trackpad_speed(&self) -> i32 {
self.lc.read().unwrap().trackpad_speed
}
pub fn fallback_keyboard_mode(&self) -> String { pub fn fallback_keyboard_mode(&self) -> String {
let peer_version = self.get_peer_version(); let peer_version = self.get_peer_version();
let platform = self.peer_platform(); let platform = self.peer_platform();
@ -448,6 +452,10 @@ impl<T: InvokeUiSession> Session<T> {
} }
} }
pub fn save_trackpad_speed(&self, trackpad_speed: i32) {
self.lc.write().unwrap().save_trackpad_speed(trackpad_speed);
}
pub fn set_custom_fps(&self, custom_fps: i32) { pub fn set_custom_fps(&self, custom_fps: i32) {
let msg = self.lc.write().unwrap().set_custom_fps(custom_fps, true); let msg = self.lc.write().unwrap().set_custom_fps(custom_fps, true);
self.send(Data::Message(msg)); self.send(Data::Message(msg));