Bug 264245. Make all popups have no nsIWidget parent to avoid the hassles of various widget implementations not keeping their position consistent with their parent. Also, aggressively invalidate cached screen coordinates in GTK1 to avoid bugs. r=bzbarsky,sr=blizzard

This commit is contained in:
roc+%cs.cmu.edu 2004-10-21 18:35:35 +00:00
Родитель 7e0e605b99
Коммит d3706fffdc
6 изменённых файлов: 66 добавлений и 51 удалений

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

@ -343,14 +343,18 @@ static void AdjustChildWidgets(nsView *aView,
nsPoint aWidgetToParentViewOrigin, float aScale, PRBool aInvalidate)
{
if (aView->HasWidget()) {
nsRect bounds = aView->GetBounds();
nsPoint widgetOrigin = aWidgetToParentViewOrigin
+ nsPoint(bounds.x, bounds.y);
nsIWidget* widget = aView->GetWidget();
widget->Move(NSTwipsToIntPixels(widgetOrigin.x, aScale),
NSTwipsToIntPixels(widgetOrigin.y, aScale));
if (aInvalidate) {
widget->Invalidate(PR_FALSE);
nsWindowType type;
widget->GetWindowType(type);
if (type != eWindowType_popup) {
nsRect bounds = aView->GetBounds();
nsPoint widgetOrigin = aWidgetToParentViewOrigin
+ nsPoint(bounds.x, bounds.y);
widget->Move(NSTwipsToIntPixels(widgetOrigin.x, aScale),
NSTwipsToIntPixels(widgetOrigin.y, aScale));
if (aInvalidate) {
widget->Invalidate(PR_FALSE);
}
}
} else {
// Don't recurse if the view has a widget, because we adjusted the view's

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

@ -396,15 +396,26 @@ void nsView::ResetWidgetBounds(PRBool aRecurse, PRBool aMoveOnly,
}
nsIDeviceContext *dx;
float t2p;
float t2p, p2t;
mViewManager->GetDeviceContext(dx);
t2p = dx->AppUnitsToDevUnits();
p2t = dx->DevUnitsToAppUnits();
NS_RELEASE(dx);
nsPoint offset(0, 0);
if (GetParent()) {
GetParent()->GetNearestWidget(&offset);
nsIWidget* parentWidget = GetParent()->GetNearestWidget(&offset);
nsWindowType type;
mWindow->GetWindowType(type);
if (type == eWindowType_popup) {
// put offset into screen coordinates
nsRect screenRect(0,0,1,1);
parentWidget->WidgetToScreen(screenRect, screenRect);
offset += nsPoint(NSIntPixelsToTwips(screenRect.x, p2t),
NSIntPixelsToTwips(screenRect.y, p2t));
}
}
nsRect newBounds(NSTwipsToIntPixels((mDimBounds.x + offset.x), t2p),
@ -568,11 +579,11 @@ NS_IMETHODIMP nsView::SetContentTransparency(PRBool aTransparent)
}
nsresult nsIView::CreateWidget(const nsIID &aWindowIID,
nsWidgetInitData *aWidgetInitData,
nsNativeWidget aNative,
PRBool aEnableDragDrop,
PRBool aResetVisibility,
nsContentType aContentType)
nsWidgetInitData *aWidgetInitData,
nsNativeWidget aNative,
PRBool aEnableDragDrop,
PRBool aResetVisibility,
nsContentType aContentType)
{
nsIDeviceContext *dx;
nsRect trect = mDimBounds;
@ -615,8 +626,13 @@ nsresult nsIView::CreateWidget(const nsIID &aWindowIID,
nsIWidget* parentWidget = GetParent() ? GetParent()->GetNearestWidget(nsnull)
: nsnull;
mWindow->Create(parentWidget, trect,
::HandleEvent, dx, nsnull, nsnull, aWidgetInitData);
if (aWidgetInitData->mWindowType == eWindowType_popup) {
mWindow->Create(parentWidget->GetNativeData(NS_NATIVE_WINDOW), trect,
::HandleEvent, dx, nsnull, nsnull, aWidgetInitData);
} else {
mWindow->Create(parentWidget, trect,
::HandleEvent, dx, nsnull, nsnull, aWidgetInitData);
}
}
if (aEnableDragDrop) {
mWindow->EnableDragDrop(PR_TRUE);

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

@ -1248,6 +1248,9 @@ nsresult nsWidget::CreateWidget(nsIWidget *aParent,
aInitData->mWindowType == eWindowType_invisible) ?
nsnull : aParent;
NS_ASSERTION(aInitData->mWindowType != eWindowType_popup ||
!aParent, "Popups should not be hooked into nsIWidget hierarchy");
BaseCreate(baseParent, aRect, aHandleEventFunction, aContext,
aAppShell, aToolkit, aInitData);

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

@ -415,6 +415,13 @@ NS_IMETHODIMP nsWindow::Destroy(void)
void nsWindow::InvalidateWindowPos(void)
{
mCachedX = mCachedY = -1;
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
// Force kid to invalidate its window position if necessary.
nsRect kidBounds;
kid->GetBounds(kidBounds);
kid->Move(kidBounds.x, kidBounds.y);
}
}
void
@ -428,7 +435,17 @@ PRBool nsWindow::GetWindowPos(nscoord &x, nscoord &y)
{
if ((mCachedX==-1) && (mCachedY==-1)) { /* Not cached */
gint xpos, ypos;
if (mMozArea)
if (mParent)
{
// Just ask our parent; it might have its position cached, so
// we can save a bunch of work.
nsRect newRect;
mParent->WidgetToScreen(mBounds, newRect);
xpos = newRect.x;
ypos = newRect.y;
}
else if (mMozArea)
{
if (mMozArea->window)
{
@ -448,8 +465,11 @@ PRBool nsWindow::GetWindowPos(nscoord &x, nscoord &y)
gdk_window_get_origin(mSuperWin->bin_window, &xpos, &ypos);
}
else
return FALSE;
return PR_FALSE;
}
else
return PR_FALSE;
mCachedX = xpos;
mCachedY = ypos;
}
@ -2617,7 +2637,7 @@ NS_IMETHODIMP nsWindow::ConstrainPosition(PRBool aAllowSlop, PRInt32 *aX, PRInt3
NS_IMETHODIMP nsWindow::Move(PRInt32 aX, PRInt32 aY)
{
InvalidateWindowPos();
InvalidateWindowPos();
// check if we are at right place already
if((aX == mBounds.x) && (aY == mBounds.y) && !mIsToplevel) {
return NS_OK;

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

@ -2032,6 +2032,9 @@ nsWindow::NativeCreate(nsIWidget *aParent,
aInitData->mWindowType == eWindowType_invisible) ?
nsnull : aParent;
NS_ASSERTION(aInitData->mWindowType != eWindowType_popup ||
!aParent, "Popups should not be hooked into nsIWidget hierarchy");
// initialize all the common bits of this class
BaseCreate(baseParent, aRect, aHandleEventFunction, aContext,
aAppShell, aToolkit, aInitData);

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

@ -1460,6 +1460,7 @@ nsWindow::StandardWindowCreate(nsIWidget *aParent,
DWORD extendedStyle = WindowExStyle();
if (mWindowType == eWindowType_popup) {
NS_ASSERTION(!aParent, "Popups should not be hooked into the nsIWidget hierarchy");
mBorderlessParent = parent;
// Don't set the parent of a popup window.
parent = NULL;
@ -2001,22 +2002,6 @@ NS_METHOD nsWindow::Move(PRInt32 aX, PRInt32 aY)
return NS_OK;
}
// When moving a borderless top-level window the window
// must be placed relative to its parent. WIN32 wants to
// place it relative to the screen, so we used the cached parent
// to calculate the parent's location then add the x,y passed to
// the move to get the screen coordinate for the borderless top-level
// window.
if (mWindowType == eWindowType_popup) {
HWND parent = mBorderlessParent;
if (parent) {
RECT pr;
VERIFY(::GetWindowRect(parent, &pr));
aX += pr.left;
aY += pr.top;
}
}
mBounds.x = aX;
mBounds.y = aY;
@ -2127,22 +2112,6 @@ NS_METHOD nsWindow::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeig
ResizeTranslucentWindow(aWidth, aHeight);
#endif
// When resizing a borderless top-level window the window
// must be placed relative to its parent. WIN32 wants to
// place it relative to the screen, so we used the cached parent
// to calculate the parent's location then add the x,y passed to
// the resize to get the screen coordinate for the borderless top-level
// window.
if (mWindowType == eWindowType_popup) {
HWND parent = mBorderlessParent;
if (parent) {
RECT pr;
VERIFY(::GetWindowRect(parent, &pr));
aX += pr.left;
aY += pr.top;
}
}
// Set cached value for lightweight and printing
mBounds.x = aX;
mBounds.y = aY;