Bug 1543940 - Use the toolbox top window for context menus r=ochameau

Depends on D28036

If a context menu is opened in the toolbox document when running in a frame with type=content, keyboard navigation will not move to the context menu when it's opened.

Differential Revision: https://phabricator.services.mozilla.com/D27695

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Julian Descottes 2019-05-08 21:36:04 +00:00
parent 039d3e7c13
commit 048903ea35
4 changed files with 26 additions and 3 deletions

View File

@ -6,6 +6,7 @@
"use strict";
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
const EventEmitter = require("devtools/shared/event-emitter");
const { getCurrentZoom } = require("devtools/shared/layout/utils");
@ -79,6 +80,12 @@ Menu.prototype.popupWithZoom = function(x, y, doc) {
* The document that should own the context menu.
*/
Menu.prototype.popup = function(screenX, screenY, doc) {
// The context-menu will be created in the topmost window to preserve keyboard
// navigation (see Bug 1543940).
// Keep a reference on the window owning the menu to hide the popup on unload.
const win = doc.defaultView;
doc = DevToolsUtils.getTopWindow(doc.defaultView).document;
let popupset = doc.querySelector("popupset");
if (!popupset) {
popupset = doc.createXULElement("popupset");
@ -103,9 +110,15 @@ Menu.prototype.popup = function(screenX, screenY, doc) {
}
this._createMenuItems(popup);
// The context menu will be created in the topmost chrome window. Hide it manually when
// the owner document is unloaded.
const onWindowUnload = () => popup.hidePopup();
win.addEventListener("unload", onWindowUnload);
// Remove the menu from the DOM once it's hidden.
popup.addEventListener("popuphidden", (e) => {
if (e.target === popup) {
win.removeEventListener("unload", onWindowUnload);
popup.remove();
this.emit("close");
}
@ -157,6 +170,11 @@ Menu.prototype._createMenuItems = function(parent) {
});
};
Menu.getMenuElementById = function(id, doc) {
const menuDoc = DevToolsUtils.getTopWindow(doc.defaultView).document;
return menuDoc.getElementById(id);
};
Menu.setApplicationMenu = () => {
throw Error("Not implemented");
};

View File

@ -391,6 +391,10 @@ Toolbox.prototype = {
return DevToolsUtils.getTopWindow(this.win);
},
get topDoc() {
return this.topWindow.document;
},
/**
* Shortcut to the document containing the toolbox UI
*/
@ -3247,7 +3251,7 @@ Toolbox.prototype = {
* @param {Number} y
*/
openTextBoxContextMenu: function(x, y) {
const menu = createEditContextMenu(this.win, "toolbox-menu");
const menu = createEditContextMenu(this.topWindow, "toolbox-menu");
// Fire event for tests
menu.once("open", () => this.emit("menu-open"));

View File

@ -768,7 +768,8 @@ class MarkupContextMenu {
const hasA11YProps = await this.walker.hasAccessibilityProperties(
this.selection.nodeFront);
if (hasA11YProps) {
this.toolbox.doc.getElementById(menuItem.id).disabled = menuItem.disabled = false;
const menuItemEl = Menu.getMenuElementById(menuItem.id, this.toolbox.doc);
menuItemEl.disabled = menuItem.disabled = false;
}
this.inspector.emit("node-menu-updated");

View File

@ -68,7 +68,7 @@ function showMenu(items, options) {
if (options.useTopLevelWindow) {
doc = getTopLevelWindow(window).document;
} else {
doc = window.parent.document;
doc = window.document;
}
menu.popup(screenX, screenY, doc);