Skip to content

Commit 5439ec3

Browse files
authored
Revert "fix web break introduced in 38f1300 fix(linux): enable mouse side buttons in remote sessions (rustdesk#14848)" (rustdesk#14973)
This reverts commit d5d0b01.
1 parent 8b8a64f commit 5439ec3

10 files changed

Lines changed: 10 additions & 266 deletions

File tree

flutter/lib/common/widgets/toolbar.dart

Lines changed: 7 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -16,43 +16,16 @@ import 'package:get/get.dart';
1616

1717
bool isEditOsPassword = false;
1818

19-
/// Action IDs that `toolbarControls` is the sole registrar for. Each call to
20-
/// `toolbarControls` (e.g. opening the toolbar menu after a permission was
21-
/// revoked or a state changed) wipes these so a previously-registered closure
22-
/// can't outlive the menu entry that owns it. The for-loop at the bottom of
23-
/// `toolbarControls` then re-registers whichever entries are still present in
24-
/// the rebuilt menu list.
25-
///
26-
/// Actions registered elsewhere — `registerSessionShortcutActions` on desktop
27-
/// owns toggle_recording, fullscreen, switch_display, switch_tab, close_tab,
28-
/// toggle_toolbar — MUST NOT appear here, otherwise this list would clobber
29-
/// their registration on every menu rebuild.
30-
///
31-
/// `kShortcutActionToggleRecording` is platform-conditional (mobile-only —
32-
/// see the `!(isDesktop || isWeb)` guard in `toolbarControls`). It is handled
33-
/// separately in the unregister pass rather than appearing in this const list.
34-
const _kToolbarOwnedActionIds = <String>[
35-
kShortcutActionSendCtrlAltDel,
36-
kShortcutActionRestartRemote,
37-
kShortcutActionInsertLock,
38-
kShortcutActionToggleBlockInput,
39-
kShortcutActionSwitchSides,
40-
kShortcutActionRefresh,
41-
kShortcutActionScreenshot,
42-
];
43-
4419
class TTextMenu {
4520
final Widget child;
4621
final VoidCallback? onPressed;
4722
Widget? trailingIcon;
4823
bool divider;
49-
final String? actionId;
5024
TTextMenu(
5125
{required this.child,
5226
required this.onPressed,
5327
this.trailingIcon,
54-
this.divider = false,
55-
this.actionId});
28+
this.divider = false});
5629

5730
Widget getChild() {
5831
if (trailingIcon != null) {
@@ -121,20 +94,6 @@ List<TTextMenu> toolbarControls(BuildContext context, String id, FFI ffi) {
12194
final sessionId = ffi.sessionId;
12295
final isDefaultConn = ffi.connType == ConnType.defaultConn;
12396

124-
// Wipe everything `toolbarControls` could have registered last call so
125-
// stale closures (e.g. for a menu entry whose permission has since been
126-
// revoked) don't outlive the menu rebuild. See _kToolbarOwnedActionIds.
127-
for (final actionId in _kToolbarOwnedActionIds) {
128-
ffi.shortcutModel.unregister(actionId);
129-
}
130-
// toggle_recording is platform-conditional — toolbarControls only builds
131-
// the menu entry on `!(isDesktop || isWeb)`. On desktop the registration
132-
// is owned by `registerSessionShortcutActions` and must NOT be touched
133-
// here. See the recording menu entry below.
134-
if (!(isDesktop || isWeb)) {
135-
ffi.shortcutModel.unregister(kShortcutActionToggleRecording);
136-
}
137-
13897
List<TTextMenu> v = [];
13998
// elevation
14099
if (isDefaultConn &&
@@ -270,8 +229,7 @@ List<TTextMenu> toolbarControls(BuildContext context, String id, FFI ffi) {
270229
v.add(
271230
TTextMenu(
272231
child: Text('${translate("Insert Ctrl + Alt + Del")}'),
273-
onPressed: () => bind.sessionCtrlAltDel(sessionId: sessionId),
274-
actionId: kShortcutActionSendCtrlAltDel),
232+
onPressed: () => bind.sessionCtrlAltDel(sessionId: sessionId)),
275233
);
276234
}
277235
// restart
@@ -284,17 +242,15 @@ List<TTextMenu> toolbarControls(BuildContext context, String id, FFI ffi) {
284242
TTextMenu(
285243
child: Text(translate('Restart remote device')),
286244
onPressed: () =>
287-
showRestartRemoteDevice(pi, id, sessionId, ffi.dialogManager),
288-
actionId: kShortcutActionRestartRemote),
245+
showRestartRemoteDevice(pi, id, sessionId, ffi.dialogManager)),
289246
);
290247
}
291248
// insertLock
292249
if (isDefaultConn && !ffiModel.viewOnly && ffi.ffiModel.keyboard) {
293250
v.add(
294251
TTextMenu(
295252
child: Text(translate('Insert Lock')),
296-
onPressed: () => bind.sessionLockScreen(sessionId: sessionId),
297-
actionId: kShortcutActionInsertLock),
253+
onPressed: () => bind.sessionLockScreen(sessionId: sessionId)),
298254
);
299255
}
300256
// blockUserInput
@@ -312,8 +268,7 @@ List<TTextMenu> toolbarControls(BuildContext context, String id, FFI ffi) {
312268
sessionId: sessionId,
313269
value: '${blockInput.value ? 'un' : ''}block-input');
314270
blockInput.value = !blockInput.value;
315-
},
316-
actionId: kShortcutActionToggleBlockInput));
271+
}));
317272
}
318273
// switchSides
319274
if (isDefaultConn &&
@@ -325,15 +280,13 @@ List<TTextMenu> toolbarControls(BuildContext context, String id, FFI ffi) {
325280
v.add(TTextMenu(
326281
child: Text(translate('Switch Sides')),
327282
onPressed: () =>
328-
showConfirmSwitchSidesDialog(sessionId, id, ffi.dialogManager),
329-
actionId: kShortcutActionSwitchSides));
283+
showConfirmSwitchSidesDialog(sessionId, id, ffi.dialogManager)));
330284
}
331285
// refresh
332286
if (pi.version.isNotEmpty) {
333287
v.add(TTextMenu(
334288
child: Text(translate('Refresh')),
335289
onPressed: () => sessionRefreshVideo(sessionId, pi),
336-
actionId: kShortcutActionRefresh,
337290
));
338291
}
339292
// record
@@ -355,8 +308,7 @@ List<TTextMenu> toolbarControls(BuildContext context, String id, FFI ffi) {
355308
)
356309
],
357310
),
358-
onPressed: () => ffi.recordingModel.toggle(),
359-
actionId: kShortcutActionToggleRecording));
311+
onPressed: () => ffi.recordingModel.toggle()));
360312
}
361313

362314
// to-do:
@@ -373,14 +325,6 @@ List<TTextMenu> toolbarControls(BuildContext context, String id, FFI ffi) {
373325
onPressed: ffi.ffiModel.timerScreenshot != null
374326
? null
375327
: () {
376-
// Live cooldown check: the menu rebuilds onPressed=null
377-
// whenever toolbarControls runs and finds timerScreenshot
378-
// != null, but the keyboard-shortcut callback holds onto
379-
// the originally-enabled closure across cooldown periods
380-
// (toolbarControls only re-runs on menu open). Without
381-
// this guard the second shortcut press during the 30s
382-
// cooldown still fires sessionTakeScreenshot.
383-
if (ffi.ffiModel.timerScreenshot != null) return;
384328
if (pi.currentDisplay == kAllDisplayValue) {
385329
msgBox(
386330
sessionId,
@@ -398,7 +342,6 @@ List<TTextMenu> toolbarControls(BuildContext context, String id, FFI ffi) {
398342
});
399343
}
400344
},
401-
actionId: kShortcutActionScreenshot,
402345
));
403346
}
404347
}
@@ -409,28 +352,6 @@ List<TTextMenu> toolbarControls(BuildContext context, String id, FFI ffi) {
409352
onPressed: () => onCopyFingerprint(FingerprintState.find(id).value),
410353
));
411354
}
412-
// Register tagged callbacks with the shortcut model so global keyboard
413-
// shortcuts can dispatch the same actions as the toolbar menu items.
414-
//
415-
// For action IDs already cleared at the top of this function (i.e. those
416-
// in [_kToolbarOwnedActionIds] plus the conditional toggle_recording),
417-
// the `else` branch below is a redundant idempotent no-op — `unregister`
418-
// just calls `Map.remove` on something already absent.
419-
//
420-
// The branch is kept as **defense in depth** for the case where a future
421-
// contributor tags a menu item with an actionId that they forget to add
422-
// to [_kToolbarOwnedActionIds]: without this `else`, the original
423-
// "stale-closure-outlives-disabled-state" bug (e.g. Screenshot cooldown
424-
// bypass) would silently come back for that new action only.
425-
for (final menu in v) {
426-
final actionId = menu.actionId;
427-
if (actionId == null) continue;
428-
if (menu.onPressed != null) {
429-
ffi.shortcutModel.register(actionId, menu.onPressed!);
430-
} else {
431-
ffi.shortcutModel.unregister(actionId);
432-
}
433-
}
434355
return v;
435356
}
436357

flutter/lib/consts.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import 'package:flutter_hbb/common.dart';
44
import 'package:flutter_hbb/models/state_model.dart';
55
import 'package:get/get.dart';
66

7-
export 'common/widgets/keyboard_shortcuts/shortcut_constants.dart';
8-
97
const int kMaxVirtualDisplayCount = 4;
108
const int kAllVirtualDisplay = -1;
119

flutter/lib/desktop/pages/desktop_setting_page.dart

Lines changed: 1 addition & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,12 @@ import 'package:flutter_hbb/common/widgets/audio_input.dart';
1010
import 'package:flutter_hbb/common/widgets/setting_widgets.dart';
1111
import 'package:flutter_hbb/consts.dart';
1212
import 'package:flutter_hbb/desktop/pages/desktop_home_page.dart';
13-
import 'package:flutter_hbb/desktop/pages/desktop_keyboard_shortcuts_page.dart';
1413
import 'package:flutter_hbb/desktop/pages/desktop_tab_page.dart';
1514
import 'package:flutter_hbb/desktop/widgets/remote_toolbar.dart';
1615
import 'package:flutter_hbb/mobile/widgets/dialog.dart';
1716
import 'package:flutter_hbb/models/platform_model.dart';
1817
import 'package:flutter_hbb/models/printer_model.dart';
1918
import 'package:flutter_hbb/models/server_model.dart';
20-
import 'package:flutter_hbb/models/shortcut_model.dart';
2119
import 'package:flutter_hbb/models/state_model.dart';
2220
import 'package:flutter_hbb/plugin/manager.dart';
2321
import 'package:flutter_hbb/plugin/widgets/desktop_settings.dart';
@@ -423,49 +421,11 @@ class _GeneralState extends State<_General> {
423421
if (!isWeb) audio(context),
424422
if (!isWeb) record(context),
425423
if (!isWeb) WaylandCard(),
426-
other(),
427-
if (!bind.isIncomingOnly()) keyboardShortcuts(),
424+
other()
428425
],
429426
).marginOnly(bottom: _kListViewBottomMargin);
430427
}
431428

432-
Widget keyboardShortcuts() {
433-
// The bindings JSON (LocalConfig key `keyboard-shortcuts`) holds three
434-
// flags + the bindings list: {enabled, pass_through, bindings}. When the
435-
// master is off, the pass-through toggle and the Configure entry are
436-
// hidden — both are meaningless without an active matcher.
437-
return StatefulBuilder(builder: (context, setLocalState) {
438-
final enabled = ShortcutModel.isEnabled();
439-
return _Card(title: 'Keyboard Shortcuts', children: [
440-
_OptionCheckBox(
441-
context,
442-
'Enable keyboard shortcuts in remote session',
443-
kShortcutLocalConfigKey,
444-
isServer: false,
445-
optGetter: ShortcutModel.isEnabled,
446-
optSetter: (_, v) async {
447-
await ShortcutModel.setEnabled(v);
448-
setLocalState(() {});
449-
},
450-
),
451-
if (enabled) ...[
452-
_OptionCheckBox(
453-
context,
454-
'Pass-through to remote',
455-
kShortcutLocalConfigKey,
456-
isServer: false,
457-
optGetter: ShortcutModel.isPassThrough,
458-
optSetter: (_, v) async {
459-
await ShortcutModel.setPassThrough(v);
460-
setLocalState(() {});
461-
},
462-
),
463-
_ShortcutsConfigureRow(),
464-
],
465-
]);
466-
});
467-
}
468-
469429
Widget theme() {
470430
final current = MyTheme.getThemeModePreference().toShortString();
471431
onChanged(String value) async {
@@ -2990,37 +2950,6 @@ class _CountDownButtonState extends State<_CountDownButton> {
29902950
}
29912951
}
29922952

2993-
// Tappable row that pushes the shortcut configuration page.
2994-
class _ShortcutsConfigureRow extends StatelessWidget {
2995-
// ignore: unused_element
2996-
const _ShortcutsConfigureRow({Key? key}) : super(key: key);
2997-
2998-
@override
2999-
Widget build(BuildContext context) {
3000-
return InkWell(
3001-
onTap: () {
3002-
Navigator.of(context).push(MaterialPageRoute(
3003-
builder: (_) => const DesktopKeyboardShortcutsPage(),
3004-
));
3005-
},
3006-
child: Row(
3007-
children: [
3008-
Expanded(
3009-
child: Text(translate('Configure shortcuts...')),
3010-
),
3011-
Icon(Icons.arrow_forward_ios,
3012-
size: 16, color: disabledTextColor(context, true))
3013-
.marginOnly(right: 4),
3014-
],
3015-
).marginOnly(
3016-
left: _kCheckBoxLeftMargin,
3017-
top: 6,
3018-
bottom: 6,
3019-
),
3020-
);
3021-
}
3022-
}
3023-
30242953
//#endregion
30252954

30262955
//#region dialogs

flutter/lib/desktop/pages/remote_page.dart

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import '../../common/widgets/toolbar.dart';
1717
import '../../models/model.dart';
1818
import '../../models/input_model.dart';
1919
import '../../models/platform_model.dart';
20-
import '../../models/shortcut_model.dart';
2120
import '../../common/shared_state.dart';
2221
import '../../utils/image.dart';
2322
import '../widgets/remote_toolbar.dart';
@@ -127,20 +126,6 @@ class _RemotePageState extends State<RemotePage>
127126
_ffi.ffiModel.pi.platform, _ffi.dialogManager);
128127
_ffi.recordingModel
129128
.updateStatus(bind.sessionGetIsRecording(sessionId: _ffi.sessionId));
130-
// Seed shortcut action callbacks once the session is ready, so that
131-
// global keyboard shortcuts work even if the user never opens the
132-
// toolbar menu. The returned list is intentionally discarded — the
133-
// side effect of registering callbacks (inside toolbarControls) is
134-
// what we want here.
135-
if (mounted) {
136-
toolbarControls(context, widget.id, _ffi);
137-
// Register the default-bound actions that `toolbarControls` doesn't
138-
// own (fullscreen, switch display, switch tab). Done in addition,
139-
// not instead of, the toolbar registration above.
140-
registerSessionShortcutActions(_ffi,
141-
tabController: widget.tabController,
142-
toolbarState: widget.toolbarState);
143-
}
144129
});
145130
_ffi.canvasModel.initializeEdgeScrollFallback(this);
146131
_ffi.start(

flutter/lib/desktop/widgets/remote_toolbar.dart

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import 'package:flutter/material.dart';
55
import 'package:flutter/services.dart';
66
import 'package:flutter_hbb/common/widgets/audio_input.dart';
77
import 'package:flutter_hbb/common/widgets/dialog.dart';
8-
import 'package:flutter_hbb/common/widgets/keyboard_shortcuts/display.dart';
98
import 'package:flutter_hbb/common/widgets/toolbar.dart';
109
import 'package:flutter_hbb/models/chat_model.dart';
1110
import 'package:flutter_hbb/models/state_model.dart';
@@ -764,31 +763,8 @@ class _ControlMenu extends StatelessWidget {
764763
if (e.divider) {
765764
return Divider();
766765
} else {
767-
final hint = e.actionId == null
768-
? null
769-
: ShortcutDisplay.formatFor(e.actionId!);
770-
final child = hint == null
771-
? e.child
772-
: Row(
773-
mainAxisSize: MainAxisSize.min,
774-
children: [
775-
Flexible(child: e.child),
776-
Padding(
777-
padding: const EdgeInsets.only(left: 16),
778-
child: Text(
779-
hint,
780-
style: Theme.of(context)
781-
.textTheme
782-
.bodySmall
783-
?.copyWith(
784-
color: Theme.of(context).hintColor,
785-
),
786-
),
787-
),
788-
],
789-
);
790766
return MenuButton(
791-
child: child,
767+
child: e.child,
792768
onPressed: e.onPressed,
793769
ffi: ffi,
794770
trailingIcon: e.trailingIcon);

flutter/lib/mobile/pages/remote_page.dart

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import '../../common/widgets/remote_input.dart';
2121
import '../../models/input_model.dart';
2222
import '../../models/model.dart';
2323
import '../../models/platform_model.dart';
24-
import '../../models/shortcut_model.dart';
2524
import '../../utils/image.dart';
2625
import '../widgets/dialog.dart';
2726
import '../widgets/custom_scale_widget.dart';
@@ -120,18 +119,6 @@ class _RemotePageState extends State<RemotePage> with WidgetsBindingObserver {
120119
}
121120
_disableAndroidSoftKeyboard(
122121
isKeyboardVisible: keyboardVisibilityController.isVisible);
123-
// Seed shortcut action callbacks once the session is ready, so that
124-
// global keyboard shortcuts work even if the user never opens the
125-
// toolbar menu. The returned list is intentionally discarded — the
126-
// side effect of registering callbacks (inside toolbarControls) is
127-
// what we want here.
128-
if (mounted) {
129-
toolbarControls(context, widget.id, gFFI);
130-
// Mobile has no DesktopTabController, so tab-switch shortcuts
131-
// remain unregistered (they will simply log a no-handler debug
132-
// line if a mobile user binds one — they have no tabs to switch).
133-
registerSessionShortcutActions(gFFI);
134-
}
135122
});
136123
WidgetsBinding.instance.addObserver(this);
137124
}

0 commit comments

Comments
 (0)