Bug 897960 - walker should support mozbrowser iframes. r=dcamp

This commit is contained in:
Paul Rouget 2013-09-08 10:58:00 +02:00
parent 2966b9b5a9
commit ad54223ef2

View File

@ -13,14 +13,15 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services", XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm"); "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.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 * 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. // Selection has been clipped to fit in its own window.
// Are we in the top-level 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; break;
} }
// We are in an iframe. // We are in an iframe.
// We take into account the parent iframe position and its // We take into account the parent iframe position and its
// offset (borders and padding). // offset (borders and padding).
let frameRect = frameWin.frameElement.getBoundingClientRect(); let frameRect = frameElement.getBoundingClientRect();
let [offsetTop, offsetLeft] = let [offsetTop, offsetLeft] =
this.getIframeContentOffset(frameWin.frameElement); this.getIframeContentOffset(frameElement);
rect.top += frameRect.top + offsetTop; rect.top += frameRect.top + offsetTop;
rect.left += frameRect.left + offsetLeft; rect.left += frameRect.left + offsetLeft;
frameWin = frameWin.parent; frameWin = this.getParentWindow(frameWin);
} }
return rect; return rect;
@ -115,22 +121,27 @@ this.LayoutHelpers = LayoutHelpers = {
while (true) { while (true) {
// Are we in the top-level 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; break;
} }
// We are in an iframe. // We are in an iframe.
// We take into account the parent iframe position and its // We take into account the parent iframe position and its
// offset (borders and padding). // offset (borders and padding).
let frameRect = frameWin.frameElement.getBoundingClientRect(); let frameRect = frameElement.getBoundingClientRect();
let [offsetTop, offsetLeft] = let [offsetTop, offsetLeft] =
this.getIframeContentOffset(frameWin.frameElement); this.getIframeContentOffset(frameElement);
rect.top += frameRect.top + offsetTop; rect.top += frameRect.top + offsetTop;
rect.left += frameRect.left + offsetLeft; rect.left += frameRect.left + offsetLeft;
frameWin = frameWin.parent; frameWin = this.getParentWindow(frameWin);
} }
return rect; return rect;
@ -203,7 +214,7 @@ this.LayoutHelpers = LayoutHelpers = {
let rect = node.getBoundingClientRect(); let rect = node.getBoundingClientRect();
// Gap between the iframe and its content window. // Gap between the iframe and its content window.
let [offsetTop, offsetLeft] = LayoutHelpers.getIframeContentOffset(node); let [offsetTop, offsetLeft] = this.getIframeContentOffset(node);
aX -= rect.left + offsetLeft; aX -= rect.left + offsetLeft;
aY -= rect.top + offsetTop; aY -= rect.top + offsetTop;
@ -296,9 +307,10 @@ this.LayoutHelpers = LayoutHelpers = {
} }
} }
if (win.parent !== win) { if (!this.isTopLevelWindow(win)) {
// We are inside an iframe. // 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. * like win.parent === win, but goes through mozbrowsers and mozapps iframes.
*
* @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.
*/ */
prettyKey: function LH_prettyKey(aElemKey, aAllowCloverleaf) isTopLevelWindow: function LH_isTopLevelWindow(win) {
{ let docShell = win.QueryInterface(Ci.nsIInterfaceRequestor)
let elemString = ""; .getInterface(Ci.nsIWebNavigation)
let elemMod = aElemKey.getAttribute("modifiers"); .QueryInterface(Ci.nsIDocShell);
if (elemMod.match("accel")) { return docShell === this._topDocShell;
if (Services.appinfo.OS == "Darwin") { },
// XXX bug 779642 Use "Cmd-" literal vs. cloverleaf meta-key until
// Orion adds variable height lines. /**
if (!aAllowCloverleaf) { * like win.parent, but goes through mozbrowsers and mozapps iframes.
elemString += "Cmd-"; */
} else { getParentWindow: function LH_getParentWindow(win) {
elemString += PlatformKeys.GetStringFromName("VK_META") + if (this.isTopLevelWindow(win)) {
PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR"); 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();
}
}; };