mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-23 02:47:07 +00:00
Bug 1642138: Improve integration with the macOS-level Window menu handling to unlock built-in OS functionality such as tiling of windows. r=mstange
Differential Revision: https://phabricator.services.mozilla.com/D159723
This commit is contained in:
parent
16d5be1fad
commit
0a408a0948
@ -438,10 +438,9 @@
|
|||||||
</menu>
|
</menu>
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
<menu id="windowMenu"
|
<menu id="windowMenu"
|
||||||
onpopupshowing="macWindowMenuDidShow();"
|
|
||||||
onpopuphidden="macWindowMenuDidHide();"
|
|
||||||
data-l10n-id="menu-window-menu">
|
data-l10n-id="menu-window-menu">
|
||||||
<menupopup id="windowPopup">
|
<menupopup id="windowPopup">
|
||||||
|
<menuseparator/>
|
||||||
<menuitem command="minimizeWindow" key="key_minimizeWindow"/>
|
<menuitem command="minimizeWindow" key="key_minimizeWindow"/>
|
||||||
<menuitem command="zoomWindow"/>
|
<menuitem command="zoomWindow"/>
|
||||||
<!-- decomment when "BringAllToFront" is implemented
|
<!-- decomment when "BringAllToFront" is implemented
|
||||||
|
@ -6,6 +6,4 @@ https_first_disabled = true
|
|||||||
run-if = os == "mac" # Mac only feature
|
run-if = os == "mac" # Mac only feature
|
||||||
support-files =
|
support-files =
|
||||||
file_shareurl.html
|
file_shareurl.html
|
||||||
[browser_window_menu_list.js]
|
|
||||||
run-if = os == "mac" # Mac only feature
|
|
||||||
[browser_file_close_tabs.js]
|
[browser_file_close_tabs.js]
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
add_task(async function test_window_menu_list() {
|
|
||||||
// This title is different depending on the build. For example, it's "Nightly"
|
|
||||||
// for a local build, "Mozilla Firefox" for an official release build.
|
|
||||||
const windowTitle = window.document.title;
|
|
||||||
await checkWindowMenu([windowTitle, "Browser chrome tests"]);
|
|
||||||
let newWindow = await BrowserTestUtils.openNewBrowserWindow();
|
|
||||||
await checkWindowMenu([windowTitle, "Browser chrome tests", windowTitle]);
|
|
||||||
await BrowserTestUtils.closeWindow(newWindow);
|
|
||||||
});
|
|
||||||
|
|
||||||
async function checkWindowMenu(labels) {
|
|
||||||
let menu = document.querySelector("#windowMenu");
|
|
||||||
// We can't toggle menubar items on OSX, so mocking instead.
|
|
||||||
await new Promise(resolve => {
|
|
||||||
menu.addEventListener("popupshown", resolve, { once: true });
|
|
||||||
menu.dispatchEvent(new MouseEvent("popupshowing"));
|
|
||||||
menu.dispatchEvent(new MouseEvent("popupshown"));
|
|
||||||
});
|
|
||||||
|
|
||||||
let menuitems = [...menu.querySelectorAll("menuseparator ~ menuitem")];
|
|
||||||
is(menuitems.length, labels.length, "Correct number of windows in the menu");
|
|
||||||
is(
|
|
||||||
menuitems.map(item => item.label).join(","),
|
|
||||||
labels.join(","),
|
|
||||||
"Correct labels on menuitems"
|
|
||||||
);
|
|
||||||
for (let menuitem of menuitems) {
|
|
||||||
ok(
|
|
||||||
menuitem instanceof customElements.get("menuitem"),
|
|
||||||
"sibling is menuitem"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We can't toggle menubar items on OSX, so mocking instead.
|
|
||||||
await new Promise(resolve => {
|
|
||||||
menu.addEventListener("popuphidden", resolve, { once: true });
|
|
||||||
menu.dispatchEvent(new MouseEvent("popuphiding"));
|
|
||||||
menu.dispatchEvent(new MouseEvent("popuphidden"));
|
|
||||||
});
|
|
||||||
}
|
|
@ -104,7 +104,6 @@
|
|||||||
</menupopup>
|
</menupopup>
|
||||||
</menu>
|
</menu>
|
||||||
<menu id="tasksMenu"/>
|
<menu id="tasksMenu"/>
|
||||||
<menu id="windowMenu"/>
|
|
||||||
<menu id="menu_Help"/>
|
<menu id="menu_Help"/>
|
||||||
</menubar>
|
</menubar>
|
||||||
</toolbar>
|
</toolbar>
|
||||||
|
@ -4,36 +4,6 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
function macWindowMenuDidShow() {
|
|
||||||
let frag = document.createDocumentFragment();
|
|
||||||
for (let win of Services.wm.getEnumerator("")) {
|
|
||||||
if (win.document.documentElement.getAttribute("inwindowmenu") == "false") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let item = document.createXULElement("menuitem");
|
|
||||||
item.setAttribute("label", win.document.title);
|
|
||||||
if (win == window) {
|
|
||||||
item.setAttribute("checked", "true");
|
|
||||||
}
|
|
||||||
item.addEventListener("command", () => {
|
|
||||||
if (win.windowState == window.STATE_MINIMIZED) {
|
|
||||||
win.restore();
|
|
||||||
}
|
|
||||||
win.focus();
|
|
||||||
});
|
|
||||||
frag.appendChild(item);
|
|
||||||
}
|
|
||||||
document.getElementById("windowPopup").appendChild(frag);
|
|
||||||
}
|
|
||||||
|
|
||||||
function macWindowMenuDidHide() {
|
|
||||||
let sep = document.getElementById("sep-window-list");
|
|
||||||
// Clear old items
|
|
||||||
while (sep.nextElementSibling) {
|
|
||||||
sep.nextElementSibling.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function zoomWindow() {
|
function zoomWindow() {
|
||||||
if (window.windowState == window.STATE_NORMAL) {
|
if (window.windowState == window.STATE_NORMAL) {
|
||||||
window.maximize();
|
window.maximize();
|
||||||
|
@ -27,8 +27,8 @@ namespace mozilla {
|
|||||||
namespace dom {
|
namespace dom {
|
||||||
class Document;
|
class Document;
|
||||||
class Element;
|
class Element;
|
||||||
}
|
} // namespace dom
|
||||||
}
|
} // namespace mozilla
|
||||||
|
|
||||||
// ApplicationMenuDelegate is used to receive Cocoa notifications.
|
// ApplicationMenuDelegate is used to receive Cocoa notifications.
|
||||||
@interface ApplicationMenuDelegate : NSObject <NSMenuDelegate> {
|
@interface ApplicationMenuDelegate : NSObject <NSMenuDelegate> {
|
||||||
|
@ -161,6 +161,7 @@ class nsMenuX final : public nsMenuParentX,
|
|||||||
void Dump(uint32_t aIndent) const;
|
void Dump(uint32_t aIndent) const;
|
||||||
|
|
||||||
static bool IsXULHelpMenu(nsIContent* aMenuContent);
|
static bool IsXULHelpMenu(nsIContent* aMenuContent);
|
||||||
|
static bool IsXULWindowMenu(nsIContent* aMenuContent);
|
||||||
|
|
||||||
// Set an observer that gets notified of menu opening and closing.
|
// Set an observer that gets notified of menu opening and closing.
|
||||||
// The menu does not keep a strong reference the observer. The observer must
|
// The menu does not keep a strong reference the observer. The observer must
|
||||||
|
@ -117,6 +117,11 @@ nsMenuX::nsMenuX(nsMenuParentX* aParent, nsMenuGroupOwnerX* aMenuGroupOwner, nsI
|
|||||||
// menu gets selected, which is bad.
|
// menu gets selected, which is bad.
|
||||||
RebuildMenu();
|
RebuildMenu();
|
||||||
|
|
||||||
|
if (IsXULWindowMenu(mContent)) {
|
||||||
|
// Let the OS know that this is our Window menu.
|
||||||
|
NSApp.windowsMenu = mNativeMenu;
|
||||||
|
}
|
||||||
|
|
||||||
mIcon = MakeUnique<nsMenuItemIconX>(this);
|
mIcon = MakeUnique<nsMenuItemIconX>(this);
|
||||||
|
|
||||||
if (mVisible) {
|
if (mVisible) {
|
||||||
@ -914,6 +919,18 @@ bool nsMenuX::IsXULHelpMenu(nsIContent* aMenuContent) {
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool nsMenuX::IsXULWindowMenu(nsIContent* aMenuContent) {
|
||||||
|
bool retval = false;
|
||||||
|
if (aMenuContent && aMenuContent->IsElement()) {
|
||||||
|
nsAutoString id;
|
||||||
|
aMenuContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::id, id);
|
||||||
|
if (id.Equals(u"windowMenu"_ns)) {
|
||||||
|
retval = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// nsChangeObserver
|
// nsChangeObserver
|
||||||
//
|
//
|
||||||
|
Loading…
x
Reference in New Issue
Block a user