Bug 373344, r+sr=roc, a=blocking1.9+
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -5771,16 +5771,17 @@ PresShell::HandleEventInternal(nsEvent*
nsAutoHandlingUserInputStatePusher userInpStatePusher(isHandlingUserInput);
nsAutoPopupStatePusher popupStatePusher(nsDOMEvent::GetEventPopupControlState(aEvent));
// FIXME. If the event was reused, we need to clear the old target,
// bug 329430
aEvent->target = nsnull;
+ nsWeakView weakView(aView);
// 1. Give event to event manager for pre event state changes and
// generation of synthetic events.
rv = manager->PreHandleEvent(mPresContext, aEvent, mCurrentEventFrame,
aStatus, aView);
// 2. Give event to the DOM for third party and JS use.
if ((GetCurrentEventFrame()) && NS_SUCCEEDED(rv)) {
// We want synthesized mouse moves to cause mouseover and mouseout
@@ -5804,17 +5805,18 @@ PresShell::HandleEventInternal(nsEvent*
}
}
}
// 3. Give event to event manager for post event state changes and
// generation of synthetic events.
if (NS_SUCCEEDED(rv)) {
rv = manager->PostHandleEvent(mPresContext, aEvent,
- GetCurrentEventFrame(), aStatus, aView);
+ GetCurrentEventFrame(), aStatus,
+ weakView.GetView());
}
}
}
return rv;
}
// Dispatch event to content only (NOT full processing)
// See also HandleEventWithTarget which does full event processing.
--- a/view/public/nsIView.h
+++ b/view/public/nsIView.h
@@ -42,31 +42,32 @@
#include "nsRect.h"
#include "nsPoint.h"
#include "nsIWidget.h"
class nsIViewManager;
class nsIScrollableView;
class nsViewManager;
class nsView;
+class nsWeakView;
// Enumerated type to indicate the visibility of a layer.
// hide - the layer is not shown.
// show - the layer is shown irrespective of the visibility of
// the layer's parent.
enum nsViewVisibility {
nsViewVisibility_kHide = 0,
nsViewVisibility_kShow = 1
};
// IID for the nsIView interface
-// 6610ae89-3909-422f-a227-ede67b97bcd1
+// 1b0215f7-f5d1-4574-9ab9-abdcceddb82e
#define NS_IVIEW_IID \
-{ 0x6610ae89, 0x3909, 0x422f, \
-{ 0xa2, 0x27, 0xed, 0xe6, 0x7b, 0x97, 0xbc, 0xd1 } }
+{ 0x1b0215f7, 0xf5d1, 0x4574, \
+ { 0x9a, 0xb9, 0xab, 0xdc, 0xce, 0xdd, 0xb8, 0x2e } }
// Public view flags are defined in this file
#define NS_VIEW_FLAGS_PUBLIC 0x00FF
// Private view flags are private to the view module,
// and are defined in nsView.h
#define NS_VIEW_FLAGS_PRIVATE 0xFF00
// Public view flags
@@ -77,16 +78,20 @@ enum nsViewVisibility {
// Indicates that the view is a floating view.
#define NS_VIEW_FLAG_FLOATING 0x0008
// If set it indicates that this view should be
// displayed above z-index:auto views if this view
// is z-index:auto also
#define NS_VIEW_FLAG_TOPMOST 0x0010
+// If set, the view disowns the widget and leaves it up
+// to other code to destroy it.
+#define NS_VIEW_DISOWNS_WIDGET 0x0020
+
struct nsViewZIndex {
PRBool mIsAuto;
PRInt32 mZIndex;
PRBool mIsTopmost;
nsViewZIndex(PRBool aIsAuto, PRInt32 aZIndex, PRBool aIsTopmost)
: mIsAuto(aIsAuto), mZIndex(aZIndex), mIsTopmost(aIsTopmost) {}
};
@@ -299,17 +304,17 @@ public:
*/
PRBool HasWidget() const { return mWindow != nsnull; }
/**
* If called, will make the view disown the widget and leave it up
* to other code to destroy it.
*/
void DisownWidget() {
- mWidgetDisowned = PR_TRUE;
+ mVFlags |= NS_VIEW_DISOWNS_WIDGET;
}
#ifdef DEBUG
/**
* Output debug info to FILE
* @param out output file handle
* @param aIndent indentation depth
* NOTE: virtual so that debugging tools not linked into gklayout can access it
@@ -319,29 +324,74 @@ public:
/**
* @result true iff this is the root view for its view manager
*/
PRBool IsRoot() const;
virtual PRBool ExternalIsRoot() const;
+ void SetDeletionObserver(nsWeakView* aDeletionObserver);
protected:
+ friend class nsWeakView;
nsViewManager *mViewManager;
nsView *mParent;
nsIWidget *mWindow;
nsView *mNextSibling;
nsView *mFirstChild;
void *mClientData;
PRInt32 mZIndex;
nsViewVisibility mVis;
nscoord mPosX, mPosY;
nsRect mDimBounds; // relative to parent
float mOpacity;
PRUint32 mVFlags;
- PRBool mWidgetDisowned;
+ nsWeakView* mDeletionObserver;
virtual ~nsIView() {}
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIView, NS_IVIEW_IID)
+// nsWeakViews must *not* be used in heap!
+class nsWeakView
+{
+public:
+ nsWeakView(nsIView* aView) : mPrev(nsnull), mView(aView)
+ {
+ if (mView) {
+ mView->SetDeletionObserver(this);
+ }
+ }
+
+ ~nsWeakView()
+ {
+ if (mView) {
+ NS_ASSERTION(mView->mDeletionObserver == this,
+ "nsWeakViews deleted in wrong order!");
+ // Clear deletion observer temporarily.
+ mView->SetDeletionObserver(nsnull);
+ // Put back the previous deletion observer.
+ mView->SetDeletionObserver(mPrev);
+ }
+ }
+
+ PRBool IsAlive() { return !!mView; }
+
+ nsIView* GetView() { return mView; }
+
+ void SetPrevious(nsWeakView* aWeakView) { mPrev = aWeakView; }
+
+ void Clear()
+ {
+ if (mPrev) {
+ mPrev->Clear();
+ }
+ mView = nsnull;
+ }
+private:
+ static void* operator new(size_t) CPP_THROW_NEW { return 0; }
+ static void operator delete(void*, size_t) {}
+ nsWeakView* mPrev;
+ nsIView* mView;
+};
+
#endif
--- a/view/src/nsView.cpp
+++ b/view/src/nsView.cpp
@@ -178,17 +178,17 @@ nsView::nsView(nsViewManager* aViewManag
mVis = aVisibility;
// Views should be transparent by default. Not being transparent is
// a promise that the view will paint all its pixels opaquely. Views
// should make this promise explicitly by calling
// SetViewContentTransparency.
mVFlags = 0;
mViewManager = aViewManager;
mDirtyRegion = nsnull;
- mWidgetDisowned = PR_FALSE;
+ mDeletionObserver = nsnull;
}
void nsView::DropMouseGrabbing() {
// check to see if we are grabbing events
if (mViewManager->GetMouseEventGrabber() == this) {
// we are grabbing events. Move the grab to the parent if we can.
PRBool boolResult; //not used
// if GetParent() returns null, then we release the grab, which is the best we can do
@@ -246,22 +246,26 @@ nsView::~nsView()
// Destroy and release the widget
if (mWindow)
{
// Release memory for the view wrapper
ViewWrapper* wrapper = GetWrapperFor(mWindow);
NS_IF_RELEASE(wrapper);
mWindow->SetClientData(nsnull);
- if (!mWidgetDisowned) {
+ if (!(mVFlags & NS_VIEW_DISOWNS_WIDGET)) {
mWindow->Destroy();
}
NS_RELEASE(mWindow);
}
delete mDirtyRegion;
+
+ if (mDeletionObserver) {
+ mDeletionObserver->Clear();
+ }
}
nsresult nsView::QueryInterface(const nsIID& aIID, void** aInstancePtr)
{
if (nsnull == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
@@ -831,8 +835,17 @@ PRBool nsIView::IsRoot() const
NS_ASSERTION(mViewManager != nsnull," View manager is null in nsView::IsRoot()");
return mViewManager->GetRootView() == this;
}
PRBool nsIView::ExternalIsRoot() const
{
return nsIView::IsRoot();
}
+
+void
+nsIView::SetDeletionObserver(nsWeakView* aDeletionObserver)
+{
+ if (mDeletionObserver && aDeletionObserver) {
+ aDeletionObserver->SetPrevious(mDeletionObserver);
+ }
+ mDeletionObserver = aDeletionObserver;
+}