Bug 486200 - Need API to compute screen coordinates of DOM elements

r=roc,dbaron, sr=roc,jst
This commit is contained in:
Daniel Brooks 2009-06-19 02:24:34 -05:00
parent e3f28bfc86
commit 9306ebacac
5 changed files with 155 additions and 2 deletions

View File

@ -170,6 +170,7 @@
#ifdef MOZ_XUL
#include "nsXULPopupManager.h"
#endif
#include "nsIFrame.h"
#include "plbase64.h"
@ -3406,6 +3407,72 @@ nsGlobalWindow::GetScreenX(PRInt32* aScreenX)
return NS_OK;
}
nsRect
nsGlobalWindow::GetInnerScreenRect()
{
if (!mDocShell)
return nsRect();
nsGlobalWindow* rootWindow =
static_cast<nsGlobalWindow*>(GetPrivateRoot());
if (rootWindow) {
rootWindow->FlushPendingNotifications(Flush_Layout);
}
nsCOMPtr<nsIPresShell> presShell;
mDocShell->GetPresShell(getter_AddRefs(presShell));
if (!presShell)
return nsRect();
nsIFrame* rootFrame = presShell->GetRootFrame();
if (!rootFrame)
return nsRect();
return rootFrame->GetScreenRectInAppUnits();
}
NS_IMETHODIMP
nsGlobalWindow::GetMozInnerScreenX(float* aScreenX)
{
FORWARD_TO_OUTER(GetMozInnerScreenX, (aScreenX), NS_ERROR_NOT_INITIALIZED);
nsRect r = GetInnerScreenRect();
*aScreenX = nsPresContext::AppUnitsToFloatCSSPixels(r.x);
return NS_OK;
}
NS_IMETHODIMP
nsGlobalWindow::GetMozInnerScreenY(float* aScreenY)
{
FORWARD_TO_OUTER(GetMozInnerScreenY, (aScreenY), NS_ERROR_NOT_INITIALIZED);
nsRect r = GetInnerScreenRect();
*aScreenY = nsPresContext::AppUnitsToFloatCSSPixels(r.y);
return NS_OK;
}
NS_IMETHODIMP
nsGlobalWindow::GetMozScreenPixelsPerCSSPixel(float* aScreenPixels)
{
FORWARD_TO_OUTER(GetMozScreenPixelsPerCSSPixel,
(aScreenPixels), NS_ERROR_NOT_INITIALIZED);
*aScreenPixels = 1;
if (!nsContentUtils::IsCallerTrustedForRead())
return NS_ERROR_DOM_SECURITY_ERR;
if (!mDocShell)
return NS_OK;
nsCOMPtr<nsPresContext> presContext;
mDocShell->GetPresContext(getter_AddRefs(presContext));
if (!presContext)
return NS_OK;
*aScreenPixels = float(nsPresContext::AppUnitsPerCSSPixel())/
presContext->AppUnitsPerDevPixel();
return NS_OK;
}
NS_IMETHODIMP
nsGlobalWindow::SetScreenX(PRInt32 aScreenX)
{

View File

@ -90,6 +90,7 @@
#include "nsIXPCScriptable.h"
#include "nsPoint.h"
#include "nsSize.h"
#include "nsRect.h"
#include "mozFlushType.h"
#include "prclist.h"
#include "nsIDOMStorageObsolete.h"
@ -589,6 +590,7 @@ protected:
nsresult GetOuterSize(nsIntSize* aSizeCSSPixels);
nsresult SetOuterSize(PRInt32 aLengthCSSPixels, PRBool aIsWidth);
nsRect GetInnerScreenRect();
PRBool IsFrame()
{

View File

@ -44,7 +44,7 @@ interface nsIControllers;
interface nsIDOMLocation;
interface nsIVariant;
[scriptable, uuid(3414EBC7-731F-4697-9F43-ACA6F5050875)]
[scriptable, uuid(62579239-b619-4bf2-8d39-0b73e8663a85)]
interface nsIDOMWindowInternal : nsIDOMWindow2
{
readonly attribute nsIDOMWindowInternal window;
@ -104,6 +104,9 @@ interface nsIDOMWindowInternal : nsIDOMWindow2
attribute long outerHeight;
attribute long screenX;
attribute long screenY;
readonly attribute float mozInnerScreenX;
readonly attribute float mozInnerScreenY;
readonly attribute float mozScreenPixelsPerCSSPixel;
/* The offset in pixels by which the window is scrolled */
readonly attribute long pageXOffset;

View File

@ -44,7 +44,9 @@ relativesrcdir = dom/tests/mochitest/general
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_TEST_FILES = test_offsets.html \
_TEST_FILES = \
test_innerScreen.xul \
test_offsets.html \
test_offsets.xul \
test_offsets.js \
test_domWindowUtils.html \

View File

@ -0,0 +1,79 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="/tests/SimpleTest/test.css" type="text/css"?>
<!--
Tests for mozInnerScreenX/Y properties
-->
<window title="Test mozInnerScreenX/Y Properties"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="text/javascript" src="/MochiKit/packed.js"/>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"/>
<!-- test resuls are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
<iframe id="f" style="margin:50px; width:200px; height:200px; border:none;"></iframe>
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
function isRounded(a, b, msg) {
is(Math.round(a), Math.round(b), msg);
}
function doTests()
{
var readable = false;
try
{
mozScreenPixelsPerCSSPixel;
readable = true;
}
catch(ex) { }
ok(!readable, "window pixels per css pixel shouldn't be readable to content");
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var devPxPerCSSPx = window.mozScreenPixelsPerCSSPixel;
var windowBO = document.documentElement.boxObject;
isRounded(window.mozInnerScreenX*devPxPerCSSPx, windowBO.screenX,
"window screen X");
isRounded(window.mozInnerScreenY*devPxPerCSSPx, windowBO.screenY,
"window screen Y");
var f = document.getElementById("f");
var fBounds = f.getBoundingClientRect();
const CI = Components.interfaces;
var fshell = f.contentWindow.QueryInterface(CI.nsIInterfaceRequestor).getInterface(CI.nsIWebNavigation).QueryInterface(CI.nsIDocShell);
var fmudv = fshell.contentViewer.QueryInterface(CI.nsIMarkupDocumentViewer);
isRounded(f.contentWindow.mozInnerScreenX,
window.mozInnerScreenX + fBounds.left,
"frame screen X");
isRounded(f.contentWindow.mozInnerScreenY,
window.mozInnerScreenY + fBounds.top,
"frame screen Y");
fmudv.fullZoom *= 2;
is(f.contentWindow.mozScreenPixelsPerCSSPixel, 2*devPxPerCSSPx,
"frame screen pixels per CSS pixel");
isRounded(f.contentWindow.mozInnerScreenX*2,
window.mozInnerScreenX + fBounds.left,
"zoomed frame screen X");
isRounded(f.contentWindow.mozInnerScreenY*2,
window.mozInnerScreenY + fBounds.top,
"zoomed frame screen Y");
fmudv.fullZoom = 1.0;
SimpleTest.finish();
}
addLoadEvent(doTests);
SimpleTest.waitForExplicitFinish();
]]>
</script>
</window>