Repository: electron/electron
Pull request: fix: updated Alt detection to explicitly exclude AltGraph/AltGr

#### Description of Change
- Fixes #49737
Fixed Linux menu-bar focus behavior so `AltGr` (AltGraph) is no longer treated as a single `Alt` . Previously, pressing AltGr could trigger menu-bar activation/toggling (especially with auto-hide RootView to explicitly exclude `AltGr`/`AltGraph` key events. Also added a Linux regression test in spec/api-browser-window-spec.ts to verify that pressing `AltGr` does not toggle auto-hide menu bar visibility.

#### Checklist
- [x] PR description included
- [x] I have built and tested this PR
- [x] `npm test` passes
- [x] tests are [changed or added](https://github.com/electron/electron/blob/main/docs/development/testing.md)
- [x] relevant API documentation, tutorials, and examples are updated and follow the [documentation style guide](https://github.com/electron/electron/blob/main/docs/development/style-guide.md)
- [x] [PR release notes](https://github.com/electron/clerk/blob/main/README.md) describe the change in a way relevant to app developers, and are [capitalized, punctuated, and past tense](https://github.com/electron/clerk/blob/main/README.md#examples).

#### Release Notes
Notes: Fixed an issue where pressing AltGr could activate or focus the menu bar. 

Changed files:
filename: shell/browser/ui/views/root_view.cc
patch: @@ -9,6 +9,7 @@
 #include "components/input/native_web_keyboard_event.h"
 #include "shell/browser/native_window.h"
 #include "shell/browser/ui/views/menu_bar.h"
+#include "ui/events/keycodes/dom/keycode_converter.h"
 #include "ui/views/layout/box_layout.h"
 
 namespace electron {
@@ -21,9 +22,21 @@ bool IsAltKey(const input::NativeWebKeyboardEvent& event) {
 
 bool IsAltModifier(const input::NativeWebKeyboardEvent& event) {
   using Mods = input::NativeWebKeyboardEvent::Modifiers;
+
+  // AltGraph (AltGr) should not be treated as a single Alt keypress for
+  // menu-bar toggling.
+  if (event.windows_key_code == ui::VKEY_ALTGR ||
+      ui::KeycodeConverter::DomKeyToKeyString(event.dom_key) == "AltGraph") {
+    return false;
+  }
+
   return (event.GetModifiers() & Mods::kKeyModifiers) == Mods::kAltKey;
 }
 
+bool IsSingleAltKey(const input::NativeWebKeyboardEvent& event) {
+  return IsAltKey(event) && IsAltModifier(event);
+}
+
 }  // namespace
 
 RootView::RootView(NativeWindow* window)
@@ -98,7 +111,7 @@ void RootView::HandleKeyEvent(const input::NativeWebKeyboardEvent& event) {
     return;
 
   // Show accelerator when "Alt" is pressed.
-  if (menu_bar_visible_ && IsAltKey(event))
+  if (menu_bar_visible_ && IsSingleAltKey(event))
     menu_bar_->SetAcceleratorVisibility(
         event.GetType() == blink::WebInputEvent::Type::kRawKeyDown);
 
@@ -121,11 +134,11 @@ void RootView::HandleKeyEvent(const input::NativeWebKeyboardEvent& event) {
 
   // Toggle the menu bar only when a single Alt is released.
   if (event.GetType() == blink::WebInputEvent::Type::kRawKeyDown &&
-      IsAltKey(event)) {
+      IsSingleAltKey(event)) {
     // When a single Alt is pressed:
     menu_bar_alt_pressed_ = true;
   } else if (event.GetType() == blink::WebInputEvent::Type::kKeyUp &&
-             IsAltKey(event) && menu_bar_alt_pressed_) {
+             IsSingleAltKey(event) && menu_bar_alt_pressed_) {
     // When a single Alt is released right after a Alt is pressed:
     menu_bar_alt_pressed_ = false;
     if (menu_bar_autohide_)

filename: spec/api-browser-window-spec.ts
patch: @@ -5925,6 +5925,23 @@ describe('BrowserWindow module', () => {
       });
     });
 
+    ifdescribe(process.platform === 'linux')('menu bar AltGr behavior', () => {
+      it('does not toggle auto-hide menu bar visibility', async () => {
+        const w = new BrowserWindow({ show: false, autoHideMenuBar: true });
+        w.setMenuBarVisibility(false);
+        expect(w.isMenuBarVisible()).to.be.false('isMenuBarVisible');
+
+        w.show();
+        await once(w, 'show');
+        w.webContents.focus();
+        w.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'AltGr' });
+        w.webContents.sendInputEvent({ type: 'keyUp', keyCode: 'AltGr' });
+        await setTimeout();
+
+        expect(w.isMenuBarVisible()).to.be.false('isMenuBarVisible');
+      });
+    });
+
     ifdescribe(process.platform !== 'darwin')('when fullscreen state is changed', () => {
       it('correctly remembers state prior to fullscreen change', async () => {
         const w = new BrowserWindow({ show: false });