mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-09-26 23:35:46 +00:00
fix(keyboard): shortcuts, drop the Toggle Input Source action
The action switches the key capture backend between key down and key up. Fired-key ownership lives in whichever matcher saw the press, the Flutter dispatcher or the Rust set, and there is no handoff between them: after the switch the repeats and the release of the held key reach the other backend, which forwards them to the remote and, while the chord is held, matches the action again and toggles the source back. Remove the shortcut instead of building a handoff for one action. The toolbar radio menu is unchanged. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ra4my61t8q1FN5n59wB16D
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
001bdbcdd9
commit
63654263ed
@@ -148,8 +148,6 @@ final List<KeyboardShortcutActionGroup> kKeyboardShortcutActionGroups = [
|
||||
KeyboardShortcutActionEntry(
|
||||
kShortcutActionKeyboardModeTranslate, 'Translate mode'),
|
||||
]),
|
||||
KeyboardShortcutActionEntry(
|
||||
kShortcutActionToggleInputSource, 'Toggle input source'),
|
||||
KeyboardShortcutActionEntry(kShortcutActionToggleViewOnly, 'View Mode'),
|
||||
KeyboardShortcutActionEntry(
|
||||
kShortcutActionToggleShowMyCursor, 'Show my cursor'),
|
||||
@@ -258,10 +256,6 @@ List<KeyboardShortcutActionGroup> filterKeyboardShortcutActionGroupsForPlatform(
|
||||
id == kShortcutActionViewModeCustom)) {
|
||||
return false;
|
||||
}
|
||||
if (!cap.includeInputSourceShortcut &&
|
||||
id == kShortcutActionToggleInputSource) {
|
||||
return false;
|
||||
}
|
||||
if (!cap.includeVoiceCallShortcut && id == kShortcutActionToggleVoiceCall) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,6 @@ const kShortcutActionImageQualityBest = 'image_quality_best';
|
||||
const kShortcutActionImageQualityBalanced = 'image_quality_balanced';
|
||||
const kShortcutActionImageQualityLow = 'image_quality_low';
|
||||
const kShortcutActionSendClipboardKeystrokes = 'send_clipboard_keystrokes';
|
||||
const kShortcutActionToggleInputSource = 'toggle_input_source';
|
||||
const kShortcutActionToggleVoiceCall = 'toggle_voice_call';
|
||||
const kShortcutActionToggleViewOnly = 'toggle_view_only';
|
||||
|
||||
|
||||
@@ -117,7 +117,6 @@ class ShortcutPlatformCapabilities {
|
||||
final bool includeResetCanvasShortcut;
|
||||
final bool includePinToolbarShortcut;
|
||||
final bool includeViewModeShortcut;
|
||||
final bool includeInputSourceShortcut;
|
||||
final bool includeVoiceCallShortcut;
|
||||
|
||||
const ShortcutPlatformCapabilities({
|
||||
@@ -131,7 +130,6 @@ class ShortcutPlatformCapabilities {
|
||||
required this.includeResetCanvasShortcut,
|
||||
required this.includePinToolbarShortcut,
|
||||
required this.includeViewModeShortcut,
|
||||
required this.includeInputSourceShortcut,
|
||||
required this.includeVoiceCallShortcut,
|
||||
});
|
||||
}
|
||||
@@ -185,10 +183,6 @@ List<Map<String, dynamic>> filterDefaultBindingsForPlatform(
|
||||
action == kShortcutActionViewModeCustom)) {
|
||||
continue;
|
||||
}
|
||||
if (!cap.includeInputSourceShortcut &&
|
||||
action == kShortcutActionToggleInputSource) {
|
||||
continue;
|
||||
}
|
||||
if (!cap.includeVoiceCallShortcut &&
|
||||
action == kShortcutActionToggleVoiceCall) {
|
||||
continue;
|
||||
|
||||
@@ -203,9 +203,6 @@ class ShortcutModel {
|
||||
/// `recordingModel.toggle()`; Web has no implementation.
|
||||
/// * Reset Canvas: only the mobile toolbar builds the menu entry
|
||||
/// (`isDefaultConn && isMobile` in `toolbarControls`).
|
||||
/// * Input Source: Web only ships a single source so toggling is a
|
||||
/// no-op; the toolbar menu hides itself when fewer than 2 sources are
|
||||
/// advertised.
|
||||
/// * Voice Call: Web bridge throws `UnimplementedError` for both
|
||||
/// `sessionRequestVoiceCall` and `sessionCloseVoiceCall`.
|
||||
static ShortcutPlatformCapabilities currentPlatformCapabilities() {
|
||||
@@ -221,7 +218,6 @@ class ShortcutModel {
|
||||
includeResetCanvasShortcut: isMobile,
|
||||
includePinToolbarShortcut: desktopLayout,
|
||||
includeViewModeShortcut: desktopLayout,
|
||||
includeInputSourceShortcut: !isWeb,
|
||||
includeVoiceCallShortcut: !isWeb,
|
||||
);
|
||||
}
|
||||
@@ -605,36 +601,4 @@ void registerSessionShortcutActions(
|
||||
ffi.inputModel.toggleRelativeMouseMode();
|
||||
});
|
||||
}
|
||||
|
||||
// Toggle Input Source — flips between the available keyboard-event capture
|
||||
// backends (e.g. JS vs Flutter on desktop). Mirrors the radio menu in
|
||||
// remote_toolbar.dart::inputSource(); when fewer than 2 sources are
|
||||
// available the menu hides itself, so this handler is a no-op too.
|
||||
// Useful for accessibility: screen-reader users sometimes need to swap
|
||||
// sources to regain control of the local keyboard (discussion #1933).
|
||||
// Web only ships a single source, so we don't register on web.
|
||||
if (!isWeb) {
|
||||
ffi.shortcutModel.register(kShortcutActionToggleInputSource, () async {
|
||||
final raw = bind.mainSupportedInputSource();
|
||||
if (raw.isEmpty) return;
|
||||
final List<dynamic> list;
|
||||
try {
|
||||
list = jsonDecode(raw) as List<dynamic>;
|
||||
} catch (_) {
|
||||
return;
|
||||
}
|
||||
if (list.length < 2) return;
|
||||
final ids = list
|
||||
.map((e) => (e is List && e.isNotEmpty) ? e[0] as String : '')
|
||||
.where((s) => s.isNotEmpty)
|
||||
.toList();
|
||||
if (ids.length < 2) return;
|
||||
final current = stateGlobal.getInputSource();
|
||||
final idx = ids.indexOf(current);
|
||||
final next = ids[(idx < 0 ? 0 : idx + 1) % ids.length];
|
||||
await stateGlobal.setInputSource(sessionId, next);
|
||||
await ffi.ffiModel.checkDesktopKeyboardMode();
|
||||
await ffi.inputModel.updateKeyboardMode();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ ShortcutPlatformCapabilities capabilities({
|
||||
bool includeResetCanvasShortcut = true,
|
||||
bool includePinToolbarShortcut = true,
|
||||
bool includeViewModeShortcut = true,
|
||||
bool includeInputSourceShortcut = true,
|
||||
bool includeVoiceCallShortcut = true,
|
||||
}) {
|
||||
return ShortcutPlatformCapabilities(
|
||||
@@ -32,7 +31,6 @@ ShortcutPlatformCapabilities capabilities({
|
||||
includeResetCanvasShortcut: includeResetCanvasShortcut,
|
||||
includePinToolbarShortcut: includePinToolbarShortcut,
|
||||
includeViewModeShortcut: includeViewModeShortcut,
|
||||
includeInputSourceShortcut: includeInputSourceShortcut,
|
||||
includeVoiceCallShortcut: includeVoiceCallShortcut,
|
||||
);
|
||||
}
|
||||
@@ -197,7 +195,6 @@ void main() {
|
||||
includeResetCanvasShortcut: false,
|
||||
includePinToolbarShortcut: false,
|
||||
includeViewModeShortcut: false,
|
||||
includeInputSourceShortcut: false,
|
||||
includeVoiceCallShortcut: false,
|
||||
),
|
||||
);
|
||||
@@ -248,7 +245,6 @@ void main() {
|
||||
includeResetCanvasShortcut: true,
|
||||
includePinToolbarShortcut: false,
|
||||
includeViewModeShortcut: false,
|
||||
includeInputSourceShortcut: false,
|
||||
includeVoiceCallShortcut: false,
|
||||
),
|
||||
);
|
||||
@@ -358,7 +354,6 @@ void main() {
|
||||
' $kShortcutActionKeyboardModeLegacy',
|
||||
' $kShortcutActionKeyboardModeMap',
|
||||
' $kShortcutActionKeyboardModeTranslate',
|
||||
kShortcutActionToggleInputSource,
|
||||
kShortcutActionToggleViewOnly,
|
||||
kShortcutActionToggleShowMyCursor,
|
||||
kShortcutActionToggleSwapCtrlCmd,
|
||||
@@ -394,7 +389,6 @@ void main() {
|
||||
includeResetCanvasShortcut: false,
|
||||
includePinToolbarShortcut: false,
|
||||
includeViewModeShortcut: false,
|
||||
includeInputSourceShortcut: false,
|
||||
includeVoiceCallShortcut: false,
|
||||
),
|
||||
);
|
||||
@@ -503,8 +497,13 @@ void main() {
|
||||
// legacy IDs (toggle_audio, view_mode_shrink/stretch, view_mode_1_to_1)
|
||||
// were renamed: their replacements are kShortcutActionToggleMute and
|
||||
// kShortcutActionViewModeOriginal/Adaptive/Custom.
|
||||
//
|
||||
// `toggle_input_source` was removed on purpose: it switches the key
|
||||
// capture backend between key down and key up, so the matcher that
|
||||
// consumed the press never sees the repeats and the release.
|
||||
const knownRemoved = [
|
||||
'toggle_audio',
|
||||
'toggle_input_source',
|
||||
'view_mode_1_to_1',
|
||||
'view_mode_shrink',
|
||||
'view_mode_stretch',
|
||||
|
||||
@@ -68,7 +68,6 @@ pub mod action_id {
|
||||
pub const IMAGE_QUALITY_BALANCED: &str = "image_quality_balanced";
|
||||
pub const IMAGE_QUALITY_LOW: &str = "image_quality_low";
|
||||
pub const SEND_CLIPBOARD_KEYSTROKES: &str = "send_clipboard_keystrokes";
|
||||
pub const TOGGLE_INPUT_SOURCE: &str = "toggle_input_source";
|
||||
pub const SWITCH_TAB_NEXT: &str = "switch_tab_next";
|
||||
pub const SWITCH_TAB_PREV: &str = "switch_tab_prev";
|
||||
pub const TOGGLE_VOICE_CALL: &str = "toggle_voice_call";
|
||||
|
||||
Reference in New Issue
Block a user