Bug 575294. part=4/5 r=roc

This commit is contained in:
Mats Palmgren 2012-06-23 03:13:56 +02:00
parent 8703f3bfcd
commit 21b1a88e69
10 changed files with 85 additions and 13 deletions

View File

@ -448,24 +448,39 @@ nsComboboxControlFrame::ShowList(bool aShowList)
return weakFrame.IsAlive();
}
class nsResizeDropdownAtFinalPosition : public nsIReflowCallback
class nsResizeDropdownAtFinalPosition
: public nsIReflowCallback, public nsRunnable
{
public:
nsResizeDropdownAtFinalPosition(nsComboboxControlFrame* aFrame)
: mFrame(aFrame) {}
: mFrame(aFrame)
{
MOZ_COUNT_CTOR(nsResizeDropdownAtFinalPosition);
}
~nsResizeDropdownAtFinalPosition()
{
MOZ_COUNT_DTOR(nsResizeDropdownAtFinalPosition);
}
virtual bool ReflowFinished()
{
if (mFrame.IsAlive()) {
static_cast<nsComboboxControlFrame*>(mFrame.GetFrame())->
AbsolutelyPositionDropDown();
}
Run();
NS_RELEASE_THIS();
return false;
}
virtual void ReflowCallbackCanceled()
{
delete this;
NS_RELEASE_THIS();
}
NS_IMETHODIMP Run()
{
if (mFrame.IsAlive()) {
static_cast<nsComboboxControlFrame*>(mFrame.GetFrame())->
AbsolutelyPositionDropDown();
}
return NS_OK;
}
nsWeakFrame mFrame;
@ -709,6 +724,23 @@ nsComboboxControlFrame::AbsolutelyPositionDropDown()
return eDropDownPositionFinal;
}
void
nsComboboxControlFrame::NotifyGeometryChange()
{
// We don't need to resize if we're not dropped down since ShowDropDown
// does that, or if we're dirty then the reflow callback does it,
// or if we have a delayed ShowDropDown pending.
if (IsDroppedDown() &&
!(GetStateBits() & NS_FRAME_IS_DIRTY) &&
!mDelayedShowDropDown) {
// Async because we're likely in a middle of a scroll here so
// frame/view positions are in flux.
nsRefPtr<nsResizeDropdownAtFinalPosition> resize =
new nsResizeDropdownAtFinalPosition(this);
NS_DispatchToCurrentThread(resize);
}
}
//----------------------------------------------------------
//
//----------------------------------------------------------
@ -834,8 +866,13 @@ nsComboboxControlFrame::Reflow(nsPresContext* aPresContext,
// First reflow our dropdown so that we know how tall we should be.
ReflowDropdown(aPresContext, aReflowState);
nsIReflowCallback* cb = new nsResizeDropdownAtFinalPosition(this);
aPresContext->PresShell()->PostReflowCallback(cb);
nsRefPtr<nsResizeDropdownAtFinalPosition> resize =
new nsResizeDropdownAtFinalPosition(this);
if (NS_SUCCEEDED(aPresContext->PresShell()->PostReflowCallback(resize))) {
// The reflow callback queue doesn't AddRef so we keep it alive until
// it's released in its ReflowFinished / ReflowCallbackCanceled.
resize.forget();
}
// Get the width of the vertical scrollbar. That will be the width of the
// dropdown button.

View File

@ -168,6 +168,7 @@ public:
* @note This method might destroy |this|.
*/
virtual nsIContent* Rollup(PRUint32 aCount, bool aGetLastRolledUp = false);
virtual void NotifyGeometryChange();
/**
* A combobox should roll up if a mousewheel event happens outside of

View File

@ -290,6 +290,7 @@ public:
virtual bool ShouldRollupOnMouseWheelEvent();
virtual bool ShouldRollupOnMouseActivate();
virtual PRUint32 GetSubmenuWidgetChain(nsTArray<nsIWidget*> *aWidgetChain);
virtual void NotifyGeometryChange() {}
static nsXULPopupManager* sInstance;

View File

@ -838,6 +838,7 @@ NS_IMETHODIMP nsChildView::Move(PRInt32 aX, PRInt32 aY)
if (mVisible)
[mView setNeedsDisplay:YES];
NotifyRollupGeometryChange(gRollupListener);
ReportMoveEvent();
return NS_OK;
@ -862,6 +863,7 @@ NS_IMETHODIMP nsChildView::Resize(PRInt32 aWidth, PRInt32 aHeight, bool aRepaint
if (mVisible && aRepaint)
[mView setNeedsDisplay:YES];
NotifyRollupGeometryChange(gRollupListener);
ReportSizeEvent();
return NS_OK;
@ -894,6 +896,7 @@ NS_IMETHODIMP nsChildView::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt3
if (mVisible && aRepaint)
[mView setNeedsDisplay:YES];
NotifyRollupGeometryChange(gRollupListener);
if (isMoving) {
ReportMoveEvent();
if (mOnDestroyCalled)

View File

@ -1063,6 +1063,8 @@ nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, bool aRepaint)
}
}
NotifyRollupGeometryChange(gRollupListener);
// synthesize a resize event if this isn't a toplevel
if (mIsTopLevel || mListenForResizes) {
nsIntRect rect(mBounds.x, mBounds.y, aWidth, aHeight);
@ -1127,6 +1129,8 @@ nsWindow::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight,
}
}
NotifyRollupGeometryChange(gRollupListener);
if (mIsTopLevel || mListenForResizes) {
// synthesize a resize event
nsIntRect rect(aX, aY, aWidth, aHeight);
@ -1190,6 +1194,7 @@ nsWindow::Move(PRInt32 aX, PRInt32 aY)
gdk_window_move(mGdkWindow, aX, aY);
}
NotifyRollupGeometryChange(gRollupListener);
return NS_OK;
}

View File

@ -45,6 +45,11 @@ class nsIRollupListener {
* the same number of widgets added to aWidgetChain.
*/
virtual PRUint32 GetSubmenuWidgetChain(nsTArray<nsIWidget*> *aWidgetChain) = 0;
/**
* Notify the RollupListener that the widget did a Move or Resize.
*/
virtual void NotifyGeometryChange() = 0;
};
#endif /* __nsIRollupListener_h__ */

View File

@ -766,7 +766,9 @@ void nsWindow::NS2PM_PARENT(POINTL& ptl)
NS_METHOD nsWindow::Move(PRInt32 aX, PRInt32 aY)
{
if (mFrame) {
return mFrame->Move(aX, aY);
nsresult rv = mFrame->Move(aX, aY);
NotifyRollupGeometryChange(gRollupListener);
return rv;
}
Resize(aX, aY, mBounds.width, mBounds.height, false);
return NS_OK;
@ -777,7 +779,9 @@ NS_METHOD nsWindow::Move(PRInt32 aX, PRInt32 aY)
NS_METHOD nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, bool aRepaint)
{
if (mFrame) {
return mFrame->Resize(aWidth, aHeight, aRepaint);
nsresult rv = mFrame->Resize(aWidth, aHeight, aRepaint);
NotifyRollupGeometryChange(gRollupListener);
return rv;
}
Resize(mBounds.x, mBounds.y, aWidth, aHeight, aRepaint);
return NS_OK;
@ -789,7 +793,9 @@ NS_METHOD nsWindow::Resize(PRInt32 aX, PRInt32 aY,
PRInt32 aWidth, PRInt32 aHeight, bool aRepaint)
{
if (mFrame) {
return mFrame->Resize(aX, aY, aWidth, aHeight, aRepaint);
nsresult rv = mFrame->Resize(aX, aY, aWidth, aHeight, aRepaint);
NotifyRollupGeometryChange(gRollupListener);
return rv;
}
// For mWnd & eWindowType_child set the cached values upfront, see bug 286555.
@ -827,6 +833,7 @@ NS_METHOD nsWindow::Resize(PRInt32 aX, PRInt32 aY,
}
}
NotifyRollupGeometryChange(gRollupListener);
return NS_OK;
}

View File

@ -546,7 +546,7 @@ nsWindow::Move(PRInt32 aX, PRInt32 aY)
mBounds.x = pos.x();
mBounds.y = pos.y();
NotifyRollupGeometryChange(gRollupListener);
return NS_OK;
}
@ -3011,6 +3011,7 @@ nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, bool aRepaint)
DispatchResizeEvent(rect, status);
}
NotifyRollupGeometryChange(gRollupListener);
return NS_OK;
}
@ -3074,6 +3075,7 @@ nsWindow::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight,
if (aRepaint)
mWidget->update();
NotifyRollupGeometryChange(gRollupListener);
return NS_OK;
}

View File

@ -1334,6 +1334,7 @@ NS_METHOD nsWindow::Move(PRInt32 aX, PRInt32 aY)
SetThemeRegion();
}
NotifyRollupGeometryChange(sRollupListener);
return NS_OK;
}
@ -1371,6 +1372,7 @@ NS_METHOD nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, bool aRepaint)
if (aRepaint)
Invalidate();
NotifyRollupGeometryChange(sRollupListener);
return NS_OK;
}
@ -1410,6 +1412,7 @@ NS_METHOD nsWindow::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeig
if (aRepaint)
Invalidate();
NotifyRollupGeometryChange(sRollupListener);
return NS_OK;
}

View File

@ -14,6 +14,7 @@
#include "nsGUIEvent.h"
#include "nsAutoPtr.h"
#include "BasicLayers.h"
#include "nsIRollupListener.h"
class nsIContent;
class nsAutoRollup;
@ -267,6 +268,13 @@ protected:
nsPopupType PopupType() const { return mPopupType; }
void NotifyRollupGeometryChange(nsIRollupListener* aRollupListener)
{
if (aRollupListener) {
aRollupListener->NotifyGeometryChange();
}
}
protected:
/**
* Starts the OMTC compositor destruction sequence.