Skip to content

fix: better shortcut registration and app icon matching on Wayland#49988

Merged
codebytere merged 3 commits into
electron:mainfrom
mitchchn:mitch/fix-wayland-ids-and-global-shortcuts
Mar 3, 2026
Merged

fix: better shortcut registration and app icon matching on Wayland#49988
codebytere merged 3 commits into
electron:mainfrom
mitchchn:mitch/fix-wayland-ids-and-global-shortcuts

Conversation

@mitchchn
Copy link
Copy Markdown
Member

@mitchchn mitchchn commented Mar 1, 2026

Description of Change

Fixes #49873, fixes #48391.

image

(In this example, the fiddle's XDG app id is 'electron', its product name is a random string, and the suggested shortcut value is Ctrl+Shift+B, correctly reflecting what the caller asked for.)

This PR addresses two related issues on Wayland:

  • Global keyboard shortcuts: all Electron apps registered shortcuts to the same hardcoded ID,and they did not actually pass the requested accelerator to the shortcut portal.
  • App icons would sometimes show up as generic "W" placeholders in the taskbar, switcher, or title bar (see Fiddle in my screenshot).

Both issues have one of their underlying causes in common: the app's XDG identifier was usually not set to an appropriate value. (And if it was set, it wasn't always being respected by Chromium.)

Choosing a better default XDG app ID

Electron currently defaults to using the productName for its XDG identifier if no desktopName is provided by the developer. But a full product name with spaces like "Electron Fiddle" is not a valid ID, and even one-word product names like "Slack" usually have lowercase .desktop files, causing a mismatch out of the box.

I chose to use the app's executable name instead of productName as the default XDG app ID if one is not specified. On Linux, an app's executable name is conventionally* the same as its .desktop filename. e.g., Firefox has firefox.desktop, firefox as its command, and firefox as its XDG app ID. This same logic applies to many Electron apps which are currently missing their icons in some environments on Wayland: Electron Fiddle's exec name and .desktop file are both already electron-fiddle, so that should also be its default XDG app ID. Slack is another example: it already has a slack command and slack.desktop, and it would start resolving its icon correctly on Wayland if the default XDG app ID lined up.

While this heuristic won't work for every app, the executable name is a safer implicit default than a product name, and developers can continue to override the value by setting desktopName in package.json.

(*Technically, apps are supposed to use fully qualified domains for .desktop names and app IDs, but if this is important to you as a developer, you really should be setting desktopName manually!)

Fixing the shortcut portal

Now that we have workable IDs, I needed to patch Chromium to fix interactions with the shortcut portal. I decided to split this into two patches:

  1. One patch to respect the Electron app's ID, which I doubt we can submit upstream.
  2. Another patch to properly configure the shortcut trigger for the XDG portal.

I will upstream the second patch as Chromium will need it as well.

Checklist

Release Notes

Notes: Global shortcuts can now be registered more reliably on Wayland using the globalShortcut API.

Fixed an issue where some apps had generic "W" icons on Wayland. This change impacts the default XDG application identifier. If you need this ID to have a stable value, set desktopName in package.json.

@mitchchn mitchchn requested a review from a team as a code owner March 1, 2026 21:44
@electron-cation electron-cation Bot added the new-pr 🌱 PR opened recently label Mar 1, 2026
@mitchchn mitchchn changed the title fix: better shortcut registration and icon matching on Wayland fix: better shortcut registration and app icon matching on Wayland Mar 1, 2026
@mitchchn
Copy link
Copy Markdown
Member Author

mitchchn commented Mar 2, 2026

/request-review @codebytere

From: Mitchell Cohen <mitch.cohen@me.com>
Date: Sun, 1 Mar 2026 16:22:00 -0500
Subject: fix: set correct app id on Linux

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also try to upstream this, yes?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe? It's also a bit related to this patch you added and there might be a way to integrate them:
https://github.com/electron/electron/pull/49054/changes#diff-5b55d26d02a38ad2ac792d96c032afa436c1f660fd34d36189452c44586bb6d8

@mitchchn
Copy link
Copy Markdown
Member Author

mitchchn commented Mar 2, 2026

CL: https://chromium-review.googlesource.com/c/chromium/src/+/7620219

@codebytere codebytere added semver/patch backwards-compatible bug fixes target/39-x-y PR should also be added to the "39-x-y" branch. target/40-x-y PR should also be added to the "40-x-y" branch. target/41-x-y PR should also be added to the "41-x-y" branch. labels Mar 3, 2026
@electron-cation electron-cation Bot removed the new-pr 🌱 PR opened recently label Mar 3, 2026
@codebytere codebytere merged commit 2f13d85 into electron:main Mar 3, 2026
138 of 141 checks passed
@release-clerk
Copy link
Copy Markdown

release-clerk Bot commented Mar 3, 2026

Release Notes Persisted

Global shortcuts can now be registered more reliably on Wayland using the globalShortcut API.

@trop
Copy link
Copy Markdown
Contributor

trop Bot commented Mar 3, 2026

I was unable to backport this PR to "40-x-y" cleanly;
you will need to perform this backport manually.

@trop trop Bot removed the target/40-x-y PR should also be added to the "40-x-y" branch. label Mar 3, 2026
@trop
Copy link
Copy Markdown
Contributor

trop Bot commented Mar 3, 2026

I was unable to backport this PR to "39-x-y" cleanly;
you will need to perform this backport manually.

@trop trop Bot added needs-manual-bp/40-x-y needs-manual-bp/39-x-y and removed target/39-x-y PR should also be added to the "39-x-y" branch. labels Mar 3, 2026
@trop
Copy link
Copy Markdown
Contributor

trop Bot commented Mar 3, 2026

I have automatically backported this PR to "41-x-y", please check out #50051

@trop trop Bot added in-flight/41-x-y merged/41-x-y PR was merged to the "41-x-y" branch. and removed target/41-x-y PR should also be added to the "41-x-y" branch. in-flight/41-x-y labels Mar 3, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes Wayland-specific integration issues by improving how Electron derives the XDG application identifier (for icon/taskbar matching and portal identity) and by ensuring global shortcuts registered via the XDG portal carry the requested trigger/accelerator.

Changes:

  • Change the default Linux desktopName initialization to use the executable basename (instead of {app.name}.desktop).
  • Update global shortcut registration metadata to include the app name in the shortcut description.
  • Add two Chromium patches: one to respect CHROME_DESKTOP for app id/session naming, and one to pass preferred_trigger to the shortcut portal.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
shell/browser/api/electron_api_global_shortcut.cc Updates shortcut description text to use the app’s name.
lib/browser/init.ts Changes default Linux desktopName derivation to use process.execPath.
default_app/main.ts Mirrors the desktopName default change for the default app loader path.
patches/chromium/fix_set_correct_app_id_on_linux.patch Chromium patch to derive app id / session prefix from CHROME_DESKTOP.
patches/chromium/fix_pass_trigger_for_global_shortcuts_on_wayland.patch Chromium patch to send preferred_trigger to the XDG shortcut portal based on the accelerator.
patches/chromium/.patches Registers the new Chromium patches in Electron’s patch list.
Comments suppressed due to low confidence (1)

patches/chromium/fix_set_correct_app_id_on_linux.patch:71

  • This patch file looks truncated/malformed: it ends immediately after the #else in the GetSessionNamePrefix hunk, and the hunk header (@@ -61,6 +86,16 @@) no longer matches the number of lines actually present. As written, git apply / e sync is likely to fail with a “malformed patch” error. Please regenerate/export this patch so the full hunk is present and the hunk line counts match the content.
+
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
   static constexpr std::string_view kSessionNamePrefix = "chrome";
 #else

Date: Sun, 1 Mar 2026 16:22:00 -0500
Subject: fix: set correct app id on Linux

Sets the Electron app's actual XDG app ID and DBus path instead of org.chromium.Chromium..
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor typo in the patch description: there are two periods after “org.chromium.Chromium”.

Suggested change
Sets the Electron app's actual XDG app ID and DBus path instead of org.chromium.Chromium..
Sets the Electron app's actual XDG app ID and DBus path instead of org.chromium.Chromium.

Copilot uses AI. Check for mistakes.
+ break;
+ case ui::VKEY_OEM_PERIOD:
+ trigger += "period";
+ break;
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AcceleratorToXdgTrigger() returns an empty string for any unhandled KeyboardCode (via the default: return "" case). Electron accelerators support many additional keys (e.g. Plus, -, /, =, ;, [/], \, etc.), so those shortcuts will still be sent to the portal without a preferred_trigger, forcing manual user re-binding. Consider expanding the key mapping (or using a more general conversion helper) so common non-alphanumeric accelerators can still produce a valid XDG trigger string instead of silently falling back to "".

Suggested change
+ break;
+ break;
+ case ui::VKEY_OEM_MINUS:
+ trigger += "minus";
+ break;
+ case ui::VKEY_OEM_PLUS:
+ trigger += "equal";
+ break;
+ case ui::VKEY_OEM_2:
+ trigger += "slash";
+ break;
+ case ui::VKEY_OEM_5:
+ trigger += "backslash";
+ break;
+ case ui::VKEY_OEM_1:
+ trigger += "semicolon";
+ break;
+ case ui::VKEY_OEM_7:
+ trigger += "apostrophe";
+ break;
+ case ui::VKEY_OEM_4:
+ trigger += "bracketleft";
+ break;
+ case ui::VKEY_OEM_6:
+ trigger += "bracketright";
+ break;
+ case ui::VKEY_OEM_3:
+ trigger += "grave";
+ break;

Copilot uses AI. Check for mistakes.
Comment thread lib/browser/init.ts
Comment on lines +128 to +131
// Set application's desktop name (Linux). These usually match the executable name,
// so use it as the default to ensure the app gets the correct icon in the taskbar and application switcher.
const desktopName = packageJson.desktopName || `${path.basename(process.execPath)}.desktop`;
app.setDesktopName(desktopName);
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes the default Linux desktopName from {app.name}.desktop to ${path.basename(process.execPath)}.desktop. There are API docs that still state the default is {app.name}.desktop (e.g. docs/api/base-window.md / docs/api/browser-window.md under win.setProgressBar). Please update the documentation to reflect the new default so developers know what value will be used when desktopName is omitted.

Copilot uses AI. Check for mistakes.
Comment thread default_app/main.ts
Comment on lines +114 to +117
// Set application's desktop name (Linux). These usually match the executable name,
// so use it as the default to ensure the app gets the correct icon in the taskbar and application switcher.
const desktopName = packageJson.desktopName || `${path.basename(process.execPath)}.desktop`;
app.setDesktopName(desktopName);
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as lib/browser/init.ts: this changes the implicit default desktopName on Linux, but the docs still describe {app.name}.desktop as the default. Please update the relevant API docs (e.g. win.setProgressBar notes in docs/api/base-window.md / docs/api/browser-window.md) so the default matches what users read.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merged/41-x-y PR was merged to the "41-x-y" branch. needs-manual-bp/40-x-y semver/patch backwards-compatible bug fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Global shortcuts registered from Electron are registered to org.chromium.Chromium Wayland app_id should be normalized to match wm_class

4 participants