Try to reduce the amount of useless X traffic that happens at startup. Don't show widgets with invalid sizes. Reduce the number of Resize() requests that are sent back to the layout engine.

git-svn-id: svn://10.0.0.236/trunk@110527 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
blizzard%redhat.com 2001-12-15 05:06:01 +00:00
parent ea7174b216
commit 3ba168fc8c
6 changed files with 341 additions and 155 deletions

View File

@ -38,7 +38,12 @@
nsCommonWidget::nsCommonWidget()
{
mOnDestroyCalled = PR_FALSE;
mIsTopLevel = PR_FALSE;
mOnDestroyCalled = PR_FALSE;
mNeedsResize = PR_FALSE;
mListenForResizes = PR_FALSE;
mIsShown = PR_FALSE;
mNeedsShow = PR_FALSE;
}
nsCommonWidget::~nsCommonWidget()
@ -55,9 +60,11 @@ nsCommonWidget::GetParent(void)
}
void
nsCommonWidget::CommonCreate(nsIWidget *aParent)
nsCommonWidget::CommonCreate(nsIWidget *aParent, nsNativeWidget aNativeParent)
{
mParent = aParent;
if (aNativeParent)
mListenForResizes = PR_TRUE;
}
void
@ -223,6 +230,22 @@ nsCommonWidget::DispatchDeactivateEvent(void)
DispatchEvent(&event, status);
}
void
nsCommonWidget::DispatchResizeEvent(nsRect &aRect, nsEventStatus &aStatus)
{
nsSizeEvent event;
InitSizeEvent(event);
event.windowSize = &aRect;
event.point.x = aRect.x;
event.point.y = aRect.y;
event.mWinWidth = aRect.width;
event.mWinHeight = aRect.height;
nsEventStatus status;
DispatchEvent(&event, status);
}
NS_IMETHODIMP
nsCommonWidget::DispatchEvent(nsGUIEvent *aEvent,
nsEventStatus &aStatus)
@ -245,6 +268,152 @@ nsCommonWidget::DispatchEvent(nsGUIEvent *aEvent,
return NS_OK;
}
NS_IMETHODIMP
nsCommonWidget::Show(PRBool aState)
{
mIsShown = aState;
printf("nsCommonWidget::Show [%p] state %d\n", (void *)this, aState);
// Ok, someone called show on a window that isn't sized to a sane
// value. Mark this window as needing to have Show() called on it
// and return.
if (aState && !AreBoundsSane()) {
printf("\tbounds are insane\n");
mNeedsShow = PR_TRUE;
return NS_OK;
}
// If someone is hiding this widget, clear any needing show flag.
if (!aState)
mNeedsShow = PR_FALSE;
// If someone is showing this window and it needs a resize then
// resize the widget.
if (aState && mNeedsResize) {
printf("\tresizing\n");
NativeResize(mBounds.x, mBounds.y, mBounds.width, mBounds.height,
PR_FALSE);
}
NativeShow(aState);
return NS_OK;
}
NS_IMETHODIMP
nsCommonWidget::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
{
mBounds.width = aWidth;
mBounds.height = aHeight;
// There are several cases here that we need to handle, based on a
// matrix of the visibility of the widget, the sanity of this resize
// and whether or not the widget was previously sane.
// Has this widget been set to visible?
if (mIsShown) {
// Are the bounds sane?
if (AreBoundsSane()) {
// Yep? Resize the window
NativeResize(aWidth, aHeight, aRepaint);
// Does it need to be shown because it was previously insane?
if (mNeedsShow)
NativeShow(PR_TRUE);
}
else {
// If someone has set this so that the needs show flag is false
// and it needs to be hidden, update the flag and hide the
// window. This flag will be cleared the next time someone
// hides the window or shows it. It also prevents us from
// calling NativeShow(PR_FALSE) excessively on the window which
// causes unneeded X traffic.
if (!mNeedsShow) {
mNeedsShow = PR_TRUE;
NativeShow(PR_FALSE);
}
}
}
// If the widget hasn't been shown, mark the widget as needing to be
// resized before it is shown.
else {
// For widgets that we listen for resizes for (widgets created
// with native parents) we apparently _always_ have to resize. I
// dunno why, but apparently we're lame like that.
if (mListenForResizes)
NativeResize(aWidth, aHeight, aRepaint);
else
mNeedsResize = PR_TRUE;
}
// synthesize a resize event if this isn't a toplevel
if (mIsTopLevel || mListenForResizes) {
nsRect rect(mBounds.x, mBounds.y, aWidth, aHeight);
nsEventStatus status;
DispatchResizeEvent(rect, status);
}
return NS_OK;
}
NS_IMETHODIMP
nsCommonWidget::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight,
PRBool aRepaint)
{
mBounds.x = aX;
mBounds.y = aY;
mBounds.width = aWidth;
mBounds.height = aHeight;
// There are several cases here that we need to handle, based on a
// matrix of the visibility of the widget, the sanity of this resize
// and whether or not the widget was previously sane.
// Has this widget been set to visible?
if (mIsShown) {
// Are the bounds sane?
if (AreBoundsSane()) {
// Yep? Resize the window
NativeResize(aX, aY, aWidth, aHeight, aRepaint);
// Does it need to be shown because it was previously insane?
if (mNeedsShow)
NativeShow(PR_TRUE);
}
else {
// If someone has set this so that the needs show flag is false
// and it needs to be hidden, update the flag and hide the
// window. This flag will be cleared the next time someone
// hides the window or shows it. It also prevents us from
// calling NativeShow(PR_FALSE) excessively on the window which
// causes unneeded X traffic.
if (!mNeedsShow) {
mNeedsShow = PR_TRUE;
NativeShow(PR_FALSE);
}
}
}
// If the widget hasn't been shown, mark the widget as needing to be
// resized before it is shown
else {
// For widgets that we listen for resizes for (widgets created
// with native parents) we apparently _always_ have to resize. I
// dunno why, but apparently we're lame like that.
if (mListenForResizes)
NativeResize(aX, aY, aWidth, aHeight, aRepaint);
else
mNeedsResize = PR_TRUE;
}
if (mIsTopLevel || mListenForResizes) {
// synthesize a resize event
nsRect rect(aX, aY, aWidth, aHeight);
nsEventStatus status;
DispatchResizeEvent(rect, status);
}
return NS_OK;
}
void
nsCommonWidget::OnDestroy(void)
{
@ -264,3 +433,12 @@ nsCommonWidget::OnDestroy(void)
nsEventStatus status;
DispatchEvent(&event, status);
}
PRBool
nsCommonWidget::AreBoundsSane(void)
{
if (mBounds.width > 1 && mBounds.height > 1)
return PR_TRUE;
return PR_FALSE;
}

View File

@ -47,7 +47,7 @@ class nsCommonWidget : public nsBaseWidget {
virtual nsIWidget *GetParent(void);
void CommonCreate(nsIWidget *aParent);
void CommonCreate(nsIWidget *aParent, nsNativeWidget aNativeParent);
// event handling code
void InitPaintEvent(nsPaintEvent &aEvent);
@ -64,19 +64,54 @@ class nsCommonWidget : public nsBaseWidget {
void DispatchLostFocusEvent(void);
void DispatchActivateEvent(void);
void DispatchDeactivateEvent(void);
NS_IMETHOD DispatchEvent(nsGUIEvent *aEvent,
nsEventStatus &aStatus);
void DispatchResizeEvent(nsRect &aRect, nsEventStatus &aStatus);
NS_IMETHOD DispatchEvent(nsGUIEvent *aEvent, nsEventStatus &aStatus);
// virtual interfaces for some nsIWidget methods
virtual void NativeResize(PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint) = 0;
virtual void NativeResize(PRInt32 aX,
PRInt32 aY,
PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint) = 0;
virtual void NativeShow (PRBool aAction) = 0;
// Some of the nsIWidget methods
NS_IMETHOD Show(PRBool aState);
NS_IMETHOD Resize(PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint);
NS_IMETHOD Resize(PRInt32 aX,
PRInt32 aY,
PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint);
// called when we are destroyed
void OnDestroy(void);
// convert a key code into a DOM code
static int ConvertKeyCodeToDOMKeyCode(int aKeysym);
// called to check and see if a widget's dimensions are sane
PRBool AreBoundsSane(void);
protected:
nsCOMPtr<nsIWidget> mParent;
// Is this a toplevel window?
PRPackedBool mIsTopLevel;
// Has someone called OnDestroy() yet?
PRPackedBool mOnDestroyCalled;
// This is a flag that tracks if we need to resize a widget or
// window before we call |Show| on that widget.
PRPackedBool mNeedsResize;
// Should we send resize events on all resizes?
PRPackedBool mListenForResizes;
// This flag tracks if we're hidden or shown.
PRPackedBool mIsShown;
PRPackedBool mNeedsShow;
};
#endif /* __nsCommonWidget_h__ */

View File

@ -75,12 +75,6 @@ nsScrollbar::Create(nsNativeWidget aParent,
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsScrollbar::Show(PRBool aState)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsScrollbar::IsVisible(PRBool & aState)
{
@ -99,19 +93,6 @@ nsScrollbar::Move(PRInt32 aX, PRInt32 aY)
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsScrollbar::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsScrollbar::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight,
PRBool aRepaint)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsScrollbar::Enable(PRBool aState)
{
@ -299,3 +280,19 @@ nsScrollbar::SetParameters(PRUint32 aMaxRange, PRUint32 aThumbSize,
return NS_ERROR_NOT_IMPLEMENTED;
}
void
nsScrollbar::NativeResize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
{
}
void
nsScrollbar::NativeResize(PRInt32 aX, PRInt32 aY,
PRInt32 aWidth, PRInt32 aHeight,
PRBool aRepaint)
{
}
void
nsScrollbar::NativeShow (PRBool aAction)
{
}

View File

@ -63,13 +63,9 @@ class nsScrollbar : public nsCommonWidget,
nsIAppShell *aAppShell = nsnull,
nsIToolkit *aToolkit = nsnull,
nsWidgetInitData *aInitData = nsnull);
NS_IMETHOD Show(PRBool aState);
NS_IMETHOD IsVisible(PRBool & aState);
NS_IMETHOD ConstrainPosition(PRInt32 *aX, PRInt32 *aY);
NS_IMETHOD Move(PRInt32 aX, PRInt32 aY);
NS_IMETHOD Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint);
NS_IMETHOD Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight,
PRBool aRepaint);
NS_IMETHOD Enable(PRBool aState);
NS_IMETHOD SetFocus(PRBool aRaise = PR_FALSE);
virtual nsIFontMetrics* GetFont(void);
@ -104,6 +100,15 @@ class nsScrollbar : public nsCommonWidget,
NS_IMETHOD GetLineIncrement(PRUint32& aSize);
NS_IMETHOD SetParameters(PRUint32 aMaxRange, PRUint32 aThumbSize,
PRUint32 aPosition, PRUint32 aLineIncrement);
// stuff from common widget
void NativeResize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint);
void NativeResize(PRInt32 aX, PRInt32 aY,
PRInt32 aWidth, PRInt32 aHeight,
PRBool aRepaint);
void NativeShow (PRBool aAction);
private:
GtkWidget *mScrollbar;

View File

@ -83,7 +83,6 @@ nsWindow::nsWindow()
mContainer = nsnull;
mDrawingarea = nsnull;
mShell = nsnull;
mIsTopLevel = PR_FALSE;
mIsDestroyed = PR_FALSE;
mWindowType = eWindowType_child;
mPreferredWidth = 0;
@ -98,6 +97,7 @@ nsWindow::nsWindow()
nsWindow::~nsWindow()
{
printf("nsWindow::~nsWindow() [%p]\n", (void *)this);
Destroy();
}
@ -133,8 +133,11 @@ nsWindow::Destroy(void)
if (mIsDestroyed)
return NS_OK;
printf("nsWindow::Destroy [%p]\n", (void *)this);
mIsDestroyed = PR_TRUE;
NativeShow(PR_FALSE);
// make sure that we remove ourself as the focus window
if (mHasFocus) {
mHasFocus = PR_FALSE;
@ -160,27 +163,6 @@ nsWindow::Destroy(void)
return NS_OK;
}
NS_IMETHODIMP
nsWindow::Show(PRBool aState)
{
if (mIsTopLevel) {
moz_drawingarea_set_visibility(mDrawingarea, aState);
if (aState) {
gtk_widget_show(GTK_WIDGET(mContainer));
gtk_widget_show(mShell);
}
else {
gtk_widget_hide(GTK_WIDGET(mShell));
gtk_widget_hide(GTK_WIDGET(mContainer));
}
}
else {
moz_drawingarea_set_visibility(mDrawingarea, aState);
}
return NS_OK;
}
NS_IMETHODIMP
nsWindow::SetModal(PRBool aModal)
{
@ -202,7 +184,7 @@ nsWindow::ConstrainPosition(PRInt32 *aX, PRInt32 *aY)
NS_IMETHODIMP
nsWindow::Move(PRInt32 aX, PRInt32 aY)
{
if ((aX == mBounds.x) && (aY == mBounds.y) && !mIsTopLevel)
if ((aX == mBounds.x) && (aY == mBounds.y))
return NS_OK;
printf("nsWindow::Move [%p] %d %d\n", (void *)this,
@ -230,73 +212,6 @@ nsWindow::Move(PRInt32 aX, PRInt32 aY)
return NS_OK;
}
NS_IMETHODIMP
nsWindow::Resize(PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint)
{
mBounds.width = aWidth;
mBounds.height = aHeight;
printf("nsWindow::Resize [%p] %d %d\n", (void *)this,
aWidth, aHeight);
if (mIsTopLevel)
gtk_window_resize(GTK_WINDOW(mShell), aWidth, aHeight);
moz_drawingarea_resize (mDrawingarea, aWidth, aHeight);
// synthesize a resize event if this isn't a toplevel
if (!mIsTopLevel) {
nsRect rect(mBounds.x, mBounds.y, aWidth, aHeight);
nsEventStatus status;
SendResizeEvent(rect, status);
}
return NS_OK;
}
NS_IMETHODIMP
nsWindow::Resize(PRInt32 aX,
PRInt32 aY,
PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint)
{
mBounds.x = aX;
mBounds.y = aY;
mBounds.width = aWidth;
mBounds.height = aHeight;
printf("nsWindow::Resize [%p] %d %d %d %d\n", (void *)this,
aX, aY, aWidth, aHeight);
if (mIsTopLevel) {
if (mParent && mWindowType == eWindowType_popup) {
nsRect oldrect, newrect;
oldrect.x = aX;
oldrect.y = aY;
mParent->WidgetToScreen(oldrect, newrect);
gtk_window_move(GTK_WINDOW(mShell), newrect.x, newrect.y);
gtk_window_resize(GTK_WINDOW(mShell), aWidth, aHeight);
}
else {
gtk_window_move(GTK_WINDOW(mShell), aX, aY);
gtk_window_resize(GTK_WINDOW(mShell), aWidth, aHeight);
moz_drawingarea_resize(mDrawingarea, aWidth, aHeight);
}
}
else {
moz_drawingarea_move_resize(mDrawingarea, aX, aY, aWidth, aHeight);
// synthesize a resize event
nsRect rect(aX, aY, aWidth, aHeight);
nsEventStatus status;
SendResizeEvent(rect, status);
}
return NS_OK;
}
NS_IMETHODIMP
nsWindow::PlaceBehind(nsIWidget *aWidget,
PRBool aActivate)
@ -697,7 +612,7 @@ gboolean
nsWindow::OnExposeEvent(GtkWidget *aWidget, GdkEventExpose *aEvent)
{
if (mIsDestroyed) {
NS_WARNING("Expose event on destroyed window!");
printf("Expose event on destroyed window [%p]!\n", (void *)this);
return NS_OK;
}
@ -766,7 +681,7 @@ nsWindow::OnSizeAllocate(GtkWidget *aWidget, GtkAllocation *aAllocation)
printf("size_allocate [%p] %d %d %d %d\n",
(void *)this, aAllocation->x, aAllocation->y,
aAllocation->width, aAllocation->height);
nsRect rect(aAllocation->x, aAllocation->y,
aAllocation->width, aAllocation->height);
@ -776,7 +691,7 @@ nsWindow::OnSizeAllocate(GtkWidget *aWidget, GtkAllocation *aAllocation)
moz_drawingarea_resize (mDrawingarea, rect.width, rect.height);
nsEventStatus status;
SendResizeEvent (rect, status);
DispatchResizeEvent (rect, status);
}
void
@ -1036,22 +951,6 @@ nsWindow::OnScrollEvent(GtkWidget *aWidget, GdkEventScroll *aEvent)
DispatchEvent(&event, status);
}
void
nsWindow::SendResizeEvent(nsRect &aRect, nsEventStatus &aStatus)
{
nsSizeEvent event;
InitSizeEvent(event);
event.windowSize = &aRect;
event.point.x = aRect.x;
event.point.y = aRect.y;
event.mWinWidth = aRect.width;
event.mWinHeight = aRect.height;
nsEventStatus status;
DispatchEvent(&event, status);
}
nsresult
nsWindow::NativeCreate(nsIWidget *aParent,
nsNativeWidget aNativeParent,
@ -1074,7 +973,7 @@ nsWindow::NativeCreate(nsIWidget *aParent,
aAppShell, aToolkit, aInitData);
// and do our common creation
CommonCreate(aParent);
CommonCreate(aParent, aNativeParent);
// save our bounds
mBounds = aRect;
@ -1234,6 +1133,78 @@ nsWindow::NativeCreate(nsIWidget *aParent,
return NS_OK;
}
void
nsWindow::NativeResize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
{
printf("nsWindow::NativeResize [%p] %d %d\n", (void *)this,
aWidth, aHeight);
// clear our resize flag
mNeedsResize = PR_FALSE;
if (mIsTopLevel)
gtk_window_resize(GTK_WINDOW(mShell), aWidth, aHeight);
moz_drawingarea_resize (mDrawingarea, aWidth, aHeight);
}
void
nsWindow::NativeResize(PRInt32 aX, PRInt32 aY,
PRInt32 aWidth, PRInt32 aHeight,
PRBool aRepaint)
{
mNeedsResize = PR_FALSE;
printf("nsWindow::NativeResize [%p] %d %d %d %d\n", (void *)this,
aX, aY, aWidth, aHeight);
if (mIsTopLevel) {
if (mParent && mWindowType == eWindowType_popup) {
nsRect oldrect, newrect;
oldrect.x = aX;
oldrect.y = aY;
mParent->WidgetToScreen(oldrect, newrect);
moz_drawingarea_resize(mDrawingarea, aWidth, aHeight);
gtk_window_move(GTK_WINDOW(mShell), newrect.x, newrect.y);
gtk_window_resize(GTK_WINDOW(mShell), aWidth, aHeight);
}
else {
gtk_window_move(GTK_WINDOW(mShell), aX, aY);
gtk_window_resize(GTK_WINDOW(mShell), aWidth, aHeight);
moz_drawingarea_resize(mDrawingarea, aWidth, aHeight);
}
}
else {
moz_drawingarea_move_resize(mDrawingarea, aX, aY, aWidth, aHeight);
}
}
void
nsWindow::NativeShow (PRBool aAction)
{
if (aAction) {
// unset our flag now that our window has been shown
mNeedsShow = PR_FALSE;
if (mIsTopLevel) {
moz_drawingarea_set_visibility(mDrawingarea, aAction);
gtk_widget_show(GTK_WIDGET(mContainer));
gtk_widget_show(mShell);
}
else {
moz_drawingarea_set_visibility(mDrawingarea, aAction);
}
}
else {
if (mIsTopLevel) {
gtk_widget_hide(GTK_WIDGET(mShell));
gtk_widget_hide(GTK_WIDGET(mContainer));
}
moz_drawingarea_set_visibility(mDrawingarea, aAction);
}
}
/* static */
nsWindow *
get_window_for_gtk_widget(GtkWidget *widget)

View File

@ -61,21 +61,12 @@ class nsWindow : public nsCommonWidget {
nsIToolkit *aToolkit,
nsWidgetInitData *aInitData);
NS_IMETHOD Destroy(void);
NS_IMETHOD Show(PRBool aState);
NS_IMETHOD SetModal(PRBool aModal);
NS_IMETHOD IsVisible(PRBool & aState);
NS_IMETHOD ConstrainPosition(PRInt32 *aX,
PRInt32 *aY);
NS_IMETHOD Move(PRInt32 aX,
PRInt32 aY);
NS_IMETHOD Resize(PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint);
NS_IMETHOD Resize(PRInt32 aX,
PRInt32 aY,
PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint);
NS_IMETHOD PlaceBehind(nsIWidget *aWidget,
PRBool aActivate);
NS_IMETHOD Enable(PRBool aState);
@ -163,10 +154,6 @@ class nsWindow : public nsCommonWidget {
GdkEventKey *aEvent);
void OnScrollEvent(GtkWidget *aWidget,
GdkEventScroll *aEvent);
void SendResizeEvent(nsRect &aRect,
nsEventStatus &aStatus);
private:
nsresult NativeCreate(nsIWidget *aParent,
nsNativeWidget aNativeParent,
@ -177,11 +164,24 @@ class nsWindow : public nsCommonWidget {
nsIToolkit *aToolkit,
nsWidgetInitData *aInitData);
void NativeResize(PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint);
void NativeResize(PRInt32 aX,
PRInt32 aY,
PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint);
void NativeShow (PRBool aAction);
private:
GtkWidget *mShell;
MozContainer *mContainer;
MozDrawingarea *mDrawingarea;
PRPackedBool mIsTopLevel;
PRPackedBool mIsDestroyed;
PRPackedBool mContainerGotFocus;