Add methods to get screen coordinates of frames and views. Bug 268576,

r+sr=roc
This commit is contained in:
bzbarsky%mit.edu 2004-11-23 17:26:19 +00:00
Родитель ee3a61b53f
Коммит 7198a5985b
12 изменённых файлов: 141 добавлений и 179 удалений

Просмотреть файл

@ -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