rep_movsd
rep_movsd

Reputation: 6895

Get absolute screen bounds of a DOM element from a Firefox extension

I have a firefox extension that needs to get the exact screen co-ordinates of a DOM element and passes it to a native DLL via js/c-types.

Now I have it mostly covered :

var gDomWindowUtils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(nsIDOMWindowUtils);

function getScreenRect(oElem)
{
    var rc =
    {
        x : 0,
        y : 0,
        w : 0,
        h : 0
    };

    var o = oElement;
    while(o != null)
    {
        rc.y += o.offsetTop;
        rc.x += o.offsetLeft;
        o = o.offsetParent;
    }

    var x = {}, y = {};
    gDomWindowUtils.getScrollXY(false, x, y);
    rc.x -= x.value;
    rc.y -= y.value;

    var scale = gDomWindowUtils.screenPixelsPerCSSPixel;
    rc.x *= scale;
    rc.y *= scale;
    rc.w *= scale;
    rc.h *= scale;

    return rc;
};

This handles scrolling and zooming, but the values I get are relative to the browser window, and not the screen.

How do I detect the offset of the client area of the actual rendering area of the browser? I can even use native code (Win32) via js/ctypes so I tried to see if I could use FindWindow() / GetWindowRect() to get it, but the whole of firefox is a single HWND, the controls are all not native windows.

So one idea I have is, since the UI of firefox is an XUL document, I should be able to get the menubar, tab bar etc etc and find the browser areas absolute offset. But, I have no clue how to access the XUL tree that defines the browser UI.

Can someone give me a pointer?

[Edit] Ignore rc.w and rc.h being undefined in the above code , it is irrelevant to the question.

Upvotes: 3

Views: 6420

Answers (2)

Wladimir Palant
Wladimir Palant

Reputation: 57681

You mostly got it already but I would recommend using getBoundingClientRect() instead of offsetLeft/offsetTop:

var rect = oElement.getBoundingClientRect();
var rc = {
  x: rect.left,
  y: rect.top,
  w: rect.width,
  h: rect.height
};

getBoundingClientRect() considers scrolling so that you no longer need to add it. You get the coordinates relative to screen using window.mozInnerScreenX and window.mozInnerScreenY:

rc.x += window.mozInnerScreenX;
rc.y += window.mozInnerScreenY;

And after that you multiply the values with screenPixelsPerCSSPixel. That should give you proper screen coordinates.

Upvotes: 9

honestann
honestann

Reputation: 1424

I will add one more "trick" that helped me with a similar problem.

Whenever my code receives a mousemove event, I capture the mouse-cursor positions in ALL the coordinates that event provides, which includes at least "screen", "client" and "pageXY" coordinates. Then for any OTHER purpose I can compute the difference between these coordinates simply by subtracting the appropriate two of those.

In your case, you'd probably compute an offset like this:

deltaX = event.screenX - event.clientX;
deltaY = event.screenY - event.clientY;

or

offsetX = event.screenX - event.pageX;
offsetY = event.screenY - event.pageY;

Then just add deltaX and deltaY or offsetX and offsetY to those coordinates to get screen coordinates.

Upvotes: 1

Related Questions