Fix/linux shortcuts inhibit (#14302)

* feat: Inhibit system shortcuts on Linux

Fixes #13013.

Signed-off-by: Max von Forell <max@vonforell.de>

* fix(linux): shortcuts inhibit

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

---------

Signed-off-by: Max von Forell <max@vonforell.de>
Signed-off-by: fufesou <linlong1266@gmail.com>
Co-authored-by: Max von Forell <max@vonforell.de>
This commit is contained in:
fufesou
2026-02-11 16:11:47 +08:00
committed by GitHub
parent 6c541f7bfd
commit 2842315b1d
9 changed files with 580 additions and 2 deletions

View File

@@ -2538,6 +2538,49 @@ class WaylandCard extends StatefulWidget {
class _WaylandCardState extends State<WaylandCard> {
final restoreTokenKey = 'wayland-restore-token';
static const _kClearShortcutsInhibitorEventKey =
'clear-gnome-shortcuts-inhibitor-permission-res';
final _clearShortcutsInhibitorFailedMsg = ''.obs;
// Don't show the shortcuts permission reset button for now.
// Users can change it manually:
// "Settings" -> "Apps" -> "RustDesk" -> "Permissions" -> "Inhibit Shortcuts".
// For resetting(clearing) the permission from the portal permission store, you can
// use (replace <desktop-id> with the RustDesk desktop file ID):
// busctl --user call org.freedesktop.impl.portal.PermissionStore \
// /org/freedesktop/impl/portal/PermissionStore org.freedesktop.impl.portal.PermissionStore \
// DeletePermission sss "gnome" "shortcuts-inhibitor" "<desktop-id>"
// On a native install this is typically "rustdesk.desktop"; on Flatpak it is usually
// the exported desktop ID derived from the Flatpak app-id (e.g. "com.rustdesk.RustDesk.desktop").
//
// We may add it back in the future if needed.
final showResetInhibitorPermission = false;
@override
void initState() {
super.initState();
if (showResetInhibitorPermission) {
platformFFI.registerEventHandler(
_kClearShortcutsInhibitorEventKey, _kClearShortcutsInhibitorEventKey,
(evt) async {
if (!mounted) return;
if (evt['success'] == true) {
setState(() {});
} else {
_clearShortcutsInhibitorFailedMsg.value =
evt['msg'] as String? ?? 'Unknown error';
}
});
}
}
@override
void dispose() {
if (showResetInhibitorPermission) {
platformFFI.unregisterEventHandler(
_kClearShortcutsInhibitorEventKey, _kClearShortcutsInhibitorEventKey);
}
super.dispose();
}
@override
Widget build(BuildContext context) {
@@ -2545,9 +2588,16 @@ class _WaylandCardState extends State<WaylandCard> {
future: bind.mainHandleWaylandScreencastRestoreToken(
key: restoreTokenKey, value: "get"),
hasData: (restoreToken) {
final hasShortcutsPermission = showResetInhibitorPermission &&
bind.mainGetCommonSync(
key: "has-gnome-shortcuts-inhibitor-permission") ==
"true";
final children = [
if (restoreToken.isNotEmpty)
_buildClearScreenSelection(context, restoreToken),
if (hasShortcutsPermission)
_buildClearShortcutsInhibitorPermission(context),
];
return Offstage(
offstage: children.isEmpty,
@@ -2592,6 +2642,50 @@ class _WaylandCardState extends State<WaylandCard> {
),
);
}
Widget _buildClearShortcutsInhibitorPermission(BuildContext context) {
onConfirm() {
_clearShortcutsInhibitorFailedMsg.value = '';
bind.mainSetCommon(
key: "clear-gnome-shortcuts-inhibitor-permission", value: "");
gFFI.dialogManager.dismissAll();
}
showConfirmMsgBox() => msgBoxCommon(
gFFI.dialogManager,
'Confirmation',
Text(
translate('confirm-clear-shortcuts-inhibitor-permission-tip'),
),
[
dialogButton('OK', onPressed: onConfirm),
dialogButton('Cancel',
onPressed: () => gFFI.dialogManager.dismissAll())
]);
return Column(children: [
Obx(
() => _clearShortcutsInhibitorFailedMsg.value.isEmpty
? Offstage()
: Align(
alignment: Alignment.topLeft,
child: Text(_clearShortcutsInhibitorFailedMsg.value,
style: DefaultTextStyle.of(context)
.style
.copyWith(color: Colors.red))
.marginOnly(bottom: 10.0)),
),
_Button(
'Reset keyboard shortcuts permission',
showConfirmMsgBox,
tip: 'clear-shortcuts-inhibitor-permission-tip',
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(
Theme.of(context).colorScheme.error.withOpacity(0.75)),
),
),
]);
}
}
// ignore: non_constant_identifier_names