Bug 743975 - remove the event handler argument to widget creation methods, r=tn
authorNeil Deakin <neil@mozilla.com>
Wed, 15 Aug 2012 14:53:09 -0400
changeset 102466 e66c290ab9fcbb37b809fc5273ef54b0cbd14339
parent 102465 54badf5d08b073d45b0f8a5da272021118dd9f99
child 102467 dfcc0507902cf689c7369acd54c9bde50cb4b2a1
push id23287
push userryanvm@gmail.com
push dateThu, 16 Aug 2012 01:37:50 +0000
treeherdermozilla-central@50e4ff05741e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstn
bugs743975
milestone17.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 743975 - remove the event handler argument to widget creation methods, r=tn
dom/plugins/base/nsPluginInstanceOwner.cpp
embedding/browser/webBrowser/nsWebBrowser.cpp
layout/generic/nsObjectFrame.cpp
view/public/nsIView.h
view/src/nsView.cpp
widget/android/nsWindow.cpp
widget/android/nsWindow.h
widget/cocoa/nsChildView.h
widget/cocoa/nsChildView.mm
widget/cocoa/nsCocoaWindow.h
widget/cocoa/nsCocoaWindow.mm
widget/gonk/nsWindow.cpp
widget/gonk/nsWindow.h
widget/gtk2/nsWindow.cpp
widget/gtk2/nsWindow.h
widget/nsIWidget.h
widget/nsIWidgetListener.h
widget/qt/nsWindow.cpp
widget/qt/nsWindow.h
widget/windows/nsWindow.cpp
widget/windows/nsWindow.h
widget/windows/nsWindowGfx.cpp
widget/xpwidgets/PuppetWidget.cpp
widget/xpwidgets/PuppetWidget.h
widget/xpwidgets/nsBaseWidget.cpp
widget/xpwidgets/nsBaseWidget.h
xpfe/appshell/src/nsWebShellWindow.cpp
xpfe/appshell/src/nsWebShellWindow.h
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -3352,17 +3352,17 @@ NS_IMETHODIMP nsPluginInstanceOwner::Cre
     }
 
     nsWidgetInitData initData;
     initData.mWindowType = eWindowType_plugin;
     initData.mUnicode = false;
     initData.clipChildren = true;
     initData.clipSiblings = true;
     rv = mWidget->Create(parentWidget.get(), nullptr, nsIntRect(0,0,0,0),
-                         nullptr, nullptr, &initData);
+                         nullptr, &initData);
     if (NS_FAILED(rv)) {
       mWidget->Destroy();
       mWidget = nullptr;
       return rv;
     }
 
     mWidget->EnableDragDrop(true);
     mWidget->Show(false);
--- a/embedding/browser/webBrowser/nsWebBrowser.cpp
+++ b/embedding/browser/webBrowser/nsWebBrowser.cpp
@@ -1114,18 +1114,17 @@ NS_IMETHODIMP nsWebBrowser::Create()
       nsWidgetInitData  widgetInit;
 
       widgetInit.clipChildren = true;
 
       widgetInit.mWindowType = eWindowType_child;
       nsIntRect bounds(mInitInfo->x, mInitInfo->y, mInitInfo->cx, mInitInfo->cy);
       
       mInternalWidget->SetWidgetListener(this);
-      mInternalWidget->Create(nullptr, mParentNativeWindow, bounds, nullptr,
-                              nullptr, &widgetInit);  
+      mInternalWidget->Create(nullptr, mParentNativeWindow, bounds, nullptr, &widgetInit);
       }
 
     nsCOMPtr<nsIDocShell> docShell(do_CreateInstance("@mozilla.org/docshell;1", &rv));
     NS_ENSURE_SUCCESS(rv, rv);
     rv = SetDocShell(docShell);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // get the system default window background colour
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -414,18 +414,17 @@ nsObjectFrame::PrepForDrawing(nsIWidget 
     GetEmptyClipConfiguration(&configuration);
     NS_ASSERTION(configuration.Length() > 0, "Empty widget configuration array!");
     configuration[0].mBounds.width = mRect.width;
     configuration[0].mBounds.height = mRect.height;
     parentWidget->ConfigureChildren(configuration);
 
     nsRefPtr<nsDeviceContext> dx;
     viewMan->GetDeviceContext(*getter_AddRefs(dx));
-    EVENT_CALLBACK eventHandler = mInnerView->AttachWidgetEventHandler(mWidget);
-    mWidget->SetEventCallback(eventHandler, dx);
+    mInnerView->AttachWidgetEventHandler(mWidget);
 
 #ifdef XP_MACOSX
     // On Mac, we need to invalidate ourselves since even windowed
     // plugins are painted through Thebes and we need to ensure
     // the Thebes layer containing the plugin is updated.
     if (parentWidget == GetNearestWidget()) {
       Invalidate(GetContentRectRelativeToSelf());
     }
--- a/view/public/nsIView.h
+++ b/view/public/nsIView.h
@@ -25,18 +25,18 @@ class nsIFrame;
 // show - the layer is shown irrespective of the visibility of 
 //        the layer's parent.
 enum nsViewVisibility {
   nsViewVisibility_kHide = 0,
   nsViewVisibility_kShow = 1
 };
 
 #define NS_IVIEW_IID    \
-  { 0x989b0d8b, 0x255d, 0x4399, \
-    { 0xbe, 0x94, 0x15, 0x00, 0x23, 0x11, 0xd5, 0xe8 } }
+  { 0xa4577c1d, 0xbc80, 0x444c, \
+    { 0xb0, 0x9d, 0x5b, 0xef, 0x94, 0x7c, 0x43, 0x31 } }
 
 // Public view flags
 
 // Indicates that the view is using auto z-indexing
 #define NS_VIEW_FLAG_AUTO_ZINDEX          0x0004
 
 // Indicates that the view is a floating view.
 #define NS_VIEW_FLAG_FLOATING             0x0008
@@ -307,17 +307,17 @@ public:
    */
   bool HasWidget() const { return mWindow != nullptr; }
 
   /**
    * Make aWidget direct its events to this view.
    * The caller must call DetachWidgetEventHandler before this view
    * is destroyed.
    */
-  EVENT_CALLBACK AttachWidgetEventHandler(nsIWidget* aWidget);
+  void AttachWidgetEventHandler(nsIWidget* aWidget);
   /**
    * Stop aWidget directing its events to this view.
    */
   void DetachWidgetEventHandler(nsIWidget* aWidget);
 
 #ifdef DEBUG
   /**
    * Output debug info to FILE
--- a/view/src/nsView.cpp
+++ b/view/src/nsView.cpp
@@ -11,18 +11,16 @@
 #include "nsGUIEvent.h"
 #include "nsIComponentManager.h"
 #include "nsGfxCIID.h"
 #include "nsIInterfaceRequestor.h"
 #include "mozilla/Attributes.h"
 #include "nsXULPopupManager.h"
 #include "nsIWidgetListener.h"
 
-static nsEventStatus HandleEvent(nsGUIEvent *aEvent);
-
 #define VIEW_WRAPPER_IID \
   { 0xbf4e1841, 0xe9ec, 0x47f2, \
     { 0xb4, 0x77, 0x0f, 0xf6, 0x0f, 0x5a, 0xac, 0xbd } }
 
 static bool
 IsPopupWidget(nsIWidget* aWidget)
 {
   nsWindowType type;
@@ -172,34 +170,16 @@ NS_IMETHODIMP ViewWrapper::GetInterface(
  * Given a widget, returns the stored ViewWrapper on it, or NULL if no
  * ViewWrapper is there.
  */
 static ViewWrapper* GetWrapperFor(nsIWidget* aWidget)
 {
   return aWidget ? static_cast<ViewWrapper *>(aWidget->GetWidgetListener()) : nullptr;
 }
 
-// Main events handler
-static nsEventStatus HandleEvent(nsGUIEvent *aEvent)
-{
-#if 0
-  printf(" %d %d %d (%d,%d) \n", aEvent->widget, aEvent->message);
-#endif
-  nsEventStatus result = nsEventStatus_eIgnore;
-  nsView *view = nsView::GetViewFor(aEvent->widget);
-
-  if (view)
-  {
-    nsCOMPtr<nsIViewManager> vm = view->GetViewManager();
-    vm->DispatchEvent(aEvent, view, &result);
-  }
-
-  return result;
-}
-
 // Attached widget event helpers
 static ViewWrapper* GetAttachedWrapperFor(nsIWidget* aWidget)
 {
   NS_PRECONDITION(nullptr != aWidget, "null widget ptr");
   return aWidget->GetAttachedViewPtr();
 }
 
 static nsView* GetAttachedViewFor(nsIWidget* aWidget)
@@ -207,28 +187,27 @@ static nsView* GetAttachedViewFor(nsIWid
   NS_PRECONDITION(nullptr != aWidget, "null widget ptr");
 
   ViewWrapper* wrapper = GetAttachedWrapperFor(aWidget);
   if (!wrapper)
     return nullptr;
   return wrapper->GetView();
 }
 
-// event handler
-static nsEventStatus AttachedHandleEvent(nsGUIEvent *aEvent)
-{ 
+nsEventStatus ViewWrapper::HandleEvent(nsGUIEvent* aEvent, bool aUseAttachedEvents)
+{
+  NS_PRECONDITION(nullptr != aEvent->widget, "null widget ptr");
+
   nsEventStatus result = nsEventStatus_eIgnore;
-  nsView *view = GetAttachedViewFor(aEvent->widget);
-
-  if (view)
-  {
+  nsIView* view = aUseAttachedEvents ? GetAttachedViewFor(aEvent->widget) :
+                                       nsView::GetViewFor(aEvent->widget);
+  if (view) {
     nsCOMPtr<nsIViewManager> vm = view->GetViewManager();
     vm->DispatchEvent(aEvent, view, &result);
   }
-
   return result;
 }
 
 nsView::nsView(nsViewManager* aViewManager, nsViewVisibility aVisibility)
 {
   MOZ_COUNT_CTOR(nsView);
 
   mVis = aVisibility;
@@ -750,18 +729,17 @@ nsresult nsView::CreateWidget(nsWidgetIn
     GetParent() ? GetParent()->GetNearestWidget(nullptr) : nullptr;
   if (!parentWidget) {
     NS_ERROR("nsView::CreateWidget without suitable parent widget??");
     return NS_ERROR_FAILURE;
   }
 
   // XXX: using aForceUseIWidgetParent=true to preserve previous
   // semantics.  It's not clear that it's actually needed.
-  mWindow = parentWidget->CreateChild(trect, ::HandleEvent,
-                                      dx, aWidgetInitData,
+  mWindow = parentWidget->CreateChild(trect, dx, aWidgetInitData,
                                       true).get();
   if (!mWindow) {
     return NS_ERROR_FAILURE;
   }
  
   InitializeWindow(aEnableDragDrop, aResetVisibility);
 
   return NS_OK;
@@ -782,18 +760,17 @@ nsresult nsView::CreateWidgetForParent(n
   aWidgetInitData = aWidgetInitData ? aWidgetInitData : &defaultInitData;
 
   nsIntRect trect = CalcWidgetBounds(aWidgetInitData->mWindowType);
 
   nsRefPtr<nsDeviceContext> dx;
   mViewManager->GetDeviceContext(*getter_AddRefs(dx));
 
   mWindow =
-    aParentWidget->CreateChild(trect, ::HandleEvent,
-                               dx, aWidgetInitData).get();
+    aParentWidget->CreateChild(trect, dx, aWidgetInitData).get();
   if (!mWindow) {
     return NS_ERROR_FAILURE;
   }
 
   InitializeWindow(aEnableDragDrop, aResetVisibility);
 
   return NS_OK;
 }
@@ -815,32 +792,30 @@ nsresult nsView::CreateWidgetForPopup(ns
 
   // XXX/cjones: having these two separate creation cases seems ... um
   // ... unnecessary, but it's the way the old code did it.  Please
   // unify them by first finding a suitable parent nsIWidget, then
   // getting rid of aForceUseIWidgetParent.
   if (aParentWidget) {
     // XXX: using aForceUseIWidgetParent=true to preserve previous
     // semantics.  It's not clear that it's actually needed.
-    mWindow = aParentWidget->CreateChild(trect, ::HandleEvent,
-                                         dx, aWidgetInitData,
+    mWindow = aParentWidget->CreateChild(trect, dx, aWidgetInitData,
                                          true).get();
   }
   else {
     nsIWidget* nearestParent = GetParent() ? GetParent()->GetNearestWidget(nullptr)
                                            : nullptr;
     if (!nearestParent) {
       // Without a parent, we can't make a popup.  This can happen
       // when printing
       return NS_ERROR_FAILURE;
     }
 
     mWindow =
-      nearestParent->CreateChild(trect, ::HandleEvent,
-                                 dx, aWidgetInitData).get();
+      nearestParent->CreateChild(trect, dx, aWidgetInitData).get();
   }
   if (!mWindow) {
     return NS_ERROR_FAILURE;
   }
 
   InitializeWindow(aEnableDragDrop, aResetVisibility);
 
   return NS_OK;
@@ -880,18 +855,17 @@ nsresult nsIView::AttachToTopLevelWidget
     oldView->DetachFromTopLevelWidget();
   }
 
   nsRefPtr<nsDeviceContext> dx;
   mViewManager->GetDeviceContext(*getter_AddRefs(dx));
 
   // Note, the previous device context will be released. Detaching
   // will not restore the old one.
-  nsresult rv = aWidget->AttachViewToTopLevel(
-    nsIWidget::UsePuppetWidgets() ? ::HandleEvent : ::AttachedHandleEvent, dx);
+  nsresult rv = aWidget->AttachViewToTopLevel(!nsIWidget::UsePuppetWidgets(), dx);
   if (NS_FAILED(rv))
     return rv;
 
   mWindow = aWidget;
   NS_ADDREF(mWindow);
 
   ViewWrapper* wrapper = new ViewWrapper(Impl());
   NS_ADDREF(wrapper);
@@ -948,28 +922,27 @@ void nsView::AssertNoWindow()
     mWindow->Destroy();
     NS_RELEASE(mWindow);
   }
 }
 
 //
 // internal window creation functions
 //
-EVENT_CALLBACK nsIView::AttachWidgetEventHandler(nsIWidget* aWidget)
+void nsIView::AttachWidgetEventHandler(nsIWidget* aWidget)
 {
 #ifdef DEBUG
   NS_ASSERTION(!aWidget->GetWidgetListener(), "Already have a widget listener");
 #endif
 
   ViewWrapper* wrapper = new ViewWrapper(Impl());
   if (!wrapper)
-    return nullptr;
+    return;
   NS_ADDREF(wrapper); // Will be released in DetachWidgetEventHandler
   aWidget->SetWidgetListener(wrapper);
-  return ::HandleEvent;
 }
 
 void nsIView::DetachWidgetEventHandler(nsIWidget* aWidget)
 {
   ViewWrapper* wrapper = GetWrapperFor(aWidget);
   NS_ASSERTION(!wrapper || wrapper->GetView() == this, "Wrong view");
   NS_IF_RELEASE(wrapper);
   aWidget->SetWidgetListener(nullptr);
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -183,17 +183,16 @@ nsWindow::IsTopLevel()
         mWindowType == eWindowType_dialog ||
         mWindowType == eWindowType_invisible;
 }
 
 NS_IMETHODIMP
 nsWindow::Create(nsIWidget *aParent,
                  nsNativeWidget aNativeParent,
                  const nsIntRect &aRect,
-                 EVENT_CALLBACK aHandleEventFunction,
                  nsDeviceContext *aContext,
                  nsWidgetInitData *aInitData)
 {
     ALOG("nsWindow[%p]::Create %p [%d %d %d %d]", (void*)this, (void*)aParent, aRect.x, aRect.y, aRect.width, aRect.height);
     nsWindow *parent = (nsWindow*) aParent;
 
     if (!AndroidBridge::Bridge()) {
         aNativeParent = nullptr;
@@ -212,17 +211,17 @@ nsWindow::Create(nsIWidget *aParent,
     // for toplevel windows, bounds are fixed to full screen size
     if (!parent) {
         mBounds.x = 0;
         mBounds.y = 0;
         mBounds.width = gAndroidBounds.width;
         mBounds.height = gAndroidBounds.height;
     }
 
-    BaseCreate(nullptr, mBounds, aHandleEventFunction, aContext, aInitData);
+    BaseCreate(nullptr, mBounds, aContext, aInitData);
 
     NS_ASSERTION(IsTopLevel() || parent, "non top level windowdoesn't have a parent!");
 
     if (IsTopLevel()) {
         gTopLevelWindows.AppendElement(this);
     }
 
     if (parent) {
@@ -630,18 +629,18 @@ nsWindow::DispatchEvent(nsGUIEvent *aEve
 {
     aStatus = DispatchEvent(aEvent);
     return NS_OK;
 }
 
 nsEventStatus
 nsWindow::DispatchEvent(nsGUIEvent *aEvent)
 {
-    if (mEventCallback) {
-        nsEventStatus status = (*mEventCallback)(aEvent);
+    if (mWidgetListener) {
+        nsEventStatus status = mWidgetListener->HandleEvent(aEvent, mUseAttachedEvents);
 
         switch (aEvent->message) {
         case NS_COMPOSITION_START:
             mIMEComposing = true;
             break;
         case NS_COMPOSITION_END:
             mIMEComposing = false;
             break;
--- a/widget/android/nsWindow.h
+++ b/widget/android/nsWindow.h
@@ -61,17 +61,16 @@ public:
 
     //
     // nsIWidget
     //
 
     NS_IMETHOD Create(nsIWidget *aParent,
                       nsNativeWidget aNativeParent,
                       const nsIntRect &aRect,
-                      EVENT_CALLBACK aHandleEventFunction,
                       nsDeviceContext *aContext,
                       nsWidgetInitData *aInitData);
     NS_IMETHOD Destroy(void);
     NS_IMETHOD ConfigureChildren(const nsTArray<nsIWidget::Configuration>&);
     NS_IMETHOD SetParent(nsIWidget* aNewParent);
     virtual nsIWidget *GetParent(void);
     virtual float GetDPI();
     NS_IMETHOD Show(bool aState);
--- a/widget/cocoa/nsChildView.h
+++ b/widget/cocoa/nsChildView.h
@@ -383,17 +383,16 @@ public:
   virtual                 ~nsChildView();
   
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIWidget interface
   NS_IMETHOD              Create(nsIWidget *aParent,
                                  nsNativeWidget aNativeParent,
                                  const nsIntRect &aRect,
-                                 EVENT_CALLBACK aHandleEventFunction,
                                  nsDeviceContext *aContext,
                                  nsWidgetInitData *aInitData = nullptr);
 
   NS_IMETHOD              Destroy();
 
   NS_IMETHOD              Show(bool aState);
   virtual bool            IsVisible() const;
 
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -259,17 +259,16 @@ nsChildView::~nsChildView()
   TearDownView(); // Safe if called twice.
 }
 
 NS_IMPL_ISUPPORTS_INHERITED1(nsChildView, nsBaseWidget, nsIPluginWidget)
 
 nsresult nsChildView::Create(nsIWidget *aParent,
                              nsNativeWidget aNativeParent,
                              const nsIntRect &aRect,
-                             EVENT_CALLBACK aHandleEventFunction,
                              nsDeviceContext *aContext,
                              nsWidgetInitData *aInitData)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   // Because the hidden window is created outside of an event loop,
   // we need to provide an autorelease pool to avoid leaking cocoa objects
   // (see bug 559075).
@@ -294,17 +293,17 @@ nsresult nsChildView::Create(nsIWidget *
     gChildViewMethodsSwizzled = true;
   }
 
   mBounds = aRect;
 
   // Ensure that the toolkit is created.
   nsToolkit::GetToolkit();
 
-  BaseCreate(aParent, aRect, aHandleEventFunction, aContext, aInitData);
+  BaseCreate(aParent, aRect, aContext, aInitData);
 
   // inherit things from the parent view and create our parallel 
   // NSView in the Cocoa display system
   mParentView = nil;
   if (aParent) {
     // This is the case when we're the popup content view of a popup window.
     SetBackgroundColor(aParent->GetBackgroundColor());
     SetForegroundColor(aParent->GetForegroundColor());
@@ -1457,32 +1456,38 @@ NS_IMETHODIMP nsChildView::DispatchEvent
 #endif
 
   NS_ASSERTION(!(mTextInputHandler && mTextInputHandler->IsIMEComposing() &&
                  NS_IS_KEY_EVENT(event)),
     "Any key events should not be fired during IME composing");
 
   aStatus = nsEventStatus_eIgnore;
 
+  nsIWidgetListener* listener = mWidgetListener;
+
+  // If the listener is NULL, check if the parent is a popup. If it is, then
+  // this child is the popup content view attached to a popup. Get the
+  // listener from the parent popup instead.
   nsCOMPtr<nsIWidget> kungFuDeathGrip = do_QueryInterface(mParentWidget ? mParentWidget : this);
-  if (mParentWidget) {
+  if (!listener && mParentWidget) {
     nsWindowType type;
     mParentWidget->GetWindowType(type);
     if (type == eWindowType_popup) {
-      // use the parent popup's widget if there is no listener
-      nsIWidgetListener* listener = nullptr;
+      // Check just in case event->widget isn't this widget
       if (event->widget)
         listener = event->widget->GetWidgetListener();
-      if (!listener)
+      if (!listener) {
         event->widget = mParentWidget;
+        listener = mParentWidget->GetWidgetListener();
+      }
     }
   }
 
-  if (mEventCallback)
-    aStatus = (*mEventCallback)(event);
+  if (listener)
+    aStatus = listener->HandleEvent(event, mUseAttachedEvents);
 
   return NS_OK;
 }
 
 bool nsChildView::DispatchWindowEvent(nsGUIEvent &event)
 {
   nsEventStatus status;
   DispatchEvent(&event, status);
--- a/widget/cocoa/nsCocoaWindow.h
+++ b/widget/cocoa/nsCocoaWindow.h
@@ -200,17 +200,16 @@ public:
     virtual ~nsCocoaWindow();
 
     NS_DECL_ISUPPORTS_INHERITED
     NS_DECL_NSPIWIDGETCOCOA
       
     NS_IMETHOD              Create(nsIWidget* aParent,
                                    nsNativeWidget aNativeParent,
                                    const nsIntRect &aRect,
-                                   EVENT_CALLBACK aHandleEventFunction,
                                    nsDeviceContext *aContext,
                                    nsWidgetInitData *aInitData = nullptr);
 
     NS_IMETHOD              Destroy();
 
     NS_IMETHOD              Show(bool aState);
     virtual nsIWidget*      GetSheetWindowParent(void);
     NS_IMETHOD              Enable(bool aState);
@@ -300,17 +299,16 @@ public:
 
     NS_IMETHOD         ReparentNativeWidget(nsIWidget* aNewParent);
 protected:
 
   nsresult             CreateNativeWindow(const NSRect &aRect,
                                           nsBorderStyle aBorderStyle,
                                           bool aRectIsFrameRect);
   nsresult             CreatePopupContentView(const nsIntRect &aRect,
-                                              EVENT_CALLBACK aHandleEventFunction,
                                               nsDeviceContext *aContext);
   void                 DestroyNativeWindow();
   void                 AdjustWindowShadow();
   void                 SetUpWindowFilter();
   void                 CleanUpWindowFilter();
   void                 UpdateBounds();
 
   virtual already_AddRefed<nsIWidget>
--- a/widget/cocoa/nsCocoaWindow.mm
+++ b/widget/cocoa/nsCocoaWindow.mm
@@ -215,17 +215,16 @@ static bool UseNativePopupWindows()
 #else
   return false;
 #endif /* MOZ_USE_NATIVE_POPUP_WINDOWS */
 }
 
 nsresult nsCocoaWindow::Create(nsIWidget *aParent,
                                nsNativeWidget aNativeParent,
                                const nsIntRect &aRect,
-                               EVENT_CALLBACK aHandleEventFunction,
                                nsDeviceContext *aContext,
                                nsWidgetInitData *aInitData)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   // Because the hidden window is created outside of an event loop,
   // we have to provide an autorelease pool (see bug 559075).
   nsAutoreleasePool localPool;
@@ -256,34 +255,33 @@ nsresult nsCocoaWindow::Create(nsIWidget
 
   // Set defaults which can be overriden from aInitData in BaseCreate
   mWindowType = eWindowType_toplevel;
   mBorderStyle = eBorderStyle_default;
 
   // Ensure that the toolkit is created.
   nsToolkit::GetToolkit();
 
-  Inherited::BaseCreate(aParent, newBounds, aHandleEventFunction, aContext,
-                        aInitData);
+  Inherited::BaseCreate(aParent, newBounds, aContext, aInitData);
 
   mParent = aParent;
 
   // Applications that use native popups don't want us to create popup windows.
   if ((mWindowType == eWindowType_popup) && UseNativePopupWindows())
     return NS_OK;
 
   nsresult rv = CreateNativeWindow(nsCocoaUtils::GeckoRectToCocoaRect(newBounds),
                                    mBorderStyle, false);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (mWindowType == eWindowType_popup) {
     if (aInitData->mIsDragPopup) {
       [mWindow setIgnoresMouseEvents:YES];
     }
-    return CreatePopupContentView(newBounds, aHandleEventFunction, aContext);
+    return CreatePopupContentView(newBounds, aContext);
   }
 
   mIsAnimationSuppressed = aInitData->mIsAnimationSuppressed;
 
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
@@ -451,31 +449,29 @@ nsresult nsCocoaWindow::CreateNativeWind
   mWindowMadeHere = true;
 
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
 NS_IMETHODIMP nsCocoaWindow::CreatePopupContentView(const nsIntRect &aRect,
-                             EVENT_CALLBACK aHandleEventFunction,
                              nsDeviceContext *aContext)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   // We need to make our content view a ChildView.
   mPopupContentView = new nsChildView();
   if (!mPopupContentView)
     return NS_ERROR_FAILURE;
 
   NS_ADDREF(mPopupContentView);
 
   nsIWidget* thisAsWidget = static_cast<nsIWidget*>(this);
-  mPopupContentView->Create(thisAsWidget, nullptr, aRect, aHandleEventFunction,
-                            aContext, nullptr);
+  mPopupContentView->Create(thisAsWidget, nullptr, aRect, aContext, nullptr);
 
   ChildView* newContentView = (ChildView*)mPopupContentView->GetNativeData(NS_NATIVE_WIDGET);
   [mWindow setContentView:newContentView];
 
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
@@ -1466,18 +1462,18 @@ NS_IMETHODIMP nsCocoaWindow::ResetInputS
 NS_IMETHODIMP 
 nsCocoaWindow::DispatchEvent(nsGUIEvent* event, nsEventStatus& aStatus)
 {
   aStatus = nsEventStatus_eIgnore;
 
   nsIWidget* aWidget = event->widget;
   NS_IF_ADDREF(aWidget);
 
-  if (mEventCallback)
-    aStatus = (*mEventCallback)(event);
+  if (mWidgetListener)
+    aStatus = mWidgetListener->HandleEvent(event, mUseAttachedEvents);
 
   NS_IF_RELEASE(aWidget);
 
   return NS_OK;
 }
 
 // aFullScreen should be the window's mFullScreen. We don't have access to that
 // from here, so we need to pass it in. mFullScreen should be the canonical
--- a/widget/gonk/nsWindow.cpp
+++ b/widget/gonk/nsWindow.cpp
@@ -278,30 +278,31 @@ nsWindow::DoDraw(void)
 
 nsEventStatus
 nsWindow::DispatchInputEvent(nsGUIEvent &aEvent)
 {
     if (!gFocusedWindow)
         return nsEventStatus_eIgnore;
 
     gFocusedWindow->UserActivity();
-    aEvent.widget = gFocusedWindow;
-    return gFocusedWindow->mEventCallback(&aEvent);
+
+    nsEventStatus status;
+    gFocusedWindow->DispatchEvent(&aEvent, status);
+    return status;
 }
 
 NS_IMETHODIMP
 nsWindow::Create(nsIWidget *aParent,
                  void *aNativeParent,
                  const nsIntRect &aRect,
-                 EVENT_CALLBACK aHandleEventFunction,
                  nsDeviceContext *aContext,
                  nsWidgetInitData *aInitData)
 {
     BaseCreate(aParent, IS_TOPLEVEL() ? sVirtualBounds : aRect,
-               aHandleEventFunction, aContext, aInitData);
+               aContext, aInitData);
 
     mBounds = aRect;
 
     nsWindow *parent = (nsWindow *)aNativeParent;
     mParent = parent;
     mVisible = false;
 
     if (!aNativeParent) {
@@ -473,17 +474,18 @@ nsWindow::GetNativeData(PRUint32 aDataTy
         return this;
     }
     return nullptr;
 }
 
 NS_IMETHODIMP
 nsWindow::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus &aStatus)
 {
-    aStatus = (*mEventCallback)(aEvent);
+    if (mWidgetListener)
+      aStatus = mWidgetListener->HandleEvent(aEvent, mUseAttachedEvents);
     return NS_OK;
 }
 
 NS_IMETHODIMP_(void)
 nsWindow::SetInputContext(const InputContext& aContext,
                           const InputContextAction& aAction)
 {
     mInputContext = aContext;
--- a/widget/gonk/nsWindow.h
+++ b/widget/gonk/nsWindow.h
@@ -46,17 +46,16 @@ public:
     virtual ~nsWindow();
 
     static void DoDraw(void);
     static nsEventStatus DispatchInputEvent(nsGUIEvent &aEvent);
 
     NS_IMETHOD Create(nsIWidget *aParent,
                       void *aNativeParent,
                       const nsIntRect &aRect,
-                      EVENT_CALLBACK aHandleEventFunction,
                       nsDeviceContext *aContext,
                       nsWidgetInitData *aInitData);
     NS_IMETHOD Destroy(void);
 
     NS_IMETHOD Show(bool aState);
     virtual bool IsVisible() const;
     NS_IMETHOD ConstrainPosition(bool aAllowSlop,
                                  PRInt32 *aX,
--- a/widget/gtk2/nsWindow.cpp
+++ b/widget/gtk2/nsWindow.cpp
@@ -451,20 +451,18 @@ nsresult
 nsWindow::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus &aStatus)
 {
 #ifdef DEBUG
     debug_DumpEvent(stdout, aEvent->widget, aEvent,
                     nsCAutoString("something"), 0);
 #endif
 
     aStatus = nsEventStatus_eIgnore;
-
-    // send it to the standard callback
-    if (mEventCallback)
-        aStatus = (* mEventCallback)(aEvent);
+    if (mWidgetListener)
+      aStatus = mWidgetListener->HandleEvent(aEvent, mUseAttachedEvents);
 
     return NS_OK;
 }
 
 void
 nsWindow::OnDestroy(void)
 {
     if (mOnDestroyCalled)
@@ -3340,17 +3338,16 @@ CreateGdkWindow(GdkWindow *parent, GtkWi
 
     return window;
 }
 
 nsresult
 nsWindow::Create(nsIWidget        *aParent,
                  nsNativeWidget    aNativeParent,
                  const nsIntRect  &aRect,
-                 EVENT_CALLBACK    aHandleEventFunction,
                  nsDeviceContext *aContext,
                  nsWidgetInitData *aInitData)
 {
     // only set the base parent if we're going to be a dialog or a
     // toplevel
     nsIWidget *baseParent = aInitData &&
         (aInitData->mWindowType == eWindowType_dialog ||
          aInitData->mWindowType == eWindowType_toplevel ||
@@ -3363,17 +3360,17 @@ nsWindow::Create(nsIWidget        *aPare
     // Send a DBus message to check whether a11y is enabled
     a11y::PreInit();
 #endif
 
     // Ensure that the toolkit is created.
     nsGTKToolkit::GetToolkit();
 
     // initialize all the common bits of this class
-    BaseCreate(baseParent, aRect, aHandleEventFunction, aContext, aInitData);
+    BaseCreate(baseParent, aRect, aContext, aInitData);
 
     // Do we need to listen for resizes?
     bool listenForResizes = false;;
     if (aNativeParent || (aInitData && aInitData->mListenForResizes))
         listenForResizes = true;
 
     // and do our common creation
     CommonCreate(aParent, listenForResizes);
--- a/widget/gtk2/nsWindow.h
+++ b/widget/gtk2/nsWindow.h
@@ -93,17 +93,16 @@ public:
 
     // called to check and see if a widget's dimensions are sane
     bool AreBoundsSane(void);
 
     // nsIWidget
     NS_IMETHOD         Create(nsIWidget        *aParent,
                               nsNativeWidget   aNativeParent,
                               const nsIntRect  &aRect,
-                              EVENT_CALLBACK   aHandleEventFunction,
                               nsDeviceContext *aContext,
                               nsWidgetInitData *aInitData);
     NS_IMETHOD         Destroy(void);
     virtual nsIWidget *GetParent();
     virtual float      GetDPI();
     virtual nsresult   SetParent(nsIWidget* aNewParent);
     NS_IMETHOD         SetModal(bool aModal);
     virtual bool       IsVisible() const;
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -423,25 +423,23 @@ class nsIWidget : public nsISupports {
      *
      * In practice at least one of aParent and aNativeParent will be null. If
      * both are null the widget isn't parented (e.g. context menus or
      * independent top level windows).
      *
      * @param     aParent       parent nsIWidget
      * @param     aNativeParent native parent widget
      * @param     aRect         the widget dimension
-     * @param     aHandleEventFunction the event handler callback function
      * @param     aContext
      * @param     aInitData     data that is used for widget initialization
      *
      */
     NS_IMETHOD Create(nsIWidget        *aParent,
                       nsNativeWidget   aNativeParent,
                       const nsIntRect  &aRect,
-                      EVENT_CALLBACK   aHandleEventFunction,
                       nsDeviceContext *aContext,
                       nsWidgetInitData *aInitData = nullptr) = 0;
 
     /**
      * Allocate, initialize, and return a widget that is a child of
      * |this|.  The returned widget (if nonnull) has gone through the
      * equivalent of CreateInstance(widgetCID) + Create(...).
      *
@@ -453,50 +451,44 @@ class nsIWidget : public nsISupports {
      *
      * |aForceUseIWidgetParent| forces |CreateChild()| to only use the
      * |nsIWidget*| this, not its native widget (if it exists), when
      * calling |Create()|.  This is a timid hack around poorly
      * understood code, and shouldn't be used in new code.
      */
     virtual already_AddRefed<nsIWidget>
     CreateChild(const nsIntRect  &aRect,
-                EVENT_CALLBACK   aHandleEventFunction,
                 nsDeviceContext  *aContext,
                 nsWidgetInitData *aInitData = nullptr,
                 bool             aForceUseIWidgetParent = false) = 0;
 
     /**
-     * Set the event callback for a widget. If a device context is not
-     * provided then the existing device context will remain, it will
-     * not be nulled out.
-     */
-    NS_IMETHOD SetEventCallback(EVENT_CALLBACK aEventFunction,
-                                nsDeviceContext *aContext) = 0;
-
-    /**
      * Attach to a top level widget. 
      *
      * In cases where a top level chrome widget is being used as a content
-     * container, attach a secondary event callback and update the device
-     * context. The primary event callback will continue to be called, so the
-     * owning base window will continue to function.
+     * container, attach a secondary listener and update the device
+     * context. The primary widget listener will continue to be called for
+     * notifications relating to the top-level window, whereas other
+     * notifications such as painting and events will instead be called via
+     * the attached listener. SetAttachedWidgetListener should be used to
+     * assign the attached listener.
      *
-     * aViewEventFunction Event callback that will receive mirrored
-     *                    events.
+     * aUseAttachedEvents if true, events are sent to the attached listener
+     * instead of the normal listener.
      * aContext The new device context for the view
      */
-    NS_IMETHOD AttachViewToTopLevel(EVENT_CALLBACK aViewEventFunction,
+    NS_IMETHOD AttachViewToTopLevel(bool aUseAttachedEvents,
                                     nsDeviceContext *aContext) = 0;
 
     /**
-     * Accessor functions to get and set secondary client data. Used by
+     * Accessor functions to get and set the attached listener. Used by
      * nsIView in connection with AttachViewToTopLevel above.
      */
-    NS_IMETHOD SetAttachedViewPtr(ViewWrapper* aViewWrapper) = 0;
-    virtual ViewWrapper* GetAttachedViewPtr() = 0;
+    virtual void SetAttachedWidgetListener(nsIWidgetListener* aListener) = 0;
+    virtual nsIWidgetListener* GetAttachedWidgetListener() = 0;
 
     /**
      * Accessor functions to get and set the listener which handles various
      * actions for the widget.
      */
     //@{
     virtual nsIWidgetListener* GetWidgetListener() = 0;
     virtual void SetWidgetListener(nsIWidgetListener* alistener) = 0;
@@ -788,19 +780,17 @@ class nsIWidget : public nsISupports {
 
     /**
      * Request activation of this window or give focus to this widget.
      *
      * @param aRaise If true, this function requests activation of this
      *               widget's toplevel window.
      *               If false, the appropriate toplevel window (which in
      *               the case of popups may not be this widget's toplevel
-     *               window) is already active, and this function indicates
-     *               that keyboard events should be reported through the
-     *               aHandleEventFunction provided to this->Create().
+     *               window) is already active.
      */
     NS_IMETHOD SetFocus(bool aRaise = false) = 0;
 
     /**
      * Get this widget's outside dimensions relative to its parent widget. For
      * popup widgets the returned rect is in screen coordinates and not
      * relative to its parent widget.
      *
--- a/widget/nsIWidgetListener.h
+++ b/widget/nsIWidgetListener.h
@@ -125,11 +125,19 @@ public:
    */
   virtual bool PaintWindow(nsIWidget* aWidget, nsIntRegion aRegion,
                            bool aSentWillPaint, bool aWillSendDidPaint) { return false; }
 
   /**
    * On some platforms, indicates that a paint occurred.
    */
   virtual void DidPaintWindow() { }
+
+  /**
+   * Handle an event.
+   */
+  virtual nsEventStatus HandleEvent(nsGUIEvent* event, bool useAttachedEvents)
+  {
+    return nsEventStatus_eIgnore;
+  }
 };
 
 #endif
--- a/widget/qt/nsWindow.cpp
+++ b/widget/qt/nsWindow.cpp
@@ -2198,17 +2198,16 @@ GetBrandName(nsXPIDLString& brandName)
         brandName.Assign(NS_LITERAL_STRING("Mozilla"));
 }
 
 
 nsresult
 nsWindow::Create(nsIWidget        *aParent,
                  nsNativeWidget    aNativeParent,
                  const nsIntRect  &aRect,
-                 EVENT_CALLBACK    aHandleEventFunction,
                  nsDeviceContext *aContext,
                  nsWidgetInitData *aInitData)
 {
     // only set the base parent if we're not going to be a dialog or a
     // toplevel
     nsIWidget *baseParent = aParent;
 
     if (aInitData &&
@@ -2217,17 +2216,17 @@ nsWindow::Create(nsIWidget        *aPare
          aInitData->mWindowType == eWindowType_invisible)) {
 
         baseParent = nullptr;
         // also drop native parent for toplevel windows
         aNativeParent = nullptr;
     }
 
     // initialize all the common bits of this class
-    BaseCreate(baseParent, aRect, aHandleEventFunction, aContext, aInitData);
+    BaseCreate(baseParent, aRect, aContext, aInitData);
 
     // and do our common creation
     mParent = aParent;
 
     // save our bounds
     mBounds = aRect;
 
     // find native parent
@@ -2251,24 +2250,22 @@ nsWindow::Create(nsIWidget        *aPare
     mListenForResizes = (aNativeParent ||
                          (aInitData && aInitData->mListenForResizes));
 
     return NS_OK;
 }
 
 already_AddRefed<nsIWidget>
 nsWindow::CreateChild(const nsIntRect&  aRect,
-                      EVENT_CALLBACK    aHandleEventFunction,
                       nsDeviceContext* aContext,
                       nsWidgetInitData* aInitData,
                       bool              /*aForceUseIWidgetParent*/)
 {
     //We need to force parent widget, otherwise GetTopLevelWindow doesn't work
     return nsBaseWidget::CreateChild(aRect,
-                                     aHandleEventFunction,
                                      aContext,
                                      aInitData,
                                      true); // Force parent
 }
 
 
 NS_IMETHODIMP
 nsWindow::SetWindowClass(const nsAString &xulWinType)
@@ -2859,29 +2856,28 @@ nsWindow::DispatchResizeEvent(nsIntRect 
 {
     aStatus = nsEventStatus_eIgnore;
     if (mWidgetListener &&
         mWidgetListener->WindowResized(this, aRect.width, aRect.height))
       aStatus = nsEventStatus_eConsumeNoDefault;
 }
 
 NS_IMETHODIMP
-nsWindow::DispatchEvent(nsGUIEvent *aEvent,
-                              nsEventStatus &aStatus)
+nsWindow::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus &aStatus)
 {
 #ifdef DEBUG
     debug_DumpEvent(stdout, aEvent->widget, aEvent,
                     nsCAutoString("something"), 0);
 #endif
 
     aStatus = nsEventStatus_eIgnore;
 
     // send it to the standard callback
-    if (mEventCallback)
-        aStatus = (* mEventCallback)(aEvent);
+    if (mWidgetListener)
+      aStatus = mWidgetListener->HandleEvent(aEvent, mUseAttachedEvents);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindow::Show(bool aState)
 {
     LOG(("nsWindow::Show [%p] state %d\n", (void *)this, aState));
--- a/widget/qt/nsWindow.h
+++ b/widget/qt/nsWindow.h
@@ -92,23 +92,21 @@ public:
     // nsIWidget
     //
 
     NS_IMETHOD         ConfigureChildren(const nsTArray<nsIWidget::Configuration>&);
 
     NS_IMETHOD         Create(nsIWidget        *aParent,
                               nsNativeWidget   aNativeParent,
                               const nsIntRect  &aRect,
-                              EVENT_CALLBACK   aHandleEventFunction,
                               nsDeviceContext *aContext,
                               nsWidgetInitData *aInitData);
 
     virtual already_AddRefed<nsIWidget>
     CreateChild(const nsIntRect&  aRect,
-                EVENT_CALLBACK    aHandleEventFunction,
                 nsDeviceContext* aContext,
                 nsWidgetInitData* aInitData = nullptr,
                 bool              aForceUseIWidgetParent = true);
 
     NS_IMETHOD         Destroy(void);
     NS_IMETHOD         SetParent(nsIWidget* aNewParent);
     virtual nsIWidget *GetParent(void);
     virtual float      GetDPI();
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -437,17 +437,16 @@ PRInt32 nsWindow::GetHeight(PRInt32 aPro
   return aProposedHeight;
 }
 
 // Create the proper widget
 nsresult
 nsWindow::Create(nsIWidget *aParent,
                  nsNativeWidget aNativeParent,
                  const nsIntRect &aRect,
-                 EVENT_CALLBACK aHandleEventFunction,
                  nsDeviceContext *aContext,
                  nsWidgetInitData *aInitData)
 {
   nsWidgetInitData defaultInitData;
   if (!aInitData)
     aInitData = &defaultInitData;
 
   mUnicodeWidget = aInitData->mUnicode;
@@ -458,17 +457,17 @@ nsWindow::Create(nsIWidget *aParent,
                           nullptr : aParent;
 
   mIsTopWidgetWindow = (nullptr == baseParent);
   mBounds = aRect;
 
   // Ensure that the toolkit is created.
   nsToolkit::GetToolkit();
 
-  BaseCreate(baseParent, aRect, aHandleEventFunction, aContext, aInitData);
+  BaseCreate(baseParent, aRect, aContext, aInitData);
 
   HWND parent;
   if (aParent) { // has a nsIWidget parent
     parent = aParent ? (HWND)aParent->GetNativeData(NS_NATIVE_WINDOW) : NULL;
     mParent = aParent;
   } else { // has a nsNative parent
     parent = (HWND)aNativeParent;
     mParent = aNativeParent ?
@@ -3485,22 +3484,21 @@ NS_IMETHODIMP nsWindow::DispatchEvent(ns
 #endif // WIDGET_DEBUG_OUTPUT
 
   aStatus = nsEventStatus_eIgnore;
 
   // Top level windows can have a view attached which requires events be sent
   // to the underlying base window and the view. Added when we combined the
   // base chrome window with the main content child for nc client area (title
   // bar) rendering.
-  if (mViewCallback) {
-    // attached view events
-    aStatus = (*mViewCallback)(event);
-  }
-  else if (mEventCallback) {
-    aStatus = (*mEventCallback)(event);
+  if (mViewWrapperPtr) {
+    aStatus = mViewWrapperPtr->HandleEvent(event, mUseAttachedEvents);
+  }
+  else if (mWidgetListener) {
+    aStatus = mWidgetListener->HandleEvent(event, mUseAttachedEvents);
   }
 
   // the window can be destroyed during processing of seemingly innocuous events like, say,
   // mousedowns due to the magic of scripting. mousedowns will return nsEventStatus_eIgnore,
   // which causes problems with the deleted window. therefore:
   if (mOnDestroyCalled)
     aStatus = nsEventStatus_eConsumeNoDefault;
   return NS_OK;
@@ -3692,17 +3690,17 @@ void nsWindow::RemoveMessageAndDispatchP
 bool nsWindow::DispatchMouseEvent(PRUint32 aEventType, WPARAM wParam,
                                     LPARAM lParam, bool aIsContextMenuKey,
                                     PRInt16 aButton, PRUint16 aInputSource)
 {
   bool result = false;
 
   UserActivity();
 
-  if (!mEventCallback) {
+  if (!mWidgetListener) {
     return result;
   }
 
   switch (aEventType) {
     case NS_MOUSE_BUTTON_DOWN:
       CaptureMouse(true);
       break;
 
@@ -3875,17 +3873,17 @@ bool nsWindow::DispatchMouseEvent(PRUint
   }
 
   pluginEvent.wParam = wParam;     // plugins NEED raw OS event flags!
   pluginEvent.lParam = lParam;
 
   event.pluginEvent = (void *)&pluginEvent;
 
   // call the event callback
-  if (nullptr != mEventCallback) {
+  if (mWidgetListener) {
     if (nsToolkit::gMouseTrailer)
       nsToolkit::gMouseTrailer->Disable();
     if (aEventType == NS_MOUSE_MOVE) {
       if (nsToolkit::gMouseTrailer && !sIsInMouseCapture) {
         nsToolkit::gMouseTrailer->SetMouseTrailerWindow(mWnd);
       }
       nsIntRect rect;
       GetBounds(rect);
@@ -4927,17 +4925,17 @@ bool nsWindow::ProcessMessage(UINT msg, 
 
     // The WM_ACTIVATE event is fired when a window is raised or lowered,
     // and the loword of wParam specifies which. But we don't want to tell
     // the focus system about this until the WM_SETFOCUS or WM_KILLFOCUS
     // events are fired. Instead, set either the sJustGotActivate or
     // gJustGotDeactivate flags and activate/deactivate once the focus
     // events arrive.
     case WM_ACTIVATE:
-      if (mEventCallback) {
+      if (mWidgetListener) {
         PRInt32 fActive = LOWORD(wParam);
 
         if (WA_INACTIVE == fActive) {
           // when minimizing a window, the deactivation and focus events will
           // be fired in the reverse order. Instead, just deactivate right away.
           if (HIWORD(wParam))
             DispatchFocusToTopLevelWindow(false);
           else
@@ -6930,23 +6928,23 @@ void nsWindow::OnDestroy()
   // Make sure we don't get destroyed in the process of tearing down.
   nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
   
   // Dispatch the destroy notification.
   if (!mInDtor)
     NotifyWindowDestroyed();
 
   // Prevent the widget from sending additional events.
-  mEventCallback = nullptr;
+  mWidgetListener = nullptr;
 
   // Free our subclass and clear |this| stored in the window props. We will no longer
   // receive events from Windows after this point.
   SubclassWindow(FALSE);
 
-  // Once mEventCallback is cleared and the subclass is reset, sCurrentWindow can be
+  // Once mWidgetListener is cleared and the subclass is reset, sCurrentWindow can be
   // cleared. (It's used in tracking windows for mouse events.)
   if (sCurrentWindow == this)
     sCurrentWindow = nullptr;
 
   // Disconnects us from our parent, will call our GetParent().
   nsBaseWidget::Destroy();
 
   // Release references to children, device context, toolkit, and app shell.
@@ -7020,16 +7018,21 @@ bool nsWindow::OnResize(nsIntRect &aWind
 {
 #ifdef CAIRO_HAS_D2D_SURFACE
   if (mD2DWindowSurface) {
     mD2DWindowSurface = NULL;
     Invalidate();
   }
 #endif
 
+  // If there is an attached view, inform it as well as the normal widget listener.
+  if (mViewWrapperPtr) {
+    mViewWrapperPtr->WindowResized(this, aWindowRect.width, aWindowRect.height);
+  }
+
   return mWidgetListener ?
          mWidgetListener->WindowResized(this, aWindowRect.width, aWindowRect.height) : false;
 }
 
 bool nsWindow::OnHotKey(WPARAM wParam, LPARAM lParam)
 {
   return true;
 }
--- a/widget/windows/nsWindow.h
+++ b/widget/windows/nsWindow.h
@@ -79,17 +79,16 @@ public:
   friend class nsWindowGfx;
 
   /**
    * nsIWidget interface
    */
   NS_IMETHOD              Create(nsIWidget *aParent,
                                  nsNativeWidget aNativeParent,
                                  const nsIntRect &aRect,
-                                 EVENT_CALLBACK aHandleEventFunction,
                                  nsDeviceContext *aContext,
                                  nsWidgetInitData *aInitData = nullptr);
   NS_IMETHOD              Destroy();
   NS_IMETHOD              SetParent(nsIWidget *aNewParent);
   virtual nsIWidget*      GetParent(void);
   virtual float           GetDPI();
   NS_IMETHOD              Show(bool bState);
   virtual bool            IsVisible() const;
--- a/widget/windows/nsWindowGfx.cpp
+++ b/widget/windows/nsWindowGfx.cpp
@@ -230,18 +230,19 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32
       // could fail. Return without asserting since it's not our fault.
       NS_WARNING("Plugin failed to subclass our window");
     }
 
     ValidateRect(mWnd, NULL);
     return true;
   }
 
-  if (mWidgetListener) {
-    mWidgetListener->WillPaintWindow(this, true);
+  nsIWidgetListener* listener = mViewWrapperPtr ? mViewWrapperPtr : mWidgetListener;
+  if (listener) {
+    listener->WillPaintWindow(this, true);
   }
 
   bool result = true;
   PAINTSTRUCT ps;
 
 #ifdef MOZ_XUL
   if (!aDC && (eTransparencyTransparent == mTransparencyMode))
   {
@@ -278,17 +279,17 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32
   }
 
 #ifdef MOZ_XUL
   bool forceRepaint = aDC || (eTransparencyTransparent == mTransparencyMode);
 #else
   bool forceRepaint = NULL != aDC;
 #endif
   nsIntRegion region = GetRegionToPaint(forceRepaint, ps, hDC);
-  if (!region.IsEmpty() && mWidgetListener)
+  if (!region.IsEmpty() && listener)
   {
     // Should probably pass in a real region here, using GetRandomRgn
     // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/clipping_4q0e.asp
 
 #ifdef WIDGET_DEBUG_OUTPUT
     debug_DumpPaintEvent(stdout,
                          this,
                          region,
@@ -410,17 +411,17 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32
 #else
             doubleBuffering = mozilla::layers::BUFFER_BUFFERED;
 #endif
           }
 
           {
             AutoLayerManagerSetup
                 setupLayerManager(this, thebesContext, doubleBuffering);
-            result = mWidgetListener->PaintWindow(this, region, true, true);
+            result = listener->PaintWindow(this, region, true, true);
           }
 
 #ifdef MOZ_XUL
           if ((IsRenderMode(gfxWindowsPlatform::RENDER_GDI) ||
                IsRenderMode(gfxWindowsPlatform::RENDER_DIRECT2D))&&
               eTransparencyTransparent == mTransparencyMode) {
             // Data from offscreen drawing surface was copied to memory bitmap of transparent
             // bitmap. Now it can be read from memory bitmap to apply alpha channel and after
@@ -525,25 +526,25 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32
                             SRCCOPY);
             }
           }
         }
         break;
       case LAYERS_OPENGL:
         static_cast<mozilla::layers::LayerManagerOGL*>(GetLayerManager())->
           SetClippingRegion(region);
-        result = mWidgetListener->PaintWindow(this, region, true, true);
+        result = listener->PaintWindow(this, region, true, true);
         break;
 #ifdef MOZ_ENABLE_D3D9_LAYER
       case LAYERS_D3D9:
         {
           LayerManagerD3D9 *layerManagerD3D9 =
             static_cast<mozilla::layers::LayerManagerD3D9*>(GetLayerManager());
           layerManagerD3D9->SetClippingRegion(region);
-          result = mWidgetListener->PaintWindow(this, region, true, true);
+          result = listener->PaintWindow(this, region, true, true);
           if (layerManagerD3D9->DeviceWasRemoved()) {
             mLayerManager->Destroy();
             mLayerManager = nullptr;
             // When our device was removed, we should have gfxWindowsPlatform
             // check if its render mode is up to date!
             gfxWindowsPlatform::GetPlatform()->UpdateRenderMode();
             Invalidate();
           }
@@ -553,17 +554,17 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32
 #ifdef MOZ_ENABLE_D3D10_LAYER
       case LAYERS_D3D10:
         {
           gfxWindowsPlatform::GetPlatform()->UpdateRenderMode();
           LayerManagerD3D10 *layerManagerD3D10 = static_cast<mozilla::layers::LayerManagerD3D10*>(GetLayerManager());
           if (layerManagerD3D10->device() != gfxWindowsPlatform::GetPlatform()->GetD3D10Device()) {
             Invalidate();
           } else {
-            result = mWidgetListener->PaintWindow(this, region, true, true);
+            result = listener->PaintWindow(this, region, true, true);
           }
         }
         break;
 #endif
       default:
         NS_ERROR("Unknown layers backend used!");
         break;
     }
@@ -590,18 +591,18 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32
     }
     ::ReleaseDC(mWnd, debugPaintFlashDC);
     ::DeleteObject(debugPaintFlashRegion);
   }
 #endif // WIDGET_DEBUG_OUTPUT
 
   mPainting = false;
 
-  if (mWidgetListener)
-    mWidgetListener->DidPaintWindow();
+  if (listener)
+    listener->DidPaintWindow();
 
   if (aNestingLevel == 0 && ::GetUpdateRect(mWnd, NULL, false)) {
     OnPaint(aDC, 1);
   }
 
   return result;
 }
 
--- a/widget/xpwidgets/PuppetWidget.cpp
+++ b/widget/xpwidgets/PuppetWidget.cpp
@@ -78,23 +78,22 @@ PuppetWidget::~PuppetWidget()
 {
   MOZ_COUNT_DTOR(PuppetWidget);
 }
 
 NS_IMETHODIMP
 PuppetWidget::Create(nsIWidget        *aParent,
                      nsNativeWidget   aNativeParent,
                      const nsIntRect  &aRect,
-                     EVENT_CALLBACK   aHandleEventFunction,
                      nsDeviceContext *aContext,
                      nsWidgetInitData *aInitData)
 {
   NS_ABORT_IF_FALSE(!aNativeParent, "got a non-Puppet native parent");
 
-  BaseCreate(nullptr, aRect, aHandleEventFunction, aContext, aInitData);
+  BaseCreate(nullptr, aRect, aContext, aInitData);
 
   mBounds = aRect;
   mEnabled = true;
   mVisible = true;
 
   mSurface = gfxPlatform::GetPlatform()
              ->CreateOffscreenSurface(gfxIntSize(1, 1),
                                       gfxASurface::ContentFromFormat(gfxASurface::ImageFormatARGB32));
@@ -115,26 +114,24 @@ PuppetWidget::Create(nsIWidget        *a
     Resize(mBounds.x, mBounds.y, mBounds.width, mBounds.height, false);
   }
 
   return NS_OK;
 }
 
 already_AddRefed<nsIWidget>
 PuppetWidget::CreateChild(const nsIntRect  &aRect,
-                          EVENT_CALLBACK   aHandleEventFunction,
                           nsDeviceContext *aContext,
                           nsWidgetInitData *aInitData,
                           bool             aForceUseIWidgetParent)
 {
   bool isPopup = IsPopup(aInitData);
   nsCOMPtr<nsIWidget> widget = nsIWidget::CreatePuppetWidget(mTabChild);
   return ((widget &&
            NS_SUCCEEDED(widget->Create(isPopup ? nullptr: this, nullptr, aRect,
-                                       aHandleEventFunction,
                                        aContext, aInitData))) ?
           widget.forget() : nullptr);
 }
 
 NS_IMETHODIMP
 PuppetWidget::Destroy()
 {
   Base::OnDestroy();
@@ -248,17 +245,17 @@ PuppetWidget::DispatchEvent(nsGUIEvent* 
                   nsCAutoString("PuppetWidget"), 0);
 #endif
 
   NS_ABORT_IF_FALSE(!mChild || mChild->mWindowType == eWindowType_popup,
                     "Unexpected event dispatch!");
 
   aStatus = nsEventStatus_eIgnore;
 
-  NS_ABORT_IF_FALSE(mViewCallback, "No view callback!");
+  NS_ABORT_IF_FALSE(mViewWrapperPtr, "No listener!");
 
   if (event->message == NS_COMPOSITION_START) {
     mIMEComposing = true;
   }
   switch (event->eventStructType) {
   case NS_COMPOSITION_EVENT:
     mIMELastReceivedSeqno = static_cast<nsCompositionEvent*>(event)->seqno;
     if (mIMELastReceivedSeqno < mIMELastBlurSeqno)
@@ -270,17 +267,18 @@ PuppetWidget::DispatchEvent(nsGUIEvent* 
       return NS_OK;
     break;
   case NS_SELECTION_EVENT:
     mIMELastReceivedSeqno = static_cast<nsSelectionEvent*>(event)->seqno;
     if (mIMELastReceivedSeqno < mIMELastBlurSeqno)
       return NS_OK;
     break;
   }
-  aStatus = (*mViewCallback)(event);
+
+  aStatus = mViewWrapperPtr->HandleEvent(event, mUseAttachedEvents);
 
   if (event->message == NS_COMPOSITION_END) {
     mIMEComposing = false;
   }
 
   return NS_OK;
 }
 
--- a/widget/xpwidgets/PuppetWidget.h
+++ b/widget/xpwidgets/PuppetWidget.h
@@ -44,23 +44,21 @@ public:
   PuppetWidget(TabChild* aTabChild);
   virtual ~PuppetWidget();
 
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_IMETHOD Create(nsIWidget*        aParent,
                     nsNativeWidget    aNativeParent,
                     const nsIntRect&  aRect,
-                    EVENT_CALLBACK    aHandleEventFunction,
                     nsDeviceContext*  aContext,
                     nsWidgetInitData* aInitData = nullptr);
 
   virtual already_AddRefed<nsIWidget>
   CreateChild(const nsIntRect  &aRect,
-              EVENT_CALLBACK   aHandleEventFunction,
               nsDeviceContext  *aContext,
               nsWidgetInitData *aInitData = nullptr,
               bool             aForceUseIWidgetParent = false);
 
   NS_IMETHOD Destroy();
 
   NS_IMETHOD Show(bool aState);
 
--- a/widget/xpwidgets/nsBaseWidget.cpp
+++ b/widget/xpwidgets/nsBaseWidget.cpp
@@ -81,26 +81,25 @@ nsAutoRollup::~nsAutoRollup()
 //
 // nsBaseWidget constructor
 //
 //-------------------------------------------------------------------------
 
 nsBaseWidget::nsBaseWidget()
 : mWidgetListener(nullptr)
 , mViewWrapperPtr(nullptr)
-, mEventCallback(nullptr)
-, mViewCallback(nullptr)
 , mContext(nullptr)
 , mCursor(eCursor_standard)
 , mWindowType(eWindowType_child)
 , mBorderStyle(eBorderStyle_none)
 , mOnDestroyCalled(false)
 , mUseAcceleratedRendering(false)
 , mForceLayersAcceleration(false)
 , mTemporarilyUseBasicLayerManager(false)
+, mUseAttachedEvents(false)
 , mBounds(0,0,0,0)
 , mOriginalBounds(nullptr)
 , mClipRectCount(0)
 , mZIndex(0)
 , mSizeMode(nsSizeMode_Normal)
 , mPopupLevel(ePopupLevelTop)
 , mPopupType(ePopupTypeAny)
 {
@@ -176,31 +175,27 @@ nsBaseWidget::~nsBaseWidget()
 
 //-------------------------------------------------------------------------
 //
 // Basic create.
 //
 //-------------------------------------------------------------------------
 void nsBaseWidget::BaseCreate(nsIWidget *aParent,
                               const nsIntRect &aRect,
-                              EVENT_CALLBACK aHandleEventFunction,
                               nsDeviceContext *aContext,
                               nsWidgetInitData *aInitData)
 {
   static bool gDisableNativeThemeCached = false;
   if (!gDisableNativeThemeCached) {
     Preferences::AddBoolVarCache(&gDisableNativeTheme,
                                  "mozilla.widget.disable-native-theme",
                                  gDisableNativeTheme);
     gDisableNativeThemeCached = true;
   }
 
-  // save the event callback function
-  mEventCallback = aHandleEventFunction;
-  
   // keep a reference to the device context
   if (aContext) {
     mContext = aContext;
     NS_ADDREF(mContext);
   }
   else {
     mContext = new nsDeviceContext();
     NS_ADDREF(mContext);
@@ -237,17 +232,16 @@ nsIWidgetListener* nsBaseWidget::GetWidg
 
 void nsBaseWidget::SetWidgetListener(nsIWidgetListener* aWidgetListener)
 {
   mWidgetListener = aWidgetListener;
 }
 
 already_AddRefed<nsIWidget>
 nsBaseWidget::CreateChild(const nsIntRect  &aRect,
-                          EVENT_CALLBACK   aHandleEventFunction,
                           nsDeviceContext *aContext,
                           nsWidgetInitData *aInitData,
                           bool             aForceUseIWidgetParent)
 {
   nsIWidget* parent = this;
   nsNativeWidget nativeParent = nullptr;
 
   if (!aForceUseIWidgetParent) {
@@ -264,53 +258,35 @@ nsBaseWidget::CreateChild(const nsIntRec
     widget = AllocateChildPopupWidget();
   } else {
     static NS_DEFINE_IID(kCChildCID, NS_CHILD_CID);
     widget = do_CreateInstance(kCChildCID);
   }
 
   if (widget &&
       NS_SUCCEEDED(widget->Create(parent, nativeParent, aRect,
-                                  aHandleEventFunction,
                                   aContext, aInitData))) {
     return widget.forget();
   }
 
   return nullptr;
 }
 
-NS_IMETHODIMP
-nsBaseWidget::SetEventCallback(EVENT_CALLBACK aEventFunction,
-                               nsDeviceContext *aContext)
-{
-  NS_ASSERTION(aEventFunction, "Must have valid event callback!");
-
-  mEventCallback = aEventFunction;
-
-  if (aContext) {
-    NS_IF_RELEASE(mContext);
-    mContext = aContext;
-    NS_ADDREF(mContext);
-  }
-
-  return NS_OK;
-}
-
 // Attach a view to our widget which we'll send events to. 
 NS_IMETHODIMP
-nsBaseWidget::AttachViewToTopLevel(EVENT_CALLBACK aViewEventFunction,
+nsBaseWidget::AttachViewToTopLevel(bool aUseAttachedEvents,
                                    nsDeviceContext *aContext)
 {
   NS_ASSERTION((mWindowType == eWindowType_toplevel ||
                 mWindowType == eWindowType_dialog ||
                 mWindowType == eWindowType_invisible ||
                 mWindowType == eWindowType_child),
                "Can't attach to window of that type");
 
-  mViewCallback = aViewEventFunction;
+  mUseAttachedEvents = aUseAttachedEvents;
 
   if (aContext) {
     if (mContext) {
       NS_IF_RELEASE(mContext);
     }
     mContext = aContext;
     NS_ADDREF(mContext);
   }
--- a/widget/xpwidgets/nsBaseWidget.h
+++ b/widget/xpwidgets/nsBaseWidget.h
@@ -148,22 +148,20 @@ public:
   NS_IMETHOD              OnIMEFocusChange(bool aFocus) { return NS_ERROR_NOT_IMPLEMENTED; }
   NS_IMETHOD              OnIMETextChange(PRUint32 aStart, PRUint32 aOldEnd, PRUint32 aNewEnd) { return NS_ERROR_NOT_IMPLEMENTED; }
   NS_IMETHOD              OnIMESelectionChange(void) { return NS_ERROR_NOT_IMPLEMENTED; }
   virtual nsIMEUpdatePreference GetIMEUpdatePreference() { return nsIMEUpdatePreference(false, false); }
   NS_IMETHOD              OnDefaultButtonLoaded(const nsIntRect &aButtonRect) { return NS_ERROR_NOT_IMPLEMENTED; }
   NS_IMETHOD              OverrideSystemMouseScrollSpeed(PRInt32 aOriginalDelta, bool aIsHorizontal, PRInt32 &aOverriddenDelta);
   virtual already_AddRefed<nsIWidget>
   CreateChild(const nsIntRect  &aRect,
-              EVENT_CALLBACK   aHandleEventFunction,
               nsDeviceContext *aContext,
               nsWidgetInitData *aInitData = nullptr,
               bool             aForceUseIWidgetParent = false);
-  NS_IMETHOD              SetEventCallback(EVENT_CALLBACK aEventFunction, nsDeviceContext *aContext);
-  NS_IMETHOD              AttachViewToTopLevel(EVENT_CALLBACK aViewEventFunction, nsDeviceContext *aContext);
+  NS_IMETHOD              AttachViewToTopLevel(bool aUseAttachedEvents, nsDeviceContext *aContext);
   virtual ViewWrapper*    GetAttachedViewPtr();
   NS_IMETHOD              SetAttachedViewPtr(ViewWrapper* aViewWrapper);
   NS_IMETHOD              RegisterTouchWindow();
   NS_IMETHOD              UnregisterTouchWindow();
 
   void NotifyWindowDestroyed();
   void NotifySizeMoveDone();
 
@@ -244,17 +242,16 @@ public:
 protected:
 
   virtual void            ResolveIconName(const nsAString &aIconName,
                                           const nsAString &aIconSuffix,
                                           nsIFile **aResult);
   virtual void            OnDestroy();
   virtual void            BaseCreate(nsIWidget *aParent,
                                      const nsIntRect &aRect,
-                                     EVENT_CALLBACK aHandleEventFunction,
                                      nsDeviceContext *aContext,
                                      nsWidgetInitData *aInitData);
 
   virtual nsIContent* GetLastRollup()
   {
     return mLastRollup;
   }
 
@@ -328,32 +325,31 @@ protected:
    * It is safe to call it several times if platform implementations
    * require the compositor to be destroyed before ~nsBaseWidget is
    * reached (This is the case with gtk2 for instance).
    */
   void DestroyCompositor();
 
   nsIWidgetListener* mWidgetListener;
   ViewWrapper*      mViewWrapperPtr;
-  EVENT_CALLBACK    mEventCallback;
-  EVENT_CALLBACK    mViewCallback;
   nsDeviceContext* mContext;
   nsRefPtr<LayerManager> mLayerManager;
   nsRefPtr<LayerManager> mBasicLayerManager;
   nsRefPtr<CompositorChild> mCompositorChild;
   nsRefPtr<CompositorParent> mCompositorParent;
   nscolor           mBackground;
   nscolor           mForeground;
   nsCursor          mCursor;
   nsWindowType      mWindowType;
   nsBorderStyle     mBorderStyle;
   bool              mOnDestroyCalled;
   bool              mUseAcceleratedRendering;
   bool              mForceLayersAcceleration;
   bool              mTemporarilyUseBasicLayerManager;
+  bool              mUseAttachedEvents;
   nsIntRect         mBounds;
   nsIntRect*        mOriginalBounds;
   // When this pointer is null, the widget is not clipped
   nsAutoArrayPtr<nsIntRect> mClipRects;
   PRUint32          mClipRectCount;
   PRInt32           mZIndex;
   nsSizeMode        mSizeMode;
   nsPopupLevel      mPopupLevel;
--- a/xpfe/appshell/src/nsWebShellWindow.cpp
+++ b/xpfe/appshell/src/nsWebShellWindow.cpp
@@ -159,17 +159,16 @@ nsresult nsWebShellWindow::Initialize(ns
     parentAsWin->GetMainWidget(getter_AddRefs(parentWidget));
     mParentWindow = do_GetWeakReference(aParent);
   }
 
   mWindow->SetWidgetListener(this);
   mWindow->Create((nsIWidget *)parentWidget,          // Parent nsIWidget
                   nullptr,                            // Native parent widget
                   r,                                  // Widget dimensions
-                  nullptr,                            // Event handler function
                   nullptr,                            // Device context
                   &widgetInitData);                   // Widget initialization data
   mWindow->GetClientBounds(r);
   // Match the default background color of content. Important on windows
   // since we no longer use content child widgets.
   mWindow->SetBackgroundColor(NS_RGB(255,255,255));
 
   // Create web shell
--- a/xpfe/appshell/src/nsWebShellWindow.h
+++ b/xpfe/appshell/src/nsWebShellWindow.h
@@ -63,18 +63,16 @@ protected:
   friend class mozilla::WebShellWindowTimerCallback;
   
   virtual ~nsWebShellWindow();
 
   void                     LoadContentAreas();
   bool                     ExecuteCloseHandler();
   void                     ConstrainToOpenerScreen(PRInt32* aX, PRInt32* aY);
 
-  static nsEventStatus HandleEvent(nsGUIEvent *aEvent);
-
   nsCOMPtr<nsITimer>      mSPTimer;
   mozilla::Mutex          mSPTimerLock;
 
   void        SetPersistenceTimer(PRUint32 aDirtyFlags);
   void        FirePersistenceTimer();
 };