diff --git a/widget/src/gtk/nsWidget.cpp b/widget/src/gtk/nsWidget.cpp index 174fcfdf6aaf..3d3c641efb20 100644 --- a/widget/src/gtk/nsWidget.cpp +++ b/widget/src/gtk/nsWidget.cpp @@ -224,6 +224,7 @@ nsWidget::nsWidget() mPreferredWidth = 0; mPreferredHeight = 0; mShown = PR_FALSE; + mInternalShown = PR_FALSE; mBounds.x = 0; mBounds.y = 0; mBounds.width = 0; @@ -438,20 +439,52 @@ NS_IMETHODIMP nsWidget::Show(PRBool bState) if (!mWidget) return NS_OK; // Will be null durring printing - if (bState) { - gtk_widget_show(mWidget); - gtk_widget_show(mMozBox); - } - else { - gtk_widget_hide(mMozBox); - gtk_widget_hide(mWidget); - } - mShown = bState; + ResetInternalVisibility(); + return NS_OK; } +void nsWidget::ResetInternalVisibility() +{ + PRBool show = mShown; + if (show) { + if (mParent != nsnull) { + nsRect parentBounds; + mParent->GetClientBounds(parentBounds); + parentBounds.x = parentBounds.y = 0; + nsRect myBounds; + GetBounds(myBounds); + if (!myBounds.Intersects(parentBounds)) { + show = PR_FALSE; + } + } + } + + if (show == mInternalShown) { + return; + } + + SetInternalVisibility(show); +} + +void nsWidget::SetInternalVisibility(PRBool aVisible) +{ + mInternalShown = aVisible; + + if (aVisible) { + if (mWidget) + gtk_widget_show(mWidget); + if (mMozBox) + gtk_widget_show(mMozBox); + } else { + if (mWidget) + gtk_widget_hide(mWidget); + if (mMozBox) + gtk_widget_hide(mMozBox); + } +} NS_IMETHODIMP nsWidget::CaptureRollupEvents(nsIRollupListener * aListener, PRBool aDoCapture, PRBool aConsumeRollupEvent) { @@ -548,12 +581,13 @@ NS_IMETHODIMP nsWidget::Move(PRInt32 aX, PRInt32 aY) mBounds.x = aX; mBounds.y = aY; - if (mMozBox) { gtk_mozbox_set_position(GTK_MOZBOX(mMozBox), aX, aY); } + ResetInternalVisibility(); + return NS_OK; } @@ -571,6 +605,17 @@ NS_IMETHODIMP nsWidget::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint) if (mWidget) gtk_widget_set_usize(mWidget, aWidth, aHeight); + ResetInternalVisibility(); + PRUint32 childCount, index; + if (NS_SUCCEEDED(mChildren->Count(&childCount))) { + for (index = 0; index < childCount; index++) { + nsCOMPtr childWidget; + if (NS_SUCCEEDED(mChildren->QueryElementAt(index, NS_GET_IID(nsIWidget), (void**)getter_AddRefs(childWidget)))) { + NS_STATIC_CAST(nsWidget*, NS_STATIC_CAST(nsIWidget*, childWidget.get()))->ResetInternalVisibility(); + } + } + } + return NS_OK; } @@ -615,6 +660,8 @@ PRBool nsWidget::OnResize(nsRect &aRect) mBounds.width = aRect.width; mBounds.height = aRect.height; + ResetInternalVisibility(); + NS_ADDREF_THIS(); PRBool result = OnResize(&event); NS_RELEASE_THIS(); @@ -636,6 +683,8 @@ PRBool nsWidget::OnMove(PRInt32 aX, PRInt32 aY) mBounds.x = aX; mBounds.y = aY; + ResetInternalVisibility(); + nsGUIEvent event; InitEvent(event, NS_MOVE); event.point.x = aX; diff --git a/widget/src/gtk/nsWidget.h b/widget/src/gtk/nsWidget.h index 0726091f6c3c..3eec27fd1942 100644 --- a/widget/src/gtk/nsWidget.h +++ b/widget/src/gtk/nsWidget.h @@ -308,7 +308,18 @@ protected: public: virtual void IMECommitEvent(GdkEventKey *aEvent); + // This MUST be called after you change the widget bounds + // or after the parent's size changes + // or when you show the widget + // We will decide whether to really show the widget or not + // We will hide the widget if it doesn't overlap the parent bounds + // This reduces problems with 16-bit coordinates wrapping. + virtual void ResetInternalVisibility(); + protected: + // override this method to do whatever you have to do to make this widget + // visible or invisibile --- i.e., the real work of Show() + virtual void SetInternalVisibility(PRBool aVisible); ////////////////////////////////////////////////////////////////// // @@ -376,10 +387,10 @@ protected: // Invalidate) nsCOMPtr mUpdateArea; - PRBool mShown; - PRUint32 mPreferredWidth, mPreferredHeight; - PRBool mListenForResizes; + PRPackedBool mListenForResizes; + PRPackedBool mShown; + PRPackedBool mInternalShown; // this is the rollup listener variables static nsCOMPtr gRollupListener; diff --git a/widget/src/gtk/nsWindow.cpp b/widget/src/gtk/nsWindow.cpp index 8ef6d3123e63..24982bc923aa 100644 --- a/widget/src/gtk/nsWindow.cpp +++ b/widget/src/gtk/nsWindow.cpp @@ -2297,7 +2297,9 @@ NS_IMETHODIMP nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect) child->GetBounds(bounds); bounds.x += aDx; bounds.y += aDy; - NS_STATIC_CAST(nsBaseWidget*, (nsIWidget*)child)->SetBounds(bounds); + nsWidget* childWidget = NS_STATIC_CAST(nsWidget*, NS_STATIC_CAST(nsIWidget*, child.get())); + childWidget->SetBounds(bounds); + childWidget->ResetInternalVisibility(); } if (NS_FAILED(children->Next())) @@ -2561,13 +2563,33 @@ NS_IMETHODIMP nsWindow::Show(PRBool bState) mShown = bState; + // show + ResetInternalVisibility(); + return NS_OK; +} + +void nsWindow::ResetInternalVisibility() +{ + if (mShell) + { // top level, always set the visibility regardless of parent geometry + SetInternalVisibility(mShown); + } + else + { + nsWidget::ResetInternalVisibility(); + } +} + +void nsWindow::SetInternalVisibility(PRBool aVisible) +{ // don't show if we are too small if (mIsTooSmall) - return NS_OK; + return; - // show - if (bState) + mInternalShown = aVisible; + + if (aVisible) { // show mSuperWin gdk_window_show(mSuperWin->bin_window); @@ -2601,8 +2623,6 @@ NS_IMETHODIMP nsWindow::Show(PRBool bState) } } - - return NS_OK; } //------------------------------------------------------------------------- @@ -2688,6 +2708,8 @@ NS_IMETHODIMP nsWindow::Move(PRInt32 aX, PRInt32 aY) mBounds.x = aX; mBounds.y = aY; + ResetInternalVisibility(); + if (mIsToplevel && mShell) { #ifdef DEBUG @@ -2736,6 +2758,17 @@ NS_IMETHODIMP nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint) mBounds.width = aWidth; mBounds.height = aHeight; + ResetInternalVisibility(); + PRUint32 childCount, index; + if (NS_SUCCEEDED(mChildren->Count(&childCount))) { + for (index = 0; index < childCount; index++) { + nsCOMPtr childWidget; + if (NS_SUCCEEDED(mChildren->QueryElementAt(index, NS_GET_IID(nsIWidget), (void**)getter_AddRefs(childWidget)))) { + NS_STATIC_CAST(nsWidget*, NS_STATIC_CAST(nsIWidget*, childWidget.get()))->ResetInternalVisibility(); + } + } + } + // code to keep the window from showing before it has been moved or resized // if we are resized to 1x1 or less, we will hide the window. Show(TRUE) will be ignored until a @@ -2773,6 +2806,7 @@ NS_IMETHODIMP nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint) gdk_window_hide(mSuperWin->bin_window); gdk_window_hide(mSuperWin->shell_window); } + mInternalShown = PR_FALSE; } else { @@ -2823,8 +2857,9 @@ NS_IMETHODIMP nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint) //g_print("not sending resize event\n"); } - if (nNeedToShow) + if (nNeedToShow) { Show(PR_TRUE); + } if (aRepaint) Invalidate(PR_FALSE); diff --git a/widget/src/gtk/nsWindow.h b/widget/src/gtk/nsWindow.h index 4907025b2838..4d0b22cae110 100644 --- a/widget/src/gtk/nsWindow.h +++ b/widget/src/gtk/nsWindow.h @@ -198,6 +198,8 @@ public: static void ClearIconEntry(PLDHashTable* aTable, PLDHashEntryHdr* aHdr); protected: + virtual void ResetInternalVisibility(); + virtual void SetInternalVisibility(PRBool aVisible); virtual void OnRealize(GtkWidget *aWidget);