gh-12782: Fix app menu items cut off on small screens (macOS) (gh-12832)

Co-authored-by: mr. m <91018726+mr-cheffy@users.noreply.github.com>
This commit is contained in:
Lukas
2026-03-24 00:48:05 +01:00
committed by GitHub
parent c812a07a84
commit 53d1ba45f6
4 changed files with 96 additions and 0 deletions

View File

@@ -331,7 +331,31 @@ window.gZenUIManager = {
this._popupTrackingElements.remove(element);
},
// On macOS, the app menu panel is displayed as a native NSPopover which
// silently clips content beyond the screen without informing Firefox's
// layout engine. This makes bottom menu items unreachable by scrolling.
// Setting max-height based on available screen space lets Firefox's layout
// handle the constraint, enabling proper overflow scrolling.
// See gh-12782
_constrainNativePopoverHeight(panel) {
if (panel.id !== "appMenu-popup") {
return;
}
// NSPopover adds 13px of chrome on all sides (26px vertical total),
// measured via Accessibility Inspector on macOS 26 (Tahoe).
// Previous macOS versions have similar or smaller values, so this is a
// conservative upper bound.
const popoverChrome = 26;
panel.style.maxHeight = `${window.screen.availHeight - popoverChrome}px`;
},
onPopupShowing(showEvent) {
if (
AppConstants.platform === "macosx" &&
Services.prefs.getBoolPref("widget.macos.native-context-menus", false)
) {
this._constrainNativePopoverHeight(showEvent.target);
}
for (const el of this._popupTrackingElements) {
// target may be inside a shadow root, not directly under the element
// we also ignore menus inside panels

View File

@@ -9,6 +9,7 @@ BROWSER_CHROME_MANIFESTS += [
"glance/browser.toml",
"live-folders/browser.toml",
"pinned/browser.toml",
"popover/browser.toml",
"spaces/browser.toml",
"split_view/browser.toml",
"tabs/browser.toml",

View File

@@ -0,0 +1,12 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
[DEFAULT]
prefs = ["zen.view.mac.show-three-dot-menu=true"]
["browser_popover_height_constraint.js"]
run-if = [
"os == 'mac'", # gh-12782
]
prefs = ["widget.macos.native-context-menus=true"]

View File

@@ -0,0 +1,59 @@
/* Any copyright is dedicated to the Public Domain.
https://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that the app menu panel respects available screen height when
// constrained. Without the fix, the panel ignores the available screen
// height and lets NSPopover silently clip the content.
// See gh-12782
add_task(async function test_appmenu_respects_screen_constraint() {
const panel = document.getElementById("appMenu-popup");
ok(panel, "appMenu-popup panel should exist");
// Mock a very small screen
const realAvailHeight = window.screen.availHeight;
const realAvailTop = window.screen.availTop;
Object.defineProperty(window.screen, "availHeight", {
value: 400,
configurable: true,
});
Object.defineProperty(window.screen, "availTop", {
value: 0,
configurable: true,
});
try {
const popupShown = BrowserTestUtils.waitForEvent(panel, "popupshown");
PanelUI.toggle({ type: "command" });
await popupShown;
await new Promise(requestAnimationFrame);
const scrollBody = panel.querySelector(".panel-subview-body");
ok(scrollBody, "Panel should have a scrollable body");
// With the fix, the panel content should be constrained to fit
// within the mocked screen height. Without the fix, the body
// will be sized to the real screen height (~639px), ignoring
// the available screen constraint.
ok(
scrollBody.clientHeight < 450,
`Scroll body height (${scrollBody.clientHeight}) should be constrained ` +
`to fit within available screen height (400), not the real screen`
);
const popupHidden = BrowserTestUtils.waitForEvent(panel, "popuphidden");
PanelUI.toggle({ type: "command" });
await popupHidden;
} finally {
Object.defineProperty(window.screen, "availHeight", {
value: realAvailHeight,
configurable: true,
});
Object.defineProperty(window.screen, "availTop", {
value: realAvailTop,
configurable: true,
});
}
});