зеркало из https://github.com/mozilla/pjs.git
Add methods to get screen coordinates of frames and views. Bug 268576,
r+sr=roc
This commit is contained in:
Родитель
ee3a61b53f
Коммит
7198a5985b
|
@ -712,7 +712,7 @@ NS_IMETHODIMP nsAccessibleText::GetCharacterExtents(PRInt32 aOffset,
|
|||
shell->GetPrimaryFrameFor(content, &frame);
|
||||
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
|
||||
|
||||
nsRect frameRect = frame->GetRect();
|
||||
nsIntRect frameScreenRect = frame->GetScreenRectExternal();
|
||||
|
||||
nsCOMPtr<nsIRenderingContext> rc;
|
||||
shell->CreateRenderingContext(frame, getter_AddRefs(rc));
|
||||
|
@ -749,43 +749,15 @@ NS_IMETHODIMP nsAccessibleText::GetCharacterExtents(PRInt32 aOffset,
|
|||
*aHeight = NSTwipsToIntPixels(tmpHeight, t2p);
|
||||
}
|
||||
|
||||
//Getting x and y
|
||||
PRInt32 tmpX, tmpY;
|
||||
tmpX = frameRect.x;
|
||||
tmpY = frameRect.y;
|
||||
|
||||
//add the width of the string before current char
|
||||
nsAutoString beforeString;
|
||||
nscoord beforeWidth;
|
||||
if (NS_SUCCEEDED(GetText(0, aOffset, beforeString)) &&
|
||||
NS_SUCCEEDED(rc->GetWidth(beforeString, beforeWidth))) {
|
||||
tmpX += beforeWidth;
|
||||
}
|
||||
|
||||
//find the topest frame, add the offset recursively
|
||||
nsIFrame* tmpFrame = frame;
|
||||
nsIFrame* parentFrame = tmpFrame->GetParent();
|
||||
while (parentFrame) {
|
||||
nsPoint origin = parentFrame->GetPosition();
|
||||
tmpX += origin.x;
|
||||
tmpY += origin.y;
|
||||
tmpFrame = parentFrame;
|
||||
parentFrame = tmpFrame->GetParent();
|
||||
}
|
||||
|
||||
tmpX = NSTwipsToIntPixels(tmpX, t2p);
|
||||
tmpY = NSTwipsToIntPixels(tmpY, t2p);
|
||||
|
||||
//change to screen co-ord
|
||||
nsIWidget *frameWidget = tmpFrame->GetWindow();
|
||||
if (frameWidget) {
|
||||
nsRect oldRect(tmpX, tmpY, 0, 0), newRect;
|
||||
if (NS_SUCCEEDED(frameWidget->WidgetToScreen(oldRect, newRect))) {
|
||||
tmpX = newRect.x;
|
||||
tmpY = newRect.y;
|
||||
}
|
||||
frameScreenRect.x += NSTwipsToIntPixels(beforeWidth, t2p);
|
||||
}
|
||||
|
||||
PRInt32 screenX = 0, screenY = 0;
|
||||
if (aCoordType == COORD_TYPE_WINDOW) {
|
||||
//co-ord type = window
|
||||
nsCOMPtr<nsIDOMDocumentView> docView(do_QueryInterface(doc));
|
||||
|
@ -798,20 +770,15 @@ NS_IMETHODIMP nsAccessibleText::GetCharacterExtents(PRInt32 aOffset,
|
|||
nsCOMPtr<nsIDOMWindowInternal> windowInter(do_QueryInterface(abstractView));
|
||||
NS_ENSURE_TRUE(windowInter, NS_ERROR_FAILURE);
|
||||
|
||||
PRInt32 screenX,screenY;
|
||||
if (NS_FAILED(windowInter->GetScreenX(&screenX)) ||
|
||||
NS_FAILED(windowInter->GetScreenY(&screenY))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
// else default: co-ord type = screen
|
||||
|
||||
*aX = tmpX - screenX;
|
||||
*aY = tmpY - screenY;
|
||||
}
|
||||
else {
|
||||
//default: co-ord type = screen
|
||||
*aX = tmpX;
|
||||
*aY = tmpY;
|
||||
}
|
||||
*aX = frameScreenRect.x - screenX;
|
||||
*aY = frameScreenRect.y - screenY;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -1200,69 +1200,22 @@ void nsSVGSVGElement::GetScreenPosition(PRInt32 &x, PRInt32 &y)
|
|||
nsIDocument *document = GetCurrentDoc();
|
||||
if (!document) return;
|
||||
|
||||
// Flush all pending notifications so that our frames are uptodate
|
||||
// Make sure to do this before we start grabbing layout objects like
|
||||
// presshells.
|
||||
document->FlushPendingNotifications(Flush_Layout);
|
||||
|
||||
nsIPresShell *presShell = document->GetShellAt(0);
|
||||
if (!presShell) {
|
||||
NS_ERROR("couldn't get presshell");
|
||||
return;
|
||||
}
|
||||
|
||||
nsPresContext *context = presShell->GetPresContext();
|
||||
if (!context) {
|
||||
NS_ERROR("couldn't get prescontext");
|
||||
return;
|
||||
}
|
||||
|
||||
// Flush all pending notifications so that our frames are uptodate
|
||||
document->FlushPendingNotifications(Flush_Layout);
|
||||
|
||||
nsIFrame* frame;
|
||||
presShell->GetPrimaryFrameFor(this, &frame);
|
||||
|
||||
float t2p;
|
||||
t2p = context->TwipsToPixels();
|
||||
|
||||
|
||||
nsIWidget* widget = nsnull;
|
||||
|
||||
while (frame) {
|
||||
// Look for a widget so we can get screen coordinates
|
||||
nsIView* view = frame->GetView();
|
||||
if (view) {
|
||||
// handle scrolled views along the way:
|
||||
nsIScrollableView* scrollableView = nsnull;
|
||||
CallQueryInterface(view, &scrollableView);
|
||||
if (scrollableView) {
|
||||
nscoord scrollX, scrollY;
|
||||
scrollableView->GetScrollPosition(scrollX, scrollY);
|
||||
x -= scrollX;
|
||||
y -= scrollY;
|
||||
}
|
||||
|
||||
// if this is a widget we break and get screen coords from it:
|
||||
widget = view->GetWidget();
|
||||
if (widget)
|
||||
break;
|
||||
}
|
||||
|
||||
// No widget yet, so count up the coordinates of the frame
|
||||
nsPoint origin = frame->GetPosition();
|
||||
x += origin.x;
|
||||
y += origin.y;
|
||||
|
||||
frame = frame->GetParent();
|
||||
}
|
||||
|
||||
|
||||
// Convert to pixels using that scale
|
||||
x = NSTwipsToIntPixels(x, t2p);
|
||||
y = NSTwipsToIntPixels(y, t2p);
|
||||
|
||||
if (widget) {
|
||||
// Add the widget's screen coordinates to the offset we've counted
|
||||
nsRect client(0,0,0,0);
|
||||
nsRect screen;
|
||||
widget->WidgetToScreen(client, screen);
|
||||
x += screen.x;
|
||||
y += screen.y;
|
||||
if (frame) {
|
||||
nsIntRect rect = frame->GetScreenRect();
|
||||
x = rect.x;
|
||||
y = rect.y;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -999,6 +999,13 @@ public:
|
|||
nsPoint GetOffsetTo(const nsIFrame* aOther) const;
|
||||
virtual nsPoint GetOffsetToExternal(const nsIFrame* aOther) const;
|
||||
|
||||
/**
|
||||
* Get the screen rect of the frame.
|
||||
* @return the pixel rect of the frame in screen coordinates.
|
||||
*/
|
||||
nsIntRect GetScreenRect() const;
|
||||
virtual nsIntRect GetScreenRectExternal() const;
|
||||
|
||||
/**
|
||||
* Returns the offset from this frame to the closest geometric parent that
|
||||
* has a view. Also returns the containing view or null in case of error
|
||||
|
|
|
@ -2296,6 +2296,37 @@ nsPoint nsIFrame::GetOffsetTo(const nsIFrame* aOther) const
|
|||
return offset;
|
||||
}
|
||||
|
||||
// virtual
|
||||
nsIntRect nsIFrame::GetScreenRectExternal() const
|
||||
{
|
||||
return GetScreenRect();
|
||||
}
|
||||
|
||||
nsIntRect nsIFrame::GetScreenRect() const
|
||||
{
|
||||
nsIntRect retval(0,0,0,0);
|
||||
nsPoint toViewOffset(0,0);
|
||||
nsIView* view = GetClosestView(&toViewOffset);
|
||||
|
||||
if (view) {
|
||||
nsPoint toWidgetOffset(0,0);
|
||||
nsIWidget* widget = view->GetNearestWidget(&toWidgetOffset);
|
||||
|
||||
if (widget) {
|
||||
nsRect ourRect = mRect;
|
||||
ourRect += toViewOffset + toWidgetOffset;
|
||||
ourRect.ScaleRoundOut(GetPresContext()->TwipsToPixels());
|
||||
// Is it safe to pass the same rect for both args of WidgetToScreen?
|
||||
// It's not clear, so let's not...
|
||||
nsIntRect ourPxRect(ourRect.x, ourRect.y, ourRect.width, ourRect.height);
|
||||
|
||||
widget->WidgetToScreen(ourPxRect, retval);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
// Returns the offset from this frame to the closest geometric parent that
|
||||
// has a view. Also returns the containing view or null in case of error
|
||||
NS_IMETHODIMP nsFrame::GetOffsetFromView(nsPresContext* aPresContext,
|
||||
|
|
|
@ -999,6 +999,13 @@ public:
|
|||
nsPoint GetOffsetTo(const nsIFrame* aOther) const;
|
||||
virtual nsPoint GetOffsetToExternal(const nsIFrame* aOther) const;
|
||||
|
||||
/**
|
||||
* Get the screen rect of the frame.
|
||||
* @return the pixel rect of the frame in screen coordinates.
|
||||
*/
|
||||
nsIntRect GetScreenRect() const;
|
||||
virtual nsIntRect GetScreenRectExternal() const;
|
||||
|
||||
/**
|
||||
* Returns the offset from this frame to the closest geometric parent that
|
||||
* has a view. Also returns the containing view or null in case of error
|
||||
|
|
|
@ -2296,6 +2296,37 @@ nsPoint nsIFrame::GetOffsetTo(const nsIFrame* aOther) const
|
|||
return offset;
|
||||
}
|
||||
|
||||
// virtual
|
||||
nsIntRect nsIFrame::GetScreenRectExternal() const
|
||||
{
|
||||
return GetScreenRect();
|
||||
}
|
||||
|
||||
nsIntRect nsIFrame::GetScreenRect() const
|
||||
{
|
||||
nsIntRect retval(0,0,0,0);
|
||||
nsPoint toViewOffset(0,0);
|
||||
nsIView* view = GetClosestView(&toViewOffset);
|
||||
|
||||
if (view) {
|
||||
nsPoint toWidgetOffset(0,0);
|
||||
nsIWidget* widget = view->GetNearestWidget(&toWidgetOffset);
|
||||
|
||||
if (widget) {
|
||||
nsRect ourRect = mRect;
|
||||
ourRect += toViewOffset + toWidgetOffset;
|
||||
ourRect.ScaleRoundOut(GetPresContext()->TwipsToPixels());
|
||||
// Is it safe to pass the same rect for both args of WidgetToScreen?
|
||||
// It's not clear, so let's not...
|
||||
nsIntRect ourPxRect(ourRect.x, ourRect.y, ourRect.width, ourRect.height);
|
||||
|
||||
widget->WidgetToScreen(ourPxRect, retval);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
// Returns the offset from this frame to the closest geometric parent that
|
||||
// has a view. Also returns the containing view or null in case of error
|
||||
NS_IMETHODIMP nsFrame::GetOffsetFromView(nsPresContext* aPresContext,
|
||||
|
|
|
@ -264,11 +264,10 @@ nsBoxObject::GetOffsetRect(nsRect& aRect)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsBoxObject::GetScreenRect(nsRect& aRect)
|
||||
nsBoxObject::GetScreenPosition(nsIntPoint& aPoint)
|
||||
{
|
||||
aRect.x = aRect.y = 0;
|
||||
aRect.Empty();
|
||||
|
||||
aPoint.x = aPoint.y = 0;
|
||||
|
||||
if (!mContent)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
|
@ -287,40 +286,10 @@ nsBoxObject::GetScreenRect(nsRect& aRect)
|
|||
nsIFrame* frame;
|
||||
presShell->GetPrimaryFrameFor(mContent, &frame);
|
||||
|
||||
PRInt32 offsetX = 0;
|
||||
PRInt32 offsetY = 0;
|
||||
nsIWidget* widget = nsnull;
|
||||
|
||||
while (frame) {
|
||||
// Look for a widget so we can get screen coordinates
|
||||
if (frame->HasView()) {
|
||||
widget = frame->GetView()->GetWidget();
|
||||
if (widget)
|
||||
break;
|
||||
}
|
||||
|
||||
// No widget yet, so count up the coordinates of the frame
|
||||
nsPoint origin = frame->GetPosition();
|
||||
offsetX += origin.x;
|
||||
offsetY += origin.y;
|
||||
|
||||
frame = frame->GetParent();
|
||||
}
|
||||
|
||||
if (widget) {
|
||||
// Get the scale from that Presentation Context
|
||||
float scale;
|
||||
scale = presContext->TwipsToPixels();
|
||||
|
||||
// Convert to pixels using that scale
|
||||
offsetX = NSTwipsToIntPixels(offsetX, scale);
|
||||
offsetY = NSTwipsToIntPixels(offsetY, scale);
|
||||
|
||||
// Add the widget's screen coordinates to the offset we've counted
|
||||
nsRect oldBox(0,0,0,0);
|
||||
widget->WidgetToScreen(oldBox, aRect);
|
||||
aRect.x += offsetX;
|
||||
aRect.y += offsetY;
|
||||
if (frame) {
|
||||
nsIntRect rect = frame->GetScreenRect();
|
||||
aPoint.x = rect.x;
|
||||
aPoint.y = rect.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -368,11 +337,11 @@ nsBoxObject::GetHeight(PRInt32* aResult)
|
|||
NS_IMETHODIMP
|
||||
nsBoxObject::GetScreenX(PRInt32 *_retval)
|
||||
{
|
||||
nsRect rect;
|
||||
nsresult rv = GetScreenRect(rect);
|
||||
nsIntPoint position;
|
||||
nsresult rv = GetScreenPosition(position);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
*_retval = rect.x;
|
||||
*_retval = position.x;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -380,11 +349,11 @@ nsBoxObject::GetScreenX(PRInt32 *_retval)
|
|||
NS_IMETHODIMP
|
||||
nsBoxObject::GetScreenY(PRInt32 *_retval)
|
||||
{
|
||||
nsRect rect;
|
||||
nsresult rv = GetScreenRect(rect);
|
||||
nsIntPoint position;
|
||||
nsresult rv = GetScreenPosition(position);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
*_retval = rect.y;
|
||||
*_retval = position.y;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "nsIBoxObject.h"
|
||||
#include "nsPIBoxObject.h"
|
||||
#include "nsIPresState.h"
|
||||
#include "nsPoint.h"
|
||||
|
||||
class nsIBoxLayoutManager;
|
||||
class nsIBoxPaintManager;
|
||||
|
@ -62,7 +63,7 @@ public:
|
|||
|
||||
virtual nsIFrame* GetFrame();
|
||||
nsresult GetOffsetRect(nsRect& aRect);
|
||||
nsresult GetScreenRect(nsRect& aRect);
|
||||
nsresult GetScreenPosition(nsIntPoint& aPoint);
|
||||
nsIDOMElement* GetChildByOrdinalAt(PRUint32 aIndex);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -2204,45 +2204,16 @@ nsMenuPopupFrame::MoveTo(PRInt32 aLeft, PRInt32 aTop)
|
|||
mContent->SetAttr(kNameSpaceID_None, nsXULAtoms::top, top, PR_FALSE);
|
||||
|
||||
nsIView* view = GetView();
|
||||
NS_ASSERTION(view->GetParent(), "Must have parent!");
|
||||
|
||||
// Retrieve screen position of parent view
|
||||
nsPoint screenPos;
|
||||
GetScreenPosition(view->GetParent(), screenPos);
|
||||
nsIntPoint screenPos = view->GetParent()->GetScreenPosition();
|
||||
|
||||
// Move the widget
|
||||
// XXXbz don't we want screenPos to be the parent _widget_'s position, then?
|
||||
view->GetWidget()->Move(aLeft - screenPos.x, aTop - screenPos.y);
|
||||
}
|
||||
|
||||
void
|
||||
nsMenuPopupFrame::GetScreenPosition(nsIView* aView, nsPoint& aScreenPosition)
|
||||
{
|
||||
nsPoint screenPos(0,0);
|
||||
|
||||
nsIView* currView = aView;
|
||||
nsIView* nextView = nsnull;
|
||||
|
||||
while (1) {
|
||||
screenPos += currView->GetPosition();
|
||||
|
||||
nextView = currView->GetParent();
|
||||
if (!nextView)
|
||||
break;
|
||||
else
|
||||
currView = nextView;
|
||||
}
|
||||
|
||||
nsIWidget* rootWidget = currView->GetWidget();
|
||||
nsRect bounds, screenBounds;
|
||||
rootWidget->GetScreenBounds(bounds);
|
||||
rootWidget->WidgetToScreen(bounds, screenBounds);
|
||||
|
||||
float t2p;
|
||||
t2p = mPresContext->TwipsToPixels();
|
||||
|
||||
aScreenPosition.x = NSTwipsToIntPixels(screenPos.x, t2p) + screenBounds.x;
|
||||
aScreenPosition.y = NSTwipsToIntPixels(screenPos.y, t2p) + screenBounds.y;
|
||||
}
|
||||
|
||||
void
|
||||
nsMenuPopupFrame::GetAutoPosition(PRBool* aShouldAutoPosition)
|
||||
{
|
||||
|
|
|
@ -178,7 +178,6 @@ public:
|
|||
void EnsureMenuItemIsVisible(nsIMenuFrame* aMenuFrame);
|
||||
|
||||
void MoveTo(PRInt32 aLeft, PRInt32 aTop);
|
||||
void GetScreenPosition(nsIView* aView, nsPoint& aScreenPosition);
|
||||
|
||||
void GetAutoPosition(PRBool* aShouldAutoPosition);
|
||||
void SetAutoPosition(PRBool aShouldAutoPosition);
|
||||
|
|
|
@ -185,6 +185,13 @@ public:
|
|||
*/
|
||||
nsPoint GetOffsetTo(const nsIView* aOther) const;
|
||||
|
||||
/**
|
||||
* Get the screen position of the view.
|
||||
* @return the pixel position of the top-left of the view in screen
|
||||
* coordinates.
|
||||
*/
|
||||
nsIntPoint GetScreenPosition() const;
|
||||
|
||||
/**
|
||||
* Called to query the visibility state of a view.
|
||||
* @result current visibility state
|
||||
|
@ -291,7 +298,7 @@ public:
|
|||
* XXX Remove this 'virtual' when gfx+widget are merged into gklayout;
|
||||
* Mac widget depends on this method, which is BOGUS!
|
||||
*/
|
||||
virtual nsIWidget* GetNearestWidget(nsPoint* aOffset);
|
||||
virtual nsIWidget* GetNearestWidget(nsPoint* aOffset) const;
|
||||
|
||||
/**
|
||||
* Create a widget to associate with this view.
|
||||
|
|
|
@ -754,11 +754,30 @@ nsPoint nsIView::GetOffsetTo(const nsIView* aOther) const
|
|||
return offset;
|
||||
}
|
||||
|
||||
nsIWidget* nsIView::GetNearestWidget(nsPoint* aOffset)
|
||||
nsIntPoint nsIView::GetScreenPosition() const
|
||||
{
|
||||
nsIntRect screenRect(0,0,0,0);
|
||||
nsPoint toWidgetOffset(0,0);
|
||||
nsIWidget* widget = GetNearestWidget(&toWidgetOffset);
|
||||
if (widget) {
|
||||
nsCOMPtr<nsIDeviceContext> dx;
|
||||
mViewManager->GetDeviceContext(*getter_AddRefs(dx));
|
||||
float t2p = dx->AppUnitsToDevUnits();
|
||||
nsIntRect ourRect(NSTwipsToIntPixels(toWidgetOffset.x, t2p),
|
||||
NSTwipsToIntPixels(toWidgetOffset.y, t2p),
|
||||
0,
|
||||
0);
|
||||
widget->WidgetToScreen(ourRect, screenRect);
|
||||
}
|
||||
|
||||
return nsIntPoint(screenRect.x, screenRect.y);
|
||||
}
|
||||
|
||||
nsIWidget* nsIView::GetNearestWidget(nsPoint* aOffset) const
|
||||
{
|
||||
nsPoint pt(0, 0);
|
||||
nsView* v;
|
||||
for (v = NS_STATIC_CAST(nsView*, this);
|
||||
const nsView* v;
|
||||
for (v = NS_STATIC_CAST(const nsView*, this);
|
||||
v && !v->HasWidget(); v = v->GetParent()) {
|
||||
pt += v->GetPosition();
|
||||
}
|
||||
|
@ -766,7 +785,7 @@ nsIWidget* nsIView::GetNearestWidget(nsPoint* aOffset)
|
|||
if (aOffset) {
|
||||
*aOffset = pt;
|
||||
}
|
||||
return NS_STATIC_CAST(nsView*, this)->GetViewManager()->GetWidget();
|
||||
return NS_STATIC_CAST(const nsView*, this)->GetViewManager()->GetWidget();
|
||||
}
|
||||
|
||||
// pt is now the offset from v's origin to this's origin
|
||||
|
|
Загрузка…
Ссылка в новой задаче