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 id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewerstn
bugs743975
milestone17.0a1
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();
 };