diff --git a/toolkit/devtools/LayoutHelpers.jsm b/toolkit/devtools/LayoutHelpers.jsm index 970dfd1c38f..38092142c50 100644 --- a/toolkit/devtools/LayoutHelpers.jsm +++ b/toolkit/devtools/LayoutHelpers.jsm @@ -13,14 +13,15 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm"); -XPCOMUtils.defineLazyGetter(this, "PlatformKeys", function() { - return Services.strings.createBundle( - "chrome://global-platform/locale/platformKeys.properties"); -}); - this.EXPORTED_SYMBOLS = ["LayoutHelpers"]; -this.LayoutHelpers = LayoutHelpers = { +this.LayoutHelpers = LayoutHelpers = function(aTopLevelWindow) { + this._topDocShell = aTopLevelWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell); +} + +LayoutHelpers.prototype = { /** * Compute the position and the dimensions for the visible portion @@ -70,22 +71,27 @@ this.LayoutHelpers = LayoutHelpers = { // Selection has been clipped to fit in its own window. // Are we in the top-level window? - if (frameWin.parent === frameWin || !frameWin.frameElement) { + if (this.isTopLevelWindow(frameWin)) { + break; + } + + let frameElement = this.getFrameElement(frameWin); + if (!frameElement) { break; } // We are in an iframe. // We take into account the parent iframe position and its // offset (borders and padding). - let frameRect = frameWin.frameElement.getBoundingClientRect(); + let frameRect = frameElement.getBoundingClientRect(); let [offsetTop, offsetLeft] = - this.getIframeContentOffset(frameWin.frameElement); + this.getIframeContentOffset(frameElement); rect.top += frameRect.top + offsetTop; rect.left += frameRect.left + offsetLeft; - frameWin = frameWin.parent; + frameWin = this.getParentWindow(frameWin); } return rect; @@ -115,22 +121,27 @@ this.LayoutHelpers = LayoutHelpers = { while (true) { // Are we in the top-level window? - if (frameWin.parent === frameWin || !frameWin.frameElement) { + if (this.isTopLevelWindow(frameWin)) { + break; + } + + let frameElement = this.getFrameElement(frameWin); + if (!frameElement) { break; } // We are in an iframe. // We take into account the parent iframe position and its // offset (borders and padding). - let frameRect = frameWin.frameElement.getBoundingClientRect(); + let frameRect = frameElement.getBoundingClientRect(); let [offsetTop, offsetLeft] = - this.getIframeContentOffset(frameWin.frameElement); + this.getIframeContentOffset(frameElement); rect.top += frameRect.top + offsetTop; rect.left += frameRect.left + offsetLeft; - frameWin = frameWin.parent; + frameWin = this.getParentWindow(frameWin); } return rect; @@ -203,7 +214,7 @@ this.LayoutHelpers = LayoutHelpers = { let rect = node.getBoundingClientRect(); // Gap between the iframe and its content window. - let [offsetTop, offsetLeft] = LayoutHelpers.getIframeContentOffset(node); + let [offsetTop, offsetLeft] = this.getIframeContentOffset(node); aX -= rect.left + offsetLeft; aY -= rect.top + offsetTop; @@ -296,9 +307,10 @@ this.LayoutHelpers = LayoutHelpers = { } } - if (win.parent !== win) { + if (!this.isTopLevelWindow(win)) { // We are inside an iframe. - LH_scrollIntoViewIfNeeded(win.frameElement, centered); + let frameElement = this.getFrameElement(win); + this.scrollIntoViewIfNeeded(frameElement, centered); } }, @@ -322,63 +334,60 @@ this.LayoutHelpers = LayoutHelpers = { }, /** - * Prettifies the modifier keys for an element. - * - * @param Node aElemKey - * The key element to get the modifiers from. - * @param boolean aAllowCloverleaf - * Pass true to use the cloverleaf symbol instead of a descriptive string. - * @return string - * A prettified and properly separated modifier keys string. + * like win.parent === win, but goes through mozbrowsers and mozapps iframes. */ - prettyKey: function LH_prettyKey(aElemKey, aAllowCloverleaf) - { - let elemString = ""; - let elemMod = aElemKey.getAttribute("modifiers"); + isTopLevelWindow: function LH_isTopLevelWindow(win) { + let docShell = win.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell); - if (elemMod.match("accel")) { - if (Services.appinfo.OS == "Darwin") { - // XXX bug 779642 Use "Cmd-" literal vs. cloverleaf meta-key until - // Orion adds variable height lines. - if (!aAllowCloverleaf) { - elemString += "Cmd-"; - } else { - elemString += PlatformKeys.GetStringFromName("VK_META") + - PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR"); + return docShell === this._topDocShell; + }, + + /** + * like win.parent, but goes through mozbrowsers and mozapps iframes. + */ + getParentWindow: function LH_getParentWindow(win) { + if (this.isTopLevelWindow(win)) { + return null; + } + + let docShell = win.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell); + + if (docShell.isBrowserOrApp) { + let parentDocShell = docShell.getSameTypeParentIgnoreBrowserAndAppBoundaries(); + return parentDocShell.contentViewer.DOMDocument.defaultView; + } else { + return win.parent; + } + }, + + /** + * like win.frameElement, but goes through mozbrowsers and mozapps iframes. + */ + getFrameElement: function LH_getFrameElement(win) { + if (this.isTopLevelWindow(win)) { + return null; + } + + let docShell = win.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell); + + if (docShell.isBrowserOrApp) { + let parentDocShell = docShell.getSameTypeParentIgnoreBrowserAndAppBoundaries(); + let parentDoc = parentDocShell.contentViewer.DOMDocument; + let allIframes = parentDoc.querySelectorAll("iframe"); + for (let f of allIframes) { + if (f.contentWindow === win) { + return f; } - } else { - elemString += PlatformKeys.GetStringFromName("VK_CONTROL") + - PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR"); } + return null; + } else { + return win.frameElement; } - if (elemMod.match("access")) { - if (Services.appinfo.OS == "Darwin") { - elemString += PlatformKeys.GetStringFromName("VK_CONTROL") + - PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR"); - } else { - elemString += PlatformKeys.GetStringFromName("VK_ALT") + - PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR"); - } - } - if (elemMod.match("shift")) { - elemString += PlatformKeys.GetStringFromName("VK_SHIFT") + - PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR"); - } - if (elemMod.match("alt")) { - elemString += PlatformKeys.GetStringFromName("VK_ALT") + - PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR"); - } - if (elemMod.match("ctrl") || elemMod.match("control")) { - elemString += PlatformKeys.GetStringFromName("VK_CONTROL") + - PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR"); - } - if (elemMod.match("meta")) { - elemString += PlatformKeys.GetStringFromName("VK_META") + - PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR"); - } - - return elemString + - (aElemKey.getAttribute("keycode").replace(/^.*VK_/, "") || - aElemKey.getAttribute("key")).toUpperCase(); - } + }, };