--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -65,16 +65,17 @@
#include "mozilla/dom/workers/Workers.h"
#include "nsJSPrincipals.h"
#include "mozilla/Attributes.h"
// Interfaces Needed
#include "nsIFrame.h"
#include "nsCanvasFrame.h"
#include "nsIWidget.h"
+#include "nsIWidgetListener.h"
#include "nsIBaseWindow.h"
#include "nsDeviceSensors.h"
#include "nsIContent.h"
#include "nsIContentViewerEdit.h"
#include "nsIDocShell.h"
#include "nsIDocShellLoadInfo.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDocShellTreeNode.h"
@@ -7703,20 +7704,21 @@ nsGlobalWindow::ActivateOrDeactivate(boo
nsCOMPtr<nsIDOMWindow> topLevelWindow;
if (topLevelWidget == mainWidget) {
topLevelWindow = static_cast<nsIDOMWindow*>(this);
} else {
// This is a workaround for the following problem:
// When a window with an open sheet loses focus, only the sheet window
// receives the NS_DEACTIVATE event. However, it's not the sheet that
// should lose the active styling, but the containing top level window.
- void* clientData;
- topLevelWidget->GetClientData(clientData); // clientData is nsXULWindow
- nsISupports* data = static_cast<nsISupports*>(clientData);
- nsCOMPtr<nsIInterfaceRequestor> req(do_QueryInterface(data));
+
+ // widgetListener should be a nsXULWindow
+ nsIWidgetListener* listener = topLevelWidget->GetWidgetListener();
+ nsCOMPtr<nsIXULWindow> window = listener->GetXULWindow();
+ nsCOMPtr<nsIInterfaceRequestor> req(do_QueryInterface(window));
topLevelWindow = do_GetInterface(req);
}
if (topLevelWindow) {
nsCOMPtr<nsPIDOMWindow> piWin(do_QueryInterface(topLevelWindow));
piWin->SetActive(aActivate);
}
}
--- a/embedding/browser/webBrowser/nsWebBrowser.cpp
+++ b/embedding/browser/webBrowser/nsWebBrowser.cpp
@@ -87,17 +87,17 @@ nsWebBrowser::~nsWebBrowser()
{
InternalDestroy();
}
NS_IMETHODIMP nsWebBrowser::InternalDestroy()
{
if (mInternalWidget) {
- mInternalWidget->SetClientData(0);
+ mInternalWidget->SetWidgetListener(nullptr);
mInternalWidget->Destroy();
mInternalWidget = nullptr; // Force release here.
}
SetDocShell(nullptr);
if(mDocShellTreeOwner)
{
@@ -1113,18 +1113,18 @@ NS_IMETHODIMP nsWebBrowser::Create()
docShellParentWidget = mInternalWidget;
nsWidgetInitData widgetInit;
widgetInit.clipChildren = true;
widgetInit.mWindowType = eWindowType_child;
nsIntRect bounds(mInitInfo->x, mInitInfo->y, mInitInfo->cx, mInitInfo->cy);
- mInternalWidget->SetClientData(static_cast<nsWebBrowser *>(this));
- mInternalWidget->Create(nullptr, mParentNativeWindow, bounds, nsWebBrowser::HandleEvent,
+ mInternalWidget->SetWidgetListener(this);
+ mInternalWidget->Create(nullptr, mParentNativeWindow, bounds, nullptr,
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);
@@ -1654,79 +1654,55 @@ static void DrawThebesLayer(ThebesLayer*
nscolor* color = static_cast<nscolor*>(aCallbackData);
aContext->NewPath();
aContext->SetColor(gfxRGBA(*color));
nsIntRect dirtyRect = aRegionToDraw.GetBounds();
aContext->Rectangle(gfxRect(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height));
aContext->Fill();
}
-/* static */
-nsEventStatus nsWebBrowser::HandleEvent(nsGUIEvent *aEvent)
+void nsWebBrowser::WindowRaised(nsIWidget* aWidget)
{
- nsWebBrowser *browser = nullptr;
- void *data = nullptr;
- nsIWidget *widget = aEvent->widget;
-
- if (!widget)
- return nsEventStatus_eIgnore;
-
- widget->GetClientData(data);
- if (!data)
- return nsEventStatus_eIgnore;
-
- browser = static_cast<nsWebBrowser *>(data);
-
- switch(aEvent->message) {
-
- case NS_PAINT: {
- LayerManager* layerManager = widget->GetLayerManager();
- NS_ASSERTION(layerManager, "Must be in paint event");
+#if defined(DEBUG_smaug)
+ nsCOMPtr<nsIDOMDocument> domDocument = do_GetInterface(mDocShell);
+ nsAutoString documentURI;
+ domDocument->GetDocumentURI(documentURI);
+ printf("nsWebBrowser::NS_ACTIVATE %p %s\n", (void*)browser,
+ NS_ConvertUTF16toUTF8(documentURI).get());
+#endif
+ Activate();
+}
- layerManager->BeginTransaction();
- nsRefPtr<ThebesLayer> root = layerManager->CreateThebesLayer();
- nsPaintEvent* paintEvent = static_cast<nsPaintEvent*>(aEvent);
- nsIntRect dirtyRect = paintEvent->region.GetBounds();
- if (root) {
- root->SetVisibleRegion(dirtyRect);
- layerManager->SetRoot(root);
- }
- layerManager->EndTransaction(DrawThebesLayer, &browser->mBackgroundColor);
- return nsEventStatus_eConsumeDoDefault;
- }
+void nsWebBrowser::WindowLowered(nsIWidget* aWidget)
+{
+#if defined(DEBUG_smaug)
+ nsCOMPtr<nsIDOMDocument> domDocument = do_GetInterface(mDocShell);
+ nsAutoString documentURI;
+ domDocument->GetDocumentURI(documentURI);
+ printf("nsWebBrowser::NS_DEACTIVATE %p %s\n", (void*)browser,
+ NS_ConvertUTF16toUTF8(documentURI).get());
+#endif
+ Deactivate();
+}
- case NS_ACTIVATE: {
-#if defined(DEBUG_smaug)
- nsCOMPtr<nsIDOMDocument> domDocument = do_GetInterface(browser->mDocShell);
- nsAutoString documentURI;
- domDocument->GetDocumentURI(documentURI);
- printf("nsWebBrowser::NS_ACTIVATE %p %s\n", (void*)browser,
- NS_ConvertUTF16toUTF8(documentURI).get());
-#endif
- browser->Activate();
- break;
+bool nsWebBrowser::PaintWindow(nsIWidget* aWidget, bool isRequest, nsIntRegion aRegion, bool aWillSendDidPaint)
+{
+ LayerManager* layerManager = aWidget->GetLayerManager();
+ NS_ASSERTION(layerManager, "Must be in paint event");
+
+ layerManager->BeginTransaction();
+ nsRefPtr<ThebesLayer> root = layerManager->CreateThebesLayer();
+ if (root) {
+ nsIntRect dirtyRect = aRegion.GetBounds();
+ root->SetVisibleRegion(dirtyRect);
+ layerManager->SetRoot(root);
}
- case NS_DEACTIVATE: {
-#if defined(DEBUG_smaug)
- nsCOMPtr<nsIDOMDocument> domDocument = do_GetInterface(browser->mDocShell);
- nsAutoString documentURI;
- domDocument->GetDocumentURI(documentURI);
- printf("nsWebBrowser::NS_DEACTIVATE %p %s\n", (void*)browser,
- NS_ConvertUTF16toUTF8(documentURI).get());
-#endif
- browser->Deactivate();
- break;
- }
-
- default:
- break;
- }
-
- return nsEventStatus_eIgnore;
+ layerManager->EndTransaction(DrawThebesLayer, &mBackgroundColor);
+ return true;
}
NS_IMETHODIMP nsWebBrowser::GetPrimaryContentWindow(nsIDOMWindow** aDOMWindow)
{
*aDOMWindow = 0;
nsCOMPtr<nsIDocShellTreeItem> item;
NS_ENSURE_TRUE(mDocShellTreeOwner, NS_ERROR_FAILURE);
--- a/embedding/browser/webBrowser/nsWebBrowser.h
+++ b/embedding/browser/webBrowser/nsWebBrowser.h
@@ -31,16 +31,17 @@
#include "nsIWebNavigation.h"
#include "nsIWebBrowserSetup.h"
#include "nsIWebBrowserPersist.h"
#include "nsIWebBrowserFocus.h"
#include "nsIWebBrowserStream.h"
#include "nsIWindowWatcher.h"
#include "nsIPrintSettings.h"
#include "nsEmbedStream.h"
+#include "nsIWidgetListener.h"
#include "nsTArray.h"
#include "nsWeakPtr.h"
class nsIContentViewerFile;
class nsWebBrowserInitInfo
{
@@ -79,16 +80,17 @@ class nsWebBrowser : public nsIWebBrowse
public nsIBaseWindow,
public nsIScrollable,
public nsITextScroll,
public nsIInterfaceRequestor,
public nsIWebBrowserPersist,
public nsIWebBrowserFocus,
public nsIWebProgressListener,
public nsIWebBrowserStream,
+ public nsIWidgetListener,
public nsSupportsWeakReference
{
friend class nsDocShellTreeOwner;
public:
nsWebBrowser();
NS_DECL_ISUPPORTS
@@ -114,17 +116,20 @@ protected:
// XXXbz why are these NS_IMETHOD? They're not interface methods!
NS_IMETHOD SetDocShell(nsIDocShell* aDocShell);
NS_IMETHOD EnsureDocShellTreeOwner();
NS_IMETHOD GetPrimaryContentWindow(nsIDOMWindow **aDomWindow);
NS_IMETHOD BindListener(nsISupports *aListener, const nsIID& aIID);
NS_IMETHOD UnBindListener(nsISupports *aListener, const nsIID& aIID);
NS_IMETHOD EnableGlobalHistory(bool aEnable);
- static nsEventStatus HandleEvent(nsGUIEvent *aEvent);
+ // nsIWidgetListener
+ virtual void WindowRaised(nsIWidget* aWidget);
+ virtual void WindowLowered(nsIWidget* aWidget);
+ virtual bool PaintWindow(nsIWidget* aWidget, bool isRequest, nsIntRegion aRegion, bool aWillSendDidPaint);
protected:
nsDocShellTreeOwner* mDocShellTreeOwner;
nsCOMPtr<nsIDocShell> mDocShell;
nsCOMPtr<nsIInterfaceRequestor> mDocShellAsReq;
nsCOMPtr<nsIBaseWindow> mDocShellAsWin;
nsCOMPtr<nsIDocShellTreeItem> mDocShellAsItem;
nsCOMPtr<nsIWebNavigation> mDocShellAsNav;
--- a/view/src/nsView.cpp
+++ b/view/src/nsView.cpp
@@ -2,48 +2,124 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsView.h"
#include "nsIWidget.h"
#include "nsWidgetsCID.h"
#include "nsViewManager.h"
+#include "nsIFrame.h"
#include "nsGUIEvent.h"
#include "nsIComponentManager.h"
#include "nsGfxCIID.h"
#include "nsIInterfaceRequestor.h"
#include "mozilla/Attributes.h"
-
-//mmptemp
+#include "nsXULPopupManager.h"
+#include "nsIWidgetListener.h"
static nsEventStatus HandleEvent(nsGUIEvent *aEvent);
-
-//#define SHOW_VIEW_BORDERS
-
#define VIEW_WRAPPER_IID \
{ 0xbf4e1841, 0xe9ec, 0x47f2, \
{ 0xb4, 0x77, 0x0f, 0xf6, 0x0f, 0x5a, 0xac, 0xbd } }
+static bool
+IsPopupWidget(nsIWidget* aWidget)
+{
+ nsWindowType type;
+ aWidget->GetWindowType(type);
+ return (type == eWindowType_popup);
+}
+
/**
* nsISupports-derived helper class that allows to store and get a view
*/
-class ViewWrapper MOZ_FINAL : public nsIInterfaceRequestor
+class ViewWrapper MOZ_FINAL : public nsIInterfaceRequestor,
+ public nsIWidgetListener
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(VIEW_WRAPPER_IID)
NS_DECL_ISUPPORTS
NS_DECL_NSIINTERFACEREQUESTOR
ViewWrapper(nsView* aView) : mView(aView) {}
nsView* GetView() { return mView; }
private:
nsView* mView;
+
+ public:
+
+ bool WindowMoved(nsIWidget* aWidget, PRInt32 x, PRInt32 y)
+ {
+ nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
+ if (pm && IsPopupWidget(aWidget)) {
+ pm->PopupMoved(mView->GetFrame(), nsIntPoint(x, y));
+ return true;
+ }
+
+ return false;
+ }
+
+ bool WindowResized(nsIWidget* aWidget, PRInt32 aWidth, PRInt32 aHeight)
+ {
+ nsIViewManager* viewManager = mView->GetViewManager();
+
+ // The root view may not be set if this is the resize associated with
+ // window creation
+ if (mView == viewManager->GetRootView()) {
+ nsRefPtr<nsDeviceContext> devContext;
+ viewManager->GetDeviceContext(*getter_AddRefs(devContext));
+ PRInt32 p2a = devContext->AppUnitsPerDevPixel();
+ viewManager->SetWindowDimensions(NSIntPixelsToAppUnits(aWidth, p2a),
+ NSIntPixelsToAppUnits(aHeight, p2a));
+ return true;
+ }
+ else if (IsPopupWidget(aWidget)) {
+ nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
+ if (pm) {
+ pm->PopupResized(mView->GetFrame(), nsIntSize(aWidth, aHeight));
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ bool RequestWindowClose(nsIWidget* aWidget)
+ {
+ nsIFrame* frame = mView->GetFrame();
+ if (frame && IsPopupWidget(aWidget) &&
+ frame->GetType() == nsGkAtoms::menuPopupFrame) {
+ nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
+ if (pm) {
+ pm->HidePopup(frame->GetContent(), false, true, false);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ void WillPaintWindow(nsIWidget* aWidget, bool aWillSendPaint)
+ {
+ mView->GetViewManager()->WillPaintWindow(aWidget, aWillSendPaint);
+ }
+
+ bool PaintWindow(nsIWidget* aWidget, nsIntRegion aRegion, bool aSentWillPaint, bool aWillSendDidPaint)
+ {
+ nsCOMPtr<nsViewManager> vm = mView->GetViewManager();
+ return vm->PaintWindow(aWidget, aRegion, aSentWillPaint, aWillSendDidPaint);
+ }
+
+ void DidPaintWindow()
+ {
+ mView->GetViewManager()->DidPaintWindow();
+ }
};
NS_DEFINE_STATIC_IID_ACCESSOR(ViewWrapper, VIEW_WRAPPER_IID)
NS_IMPL_ADDREF(ViewWrapper)
NS_IMPL_RELEASE(ViewWrapper)
#ifndef DEBUG
NS_IMPL_QUERY_INTERFACE2(ViewWrapper, ViewWrapper, nsIInterfaceRequestor)
@@ -88,33 +164,17 @@ 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)
{
- // The widget's client data points back to the owning view
- if (aWidget) {
- void* clientData;
- aWidget->GetClientData(clientData);
- nsISupports* data = (nsISupports*)clientData;
-
- if (data) {
- ViewWrapper* wrapper;
- CallQueryInterface(data, &wrapper);
- // Give a weak reference to the caller. There will still be at least one
- // reference left, since the wrapper was addrefed when set on the widget.
- if (wrapper)
- wrapper->Release();
- return wrapper;
- }
- }
- return nullptr;
+ 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
@@ -251,17 +311,17 @@ void nsView::DestroyWidget()
// Destroy. Just clear our event view ptr and free our reference to it.
if (mWidgetIsTopLevel) {
ViewWrapper* wrapper = GetAttachedWrapperFor(mWindow);
NS_IF_RELEASE(wrapper);
mWindow->SetAttachedViewPtr(nullptr);
}
else {
- mWindow->SetClientData(nullptr);
+ mWindow->SetWidgetListener(nullptr);
mWindow->Destroy();
}
NS_RELEASE(mWindow);
}
}
nsresult nsView::QueryInterface(const nsIID& aIID, void** aInstancePtr)
@@ -783,17 +843,17 @@ nsresult nsView::CreateWidgetForPopup(ns
void
nsView::InitializeWindow(bool aEnableDragDrop, bool aResetVisibility)
{
NS_ABORT_IF_FALSE(mWindow, "Must have a window to initialize");
ViewWrapper* wrapper = new ViewWrapper(this);
NS_ADDREF(wrapper); // Will be released in ~nsView
- mWindow->SetClientData(wrapper);
+ mWindow->SetWidgetListener(wrapper);
if (aEnableDragDrop) {
mWindow->EnableDragDrop(true);
}
// propagate the z-index to the widget.
UpdateNativeWidgetZIndexes(this, FindNonAutoZIndex(this));
@@ -874,47 +934,45 @@ void nsView::SetZIndex(bool aAuto, PRInt
void nsView::AssertNoWindow()
{
// XXX: it would be nice to make this a strong assert
if (NS_UNLIKELY(mWindow)) {
NS_ERROR("We already have a window for this view? BAD");
ViewWrapper* wrapper = GetWrapperFor(mWindow);
NS_IF_RELEASE(wrapper);
- mWindow->SetClientData(nullptr);
+ mWindow->SetWidgetListener(nullptr);
mWindow->Destroy();
NS_RELEASE(mWindow);
}
}
//
// internal window creation functions
//
EVENT_CALLBACK nsIView::AttachWidgetEventHandler(nsIWidget* aWidget)
{
#ifdef DEBUG
- void* data = nullptr;
- aWidget->GetClientData(data);
- NS_ASSERTION(!data, "Already got client data");
+ NS_ASSERTION(!aWidget->GetWidgetListener(), "Already have a widget listener");
#endif
ViewWrapper* wrapper = new ViewWrapper(Impl());
if (!wrapper)
return nullptr;
NS_ADDREF(wrapper); // Will be released in DetachWidgetEventHandler
- aWidget->SetClientData(wrapper);
+ 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->SetClientData(nullptr);
+ aWidget->SetWidgetListener(nullptr);
}
#ifdef DEBUG
void nsIView::List(FILE* out, PRInt32 aIndent) const
{
PRInt32 i;
for (i = aIndent; --i >= 0; ) fputs(" ", out);
fprintf(out, "%p ", (void*)this);
--- a/view/src/nsViewManager.cpp
+++ b/view/src/nsViewManager.cpp
@@ -640,262 +640,135 @@ void nsViewManager::InvalidateViews(nsVi
// Invalidate all children as well.
nsView* childView = aView->GetFirstChild();
while (nullptr != childView) {
childView->GetViewManager()->InvalidateViews(childView);
childView = childView->GetNextSibling();
}
}
-static bool
-IsViewForPopup(nsIView* aView)
+void nsViewManager::WillPaintWindow(nsIWidget* aWidget, bool aWillSendDidPaint)
{
- nsIWidget* widget = aView->GetWidget();
- if (widget) {
- nsWindowType type;
- widget->GetWindowType(type);
- return (type == eWindowType_popup);
+ if (IsRefreshDriverPaintingEnabled())
+ return;
+
+ if (!aWidget || !mContext)
+ return;
+
+ // If an ancestor widget was hidden and then shown, we could
+ // have a delayed resize to handle.
+ for (nsViewManager *vm = this; vm;
+ vm = vm->mRootView->GetParent()
+ ? vm->mRootView->GetParent()->GetViewManager()
+ : nullptr) {
+ if (vm->mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) &&
+ vm->mRootView->IsEffectivelyVisible() &&
+ mPresShell && mPresShell->IsVisible()) {
+ vm->FlushDelayedResize(true);
+ vm->InvalidateView(vm->mRootView);
+ }
+ }
+
+ // Flush things like reflows and plugin widget geometry updates by
+ // calling WillPaint on observer presShells.
+ nsRefPtr<nsViewManager> rootVM = RootViewManager();
+ if (mPresShell) {
+ rootVM->CallWillPaintOnObservers(aWillSendDidPaint);
+ }
+
+ // Flush view widget geometry updates and invalidations.
+ rootVM->ProcessPendingUpdates();
+}
+
+bool nsViewManager::PaintWindow(nsIWidget* aWidget, nsIntRegion aRegion,
+ bool aSentWillPaint, bool aWillSendDidPaint)
+ {
+ if (!aWidget || !mContext)
+ return false;
+
+ NS_ASSERTION(IsPaintingAllowed(),
+ "shouldn't be receiving paint events while painting is disallowed!");
+
+ if (!aSentWillPaint && !IsRefreshDriverPaintingEnabled()) {
+ WillPaintWindow(aWidget, aWillSendDidPaint);
+ }
+
+ // Get the view pointer here since NS_WILL_PAINT might have
+ // destroyed it during CallWillPaintOnObservers (bug 378273).
+ nsView* view = nsView::GetViewFor(aWidget);
+ if (view && !aRegion.IsEmpty()) {
+ Refresh(view, aRegion, aWillSendDidPaint);
}
- return false;
+ return true;
+}
+
+void nsViewManager::DidPaintWindow()
+{
+ if (!IsRefreshDriverPaintingEnabled()) {
+ mRootViewManager->CallDidPaintOnObserver();
+ }
}
-NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent,
- nsIView* aView, nsEventStatus *aStatus)
+nsresult nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsIView* aView, nsEventStatus* aStatus)
{
- NS_ASSERTION(!aView || static_cast<nsView*>(aView)->GetViewManager() == this,
- "wrong view manager");
+ SAMPLE_LABEL("event", "nsViewManager::DispatchEvent");
+
+ if ((NS_IS_MOUSE_EVENT(aEvent) &&
+ // Ignore mouse events that we synthesize.
+ static_cast<nsMouseEvent*>(aEvent)->reason == nsMouseEvent::eReal &&
+ // Ignore mouse exit and enter (we'll get moves if the user
+ // is really moving the mouse) since we get them when we
+ // create and destroy widgets.
+ aEvent->message != NS_MOUSE_EXIT &&
+ aEvent->message != NS_MOUSE_ENTER) ||
+ NS_IS_KEY_EVENT(aEvent) ||
+ NS_IS_IME_EVENT(aEvent) ||
+ aEvent->message == NS_PLUGIN_INPUT_EVENT) {
+ gLastUserEventTime = PR_IntervalToMicroseconds(PR_IntervalNow());
+ }
+
+ // Find the view whose coordinates system we're in.
+ nsIView* view = aView;
+ bool dispatchUsingCoordinates = NS_IsEventUsingCoordinates(aEvent);
+ if (dispatchUsingCoordinates) {
+ // Will dispatch using coordinates. Pretty bogus but it's consistent
+ // with what presshell does.
+ view = GetDisplayRootFor(view);
+ }
- SAMPLE_LABEL("event", "nsViewManager::DispatchEvent");
+ // If the view has no frame, look for a view that does.
+ nsIFrame* frame = view->GetFrame();
+ if (!frame &&
+ (dispatchUsingCoordinates || NS_IS_KEY_EVENT(aEvent) ||
+ NS_IS_IME_RELATED_EVENT(aEvent) ||
+ NS_IS_NON_RETARGETED_PLUGIN_EVENT(aEvent) ||
+ aEvent->message == NS_PLUGIN_ACTIVATE ||
+ aEvent->message == NS_PLUGIN_FOCUS)) {
+ while (view && !view->GetFrame()) {
+ view = view->GetParent();
+ }
+
+ if (view) {
+ frame = view->GetFrame();
+ }
+ }
+
+ if (nullptr != frame) {
+ // Hold a refcount to the presshell. The continued existence of the
+ // presshell will delay deletion of this view hierarchy should the event
+ // want to cause its destruction in, say, some JavaScript event handler.
+ nsCOMPtr<nsIPresShell> shell = view->GetViewManager()->GetPresShell();
+ if (shell) {
+ return shell->HandleEvent(frame, aEvent, false, aStatus);
+ }
+ }
*aStatus = nsEventStatus_eIgnore;
- switch(aEvent->message)
- {
- case NS_SIZE:
- {
- if (aView)
- {
- // client area dimensions are set on the view
- nscoord width = ((nsSizeEvent*)aEvent)->windowSize->width;
- nscoord height = ((nsSizeEvent*)aEvent)->windowSize->height;
-
- // The root view may not be set if this is the resize associated with
- // window creation
-
- if (aView == mRootView)
- {
- PRInt32 p2a = AppUnitsPerDevPixel();
- SetWindowDimensions(NSIntPixelsToAppUnits(width, p2a),
- NSIntPixelsToAppUnits(height, p2a));
- *aStatus = nsEventStatus_eConsumeNoDefault;
- }
- else if (IsViewForPopup(aView))
- {
- nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
- if (pm)
- {
- pm->PopupResized(aView->GetFrame(), nsIntSize(width, height));
- *aStatus = nsEventStatus_eConsumeNoDefault;
- }
- }
- }
- }
-
- break;
-
- case NS_MOVE:
- {
- // A popup's parent view is the root view for the parent window, so when
- // a popup moves, the popup's frame and view position must be updated
- // to match.
- if (aView && IsViewForPopup(aView))
- {
- nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
- if (pm)
- {
- pm->PopupMoved(aView->GetFrame(), aEvent->refPoint);
- *aStatus = nsEventStatus_eConsumeNoDefault;
- }
- }
- break;
- }
-
- case NS_XUL_CLOSE:
- {
- // if this is a popup, make a request to hide it. Note that a popuphidden
- // event listener may cancel the event and the popup will not be hidden.
- nsIWidget* widget = aView->GetWidget();
- if (widget) {
- nsWindowType type;
- widget->GetWindowType(type);
- if (type == eWindowType_popup) {
- nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
- if (pm) {
- pm->HidePopup(aView->GetFrame());
- *aStatus = nsEventStatus_eConsumeNoDefault;
- }
- }
- }
- }
- break;
-
- case NS_WILL_PAINT:
- {
- if (!aView || !mContext)
- break;
-
- *aStatus = nsEventStatus_eConsumeNoDefault;
-
- if (!IsRefreshDriverPaintingEnabled()) {
-
- nsPaintEvent *event = static_cast<nsPaintEvent*>(aEvent);
-
- NS_ASSERTION(static_cast<nsView*>(aView) ==
- nsView::GetViewFor(event->widget),
- "view/widget mismatch");
-
- // If an ancestor widget was hidden and then shown, we could
- // have a delayed resize to handle.
- for (nsViewManager *vm = this; vm;
- vm = vm->mRootView->GetParent()
- ? vm->mRootView->GetParent()->GetViewManager()
- : nullptr) {
- if (vm->mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) &&
- vm->mRootView->IsEffectivelyVisible() &&
- mPresShell && mPresShell->IsVisible()) {
- vm->FlushDelayedResize(true);
- vm->InvalidateView(vm->mRootView);
- }
- }
-
- // Flush things like reflows and plugin widget geometry updates by
- // calling WillPaint on observer presShells.
- nsRefPtr<nsViewManager> rootVM = RootViewManager();
- if (mPresShell) {
- rootVM->CallWillPaintOnObservers(event->willSendDidPaint);
- }
- // Flush view widget geometry updates and invalidations.
- rootVM->ProcessPendingUpdates();
- }
- }
- break;
-
- case NS_PAINT:
- {
- if (!aView || !mContext)
- break;
-
- *aStatus = nsEventStatus_eConsumeNoDefault;
- nsPaintEvent *event = static_cast<nsPaintEvent*>(aEvent);
- nsView* view = static_cast<nsView*>(aView);
- NS_ASSERTION(view == nsView::GetViewFor(event->widget),
- "view/widget mismatch");
- NS_ASSERTION(IsPaintingAllowed(),
- "shouldn't be receiving paint events while painting is "
- "disallowed!");
-
- if (!event->didSendWillPaint && !IsRefreshDriverPaintingEnabled()) {
- // Send NS_WILL_PAINT event ourselves.
- nsPaintEvent willPaintEvent(true, NS_WILL_PAINT, event->widget);
- willPaintEvent.willSendDidPaint = event->willSendDidPaint;
- DispatchEvent(&willPaintEvent, view, aStatus);
-
- // Get the view pointer again since NS_WILL_PAINT might have
- // destroyed it during CallWillPaintOnObservers (bug 378273).
- view = nsView::GetViewFor(event->widget);
- }
-
- if (!view || event->region.IsEmpty())
- break;
-
- // Paint.
- Refresh(view, event->region, event->willSendDidPaint);
-
- break;
- }
-
- case NS_DID_PAINT: {
- if (!IsRefreshDriverPaintingEnabled()) {
- nsRefPtr<nsViewManager> rootVM = RootViewManager();
- rootVM->CallDidPaintOnObserver();
- }
- break;
- }
-
- case NS_SETZLEVEL:
- /* Don't pass these events through. Passing them through
- causes performance problems on pages with lots of views/frames
- @see bug 112861 */
- *aStatus = nsEventStatus_eConsumeNoDefault;
- break;
-
- default:
- {
- if ((NS_IS_MOUSE_EVENT(aEvent) &&
- // Ignore mouse events that we synthesize.
- static_cast<nsMouseEvent*>(aEvent)->reason ==
- nsMouseEvent::eReal &&
- // Ignore mouse exit and enter (we'll get moves if the user
- // is really moving the mouse) since we get them when we
- // create and destroy widgets.
- aEvent->message != NS_MOUSE_EXIT &&
- aEvent->message != NS_MOUSE_ENTER) ||
- NS_IS_KEY_EVENT(aEvent) ||
- NS_IS_IME_EVENT(aEvent) ||
- aEvent->message == NS_PLUGIN_INPUT_EVENT) {
- gLastUserEventTime = PR_IntervalToMicroseconds(PR_IntervalNow());
- }
-
- if (aEvent->message == NS_DEACTIVATE) {
- // if a window is deactivated, clear the mouse capture regardless
- // of what is capturing
- nsIPresShell::ClearMouseCapture(nullptr);
- }
-
- // Find the view whose coordinates system we're in.
- nsIView* view = aView;
- bool dispatchUsingCoordinates = NS_IsEventUsingCoordinates(aEvent);
- if (dispatchUsingCoordinates) {
- // Will dispatch using coordinates. Pretty bogus but it's consistent
- // with what presshell does.
- view = GetDisplayRootFor(view);
- }
-
- // If the view has no frame, look for a view that does.
- nsIFrame* frame = view->GetFrame();
- if (!frame &&
- (dispatchUsingCoordinates || NS_IS_KEY_EVENT(aEvent) ||
- NS_IS_IME_RELATED_EVENT(aEvent) ||
- NS_IS_NON_RETARGETED_PLUGIN_EVENT(aEvent) ||
- aEvent->message == NS_PLUGIN_ACTIVATE ||
- aEvent->message == NS_PLUGIN_FOCUS)) {
- while (view && !view->GetFrame()) {
- view = view->GetParent();
- }
-
- if (view) {
- frame = view->GetFrame();
- }
- }
-
- if (nullptr != frame) {
- // Hold a refcount to the presshell. The continued existence of the
- // presshell will delay deletion of this view hierarchy should the event
- // want to cause its destruction in, say, some JavaScript event handler.
- nsCOMPtr<nsIPresShell> shell = view->GetViewManager()->GetPresShell();
- if (shell) {
- shell->HandleEvent(frame, aEvent, false, aStatus);
- }
- }
-
- break;
- }
- }
-
return NS_OK;
}
// Recursively reparent widgets if necessary
void nsViewManager::ReparentChildWidgets(nsIView* aView, nsIWidget *aNewWidget)
{
NS_PRECONDITION(aNewWidget, "");
--- a/view/src/nsViewManager.h
+++ b/view/src/nsViewManager.h
@@ -163,16 +163,21 @@ public: // NOT in nsIViewManager, so pri
nsViewManager* RootViewManager() const { return mRootViewManager; }
bool IsRootVM() const { return this == RootViewManager(); }
// Whether synchronous painting is allowed at the moment. For example,
// widget geometry changes can cause synchronous painting, so they need to
// be deferred while refresh is disabled.
bool IsPaintingAllowed() { return RootViewManager()->mRefreshDisableCount == 0; }
+ void WillPaintWindow(nsIWidget* aWidget, bool aWillSendDidPaint);
+ bool PaintWindow(nsIWidget* aWidget, nsIntRegion aRegion,
+ bool aSentWillPaint, bool aWillSendDidPaint);
+ void DidPaintWindow();
+
// Call this when you need to let the viewmanager know that it now has
// pending updates.
void PostPendingUpdate();
PRUint32 AppUnitsPerDevPixel() const
{
return mContext->AppUnitsPerDevPixel();
}
--- a/widget/Makefile.in
+++ b/widget/Makefile.in
@@ -67,16 +67,17 @@ EXPORTS = \
nsEvent.h \
nsNativeWidget.h \
nsWidgetInitData.h \
nsWidgetsCID.h \
nsIPluginWidget.h \
nsINativeKeyBindings.h \
nsIDeviceContextSpec.h \
nsIRollupListener.h \
+ nsIWidgetListener.h \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
EXPORTS += \
nsINativeMenuService.h \
nsIPrintDialogService.h \
$(NULL)
endif
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -17,16 +17,17 @@ using mozilla::dom::ContentParent;
using mozilla::dom::ContentChild;
using mozilla::unused;
#include "nsAppShell.h"
#include "nsIdleService.h"
#include "nsWindow.h"
#include "nsIObserverService.h"
#include "nsFocusManager.h"
+#include "nsIWidgetListener.h"
#include "nsRenderingContext.h"
#include "nsIDOMSimpleGestureEvent.h"
#include "nsDOMTouchEvent.h"
#include "nsGkAtoms.h"
#include "nsWidgetsCID.h"
#include "nsGfxCIID.h"
@@ -565,31 +566,34 @@ nsWindow::BringToFront()
nsWindow *newTop = this;
if (!gTopLevelWindows.IsEmpty())
oldTop = gTopLevelWindows[0];
gTopLevelWindows.RemoveElement(this);
gTopLevelWindows.InsertElementAt(0, this);
if (oldTop) {
- nsGUIEvent event(true, NS_DEACTIVATE, oldTop);
- DispatchEvent(&event);
+ nsIWidgetListener* listener = oldTop->GetWidgetListener();
+ if (listener) {
+ listener->WindowDeactivated();
+ }
}
if (Destroyed()) {
// somehow the deactivate event handler destroyed this window.
// try to recover by grabbing the next window in line and activating
// that instead
if (gTopLevelWindows.IsEmpty())
return;
newTop = gTopLevelWindows[0];
}
- nsGUIEvent event(true, NS_ACTIVATE, newTop);
- DispatchEvent(&event);
+ if (mWidgetListener) {
+ mWidgetListener->WindowActivated();
+ }
// force a window resize
nsAppShell::gAppShell->ResendLastResizeEvent(newTop);
RedrawAll();
}
NS_IMETHODIMP
nsWindow::GetScreenBounds(nsIntRect &aRect)
@@ -959,70 +963,69 @@ nsWindow::DrawTo(gfxASurface *targetSurf
nsIntRect boundsRect(0, 0, mBounds.width, mBounds.height);
return DrawTo(targetSurface, boundsRect);
}
bool
nsWindow::DrawTo(gfxASurface *targetSurface, const nsIntRect &invalidRect)
{
mozilla::layers::RenderTraceScope trace("DrawTo", "717171");
- if (!mIsVisible)
+ if (!mIsVisible || !mWidgetListener)
return false;
nsRefPtr<nsWindow> kungFuDeathGrip(this);
- nsEventStatus status;
nsIntRect boundsRect(0, 0, mBounds.width, mBounds.height);
// Figure out if any of our children cover this widget completely
PRInt32 coveringChildIndex = -1;
for (PRUint32 i = 0; i < mChildren.Length(); ++i) {
if (mChildren[i]->mBounds.IsEmpty())
continue;
if (mChildren[i]->mBounds.Contains(boundsRect)) {
coveringChildIndex = PRInt32(i);
}
}
// If we have no covering child, then we need to render this.
if (coveringChildIndex == -1) {
- nsPaintEvent event(true, NS_PAINT, this);
- event.region = invalidRect;
+ bool painted = false;
+ nsIntRegion region = invalidRect;
switch (GetLayerManager(nullptr)->GetBackendType()) {
case mozilla::layers::LAYERS_BASIC: {
nsRefPtr<gfxContext> ctx = new gfxContext(targetSurface);
{
mozilla::layers::RenderTraceScope trace2("Basic DrawTo", "727272");
AutoLayerManagerSetup
setupLayerManager(this, ctx, mozilla::layers::BUFFER_NONE);
- status = DispatchEvent(&event);
+ painted = mWidgetListener->PaintWindow(this, region, false, false);
}
// XXX uhh.. we can't just ignore this because we no longer have
// what we needed before, but let's keep drawing the children anyway?
#if 0
- if (status == nsEventStatus_eIgnore)
+ if (!painted)
return false;
#endif
// XXX if we got an ignore for the parent, do we still want to draw the children?
// We don't really have a good way not to...
break;
}
case mozilla::layers::LAYERS_OPENGL: {
static_cast<mozilla::layers::LayerManagerOGL*>(GetLayerManager(nullptr))->
SetClippingRegion(nsIntRegion(boundsRect));
- status = DispatchEvent(&event);
+ painted = mWidgetListener->PaintWindow(this, region, false, false);
break;
}
default:
NS_ERROR("Invalid layer manager");
}
// We had no covering child, so make sure we draw all the children,
@@ -1222,34 +1225,24 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
sview.EndDrawing();
}
}
void
nsWindow::OnSizeChanged(const gfxIntSize& aSize)
{
- int w = aSize.width;
- int h = aSize.height;
-
- ALOG("nsWindow: %p OnSizeChanged [%d %d]", (void*)this, w, h);
-
- nsRefPtr<nsWindow> kungFuDeathGrip(this);
- nsSizeEvent event(true, NS_SIZE, this);
- InitEvent(event);
+ ALOG("nsWindow: %p OnSizeChanged [%d %d]", (void*)this, aSize.width, aSize.height);
- nsIntRect wsz(0, 0, w, h);
- event.windowSize = &wsz;
- event.mWinWidth = w;
- event.mWinHeight = h;
+ mBounds.width = aSize.width;
+ mBounds.height = aSize.height;
- mBounds.width = w;
- mBounds.height = h;
-
- DispatchEvent(&event);
+ if (mWidgetListener) {
+ mWidgetListener->WindowResized(this, aSize.width, aSize.height);
+ }
}
void
nsWindow::InitEvent(nsGUIEvent& event, nsIntPoint* aPoint)
{
if (aPoint) {
event.refPoint.x = aPoint->x;
event.refPoint.y = aPoint->y;
--- a/widget/cocoa/nsChildView.h
+++ b/widget/cocoa/nsChildView.h
@@ -474,17 +474,19 @@ public:
PRUint32 aModifierFlags);
virtual nsresult SynthesizeNativeMouseMove(nsIntPoint aPoint)
{ return SynthesizeNativeMouseEvent(aPoint, NSMouseMoved, 0); }
// Mac specific methods
virtual bool DispatchWindowEvent(nsGUIEvent& event);
-
+
+ bool PaintWindow(nsIntRegion aRegion);
+
#ifdef ACCESSIBILITY
already_AddRefed<Accessible> GetDocumentAccessible();
#endif
virtual void CreateCompositor();
virtual gfxASurface* GetThebesSurface();
virtual void DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect);
@@ -514,18 +516,18 @@ public:
mozilla::widget::TextInputHandler* GetTextInputHandler()
{
return mTextInputHandler;
}
protected:
- bool ReportMoveEvent();
- bool ReportSizeEvent();
+ void ReportMoveEvent();
+ void ReportSizeEvent();
// override to create different kinds of child views. Autoreleases, so
// caller must retain.
virtual NSView* CreateCocoaView(NSRect inFrame);
void TearDownView();
virtual already_AddRefed<nsIWidget>
AllocateChildPopupWidget()
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -26,16 +26,17 @@
#include "nsIViewManager.h"
#include "nsIInterfaceRequestor.h"
#include "nsIFile.h"
#include "nsILocalFileMac.h"
#include "nsGfxCIID.h"
#include "nsIDOMSimpleGestureEvent.h"
#include "nsNPAPIPluginInstance.h"
#include "nsThemeConstants.h"
+#include "nsIWidgetListener.h"
#include "nsDragService.h"
#include "nsClipboard.h"
#include "nsCursorManager.h"
#include "nsWindowMap.h"
#include "nsCocoaFeatures.h"
#include "nsCocoaUtils.h"
#include "nsMenuUtilsX.h"
@@ -1461,62 +1462,76 @@ NS_IMETHODIMP nsChildView::DispatchEvent
aStatus = nsEventStatus_eIgnore;
nsCOMPtr<nsIWidget> kungFuDeathGrip = do_QueryInterface(mParentWidget ? mParentWidget : this);
if (mParentWidget) {
nsWindowType type;
mParentWidget->GetWindowType(type);
if (type == eWindowType_popup) {
- // use the parent popup's widget if there is no view
- void* clientData = nullptr;
+ // use the parent popup's widget if there is no listener
+ nsIWidgetListener* listener = nullptr;
if (event->widget)
- event->widget->GetClientData(clientData);
- if (!clientData)
+ listener = event->widget->GetWidgetListener();
+ if (!listener)
event->widget = mParentWidget;
}
}
- bool restoreIsDispatchPaint = mIsDispatchPaint;
- mIsDispatchPaint = mIsDispatchPaint || event->eventStructType == NS_PAINT_EVENT;
-
if (mEventCallback)
aStatus = (*mEventCallback)(event);
- mIsDispatchPaint = restoreIsDispatchPaint;
-
return NS_OK;
}
bool nsChildView::DispatchWindowEvent(nsGUIEvent &event)
{
nsEventStatus status;
DispatchEvent(&event, status);
return ConvertStatus(status);
}
+bool nsChildView::PaintWindow(nsIntRegion aRegion)
+{
+ nsIWidget* widget = this;
+ nsIWidgetListener* listener = mWidgetListener;
+
+ // If there is no listener, use the parent popup's listener if that exists.
+ if (!listener && mParentWidget) {
+ nsWindowType type;
+ mParentWidget->GetWindowType(type);
+ if (type == eWindowType_popup) {
+ widget = mParentWidget;
+ listener = mParentWidget->GetWidgetListener();
+ }
+ }
+
+ if (!listener)
+ return false;
+
+ bool returnValue = false;
+ bool oldDispatchPaint = mIsDispatchPaint;
+ mIsDispatchPaint = true;
+ returnValue = listener->PaintWindow(widget, aRegion, true, false);
+ mIsDispatchPaint = oldDispatchPaint;
+ return returnValue;
+}
+
#pragma mark -
-bool nsChildView::ReportMoveEvent()
-{
- nsGUIEvent moveEvent(true, NS_MOVE, this);
- moveEvent.refPoint.x = mBounds.x;
- moveEvent.refPoint.y = mBounds.y;
- moveEvent.time = PR_IntervalNow();
- return DispatchWindowEvent(moveEvent);
-}
-
-bool nsChildView::ReportSizeEvent()
-{
- nsSizeEvent sizeEvent(true, NS_SIZE, this);
- sizeEvent.time = PR_IntervalNow();
- sizeEvent.windowSize = &mBounds;
- sizeEvent.mWinWidth = mBounds.width;
- sizeEvent.mWinHeight = mBounds.height;
- return DispatchWindowEvent(sizeEvent);
+void nsChildView::ReportMoveEvent()
+{
+ if (mWidgetListener)
+ mWidgetListener->WindowMoved(this, mBounds.x, mBounds.y);
+}
+
+void nsChildView::ReportSizeEvent()
+{
+ if (mWidgetListener)
+ mWidgetListener->WindowResized(this, mBounds.width, mBounds.height);
}
#pragma mark -
// Return the offset between this child view and the screen.
// @return -- widget origin in screen coordinates
nsIntPoint nsChildView::WidgetToScreenOffset()
{
@@ -2488,69 +2503,65 @@ NSEvent* gLastDragMouseDownEvent = nil;
fprintf (stderr, "---- Update[%p][%p] [%f %f %f %f] cgc: %p\n gecko bounds: [%d %d %d %d]\n",
self, mGeckoChild,
aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height, aContext,
geckoBounds.x, geckoBounds.y, geckoBounds.width, geckoBounds.height);
CGAffineTransform xform = CGContextGetCTM(aContext);
fprintf (stderr, " xform in: [%f %f %f %f %f %f]\n", xform.a, xform.b, xform.c, xform.d, xform.tx, xform.ty);
#endif
- // Create the event so we can fill in its region
- nsPaintEvent paintEvent(true, NS_PAINT, mGeckoChild);
- paintEvent.didSendWillPaint = true;
+ nsIntRegion region;
nsIntRect boundingRect =
nsIntRect(aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height);
const NSRect *rects;
NSInteger count, i;
[[NSView focusView] getRectsBeingDrawn:&rects count:&count];
if (count < MAX_RECTS_IN_REGION) {
for (i = 0; i < count; ++i) {
// Add the rect to the region.
const NSRect& r = [self convertRect:rects[i] fromView:[NSView focusView]];
- paintEvent.region.Or(paintEvent.region,
- nsIntRect(r.origin.x, r.origin.y, r.size.width, r.size.height));
+ region.Or(region, nsIntRect(r.origin.x, r.origin.y, r.size.width, r.size.height));
}
- paintEvent.region.And(paintEvent.region, boundingRect);
+ region.And(region, boundingRect);
} else {
- paintEvent.region = boundingRect;
+ region = boundingRect;
}
#ifndef NP_NO_QUICKDRAW
// Subtract quickdraw plugin rectangles from the region
NSArray* subviews = [self subviews];
for (int i = 0; i < int([subviews count]); ++i) {
NSView* view = [subviews objectAtIndex:i];
if (![view isKindOfClass:[ChildView class]] || [view isHidden])
continue;
ChildView* cview = (ChildView*) view;
if ([cview isPluginView] && [cview pluginDrawingModel] == NPDrawingModelQuickDraw) {
NSRect frame = [view frame];
- paintEvent.region.Sub(paintEvent.region,
- nsIntRect(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height));
+ region.Sub(region, nsIntRect(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height));
}
}
#endif
LayerManager *layerManager = mGeckoChild->GetLayerManager(nullptr);
if (layerManager->GetBackendType() == mozilla::layers::LAYERS_OPENGL) {
NSOpenGLContext *glContext;
LayerManagerOGL *manager = static_cast<LayerManagerOGL*>(layerManager);
- manager->SetClippingRegion(paintEvent.region);
+ manager->SetClippingRegion(region);
glContext = (NSOpenGLContext *)manager->gl()->GetNativeData(mozilla::gl::GLContext::NativeGLContext);
if (!mGLContext) {
[self setGLContext:glContext];
}
[glContext setView:self];
[glContext update];
- mGeckoChild->DispatchWindowEvent(paintEvent);
+ mGeckoChild->PaintWindow(region);
// Force OpenGL to refresh the very first time we draw. This works around a
// Mac OS X bug that stops windows updating on OS X when we use OpenGL.
if (!mDidForceRefreshOpenGL) {
[self performSelector:@selector(forceRefreshOpenGL) withObject:nil afterDelay:0];
mDidForceRefreshOpenGL = YES;
}
@@ -2561,32 +2572,32 @@ NSEvent* gLastDragMouseDownEvent = nil;
NSSize bufferSize = [self bounds].size;
nsRefPtr<gfxQuartzSurface> targetSurface =
new gfxQuartzSurface(aContext, gfxSize(bufferSize.width, bufferSize.height));
targetSurface->SetAllowUseAsSource(false);
nsRefPtr<gfxContext> targetContext = new gfxContext(targetSurface);
// Set up the clip region.
- nsIntRegionRectIterator iter(paintEvent.region);
+ nsIntRegionRectIterator iter(region);
targetContext->NewPath();
for (;;) {
const nsIntRect* r = iter.Next();
if (!r)
break;
targetContext->Rectangle(gfxRect(r->x, r->y, r->width, r->height));
}
targetContext->Clip();
nsAutoRetainCocoaObject kungFuDeathGrip(self);
bool painted;
{
nsBaseWidget::AutoLayerManagerSetup
setupLayerManager(mGeckoChild, targetContext, BUFFER_NONE);
- painted = mGeckoChild->DispatchWindowEvent(paintEvent);
+ painted = mGeckoChild->PaintWindow(region);
}
// Force OpenGL to refresh the very first time we draw. This works around a
// Mac OS X bug that stops windows updating on OS X when we use OpenGL.
if (painted && !mDidForceRefreshOpenGL &&
layerManager->AsShadowManager() && mUsingOMTCompositor) {
if (!mDidForceRefreshOpenGL) {
[self performSelector:@selector(forceRefreshOpenGL) withObject:nil afterDelay:0];
@@ -2636,17 +2647,17 @@ NSEvent* gLastDragMouseDownEvent = nil;
}
}
- (void)viewWillDraw
{
if (mGeckoChild) {
// The OS normally *will* draw our NSWindow, no matter what we do here.
// But Gecko can delete our parent widget(s) (along with mGeckoChild)
- // while processing an NS_WILL_PAINT event, which closes our NSWindow and
+ // while processing a paint request, which closes our NSWindow and
// makes the OS throw an NSInternalInconsistencyException assertion when
// it tries to draw it. Sometimes the OS also aborts the browser process.
// So we need to retain our parent(s) here and not release it/them until
// the next time through the main thread's run loop. When we do this we
// also need to retain and release mGeckoChild, which holds a strong
// reference to us (otherwise we might have been deleted by the time
// releaseWidgets: is called on us). See bug 550392.
nsIWidget* parent = mGeckoChild->GetParent();
@@ -2658,18 +2669,21 @@ NSEvent* gLastDragMouseDownEvent = nil;
parent = parent->GetParent();
}
NS_ADDREF(mGeckoChild);
[widgetArray addObject:[NSNumber numberWithUnsignedInteger:(NSUInteger)mGeckoChild]];
[self performSelector:@selector(releaseWidgets:)
withObject:widgetArray
afterDelay:0];
}
- nsPaintEvent paintEvent(true, NS_WILL_PAINT, mGeckoChild);
- mGeckoChild->DispatchWindowEvent(paintEvent);
+
+ nsIWidgetListener* listener = mGeckoChild->GetWidgetListener();
+ if (listener) {
+ listener->WillPaintWindow(mGeckoChild, false);
+ }
}
[super viewWillDraw];
}
// Allows us to turn off setting up the clip region
// before each drawRect. We already clip within gecko.
- (BOOL)wantsDefaultClipping
{
@@ -4283,32 +4297,36 @@ static PRInt32 RoundUp(double aDouble)
// check to see if the window implements the mozWindow protocol. This
// allows embedders to avoid re-entrant calls to -makeKeyAndOrderFront,
// which can happen because these activate calls propagate out
// to the embedder via nsIEmbeddingSiteWindow::SetFocus().
BOOL isMozWindow = [[self window] respondsToSelector:@selector(setSuppressMakeKeyFront:)];
if (isMozWindow)
[[self window] setSuppressMakeKeyFront:YES];
- [self sendFocusEvent:NS_ACTIVATE];
+ nsIWidgetListener* listener = mGeckoChild->GetWidgetListener();
+ if (listener)
+ listener->WindowActivated();
if (isMozWindow)
[[self window] setSuppressMakeKeyFront:NO];
NS_OBJC_END_TRY_ABORT_BLOCK;
}
- (void)viewsWindowDidResignKey
{
if (!mGeckoChild)
return;
nsAutoRetainCocoaObject kungFuDeathGrip(self);
- [self sendFocusEvent:NS_DEACTIVATE];
+ nsIWidgetListener* listener = mGeckoChild->GetWidgetListener();
+ if (listener)
+ listener->WindowDeactivated();
}
// If the call to removeFromSuperview isn't delayed from nsChildView::
// TearDownView(), the NSView hierarchy might get changed during calls to
// [ChildView drawRect:], which leads to "beyond bounds" exceptions in
// NSCFArray. For more info see bmo bug 373122. Apple's docs claim that
// removeFromSuperviewWithoutNeedingDisplay "can be safely invoked during
// display" (whatever "display" means). But it's _not_ true that it can be
--- a/widget/cocoa/nsCocoaWindow.h
+++ b/widget/cocoa/nsCocoaWindow.h
@@ -146,17 +146,16 @@ typedef struct _nsCocoaWindowList {
// NS_DEACTIVATE to Gecko for toplevel widgets. Starts out
// false.
bool mToplevelActiveState;
BOOL mHasEverBeenZoomed;
}
+ (void)paintMenubarForWindow:(NSWindow*)aWindow;
- (id)initWithGeckoWindow:(nsCocoaWindow*)geckoWind;
- (void)windowDidResize:(NSNotification*)aNotification;
-- (void)sendFocusEvent:(PRUint32)eventType;
- (nsCocoaWindow*)geckoWidget;
- (bool)toplevelActiveState;
- (void)sendToplevelActivateEvents;
- (void)sendToplevelDeactivateEvents;
@end
@class ToolbarWindow;
--- a/widget/cocoa/nsCocoaWindow.mm
+++ b/widget/cocoa/nsCocoaWindow.mm
@@ -24,16 +24,17 @@
#include "nsThreadUtils.h"
#include "nsMenuBarX.h"
#include "nsMenuUtilsX.h"
#include "nsStyleConsts.h"
#include "nsNativeThemeColors.h"
#include "nsChildView.h"
#include "nsCocoaFeatures.h"
#include "nsIScreenManager.h"
+#include "nsIWidgetListener.h"
#include "gfxPlatform.h"
#include "qcms.h"
#include "mozilla/Preferences.h"
namespace mozilla {
namespace layers {
@@ -1402,27 +1403,20 @@ NS_IMETHODIMP nsCocoaWindow::Invalidate(
// knows about it.
bool nsCocoaWindow::DragEvent(unsigned int aMessage, Point aMouseGlobal, UInt16 aKeyModifiers)
{
return false;
}
NS_IMETHODIMP nsCocoaWindow::SendSetZLevelEvent()
{
- nsZLevelEvent event(true, NS_SETZLEVEL, this);
-
- event.refPoint.x = mBounds.x;
- event.refPoint.y = mBounds.y;
- event.time = PR_IntervalNow();
-
- event.mImmediate = true;
-
- nsEventStatus status = nsEventStatus_eIgnore;
- DispatchEvent(&event, status);
-
+ nsWindowZ placement = nsWindowZTop;
+ nsIWidget* actualBelow;
+ if (mWidgetListener)
+ mWidgetListener->ZLevelChanged(true, &placement, nullptr, &actualBelow);
return NS_OK;
}
NS_IMETHODIMP nsCocoaWindow::GetChildSheet(bool aShown, nsCocoaWindow** _retval)
{
nsIWidget* child = GetFirstChild();
while (child) {
@@ -1512,22 +1506,18 @@ nsCocoaWindow::ReportMoveEvent()
if (mInReportMoveEvent) {
return;
}
mInReportMoveEvent = true;
UpdateBounds();
// Dispatch the move event to Gecko
- nsGUIEvent guiEvent(true, NS_MOVE, this);
- guiEvent.refPoint.x = mBounds.x;
- guiEvent.refPoint.y = mBounds.y;
- guiEvent.time = PR_IntervalNow();
- nsEventStatus status = nsEventStatus_eIgnore;
- DispatchEvent(&guiEvent, status);
+ if (mWidgetListener)
+ mWidgetListener->WindowMoved(this, mBounds.x, mBounds.y);
mInReportMoveEvent = false;
NS_OBJC_END_TRY_ABORT_BLOCK;
}
void
nsCocoaWindow::DispatchSizeModeEvent()
@@ -1541,42 +1531,33 @@ nsCocoaWindow::DispatchSizeModeEvent()
// Don't dispatch a sizemode event if:
// 1. the window is transitioning to fullscreen
// 2. the new sizemode is the same as the current sizemode
if (mInFullScreenTransition || mSizeMode == newMode) {
return;
}
mSizeMode = newMode;
- nsSizeModeEvent event(true, NS_SIZEMODE, this);
- event.mSizeMode = mSizeMode;
- event.time = PR_IntervalNow();
-
- nsEventStatus status = nsEventStatus_eIgnore;
- DispatchEvent(&event, status);
+ if (mWidgetListener) {
+ mWidgetListener->SizeModeChanged(newMode);
+ }
}
void
nsCocoaWindow::ReportSizeEvent()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
UpdateBounds();
- nsSizeEvent sizeEvent(true, NS_SIZE, this);
- sizeEvent.time = PR_IntervalNow();
-
- nsIntRect innerBounds;
- GetClientBounds(innerBounds);
- sizeEvent.windowSize = &innerBounds;
- sizeEvent.mWinWidth = mBounds.width;
- sizeEvent.mWinHeight = mBounds.height;
-
- nsEventStatus status = nsEventStatus_eIgnore;
- DispatchEvent(&sizeEvent, status);
+ if (mWidgetListener) {
+ nsIntRect innerBounds;
+ GetClientBounds(innerBounds);
+ mWidgetListener->WindowResized(this, innerBounds.width, innerBounds.height);
+ }
NS_OBJC_END_TRY_ABORT_BLOCK;
}
void nsCocoaWindow::SetMenuBar(nsMenuBarX *aMenuBar)
{
if (mMenuBar)
mMenuBar->SetParent(nullptr);
@@ -2131,21 +2112,19 @@ bool nsCocoaWindow::ShouldFocusPlugin()
- (void)windowDidMove:(NSNotification *)aNotification
{
if (mGeckoWindow)
mGeckoWindow->ReportMoveEvent();
}
- (BOOL)windowShouldClose:(id)sender
{
- // We only want to send NS_XUL_CLOSE and let gecko close the window
- nsGUIEvent guiEvent(true, NS_XUL_CLOSE, mGeckoWindow);
- guiEvent.time = PR_IntervalNow();
- nsEventStatus status = nsEventStatus_eIgnore;
- mGeckoWindow->DispatchEvent(&guiEvent, status);
+ nsIWidgetListener* listener = mGeckoWindow ? mGeckoWindow->GetWidgetListener() : nullptr;
+ if (listener)
+ listener->RequestWindowClose(mGeckoWindow);
return NO; // gecko will do it
}
- (void)windowWillClose:(NSNotification *)aNotification
{
RollUpPopups();
}
@@ -2170,27 +2149,16 @@ bool nsCocoaWindow::ShouldFocusPlugin()
{
if (!mHasEverBeenZoomed && [window isZoomed])
return NO; // See bug 429954.
mHasEverBeenZoomed = YES;
return YES;
}
-- (void)sendFocusEvent:(PRUint32)eventType
-{
- if (!mGeckoWindow)
- return;
-
- nsEventStatus status = nsEventStatus_eIgnore;
- nsGUIEvent focusGuiEvent(true, eventType, mGeckoWindow);
- focusGuiEvent.time = PR_IntervalNow();
- mGeckoWindow->DispatchEvent(&focusGuiEvent, status);
-}
-
- (void)didEndSheet:(NSWindow*)sheet returnCode:(int)returnCode contextInfo:(void*)contextInfo
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
// Note: 'contextInfo' (if it is set) is the window that is the parent of
// the sheet. The value of contextInfo is determined in
// nsCocoaWindow::Show(). If it's set, 'contextInfo' is always the top-
// level window, not another sheet itself. But 'contextInfo' is nil if
@@ -2212,26 +2180,30 @@ bool nsCocoaWindow::ShouldFocusPlugin()
- (bool)toplevelActiveState
{
return mToplevelActiveState;
}
- (void)sendToplevelActivateEvents
{
- if (!mToplevelActiveState) {
- [self sendFocusEvent:NS_ACTIVATE];
+ if (!mToplevelActiveState && mGeckoWindow) {
+ nsIWidgetListener* listener = mGeckoWindow->GetWidgetListener();
+ if (listener)
+ listener->WindowActivated();
mToplevelActiveState = true;
}
}
- (void)sendToplevelDeactivateEvents
{
- if (mToplevelActiveState) {
- [self sendFocusEvent:NS_DEACTIVATE];
+ if (mToplevelActiveState && mGeckoWindow) {
+ nsIWidgetListener* listener = mGeckoWindow->GetWidgetListener();
+ if (listener)
+ listener->WindowDeactivated();
mToplevelActiveState = false;
}
}
@end
static float
GetDPI(NSWindow* aWindow)
@@ -2672,20 +2644,20 @@ static const NSString* kStateShowsToolba
RollUpPopups();
if ([[self delegate] isKindOfClass:[WindowDelegate class]]) {
WindowDelegate *windowDelegate = (WindowDelegate *)[self delegate];
nsCocoaWindow *geckoWindow = [windowDelegate geckoWidget];
if (!geckoWindow)
return;
- nsEventStatus status = nsEventStatus_eIgnore;
- nsGUIEvent guiEvent(true, NS_OS_TOOLBAR, geckoWindow);
- guiEvent.time = PR_IntervalNow();
- geckoWindow->DispatchEvent(&guiEvent, status);
+
+ nsIWidgetListener* listener = geckoWindow->GetWidgetListener();
+ if (listener)
+ listener->OSToolbarButtonPressed();
}
NS_OBJC_END_TRY_ABORT_BLOCK;
}
// Retain and release "self" to avoid crashes when our widget (and its native
// window) is closed as a result of processing a key equivalent (e.g.
// Command+w or Command+q). This workaround is only needed for a window
--- a/widget/gonk/nsWindow.cpp
+++ b/widget/gonk/nsWindow.cpp
@@ -29,16 +29,17 @@
#include "GLContextProvider.h"
#include "LayerManagerOGL.h"
#include "nsAutoPtr.h"
#include "nsAppShell.h"
#include "nsIdleService.h"
#include "nsScreenManagerGonk.h"
#include "nsTArray.h"
#include "nsWindow.h"
+#include "nsIWidgetListener.h"
#include "cutils/properties.h"
#include "BasicLayers.h"
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
#define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "Gonk", ## args)
#define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "Gonk", ## args)
#define IS_TOPLEVEL() (mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog)
@@ -100,26 +101,22 @@ EffectiveScreenRotation()
class ScreenOnOffEvent : public nsRunnable {
public:
ScreenOnOffEvent(bool on)
: mIsOn(on)
{}
NS_IMETHOD Run() {
- nsSizeModeEvent event(true, NS_SIZEMODE, NULL);
- nsEventStatus status;
-
- event.time = PR_Now() / 1000;
- event.mSizeMode = mIsOn ? nsSizeMode_Fullscreen : nsSizeMode_Minimized;
-
for (PRUint32 i = 0; i < sTopWindows.Length(); i++) {
nsWindow *win = sTopWindows[i];
- event.widget = win;
- win->DispatchEvent(&event, status);
+
+ if (nsIWidgetListener* listener = win->GetWidgetListener()) {
+ listener->SizeModeChanged(mIsOn ? nsSizeMode_Fullscreen : nsSizeMode_Minimized);
+ }
}
return NS_OK;
}
private:
bool mIsOn;
};
@@ -231,50 +228,53 @@ nsWindow::DoDraw(void)
return;
}
if (!gWindowToRedraw) {
LOG(" no window to draw, bailing");
return;
}
- nsPaintEvent event(true, NS_PAINT, gWindowToRedraw);
- event.region = gWindowToRedraw->mDirtyRegion;
+ nsIntRegion region = gWindowToRedraw->mDirtyRegion;
gWindowToRedraw->mDirtyRegion.SetEmpty();
LayerManager* lm = gWindowToRedraw->GetLayerManager();
if (mozilla::layers::LAYERS_OPENGL == lm->GetBackendType()) {
LayerManagerOGL* oglm = static_cast<LayerManagerOGL*>(lm);
- oglm->SetClippingRegion(event.region);
+ oglm->SetClippingRegion(region);
oglm->SetWorldTransform(sRotationMatrix);
- gWindowToRedraw->mEventCallback(&event);
+
+ if (nsIWidgetListener* listener = gWindowToRedraw->GetWidgetListener())
+ listener->PaintWindow(gWindowToRedraw, region, false, false);
} else if (mozilla::layers::LAYERS_BASIC == lm->GetBackendType()) {
MOZ_ASSERT(sFramebufferOpen || sUsingOMTC);
nsRefPtr<gfxASurface> targetSurface;
if(sUsingOMTC)
targetSurface = sOMTCSurface;
else
targetSurface = Framebuffer::BackBuffer();
{
nsRefPtr<gfxContext> ctx = new gfxContext(targetSurface);
- gfxUtils::PathFromRegion(ctx, event.region);
+ gfxUtils::PathFromRegion(ctx, region);
ctx->Clip();
// No double-buffering needed.
AutoLayerManagerSetup setupLayerManager(
gWindowToRedraw, ctx, mozilla::layers::BUFFER_NONE,
ScreenRotation(EffectiveScreenRotation()));
- gWindowToRedraw->mEventCallback(&event);
+
+ if (nsIWidgetListener* listener = gWindowToRedraw->GetWidgetListener())
+ listener->PaintWindow(gWindowToRedraw, region, false, false);
}
if (!sUsingOMTC) {
targetSurface->Flush();
- Framebuffer::Present(event.region);
+ Framebuffer::Present(region);
}
} else {
NS_RUNTIMEABORT("Unexpected layer manager type");
}
}
nsEventStatus
nsWindow::DispatchInputEvent(nsGUIEvent &aEvent)
@@ -388,26 +388,19 @@ nsWindow::Resize(PRInt32 aWidth,
NS_IMETHODIMP
nsWindow::Resize(PRInt32 aX,
PRInt32 aY,
PRInt32 aWidth,
PRInt32 aHeight,
bool aRepaint)
{
- nsSizeEvent event(true, NS_SIZE, this);
- event.time = PR_Now() / 1000;
-
- nsIntRect rect(aX, aY, aWidth, aHeight);
- mBounds = rect;
- event.windowSize = ▭
- event.mWinWidth = sVirtualBounds.width;
- event.mWinHeight = sVirtualBounds.height;
-
- (*mEventCallback)(&event);
+ mBounds = nsIntRect(aX, aY, aWidth, aHeight);
+ if (mWidgetListener)
+ mWidgetListener->WindowResized(this, aWidth, aHeight);
if (aRepaint && gWindowToRedraw)
gWindowToRedraw->Invalidate(sVirtualBounds);
return NS_OK;
}
NS_IMETHODIMP
@@ -619,25 +612,25 @@ nsWindow::GetThebesSurface()
// on direct assignment to a gfxASurface
return new gfxImageSurface(gfxIntSize(5,5), gfxImageSurface::ImageFormatRGB24);
}
void
nsWindow::BringToTop()
{
if (!sTopWindows.IsEmpty()) {
- nsGUIEvent event(true, NS_DEACTIVATE, sTopWindows[0]);
- (*mEventCallback)(&event);
+ if (nsIWidgetListener* listener = sTopWindows[0]->GetWidgetListener())
+ listener->WindowDeactivated();
}
sTopWindows.RemoveElement(this);
sTopWindows.InsertElementAt(0, this);
- nsGUIEvent event(true, NS_ACTIVATE, this);
- (*mEventCallback)(&event);
+ if (mWidgetListener)
+ mWidgetListener->WindowActivated();
Invalidate(sVirtualBounds);
}
void
nsWindow::UserActivity()
{
if (!mIdleService) {
mIdleService = do_GetService("@mozilla.org/widget/idleservice;1");
--- a/widget/gtk2/nsWindow.cpp
+++ b/widget/gtk2/nsWindow.cpp
@@ -15,16 +15,17 @@
#include "prlink.h"
#include "nsWindow.h"
#include "nsGTKToolkit.h"
#include "nsIRollupListener.h"
#include "nsIDOMNode.h"
#include "nsWidgetsCID.h"
#include "nsDragService.h"
+#include "nsIWidgetListener.h"
#include "nsGtkKeyUtils.h"
#include "nsGtkCursors.h"
#include <gtk/gtk.h>
#if defined(MOZ_WIDGET_GTK3)
#include <gtk/gtkx.h>
#endif
@@ -415,50 +416,34 @@ void
nsWindow::CommonCreate(nsIWidget *aParent, bool aListenForResizes)
{
mParent = aParent;
mListenForResizes = aListenForResizes;
mCreated = true;
}
void
-nsWindow::DispatchResizeEvent(nsIntRect &aRect, nsEventStatus &aStatus)
-{
- nsSizeEvent event(true, NS_SIZE, this);
-
- event.windowSize = &aRect;
- event.refPoint.x = aRect.x;
- event.refPoint.y = aRect.y;
- event.mWinWidth = aRect.width;
- event.mWinHeight = aRect.height;
-
- nsEventStatus status;
- DispatchEvent(&event, status);
-}
-
-void
nsWindow::DispatchActivateEvent(void)
{
NS_ASSERTION(mContainer || mIsDestroyed,
"DispatchActivateEvent only intended for container windows");
#ifdef ACCESSIBILITY
DispatchActivateEventAccessible();
#endif //ACCESSIBILITY
- nsGUIEvent event(true, NS_ACTIVATE, this);
- nsEventStatus status;
- DispatchEvent(&event, status);
+
+ if (mWidgetListener)
+ mWidgetListener->WindowActivated();
}
void
nsWindow::DispatchDeactivateEvent(void)
{
- nsGUIEvent event(true, NS_DEACTIVATE, this);
- nsEventStatus status;
- DispatchEvent(&event, status);
+ if (mWidgetListener)
+ mWidgetListener->WindowDeactivated();
#ifdef ACCESSIBILITY
DispatchDeactivateEventAccessible();
#endif //ACCESSIBILITY
}
@@ -1079,21 +1064,20 @@ nsWindow::Resize(PRInt32 aWidth, PRInt32
}
else {
mNeedsResize = true;
}
}
NotifyRollupGeometryChange(gRollupListener);
- // synthesize a resize event if this isn't a toplevel
+ // send a resize notification if this is a toplevel
if (mIsTopLevel || mListenForResizes) {
- nsIntRect rect(mBounds.x, mBounds.y, aWidth, aHeight);
- nsEventStatus status;
- DispatchResizeEvent(rect, status);
+ if (mWidgetListener)
+ mWidgetListener->WindowResized(this, aWidth, aHeight);
}
return NS_OK;
}
NS_IMETHODIMP
nsWindow::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight,
bool aRepaint)
@@ -1148,20 +1132,18 @@ nsWindow::Resize(PRInt32 aX, PRInt32 aY,
else {
mNeedsResize = true;
}
}
NotifyRollupGeometryChange(gRollupListener);
if (mIsTopLevel || mListenForResizes) {
- // synthesize a resize event
- nsIntRect rect(aX, aY, aWidth, aHeight);
- nsEventStatus status;
- DispatchResizeEvent(rect, status);
+ if (mWidgetListener)
+ mWidgetListener->WindowResized(this, aWidth, aHeight);
}
return NS_OK;
}
NS_IMETHODIMP
nsWindow::Enable(bool aState)
{
@@ -1448,17 +1430,17 @@ nsWindow::SetFocus(bool aRaise)
// Ensure owningWidget is the focused GtkWidget within its toplevel window.
//
// For eWindowType_popup, this GtkWidget may not actually be the one that
// receives the key events as it may be the parent window that is active.
if (!gtk_widget_is_focus(owningWidget)) {
// This is synchronous. It takes focus from a plugin or from a widget
// in an embedder. The focus manager already knows that this window
// is active so gBlockActivateEvent avoids another (unnecessary)
- // NS_ACTIVATE event.
+ // activate notification.
gBlockActivateEvent = true;
gtk_widget_grab_focus(owningWidget);
gBlockActivateEvent = false;
}
// If this is the widget that already has focus, return.
if (gFocusWindow == this) {
LOGFOCUS((" already have focus [%p]\n", (void *)this));
@@ -2016,57 +1998,44 @@ gdk_window_flash(GdkWindow * aGdkWind
gdk_gc_destroy(gc);
gdk_region_offset(aRegion, -x, -y);
}
#endif /* MOZ_X11 */
#endif // DEBUG
#endif
-static void
-DispatchDidPaint(nsIWidget* aWidget)
-{
- nsEventStatus status;
- nsPaintEvent didPaintEvent(true, NS_DID_PAINT, aWidget);
- aWidget->DispatchEvent(&didPaintEvent, status);
-}
-
#if defined(MOZ_WIDGET_GTK2)
gboolean
nsWindow::OnExposeEvent(GdkEventExpose *aEvent)
#else
gboolean
nsWindow::OnExposeEvent(cairo_t *cr)
#endif
{
if (mIsDestroyed) {
return FALSE;
}
// Windows that are not visible will be painted after they become visible.
if (!mGdkWindow || mIsFullyObscured || !mHasMappedToplevel)
return FALSE;
- // Dispatch WILL_PAINT to allow scripts etc. to run before we
- // dispatch PAINT
+ // Dispatch WillPaintWindow notification to allow scripts etc. to run
+ // before we paint
{
- nsEventStatus status;
- nsPaintEvent willPaintEvent(true, NS_WILL_PAINT, this);
- willPaintEvent.willSendDidPaint = true;
- DispatchEvent(&willPaintEvent, status);
-
- // If the window has been destroyed during WILL_PAINT, there is
- // nothing left to do.
+ if (mWidgetListener)
+ mWidgetListener->WillPaintWindow(this, true);
+
+ // If the window has been destroyed during the will paint notification,
+ // there is nothing left to do.
if (!mGdkWindow)
return TRUE;
}
- nsPaintEvent event(true, NS_PAINT, this);
- event.willSendDidPaint = true;
-
#if defined(MOZ_WIDGET_GTK2)
GdkRectangle *rects;
gint nrects;
gdk_region_get_rectangles(aEvent->region, &rects, &nrects);
if (NS_UNLIKELY(!rects)) // OOM
return FALSE;
#else
#ifdef cairo_copy_clip_rectangle_list
@@ -2088,57 +2057,58 @@ nsWindow::OnExposeEvent(cairo_t *cr)
rects[0] = aEvent->area;
nrects = 1;
}
#endif
LOGDRAW(("sending expose event [%p] %p 0x%lx (rects follow):\n",
(void *)this, (void *)mGdkWindow,
gdk_x11_window_get_xid(mGdkWindow)));
+
+ nsIntRegion region;
#if defined(MOZ_WIDGET_GTK2)
GdkRectangle *r = rects;
GdkRectangle *r_end = rects + nrects;
#else
cairo_rectangle_t *r = rects->rectangles;
cairo_rectangle_t *r_end = r + rects->num_rectangles;
#endif
for (; r < r_end; ++r) {
- event.region.Or(event.region, nsIntRect(r->x, r->y, r->width, r->height));
+ region.Or(region, nsIntRect(r->x, r->y, r->width, r->height));
LOGDRAW(("\t%d %d %d %d\n", r->x, r->y, r->width, r->height));
}
- // Our bounds may have changed after dispatching WILL_PAINT. Clip
- // to the new bounds here. The event region is relative to this
+ // Our bounds may have changed after calling WillPaintWindow. Clip
+ // to the new bounds here. The region is relative to this
// window.
- event.region.And(event.region,
- nsIntRect(0, 0, mBounds.width, mBounds.height));
+ region.And(region, nsIntRect(0, 0, mBounds.width, mBounds.height));
bool translucent = eTransparencyTransparent == GetTransparencyMode();
if (!translucent) {
GList *children =
gdk_window_peek_children(mGdkWindow);
while (children) {
GdkWindow *gdkWin = GDK_WINDOW(children->data);
nsWindow *kid = get_window_for_gdk_window(gdkWin);
if (kid && gdk_window_is_visible(gdkWin)) {
nsAutoTArray<nsIntRect,1> clipRects;
kid->GetWindowClipRegion(&clipRects);
nsIntRect bounds;
kid->GetBounds(bounds);
for (PRUint32 i = 0; i < clipRects.Length(); ++i) {
nsIntRect r = clipRects[i] + bounds.TopLeft();
- event.region.Sub(event.region, r);
+ region.Sub(region, r);
}
}
children = children->next;
}
}
- if (event.region.IsEmpty()) {
+ if (region.IsEmpty()) {
#if defined(MOZ_WIDGET_GTK2)
g_free(rects);
#else
cairo_rectangle_list_destroy(rects);
#endif
return TRUE;
}
// If this widget uses OMTC...
@@ -2146,34 +2116,38 @@ nsWindow::OnExposeEvent(cairo_t *cr)
nsEventStatus status;
#if defined(MOZ_WIDGET_GTK2)
nsRefPtr<gfxContext> ctx = new gfxContext(GetThebesSurface());
#else
nsRefPtr<gfxContext> ctx = new gfxContext(GetThebesSurface(cr));
#endif
nsBaseWidget::AutoLayerManagerSetup
setupLayerManager(this, ctx, mozilla::layers::BUFFER_NONE);
- DispatchEvent(&event, status);
+
+ if (mWidgetListener)
+ mWidgetListener->PaintWindow(this, region, true, true);
g_free(rects);
- DispatchDidPaint(this);
+ if (mWidgetListener)
+ mWidgetListener->DidPaintWindow();
return TRUE;
} else if (GetLayerManager()->GetBackendType() == mozilla::layers::LAYERS_OPENGL) {
LayerManagerOGL *manager = static_cast<LayerManagerOGL*>(GetLayerManager());
- manager->SetClippingRegion(event.region);
-
- nsEventStatus status;
- DispatchEvent(&event, status);
+ manager->SetClippingRegion(region);
+
+ if (mWidgetListener)
+ mWidgetListener->PaintWindow(this, region, true, true);
g_free(rects);
- DispatchDidPaint(this);
+ if (mWidgetListener)
+ mWidgetListener->DidPaintWindow();
return TRUE;
}
#if defined(MOZ_WIDGET_GTK2)
nsRefPtr<gfxContext> ctx = new gfxContext(GetThebesSurface());
#else
nsRefPtr<gfxContext> ctx = new gfxContext(GetThebesSurface(cr));
@@ -2183,21 +2157,21 @@ nsWindow::OnExposeEvent(cairo_t *cr)
nsIntRect boundsRect; // for translucent only
ctx->NewPath();
if (translucent) {
// Collapse update area to the bounding box. This is so we only have to
// call UpdateTranslucentWindowAlpha once. After we have dropped
// support for non-Thebes graphics, UpdateTranslucentWindowAlpha will be
// our private interface so we can rework things to avoid this.
- boundsRect = event.region.GetBounds();
+ boundsRect = region.GetBounds();
ctx->Rectangle(gfxRect(boundsRect.x, boundsRect.y,
boundsRect.width, boundsRect.height));
} else {
- gfxUtils::PathFromRegion(ctx, event.region);
+ gfxUtils::PathFromRegion(ctx, region);
}
ctx->Clip();
BufferMode layerBuffering;
if (translucent) {
// The double buffering is done here to extract the shape mask.
// (The shape mask won't be necessary when a visual with an alpha
// channel is used on compositing window managers.)
@@ -2221,28 +2195,30 @@ nsWindow::OnExposeEvent(cairo_t *cr)
// XXX aEvent->region may refer to a newly-invalid area. FIXME
if (0 && WANT_PAINT_FLASHING && gtk_widget_get_window(aEvent))
gdk_window_flash(mGdkWindow, 1, 100, aEvent->region);
#endif
#endif
#endif // MOZ_X11
- nsEventStatus status;
+ bool painted = false;
{
AutoLayerManagerSetup setupLayerManager(this, ctx, layerBuffering);
- DispatchEvent(&event, status);
+
+ if (mWidgetListener)
+ painted = mWidgetListener->PaintWindow(this, region, true, true);
}
#ifdef MOZ_X11
- // DispatchEvent can Destroy us (bug 378273), avoid doing any paint
+ // PaintWindow can Destroy us (bug 378273), avoid doing any paint
// operations below if that happened - it will lead to XError and exit().
if (translucent) {
if (NS_LIKELY(!mIsDestroyed)) {
- if (status != nsEventStatus_eIgnore) {
+ if (painted) {
nsRefPtr<gfxPattern> pattern = ctx->PopGroup();
nsRefPtr<gfxImageSurface> img =
new gfxImageSurface(gfxIntSize(boundsRect.width, boundsRect.height),
gfxImageSurface::ImageFormatA8);
if (img && !img->CairoStatus()) {
img->SetDeviceOffset(gfxPoint(-boundsRect.x, -boundsRect.y));
@@ -2276,17 +2252,18 @@ nsWindow::OnExposeEvent(cairo_t *cr)
#endif // MOZ_X11
#if defined(MOZ_WIDGET_GTK2)
g_free(rects);
#else
cairo_rectangle_list_destroy(rects);
#endif
- DispatchDidPaint(this);
+ if (mWidgetListener)
+ mWidgetListener->DidPaintWindow();
// Synchronously flush any new dirty areas
#if defined(MOZ_WIDGET_GTK2)
GdkRegion* dirtyArea = gdk_window_get_update_area(mGdkWindow);
#else
cairo_region_t* dirtyArea = gdk_window_get_update_area(mGdkWindow);
#endif
@@ -2352,33 +2329,29 @@ nsWindow::OnConfigureEvent(GtkWidget *aW
// Override-redirect window
//
// These windows should not be moved by the window manager, and so any
// change in position is a result of our direction. mBounds has
// already been set in Move() or Resize(), and that is more
// up-to-date than the position in the ConfigureNotify event if the
// event is from an earlier window move.
//
- // Skipping the NS_MOVE dispatch saves context menus from an infinite
+ // Skipping the WindowMoved call saves context menus from an infinite
// loop when nsXULPopupManager::PopupMoved moves the window to the new
// position and nsMenuPopupFrame::SetPopupPosition adds
// offsetForContextMenu on each iteration.
return FALSE;
}
mBounds.MoveTo(screenBounds.TopLeft());
- nsGUIEvent event(true, NS_MOVE, this);
-
- event.refPoint = mBounds.TopLeft();
-
// XXX mozilla will invalidate the entire window after this move
// complete. wtf?
- nsEventStatus status;
- DispatchEvent(&event, status);
+ if (mWidgetListener)
+ mWidgetListener->WindowMoved(this, mBounds.x, mBounds.y);
return FALSE;
}
void
nsWindow::OnContainerUnrealize(GtkWidget *aWidget)
{
// The GdkWindows are about to be destroyed (but not deleted), so remove
@@ -2413,30 +2386,25 @@ nsWindow::OnSizeAllocate(GtkWidget *aWid
if (!mGdkWindow)
return;
if (mTransparencyBitmap) {
ApplyTransparencyBitmap();
}
- nsEventStatus status;
- DispatchResizeEvent (rect, status);
+ if (mWidgetListener)
+ mWidgetListener->WindowResized(this, rect.width, rect.height);
}
void
nsWindow::OnDeleteEvent(GtkWidget *aWidget, GdkEventAny *aEvent)
{
- nsGUIEvent event(true, NS_XUL_CLOSE, this);
-
- event.refPoint.x = 0;
- event.refPoint.y = 0;
-
- nsEventStatus status;
- DispatchEvent(&event, status);
+ if (mWidgetListener)
+ mWidgetListener->RequestWindowClose(this);
}
void
nsWindow::OnEnterNotifyEvent(GtkWidget *aWidget, GdkEventCrossing *aEvent)
{
// This skips NotifyVirtual and NotifyNonlinearVirtual enter notify events
// when the pointer enters a child window. If the destination window is a
// Gecko window then we'll catch the corresponding event on that window,
@@ -2825,25 +2793,25 @@ nsWindow::OnContainerFocusInEvent(GtkWid
GtkWidget* top_window = nullptr;
GetToplevelWidget(&top_window);
if (top_window && (gtk_widget_get_visible(top_window)))
SetUrgencyHint(top_window, false);
// Return if being called within SetFocus because the focus manager
// already knows that the window is active.
if (gBlockActivateEvent) {
- LOGFOCUS(("NS_ACTIVATE event is blocked [%p]\n", (void *)this));
+ LOGFOCUS(("activated notification is blocked [%p]\n", (void *)this));
return;
}
// This is not usually the correct window for dispatching key events,
// but the focus manager will call SetFocus to set the correct window if
// keyboard input will be accepted. Setting a non-NULL value here
- // prevents OnButtonPressEvent() from dispatching NS_ACTIVATE if the
- // widget is already active.
+ // prevents OnButtonPressEvent() from dispatching an activation
+ // notification if the widget is already active.
gFocusWindow = this;
DispatchActivateEvent();
LOGFOCUS(("Events sent from focus in event [%p]\n", (void *)this));
}
void
@@ -3209,59 +3177,53 @@ nsWindow::OnWindowStateEvent(GtkWidget *
(GDK_WINDOW_STATE_ICONIFIED|GDK_WINDOW_STATE_WITHDRAWN));
if (mHasMappedToplevel != mapped) {
SetHasMappedToplevel(mapped);
}
return;
}
// else the widget is a shell widget.
- nsSizeModeEvent event(true, NS_SIZEMODE, this);
-
// We don't care about anything but changes in the maximized/icon/fullscreen
// states
if ((aEvent->changed_mask
& (GDK_WINDOW_STATE_ICONIFIED |
GDK_WINDOW_STATE_MAXIMIZED |
GDK_WINDOW_STATE_FULLSCREEN)) == 0) {
return;
}
if (aEvent->new_window_state & GDK_WINDOW_STATE_ICONIFIED) {
LOG(("\tIconified\n"));
- event.mSizeMode = nsSizeMode_Minimized;
mSizeState = nsSizeMode_Minimized;
#ifdef ACCESSIBILITY
DispatchMinimizeEventAccessible();
#endif //ACCESSIBILITY
}
else if (aEvent->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) {
LOG(("\tFullscreen\n"));
- event.mSizeMode = nsSizeMode_Fullscreen;
mSizeState = nsSizeMode_Fullscreen;
}
else if (aEvent->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) {
LOG(("\tMaximized\n"));
- event.mSizeMode = nsSizeMode_Maximized;
mSizeState = nsSizeMode_Maximized;
#ifdef ACCESSIBILITY
DispatchMaximizeEventAccessible();
#endif //ACCESSIBILITY
}
else {
LOG(("\tNormal\n"));
- event.mSizeMode = nsSizeMode_Normal;
mSizeState = nsSizeMode_Normal;
#ifdef ACCESSIBILITY
DispatchRestoreEventAccessible();
#endif //ACCESSIBILITY
}
- nsEventStatus status;
- DispatchEvent(&event, status);
+ if (mWidgetListener)
+ mWidgetListener->SizeModeChanged(mSizeState);
}
void
nsWindow::ThemeChanged()
{
NotifyThemeChanged();
if (!mGdkWindow || NS_UNLIKELY(mIsDestroyed))
@@ -5845,18 +5807,16 @@ nsWindow::DispatchEventToRootAccessible(
// Get the root document accessible and fire event to it.
Accessible *acc = GetAccessible();
if (acc) {
accService->FireAccessibleEvent(aEventType, acc);
}
}
-// XXXndeakin what is all this for? Accessibility should be receiving these
-// notifications of gtk the same as other platforms.
void
nsWindow::DispatchActivateEventAccessible(void)
{
DispatchEventToRootAccessible(nsIAccessibleEvent::EVENT_WINDOW_ACTIVATE);
}
void
nsWindow::DispatchDeactivateEventAccessible(void)
--- a/widget/gtk2/nsWindow.h
+++ b/widget/gtk2/nsWindow.h
@@ -80,17 +80,16 @@ public:
NS_DECL_ISUPPORTS_INHERITED
void CommonCreate(nsIWidget *aParent, bool aListenForResizes);
// event handling code
void DispatchActivateEvent(void);
void DispatchDeactivateEvent(void);
- void DispatchResizeEvent(nsIntRect &aRect, nsEventStatus &aStatus);
virtual nsresult DispatchEvent(nsGUIEvent *aEvent, nsEventStatus &aStatus);
// called when we are destroyed
void OnDestroy(void);
// called to check and see if a widget's dimensions are sane
bool AreBoundsSane(void);
@@ -358,17 +357,17 @@ private:
GdkWindow *mGdkWindow;
GtkWindowGroup *mWindowGroup;
PRUint32 mHasMappedToplevel : 1,
mIsFullyObscured : 1,
mRetryPointerGrab : 1;
GtkWindow *mTransientParent;
- PRInt32 mSizeState;
+ nsSizeMode mSizeState;
PluginType mPluginType;
PRInt32 mTransparencyBitmapWidth;
PRInt32 mTransparencyBitmapHeight;
#ifdef MOZ_HAVE_SHMIMAGE
// If we're using xshm rendering, mThebesSurface wraps mShmImage
nsRefPtr<nsShmImage> mShmImage;
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -30,16 +30,17 @@ class nsRenderingContext;
class nsDeviceContext;
struct nsFont;
class nsIRollupListener;
class nsGUIEvent;
class imgIContainer;
class gfxASurface;
class nsIContent;
class ViewWrapper;
+class nsIWidgetListener;
namespace mozilla {
namespace dom {
class TabChild;
}
namespace layers {
class LayerManager;
class PLayersChild;
@@ -82,18 +83,18 @@ typedef nsEventStatus (* EVENT_CALLBACK)
#endif
#ifdef XP_WIN
#define NS_NATIVE_TSF_THREAD_MGR 100
#define NS_NATIVE_TSF_CATEGORY_MGR 101
#define NS_NATIVE_TSF_DISPLAY_ATTR_MGR 102
#endif
#define NS_IWIDGET_IID \
- { 0x91aafae4, 0xd814, 0x4803, \
- { 0x9a, 0xf5, 0xb0, 0x2f, 0x1b, 0x2c, 0xaf, 0x57 } }
+ { 0xb8f43b25, 0x9036, 0x44e7, \
+ { 0xaa, 0xe2, 0x33, 0x76, 0x6c, 0x35, 0x91, 0xfc } }
/*
* Window shadow styles
* Also used for the -moz-window-shadow CSS property
*/
#define NS_STYLE_WINDOW_SHADOW_NONE 0
#define NS_STYLE_WINDOW_SHADOW_DEFAULT 1
@@ -488,22 +489,22 @@ class nsIWidget : public nsISupports {
/**
* Accessor functions to get and set secondary client data. Used by
* nsIView in connection with AttachViewToTopLevel above.
*/
NS_IMETHOD SetAttachedViewPtr(ViewWrapper* aViewWrapper) = 0;
virtual ViewWrapper* GetAttachedViewPtr() = 0;
/**
- * Accessor functions to get and set the client data associated with the
- * widget.
+ * Accessor functions to get and set the listener which handles various
+ * actions for the widget.
*/
//@{
- NS_IMETHOD GetClientData(void*& aClientData) = 0;
- NS_IMETHOD SetClientData(void* aClientData) = 0;
+ virtual nsIWidgetListener* GetWidgetListener() = 0;
+ virtual void SetWidgetListener(nsIWidgetListener* alistener) = 0;
//@}
/**
* Close and destroy the internal native window.
* This method does not delete the widget.
*/
NS_IMETHOD Destroy(void) = 0;
new file mode 100644
--- /dev/null
+++ b/widget/nsIWidgetListener.h
@@ -0,0 +1,129 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozila.org code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsIWidgetListener_h__
+#define nsIWidgetListener_h__
+
+#include "nscore.h"
+#include "nsGUIEvent.h"
+#include "nsIXULWindow.h"
+
+class nsIView;
+
+class nsIWidgetListener
+{
+public:
+
+ /**
+ * If this listener is for an nsIXULWindow, return it. If this is null, then
+ * this is likely a listener for a view, which can be determined using
+ * GetView. If both methods return null, this will be an nsWebBrowser.
+ */
+ virtual nsIXULWindow* GetXULWindow() { return nullptr; }
+
+ /**
+ * If this listener is for an nsIView, return it.
+ */
+ virtual nsIView* GetView() { return nullptr; }
+
+ /**
+ * Called when a window is moved to location (x, y). Returns true if the
+ * notification was handled. Coordinates are outer window screen coordinates.
+ */
+ virtual bool WindowMoved(nsIWidget* aWidget, PRInt32 aX, PRInt32 aY) { return false; }
+
+ /**
+ * Called when a window is resized to (width, height). Returns true if the
+ * notification was handled. Coordinates are outer window screen coordinates.
+ */
+ virtual bool WindowResized(nsIWidget* aWidget, PRInt32 aWidth, PRInt32 aHeight) { return false; }
+
+ /**
+ * Called when the size mode (minimized, maximized, fullscreen) is changed.
+ */
+ virtual void SizeModeChanged(nsSizeMode sizeMode) { }
+
+ /**
+ * Called when the z-order of the window is changed. Returns true if the
+ * notification was handled. aPlacement indicates the new z order. If
+ * placement is nsWindowZRelative, then aRequestBelow should be the
+ * window to place below. On return, aActualBelow will be set to the
+ * window actually behind. This generally only applies to Windows.
+ */
+ virtual bool ZLevelChanged(bool aImmediate, nsWindowZ *aPlacement,
+ nsIWidget* aRequestBelow, nsIWidget** aActualBelow) { return false; }
+
+ /**
+ * Called when the window is activated and focused.
+ */
+ virtual void WindowActivated() { }
+
+ /**
+ * Called when the window is deactivated and no longer focused.
+ */
+ virtual void WindowDeactivated() { }
+
+ /**
+ * Called when the show/hide toolbar button on the Mac titlebar is pressed.
+ */
+ virtual void OSToolbarButtonPressed() { }
+
+ /**
+ * Called when a request is made to close the window. Returns true if the
+ * notification was handled. Returns true if the notification was handled.
+ */
+ virtual bool RequestWindowClose(nsIWidget* aWidget) { return false; }
+
+ /*
+ * Indicate that a paint is about to occur on this window.
+ */
+ virtual void WillPaintWindow(nsIWidget* aWidget, bool aWillSendDidPaint) { }
+
+ /**
+ * Paint the specified region of the window. If aSentWillPaint is true,
+ * then WillPaintWindow has already been called. If aWillSendDidPaint is true,
+ * then a call to DidPaintWindow will be made afterwards. Returns true if the
+ * notification was handled.
+ */
+ virtual bool PaintWindow(nsIWidget* aWidget, nsIntRegion aRegion,
+ bool aSentWillPaint, bool aWillSendDidPaint) { return false; }
+
+ /**
+ * On some platforms, indicates that a paint occurred.
+ */
+ virtual void DidPaintWindow() { }
+};
+
+#endif
--- a/widget/qt/nsWindow.cpp
+++ b/widget/qt/nsWindow.cpp
@@ -63,16 +63,17 @@ using namespace QtMobility;
#include "nsIdleService.h"
#include "nsRenderingContext.h"
#include "nsIRollupListener.h"
#include "nsWidgetsCID.h"
#include "nsQtKeyUtils.h"
#include "mozilla/Services.h"
#include "mozilla/Preferences.h"
+#include "nsIWidgetListener.h"
#include "nsIStringBundle.h"
#include "nsGfxCIID.h"
#include "imgIContainer.h"
#include "nsGfxCIID.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsAutoPtr.h"
@@ -654,16 +655,18 @@ nsWindow::SetFocus(bool aRaise)
QWidget *widget = GetViewWidget();
if (widget)
widget->raise();
realFocusItem->setFocus(Qt::ActiveWindowFocusReason);
}
else
realFocusItem->setFocus(Qt::OtherFocusReason);
+ // XXXndeakin why is this here? It should dispatch only when the OS
+ // notifies us.
DispatchActivateEvent();
return NS_OK;
}
NS_IMETHODIMP
nsWindow::GetScreenBounds(nsIntRect &aRect)
{
@@ -987,115 +990,102 @@ GetSurfaceForQWidget(QWidget* aDrawable)
DefaultVisualOfScreen(gfxQtPlatform::GetXScreen(aDrawable)),
gfxIntSize(aDrawable->size().width(),
aDrawable->size().height()));
NS_IF_ADDREF(result);
return result;
}
#endif
-static void
-DispatchDidPaint(nsIWidget* aWidget)
-{
- nsEventStatus status;
- nsPaintEvent didPaintEvent(true, NS_DID_PAINT, aWidget);
- aWidget->DispatchEvent(&didPaintEvent, status);
-}
-
-nsEventStatus
+bool
nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption, QWidget* aWidget)
{
if (mIsDestroyed) {
LOG(("Expose event on destroyed window [%p] window %p\n",
(void *)this, mWidget));
- return nsEventStatus_eIgnore;
+ return false;
}
- // Dispatch WILL_PAINT to allow scripts etc. to run before we
- // dispatch PAINT
+ // Call WillPaintWindow to allow scripts etc. to run before we paint
{
- nsEventStatus status;
- nsPaintEvent willPaintEvent(true, NS_WILL_PAINT, this);
- willPaintEvent.willSendDidPaint = true;
- DispatchEvent(&willPaintEvent, status);
+ if (mWidgetListener)
+ mWidgetListener->WillPaintWindow(this, true);
}
if (!mWidget)
- return nsEventStatus_eIgnore;
+ return false;
QRectF r;
if (aOption)
r = aOption->exposedRect;
else
r = mWidget->boundingRect();
if (r.isEmpty())
return nsEventStatus_eIgnore;
if (!mDirtyScrollArea.isEmpty())
mDirtyScrollArea = QRegion();
- nsEventStatus status;
+ bool painted = false;
nsIntRect rect(r.x(), r.y(), r.width(), r.height());
nsFastStartup* startup = nsFastStartup::GetSingleton();
if (startup) {
startup->RemoveFakeLayout();
}
if (GetLayerManager(nullptr)->GetBackendType() == mozilla::layers::LAYERS_OPENGL) {
aPainter->beginNativePainting();
- nsPaintEvent event(true, NS_PAINT, this);
- event.willSendDidPaint = true;
- event.refPoint.x = r.x();
- event.refPoint.y = r.y();
- event.region = nsIntRegion(rect);
+ nsIntRegion region(rect);
static_cast<mozilla::layers::LayerManagerOGL*>(GetLayerManager(nullptr))->
- SetClippingRegion(event.region);
+ SetClippingRegion(region);
gfxMatrix matr;
matr.Translate(gfxPoint(aPainter->transform().dx(), aPainter->transform().dy()));
#ifdef MOZ_ENABLE_QTMOBILITY
// This is needed for rotate transformation on MeeGo
// This will work very slow if pixman does not handle rotation very well
matr.Rotate((M_PI/180) * gOrientationFilter.GetWindowRotationAngle());
static_cast<mozilla::layers::LayerManagerOGL*>(GetLayerManager(nullptr))->
SetWorldTransform(matr);
#endif //MOZ_ENABLE_QTMOBILITY
- status = DispatchEvent(&event);
+ if (mWidgetListener)
+ painted = mWidgetListener->PaintWindow(this, region, true, true);
aPainter->endNativePainting();
- DispatchDidPaint(this);
- return status;
+ if (mWidgetListener)
+ mWidgetListener->DidPaintWindow();
+ return painted;
}
gfxQtPlatform::RenderMode renderMode = gfxQtPlatform::GetPlatform()->GetRenderMode();
int depth = aPainter->device()->depth();
nsRefPtr<gfxASurface> targetSurface = nullptr;
if (renderMode == gfxQtPlatform::RENDER_BUFFERED) {
// Prepare offscreen buffers iamge or xlib, depends from paintEngineType
if (!UpdateOffScreenBuffers(depth, QSize(r.width(), r.height())))
- return nsEventStatus_eIgnore;
+ return false;
targetSurface = gBufferSurface;
#ifdef CAIRO_HAS_QT_SURFACE
} else if (renderMode == gfxQtPlatform::RENDER_QPAINTER) {
targetSurface = new gfxQPainterSurface(aPainter);
#endif
} else if (renderMode == gfxQtPlatform::RENDER_DIRECT) {
if (!UpdateOffScreenBuffers(depth, aWidget->size(), aWidget)) {
- return nsEventStatus_eIgnore;
+ return false;
}
targetSurface = gBufferSurface;
}
if (NS_UNLIKELY(!targetSurface))
- return nsEventStatus_eIgnore;
+ return false;
nsRefPtr<gfxContext> ctx = new gfxContext(targetSurface);
// We will paint to 0, 0 position in offscrenn buffer
if (renderMode == gfxQtPlatform::RENDER_BUFFERED) {
ctx->Translate(gfxPoint(-r.x(), -r.y()));
}
else if (renderMode == gfxQtPlatform::RENDER_DIRECT) {
@@ -1108,34 +1098,32 @@ nsWindow::DoPaint(QPainter* aPainter, co
NS_ASSERTION(PIXMAN_VERSION > PIXMAN_VERSION_ENCODE(0, 21, 2) ||
!gOrientationFilter.GetWindowRotationAngle(),
"Old pixman and rotate transform, it is going to be slow");
#endif //MOZ_ENABLE_QTMOBILITY
ctx->SetMatrix(matr);
}
- nsPaintEvent event(true, NS_PAINT, this);
- event.willSendDidPaint = true;
- event.refPoint.x = rect.x;
- event.refPoint.y = rect.y;
- event.region = nsIntRegion(rect);
{
AutoLayerManagerSetup
setupLayerManager(this, ctx, mozilla::layers::BUFFER_NONE);
- status = DispatchEvent(&event);
+ if (mWidgetListener) {
+ nsIntRegion region(rect);
+ painted = mWidgetListener->PaintWindow(this, region, true, true);
+ }
}
// DispatchEvent can Destroy us (bug 378273), avoid doing any paint
// operations below if that happened - it will lead to XError and exit().
if (NS_UNLIKELY(mIsDestroyed))
- return status;
-
- if (status == nsEventStatus_eIgnore)
- return status;
+ return painted;
+
+ if (!painted)
+ return false;
LOGDRAW(("[%p] draw done\n", this));
// Handle buffered painting mode
if (renderMode == gfxQtPlatform::RENDER_BUFFERED) {
#if defined(MOZ_X11) && defined(Q_WS_X11)
if (gBufferSurface->GetType() == gfxASurface::SurfaceTypeXlib) {
// Paint offscreen pixmap to QPainter
@@ -1188,46 +1176,41 @@ nsWindow::DoPaint(QPainter* aPainter, co
_gfximage_to_qformat(imgs->Format()));
aPainter->drawImage(trans, img, trans);
}
}
}
ctx = nullptr;
targetSurface = nullptr;
- DispatchDidPaint(this);
+ if (mWidgetListener)
+ mWidgetListener->DidPaintWindow();
// check the return value!
- return status;
+ return painted;
}
nsEventStatus
nsWindow::OnMoveEvent(QGraphicsSceneHoverEvent *aEvent)
{
LOG(("configure event [%p] %d %d\n", (void *)this,
aEvent->pos().x(), aEvent->pos().y()));
// can we shortcut?
- if (!mWidget)
+ if (!mWidget || !mWidgetListener)
return nsEventStatus_eIgnore;
if ((mBounds.x == aEvent->pos().x() &&
mBounds.y == aEvent->pos().y()))
{
return nsEventStatus_eIgnore;
}
- nsGUIEvent event(true, NS_MOVE, this);
-
- event.refPoint.x = aEvent->pos().x();
- event.refPoint.y = aEvent->pos().y();
-
- // XXX mozilla will invalidate the entire window after this move
- // complete. wtf?
- return DispatchEvent(&event);
+ bool moved = mWidgetListener->WindowMoved(this, aEvent->pos().x(), aEvent->pos().y());
+ return moved ? nsEventStatus_eConsumeNoDefault : nsEventStatus_eIgnore;
}
nsEventStatus
nsWindow::OnResizeEvent(QGraphicsSceneResizeEvent *aEvent)
{
nsIntRect rect;
// Generate XPFE resize event
@@ -1242,22 +1225,20 @@ nsWindow::OnResizeEvent(QGraphicsSceneRe
nsEventStatus status;
DispatchResizeEvent(rect, status);
return status;
}
nsEventStatus
nsWindow::OnCloseEvent(QCloseEvent *aEvent)
{
- nsGUIEvent event(true, NS_XUL_CLOSE, this);
-
- event.refPoint.x = 0;
- event.refPoint.y = 0;
-
- return DispatchEvent(&event);
+ if (!mWidgetListener)
+ return nsEventStatus_eIgnore;
+ mWidgetListener->RequestWindowClose(this);
+ return nsEventStatus_eConsumeNoDefault;
}
nsEventStatus
nsWindow::OnEnterNotifyEvent(QGraphicsSceneHoverEvent *aEvent)
{
nsMouseEvent event(true, NS_MOUSE_ENTER, this, nsMouseEvent::eReal);
event.refPoint.x = nscoord(aEvent->pos().x());
@@ -2841,27 +2822,25 @@ nsWindow::GetDPI()
}
return float(rootWindow->height()/heightInches);
}
void
nsWindow::DispatchActivateEvent(void)
{
- nsGUIEvent event(true, NS_ACTIVATE, this);
- nsEventStatus status;
- DispatchEvent(&event, status);
+ if (mWidgetListener)
+ mWidgetListener->WindowActivated();
}
void
nsWindow::DispatchDeactivateEvent(void)
{
- nsGUIEvent event(true, NS_DEACTIVATE, this);
- nsEventStatus status;
- DispatchEvent(&event, status);
+ if (mWidgetListener)
+ mWidgetListener->WindowDeactivated();
}
void
nsWindow::DispatchActivateEventOnTopLevelWindow(void)
{
nsWindow * topLevelWindow = static_cast<nsWindow*>(GetTopLevelWidget());
if (topLevelWindow != nullptr)
topLevelWindow->DispatchActivateEvent();
@@ -2873,26 +2852,20 @@ nsWindow::DispatchDeactivateEventOnTopLe
nsWindow * topLevelWindow = static_cast<nsWindow*>(GetTopLevelWidget());
if (topLevelWindow != nullptr)
topLevelWindow->DispatchDeactivateEvent();
}
void
nsWindow::DispatchResizeEvent(nsIntRect &aRect, nsEventStatus &aStatus)
{
- nsSizeEvent event(true, NS_SIZE, this);
-
- event.windowSize = &aRect;
- event.refPoint.x = aRect.x;
- event.refPoint.y = aRect.y;
- event.mWinWidth = aRect.width;
- event.mWinHeight = aRect.height;
-
- nsEventStatus status;
- DispatchEvent(&event, status);
+ aStatus = nsEventStatus_eIgnore;
+ if (mWidgetListener &&
+ mWidgetListener->WindowResized(this, aRect.width, aRect.height))
+ aStatus = nsEventStatus_eConsumeNoDefault;
}
NS_IMETHODIMP
nsWindow::DispatchEvent(nsGUIEvent *aEvent,
nsEventStatus &aStatus)
{
#ifdef DEBUG
debug_DumpEvent(stdout, aEvent->widget, aEvent,
--- a/widget/qt/nsWindow.h
+++ b/widget/qt/nsWindow.h
@@ -77,17 +77,17 @@ class nsIdleService;
class nsWindow : public nsBaseWidget,
public nsSupportsWeakReference
{
public:
nsWindow();
virtual ~nsWindow();
- nsEventStatus DoPaint( QPainter* aPainter, const QStyleOptionGraphicsItem * aOption, QWidget* aWidget);
+ bool DoPaint( QPainter* aPainter, const QStyleOptionGraphicsItem * aOption, QWidget* aWidget);
static void ReleaseGlobals();
NS_DECL_ISUPPORTS_INHERITED
//
// nsIWidget
//
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -110,16 +110,17 @@
#include "gfxWindowsPlatform.h"
#include "Layers.h"
#include "nsPrintfCString.h"
#include "mozilla/Preferences.h"
#include "nsISound.h"
#include "WinTaskbar.h"
#include "WinUtils.h"
#include "WidgetUtils.h"
+#include "nsIWidgetListener.h"
#ifdef MOZ_ENABLE_D3D9_LAYER
#include "LayerManagerD3D9.h"
#endif
#ifdef MOZ_ENABLE_D3D10_LAYER
#include "LayerManagerD3D10.h"
#endif
@@ -1582,20 +1583,19 @@ NS_IMETHODIMP nsWindow::SetSizeMode(PRIn
::GetWindowPlacement(mWnd, &pl);
// Don't call ::ShowWindow if we're trying to "restore" a window that is
// already in a normal state. Prevents a bug where snapping to one side
// of the screen and then minimizing would cause Windows to forget our
// window's correct restored position/size.
if( !(pl.showCmd == SW_SHOWNORMAL && mode == SW_RESTORE) ) {
::ShowWindow(mWnd, mode);
}
- // we dispatch an activate event here to ensure that the right child window
- // is focused
+ // we activate here to ensure that the right child window is focused
if (mode == SW_MAXIMIZE || mode == SW_SHOW)
- DispatchFocusToTopLevelWindow(NS_ACTIVATE);
+ DispatchFocusToTopLevelWindow(true);
}
return rv;
}
// Constrain a potential move to fit onscreen
NS_METHOD nsWindow::ConstrainPosition(bool aAllowSlop,
PRInt32 *aX, PRInt32 *aY)
{
@@ -2695,21 +2695,18 @@ nsWindow::MakeFullScreen(bool aFullScree
Invalidate();
}
// Notify the taskbar that we have exited full screen mode.
if (!aFullScreen && taskbarInfo) {
taskbarInfo->PrepareFullScreenHWND(mWnd, FALSE);
}
- // Let the dom know via web shell window
- nsSizeModeEvent event(true, NS_SIZEMODE, this);
- event.mSizeMode = mSizeMode;
- InitEvent(event);
- DispatchWindowEvent(&event);
+ if (mWidgetListener)
+ mWidgetListener->SizeModeChanged(mSizeMode);
return rv;
}
/**************************************************************
*
* SECTION: Native data storage
*
@@ -3484,38 +3481,21 @@ NS_IMETHODIMP nsWindow::DispatchEvent(ns
event->widget,
event,
nsCAutoString("something"),
(PRInt32) mWnd);
#endif // WIDGET_DEBUG_OUTPUT
aStatus = nsEventStatus_eIgnore;
- // skip processing of suppressed blur events
- if (event->message == NS_DEACTIVATE && BlurEventsSuppressed())
- return NS_OK;
-
// 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) {
- // A subset of events are sent to the base xul window first
- switch(event->message) {
- // sent to the base window, then to the view
- case NS_SIZE:
- case NS_DEACTIVATE:
- case NS_ACTIVATE:
- case NS_SIZEMODE:
- case NS_SETZLEVEL:
- case NS_XUL_CLOSE:
- case NS_MOVE:
- (*mEventCallback)(event); // web shell / xul window
- break;
- };
// attached view events
aStatus = (*mViewCallback)(event);
}
else if (mEventCallback) {
aStatus = (*mEventCallback)(event);
}
// the window can be destroyed during processing of seemingly innocuous events like, say,
@@ -3942,22 +3922,28 @@ bool nsWindow::DispatchMouseEvent(PRUint
// the context menu key code in nsEventListenerManager::HandleEvent()
// released it already.
return result;
}
return result;
}
-bool nsWindow::DispatchFocusToTopLevelWindow(PRUint32 aEventType)
-{
- if (aEventType == NS_ACTIVATE)
+void nsWindow::DispatchFocusToTopLevelWindow(bool aIsActivate)
+{
+ if (aIsActivate)
sJustGotActivate = false;
sJustGotDeactivate = false;
+ if (!aIsActivate && BlurEventsSuppressed())
+ return;
+
+ if (!mWidgetListener)
+ return;
+
// retrive the toplevel window or dialog
HWND curWnd = mWnd;
HWND toplevelWnd = NULL;
while (curWnd) {
toplevelWnd = curWnd;
nsWindow *win = WinUtils::GetNSWindowPtr(curWnd);
if (win) {
@@ -3967,57 +3953,23 @@ bool nsWindow::DispatchFocusToTopLevelWi
break;
}
curWnd = ::GetParent(curWnd); // Parent or owner (if has no parent)
}
if (toplevelWnd) {
nsWindow *win = WinUtils::GetNSWindowPtr(toplevelWnd);
- if (win)
- return win->DispatchFocus(aEventType);
- }
-
- return false;
-}
-
-// Deal with focus messages
-bool nsWindow::DispatchFocus(PRUint32 aEventType)
-{
- // call the event callback
- if (mEventCallback) {
- nsGUIEvent event(true, aEventType, this);
- InitEvent(event);
-
- //focus and blur event should go to their base widget loc, not current mouse pos
- event.refPoint.x = 0;
- event.refPoint.y = 0;
-
- NPEvent pluginEvent;
-
- switch (aEventType)
- {
- case NS_ACTIVATE:
- pluginEvent.event = WM_SETFOCUS;
- break;
- case NS_DEACTIVATE:
- pluginEvent.event = WM_KILLFOCUS;
- break;
- case NS_PLUGIN_ACTIVATE:
- pluginEvent.event = WM_KILLFOCUS;
- break;
- default:
- break;
- }
-
- event.pluginEvent = (void *)&pluginEvent;
-
- return DispatchWindowEvent(&event);
- }
- return false;
+ if (win) {
+ if (aIsActivate)
+ mWidgetListener->WindowActivated();
+ else
+ mWidgetListener->WindowDeactivated();
+ }
+ }
}
bool nsWindow::IsTopLevelMouseExit(HWND aWnd)
{
DWORD pos = ::GetMessagePos();
POINT mp;
mp.x = GET_X_LPARAM(pos);
mp.y = GET_Y_LPARAM(pos);
@@ -4682,17 +4634,18 @@ bool nsWindow::ProcessMessage(UINT msg,
{
RECT rect;
::GetWindowRect(mWnd, &rect);
result = OnMove(rect.left, rect.top);
}
break;
case WM_CLOSE: // close request
- DispatchStandardEvent(NS_XUL_CLOSE);
+ if (mWidgetListener)
+ mWidgetListener->RequestWindowClose(this);
result = true; // abort window closure
break;
case WM_DESTROY:
// clean up.
OnDestroy();
result = true;
break;
@@ -4971,28 +4924,27 @@ bool nsWindow::ProcessMessage(UINT msg,
// default = false - tell the driver that the event was not handled
}
break;
// 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
- // gJustGotDeativate flags and fire the NS_ACTIVATE or NS_DEACTIVATE
- // events once the focus events arrive.
+ // gJustGotDeactivate flags and activate/deactivate once the focus
+ // events arrive.
case WM_ACTIVATE:
if (mEventCallback) {
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 dispatch
- // NS_DEACTIVATE right away.
+ // be fired in the reverse order. Instead, just deactivate right away.
if (HIWORD(wParam))
- result = DispatchFocusToTopLevelWindow(NS_DEACTIVATE);
+ DispatchFocusToTopLevelWindow(false);
else
sJustGotDeactivate = true;
if (mIsTopWidgetWindow)
mLastKeyboardLayout = gKbdLayout.GetLayout();
} else {
StopFlashing();
@@ -5049,23 +5001,23 @@ bool nsWindow::ProcessMessage(UINT msg,
case WM_SETFOCUS:
// If previous focused window isn't ours, it must have received the
// redirected message. So, we should forget it.
if (!WinUtils::IsOurProcessWindow(HWND(wParam))) {
ForgetRedirectedKeyDownMessage();
}
if (sJustGotActivate) {
- result = DispatchFocusToTopLevelWindow(NS_ACTIVATE);
+ DispatchFocusToTopLevelWindow(true);
}
break;
case WM_KILLFOCUS:
if (sJustGotDeactivate) {
- result = DispatchFocusToTopLevelWindow(NS_DEACTIVATE);
+ DispatchFocusToTopLevelWindow(false);
}
break;
case WM_WINDOWPOSCHANGED:
{
WINDOWPOS *wp = (LPWINDOWPOS)lParam;
OnWindowPosChanged(wp, result);
}
@@ -5309,17 +5261,17 @@ bool nsWindow::ProcessMessage(UINT msg,
// With OOPP, the plugin window exists in another process and is a child of
// this window. This window is a placeholder plugin window for the dom. We
// receive this event when the child window receives focus. (sent from
// PluginInstanceParent.cpp)
::SendMessage(mWnd, WM_MOUSEACTIVATE, 0, 0); // See nsPluginNativeWindowWin.cpp
} else {
// WM_KILLFOCUS was received by the child process.
if (sJustGotDeactivate) {
- DispatchFocusToTopLevelWindow(NS_DEACTIVATE);
+ DispatchFocusToTopLevelWindow(false);
}
}
}
}
break;
}
//*aRetValue = result;
@@ -5925,46 +5877,42 @@ void nsWindow::OnWindowPosChanged(WINDOW
// Bug 566135 - Windows theme code calls show window on SW_SHOWMINIMIZED
// windows when fullscreen games disable desktop composition. If we're
// minimized and not being activated, ignore the event and let windows
// handle it.
if (mSizeMode == nsSizeMode_Minimized && (wp->flags & SWP_NOACTIVATE))
return;
- nsSizeModeEvent event(true, NS_SIZEMODE, this);
-
WINDOWPLACEMENT pl;
pl.length = sizeof(pl);
::GetWindowPlacement(mWnd, &pl);
- if (pl.showCmd == SW_SHOWMAXIMIZED)
- event.mSizeMode = (mFullscreenMode ? nsSizeMode_Fullscreen : nsSizeMode_Maximized);
- else if (pl.showCmd == SW_SHOWMINIMIZED)
- event.mSizeMode = nsSizeMode_Minimized;
- else if (mFullscreenMode)
- event.mSizeMode = nsSizeMode_Fullscreen;
- else
- event.mSizeMode = nsSizeMode_Normal;
-
- // Windows has just changed the size mode of this window. The following
- // NS_SIZEMODE event will trigger a call into SetSizeMode where we will
+ // Windows has just changed the size mode of this window. The call to
+ // SizeModeChanged will trigger a call into SetSizeMode where we will
// set the min/max window state again or for nsSizeMode_Normal, call
// SetWindow with a parameter of SW_RESTORE. There's no need however as
// this window's mode has already changed. Updating mSizeMode here
// insures the SetSizeMode call is a no-op. Addresses a bug on Win7 related
// to window docking. (bug 489258)
- mSizeMode = event.mSizeMode;
+ if (pl.showCmd == SW_SHOWMAXIMIZED)
+ mSizeMode = (mFullscreenMode ? nsSizeMode_Fullscreen : nsSizeMode_Maximized);
+ else if (pl.showCmd == SW_SHOWMINIMIZED)
+ mSizeMode = nsSizeMode_Minimized;
+ else if (mFullscreenMode)
+ mSizeMode = nsSizeMode_Fullscreen;
+ else
+ mSizeMode = nsSizeMode_Normal;
// If !sTrimOnMinimize, we minimize windows using SW_SHOWMINIMIZED (See
// SetSizeMode for internal calls, and WM_SYSCOMMAND for external). This
// prevents the working set from being trimmed but keeps the window active.
// After the window is minimized, we need to do some touch up work on the
// active window. (bugs 76831 & 499816)
- if (!sTrimOnMinimize && nsSizeMode_Minimized == event.mSizeMode)
+ if (!sTrimOnMinimize && nsSizeMode_Minimized == mSizeMode)
ActivateOtherWindowHelper(mWnd);
#ifdef WINSTATE_DEBUG_OUTPUT
switch (mSizeMode) {
case nsSizeMode_Normal:
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
("*** mSizeMode: nsSizeMode_Normal\n"));
break;
@@ -5977,25 +5925,24 @@ void nsWindow::OnWindowPosChanged(WINDOW
("*** mSizeMode: nsSizeMode_Maximized\n");
break;
default:
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, ("*** mSizeMode: ??????\n");
break;
};
#endif
- InitEvent(event);
-
- result = DispatchWindowEvent(&event);
-
- // If window was restored, NS_ACTIVATE dispatch was bypassed during the
+ if (mWidgetListener)
+ mWidgetListener->SizeModeChanged(mSizeMode);
+
+ // If window was restored, window activation was bypassed during the
// SetSizeMode call originating from OnWindowPosChanging to avoid saving
- // pre-restore attributes. Force dispatch now to get correct attributes.
+ // pre-restore attributes. Force activation now to get correct attributes.
if (mLastSizeMode != nsSizeMode_Normal && mSizeMode == nsSizeMode_Normal)
- DispatchFocusToTopLevelWindow(NS_ACTIVATE);
+ DispatchFocusToTopLevelWindow(true);
// Skip window size change events below on minimization.
if (mSizeMode == nsSizeMode_Minimized)
return;
}
// Handle window size changes
if (!(wp->flags & SWP_NOSIZE)) {
@@ -6112,69 +6059,61 @@ void nsWindow::OnWindowPosChanging(LPWIN
// browser know we are changing size modes, so alternative css can kick in.
// If we're going into fullscreen mode, ignore this, since it'll reset
// margins to normal mode.
if ((info->flags & SWP_FRAMECHANGED && !(info->flags & SWP_NOSIZE)) &&
mSizeMode != nsSizeMode_Fullscreen) {
WINDOWPLACEMENT pl;
pl.length = sizeof(pl);
::GetWindowPlacement(mWnd, &pl);
- PRInt32 sizeMode;
+ nsSizeMode sizeMode;
if (pl.showCmd == SW_SHOWMAXIMIZED)
sizeMode = (mFullscreenMode ? nsSizeMode_Fullscreen : nsSizeMode_Maximized);
else if (pl.showCmd == SW_SHOWMINIMIZED)
sizeMode = nsSizeMode_Minimized;
else if (mFullscreenMode)
sizeMode = nsSizeMode_Fullscreen;
else
sizeMode = nsSizeMode_Normal;
- nsSizeModeEvent event(true, NS_SIZEMODE, this);
-
- InitEvent(event);
- event.mSizeMode = static_cast<nsSizeMode>(sizeMode);
- DispatchWindowEvent(&event);
+ if (mWidgetListener)
+ mWidgetListener->SizeModeChanged(sizeMode);
UpdateNonClientMargins(sizeMode, false);
}
// enforce local z-order rules
if (!(info->flags & SWP_NOZORDER)) {
HWND hwndAfter = info->hwndInsertAfter;
-
- nsZLevelEvent event(true, NS_SETZLEVEL, this);
+
nsWindow *aboveWindow = 0;
-
- InitEvent(event);
+ nsWindowZ placement;
if (hwndAfter == HWND_BOTTOM)
- event.mPlacement = nsWindowZBottom;
+ placement = nsWindowZBottom;
else if (hwndAfter == HWND_TOP || hwndAfter == HWND_TOPMOST || hwndAfter == HWND_NOTOPMOST)
- event.mPlacement = nsWindowZTop;
+ placement = nsWindowZTop;
else {
- event.mPlacement = nsWindowZRelative;
+ placement = nsWindowZRelative;
aboveWindow = WinUtils::GetNSWindowPtr(hwndAfter);
}
- event.mReqBelow = aboveWindow;
- event.mActualBelow = nullptr;
-
- event.mImmediate = false;
- event.mAdjusted = false;
- DispatchWindowEvent(&event);
-
- if (event.mAdjusted) {
- if (event.mPlacement == nsWindowZBottom)
- info->hwndInsertAfter = HWND_BOTTOM;
- else if (event.mPlacement == nsWindowZTop)
- info->hwndInsertAfter = HWND_TOP;
- else {
- info->hwndInsertAfter = (HWND)event.mActualBelow->GetNativeData(NS_NATIVE_WINDOW);
+
+ if (mWidgetListener) {
+ nsCOMPtr<nsIWidget> actualBelow = nullptr;
+ if (mWidgetListener->ZLevelChanged(false, &placement,
+ aboveWindow, getter_AddRefs(actualBelow))) {
+ if (placement == nsWindowZBottom)
+ info->hwndInsertAfter = HWND_BOTTOM;
+ else if (placement == nsWindowZTop)
+ info->hwndInsertAfter = HWND_TOP;
+ else {
+ info->hwndInsertAfter = (HWND)actualBelow->GetNativeData(NS_NATIVE_WINDOW);
+ }
}
}
- NS_IF_RELEASE(event.mActualBelow);
}
// prevent rude external programs from making hidden window visible
if (mWindowType == eWindowType_invisible)
info->flags &= ~SWP_SHOWWINDOW;
}
void nsWindow::UserActivity()
{
@@ -7068,59 +7007,31 @@ void nsWindow::OnDestroy()
}
// OnMove
bool nsWindow::OnMove(PRInt32 aX, PRInt32 aY)
{
mBounds.x = aX;
mBounds.y = aY;
- nsGUIEvent event(true, NS_MOVE, this);
- InitEvent(event);
- event.refPoint.x = aX;
- event.refPoint.y = aY;
-
- return DispatchWindowEvent(&event);
+ return mWidgetListener ? mWidgetListener->WindowMoved(this, aX, aY) : false;
}
// Send a resize message to the listener
bool nsWindow::OnResize(nsIntRect &aWindowRect)
{
#ifdef CAIRO_HAS_D2D_SURFACE
if (mD2DWindowSurface) {
mD2DWindowSurface = NULL;
Invalidate();
}
#endif
- // call the event callback
- if (mEventCallback) {
- nsSizeEvent event(true, NS_SIZE, this);
- InitEvent(event);
- event.windowSize = &aWindowRect;
- RECT r;
- if (::GetWindowRect(mWnd, &r)) {
- event.mWinWidth = PRInt32(r.right - r.left);
- event.mWinHeight = PRInt32(r.bottom - r.top);
- } else {
- event.mWinWidth = 0;
- event.mWinHeight = 0;
- }
-
-#if 0
- PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
- ("[%X] OnResize: client:(%d x %d x %d x %d) window:(%d x %d)\n", this,
- aWindowRect.x, aWindowRect.y, aWindowRect.width, aWindowRect.height,
- event.mWinWidth, event.mWinHeight));
-#endif
-
- return DispatchWindowEvent(&event);
- }
-
- return false;
+ return mWidgetListener ?
+ mWidgetListener->WindowResized(this, aWindowRect.width, aWindowRect.height) : false;
}
bool nsWindow::OnHotKey(WPARAM wParam, LPARAM lParam)
{
return true;
}
// Can be overriden. Controls auto-erase of background.
--- a/widget/windows/nsWindow.h
+++ b/widget/windows/nsWindow.h
@@ -324,18 +324,17 @@ protected:
return mTransparencyMode == eTransparencyGlass ||
mTransparencyMode == eTransparencyBorderlessGlass;
}
/**
* Event processing helpers
*/
bool DispatchPluginEvent(const MSG &aMsg);
- bool DispatchFocusToTopLevelWindow(PRUint32 aEventType);
- bool DispatchFocus(PRUint32 aEventType);
+ void DispatchFocusToTopLevelWindow(bool aIsActivate);
bool DispatchStandardEvent(PRUint32 aMsg);
bool DispatchCommandEvent(PRUint32 aEventCommand);
void RelayMouseEvent(UINT aMsg, WPARAM wParam, LPARAM lParam);
static void RemoveNextCharMessage(HWND aWnd);
void RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg,
UINT aLastMsg,
nsFakeCharMessage* aFakeCharMessage = nullptr);
virtual bool ProcessMessage(UINT msg, WPARAM &wParam,
--- a/widget/windows/nsWindowGfx.cpp
+++ b/widget/windows/nsWindowGfx.cpp
@@ -29,16 +29,17 @@ using mozilla::plugins::PluginInstancePa
#include "gfxImageSurface.h"
#include "gfxWindowsSurface.h"
#include "gfxWindowsPlatform.h"
#include "nsGfxCIID.h"
#include "gfxContext.h"
#include "nsRenderingContext.h"
#include "prmem.h"
#include "WinUtils.h"
+#include "nsIWidgetListener.h"
#include "mozilla/unused.h"
#include "LayerManagerOGL.h"
#include "BasicLayers.h"
#ifdef MOZ_ENABLE_D3D9_LAYER
#include "LayerManagerD3D9.h"
#endif
#ifdef MOZ_ENABLE_D3D10_LAYER
@@ -229,23 +230,22 @@ 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;
}
- nsPaintEvent willPaintEvent(true, NS_WILL_PAINT, this);
- willPaintEvent.willSendDidPaint = true;
- DispatchWindowEvent(&willPaintEvent);
+ if (mWidgetListener) {
+ mWidgetListener->WillPaintWindow(this, true);
+ }
bool result = true;
PAINTSTRUCT ps;
- nsEventStatus eventStatus = nsEventStatus_eIgnore;
#ifdef MOZ_XUL
if (!aDC && (eTransparencyTransparent == mTransparencyMode))
{
// For layered translucent windows all drawing should go to memory DC and no
// WM_PAINT messages are normally generated. To support asynchronous painting
// we force generation of WM_PAINT messages by invalidating window areas with
// RedrawWindow, InvalidateRect or InvalidateRgn function calls.
@@ -272,38 +272,31 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32
}
#endif // WIDGET_DEBUG_OUTPUT
HDC hDC = aDC ? aDC : (::BeginPaint(mWnd, &ps));
if (!IsRenderMode(gfxWindowsPlatform::RENDER_DIRECT2D)) {
mPaintDC = hDC;
}
- // generate the event and call the event callback
- nsPaintEvent event(true, NS_PAINT, this);
- InitEvent(event);
-
#ifdef MOZ_XUL
bool forceRepaint = aDC || (eTransparencyTransparent == mTransparencyMode);
#else
bool forceRepaint = NULL != aDC;
#endif
- event.region = GetRegionToPaint(forceRepaint, ps, hDC);
- event.willSendDidPaint = true;
- event.didSendWillPaint = true;
-
- if (!event.region.IsEmpty() && mEventCallback)
+ nsIntRegion region = GetRegionToPaint(forceRepaint, ps, hDC);
+ if (!region.IsEmpty() && mWidgetListener)
{
// 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,
- &event,
+ region,
nsCAutoString("noname"),
(PRInt32) mWnd);
#endif // WIDGET_DEBUG_OUTPUT
switch (GetLayerManager()->GetBackendType()) {
case LAYERS_BASIC:
{
nsRefPtr<gfxASurface> targetSurface;
@@ -380,17 +373,17 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32
if (!targetSurface) {
NS_ERROR("Invalid RenderMode!");
return false;
}
nsRefPtr<gfxContext> thebesContext = new gfxContext(targetSurface);
if (IsRenderMode(gfxWindowsPlatform::RENDER_DIRECT2D)) {
const nsIntRect* r;
- for (nsIntRegionRectIterator iter(event.region);
+ for (nsIntRegionRectIterator iter(region);
(r = iter.Next()) != nullptr;) {
thebesContext->Rectangle(gfxRect(r->x, r->y, r->width, r->height), true);
}
thebesContext->Clip();
thebesContext->SetOperator(gfxContext::OPERATOR_CLEAR);
thebesContext->Paint();
thebesContext->SetOperator(gfxContext::OPERATOR_OVER);
}
@@ -417,17 +410,17 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32
#else
doubleBuffering = mozilla::layers::BUFFER_BUFFERED;
#endif
}
{
AutoLayerManagerSetup
setupLayerManager(this, thebesContext, doubleBuffering);
- result = DispatchWindowEvent(&event, eventStatus);
+ result = mWidgetListener->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
@@ -531,26 +524,26 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32
DIB_RGB_COLORS,
SRCCOPY);
}
}
}
break;
case LAYERS_OPENGL:
static_cast<mozilla::layers::LayerManagerOGL*>(GetLayerManager())->
- SetClippingRegion(event.region);
- result = DispatchWindowEvent(&event, eventStatus);
+ SetClippingRegion(region);
+ result = mWidgetListener->PaintWindow(this, region, true, true);
break;
#ifdef MOZ_ENABLE_D3D9_LAYER
case LAYERS_D3D9:
{
LayerManagerD3D9 *layerManagerD3D9 =
static_cast<mozilla::layers::LayerManagerD3D9*>(GetLayerManager());
- layerManagerD3D9->SetClippingRegion(event.region);
- result = DispatchWindowEvent(&event, eventStatus);
+ layerManagerD3D9->SetClippingRegion(region);
+ result = mWidgetListener->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();
}
@@ -560,17 +553,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 = DispatchWindowEvent(&event, eventStatus);
+ result = mWidgetListener->PaintWindow(this, region, true, true);
}
}
break;
#endif
default:
NS_ERROR("Unknown layers backend used!");
break;
}
@@ -584,31 +577,31 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32
mLastPaintEndTime = TimeStamp::Now();
#if defined(WIDGET_DEBUG_OUTPUT)
if (debug_WantPaintFlashing())
{
// Only flash paint events which have not ignored the paint message.
// Those that ignore the paint message aren't painting anything so there
// is only the overhead of the dispatching the paint event.
- if (nsEventStatus_eIgnore != eventStatus) {
+ if (result) {
::InvertRgn(debugPaintFlashDC, debugPaintFlashRegion);
PR_Sleep(PR_MillisecondsToInterval(30));
::InvertRgn(debugPaintFlashDC, debugPaintFlashRegion);
PR_Sleep(PR_MillisecondsToInterval(30));
}
::ReleaseDC(mWnd, debugPaintFlashDC);
::DeleteObject(debugPaintFlashRegion);
}
#endif // WIDGET_DEBUG_OUTPUT
mPainting = false;
- nsPaintEvent didPaintEvent(true, NS_DID_PAINT, this);
- DispatchWindowEvent(&didPaintEvent);
+ if (mWidgetListener)
+ mWidgetListener->DidPaintWindow();
if (aNestingLevel == 0 && ::GetUpdateRect(mWnd, NULL, false)) {
OnPaint(aDC, 1);
}
return result;
}
--- a/widget/xpwidgets/PuppetWidget.cpp
+++ b/widget/xpwidgets/PuppetWidget.cpp
@@ -12,16 +12,17 @@
#if defined(MOZ_ENABLE_D3D10_LAYER)
# include "LayerManagerD3D10.h"
#endif
#include "mozilla/dom/TabChild.h"
#include "mozilla/Hal.h"
#include "mozilla/layers/CompositorChild.h"
#include "mozilla/layers/PLayersChild.h"
#include "PuppetWidget.h"
+#include "nsIWidgetListener.h"
using namespace mozilla::dom;
using namespace mozilla::hal;
using namespace mozilla::layers;
using namespace mozilla::widget;
static void
InvalidateRegion(nsIWidget* aWidget, const nsIntRegion& aRegion)
@@ -179,18 +180,21 @@ PuppetWidget::Resize(PRInt32 aWidth,
// XXX: roc says that |aRepaint| dictates whether or not to
// invalidate the expanded area
if (oldBounds.Size() < mBounds.Size() && aRepaint) {
nsIntRegion dirty(mBounds);
dirty.Sub(dirty, oldBounds);
InvalidateRegion(this, dirty);
}
- if (!oldBounds.IsEqualEdges(mBounds)) {
- DispatchResizeEvent();
+ // XXXndeakin this isn't the right widget listener to use. It should use
+ // the view wrapper pointer but that won't compile. This will be fixed up
+ // in a later patch.
+ if (!oldBounds.IsEqualEdges(mBounds) && mWidgetListener) {
+ mWidgetListener->WindowResized(this, mBounds.width, mBounds.height);
}
return NS_OK;
}
NS_IMETHODIMP
PuppetWidget::SetFocus(bool aRaise)
{
@@ -471,88 +475,68 @@ PuppetWidget::SetCursor(nsCursor aCursor
if (!mTabChild ||
!mTabChild->SendSetCursor(aCursor)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsresult
-PuppetWidget::DispatchPaintEvent()
+PuppetWidget::Paint()
{
NS_ABORT_IF_FALSE(!mDirtyRegion.IsEmpty(), "paint event logic messed up");
- nsIntRect dirtyRect = mDirtyRegion.GetBounds();
- nsPaintEvent event(true, NS_PAINT, this);
- event.refPoint.x = dirtyRect.x;
- event.refPoint.y = dirtyRect.y;
- event.region = mDirtyRegion;
- event.willSendDidPaint = true;
+ if (!mWidgetListener)
+ return NS_OK;
+
+ nsIntRegion region = mDirtyRegion;
// reset repaint tracking
mDirtyRegion.SetEmpty();
mPaintTask.Revoke();
- nsEventStatus status;
{
#ifdef DEBUG
- debug_DumpPaintEvent(stderr, this, &event,
+ debug_DumpPaintEvent(stderr, this, region,
nsCAutoString("PuppetWidget"), 0);
#endif
if (mozilla::layers::LAYERS_D3D10 == mLayerManager->GetBackendType()) {
- DispatchEvent(&event, status);
+ mWidgetListener->PaintWindow(this, region, false, true);
} else {
nsRefPtr<gfxContext> ctx = new gfxContext(mSurface);
ctx->Rectangle(gfxRect(0,0,0,0));
ctx->Clip();
AutoLayerManagerSetup setupLayerManager(this, ctx,
BUFFER_NONE);
- DispatchEvent(&event, status);
+ mWidgetListener->PaintWindow(this, region, false, true);
mTabChild->NotifyPainted();
}
}
- nsPaintEvent didPaintEvent(true, NS_DID_PAINT, this);
- DispatchEvent(&didPaintEvent, status);
+ mWidgetListener->DidPaintWindow();
return NS_OK;
}
-nsresult
-PuppetWidget::DispatchResizeEvent()
-{
- nsSizeEvent event(true, NS_SIZE, this);
-
- nsIntRect rect = mBounds; // copy in case something messes with it
- event.windowSize = ▭
- event.refPoint.x = rect.x;
- event.refPoint.y = rect.y;
- event.mWinWidth = rect.width;
- event.mWinHeight = rect.height;
-
- nsEventStatus status;
- return DispatchEvent(&event, status);
-}
-
void
PuppetWidget::SetChild(PuppetWidget* aChild)
{
NS_ABORT_IF_FALSE(this != aChild, "can't parent a widget to itself");
NS_ABORT_IF_FALSE(!aChild->mChild,
"fake widget 'hierarchy' only expected to have one level");
mChild = aChild;
}
NS_IMETHODIMP
PuppetWidget::PaintTask::Run()
{
if (mWidget) {
- mWidget->DispatchPaintEvent();
+ mWidget->Paint();
}
return NS_OK;
}
float
PuppetWidget::GetDPI()
{
if (mDPI < 0) {
--- a/widget/xpwidgets/PuppetWidget.h
+++ b/widget/xpwidgets/PuppetWidget.h
@@ -161,18 +161,17 @@ public:
// Gets the DPI of the screen corresponding to this widget.
// Contacts the parent process which gets the DPI from the
// proper widget there. TODO: Handle DPI changes that happen
// later on.
virtual float GetDPI();
private:
- nsresult DispatchPaintEvent();
- nsresult DispatchResizeEvent();
+ nsresult Paint();
void SetChild(PuppetWidget* aChild);
nsresult IMEEndComposition(bool aCancel);
class PaintTask : public nsRunnable {
public:
NS_DECL_NSIRUNNABLE
--- a/widget/xpwidgets/nsBaseWidget.cpp
+++ b/widget/xpwidgets/nsBaseWidget.cpp
@@ -23,16 +23,17 @@
#include "LayerManagerOGL.h"
#include "nsIXULRuntime.h"
#include "nsIXULWindow.h"
#include "nsIBaseWindow.h"
#include "nsIDocShell.h"
#include "nsView.h"
#include "nsIViewManager.h"
#include "nsEventStateManager.h"
+#include "nsIWidgetListener.h"
#include "nsIGfxInfo.h"
#include "npapi.h"
#include "base/thread.h"
#include "prenv.h"
#include "mozilla/Attributes.h"
#ifdef ACCESSIBILITY
#include "nsAccessibilityService.h"
@@ -81,17 +82,17 @@ nsAutoRollup::~nsAutoRollup()
//-------------------------------------------------------------------------
//
// nsBaseWidget constructor
//
//-------------------------------------------------------------------------
nsBaseWidget::nsBaseWidget()
-: mClientData(nullptr)
+: mWidgetListener(nullptr)
, mViewWrapperPtr(nullptr)
, mEventCallback(nullptr)
, mViewCallback(nullptr)
, mContext(nullptr)
, mCursor(eCursor_standard)
, mWindowType(eWindowType_child)
, mBorderStyle(eBorderStyle_none)
, mOnDestroyCalled(false)
@@ -227,26 +228,24 @@ NS_IMETHODIMP nsBaseWidget::CaptureMouse
}
//-------------------------------------------------------------------------
//
// Accessor functions to get/set the client data
//
//-------------------------------------------------------------------------
-NS_IMETHODIMP nsBaseWidget::GetClientData(void*& aClientData)
+nsIWidgetListener* nsBaseWidget::GetWidgetListener()
{
- aClientData = mClientData;
- return NS_OK;
+ return mWidgetListener;
}
-NS_IMETHODIMP nsBaseWidget::SetClientData(void* aClientData)
+void nsBaseWidget::SetWidgetListener(nsIWidgetListener* aWidgetListener)
{
- mClientData = aClientData;
- return NS_OK;
+ mWidgetListener = aWidgetListener;
}
already_AddRefed<nsIWidget>
nsBaseWidget::CreateChild(const nsIntRect &aRect,
EVENT_CALLBACK aHandleEventFunction,
nsDeviceContext *aContext,
nsWidgetInitData *aInitData,
bool aForceUseIWidgetParent)
@@ -1341,21 +1340,22 @@ void nsBaseWidget::SetSizeConstraints(co
// probably in the middle of a reflow.
}
const widget::SizeConstraints& nsBaseWidget::GetSizeConstraints() const
{
return mSizeConstraints;
}
-// If clientData is non-null, then get the presShell from either the window
+// If widgetListener is non-null, then get the presShell from either the window
// or the view. Otherwise, assume that this is a widget attached to a view.
static nsIPresShell* GetPresShell(nsIWidget* aWidget, void* clientData)
{
- nsCOMPtr<nsIXULWindow> window(do_QueryInterface(static_cast<nsISupports *>(clientData)));
+ nsCOMPtr<nsIXULWindow> window =
+ aWidgetListener ? aWidgetListener->GetXULWindow() : nullptr;
if (window) {
nsCOMPtr<nsIDocShell> docShell;
window->GetDocShell(getter_AddRefs(docShell));
if (docShell) {
nsCOMPtr<nsIPresShell> presShell;
docShell->GetPresShell(getter_AddRefs(presShell));
return presShell.get();
}
@@ -1368,19 +1368,23 @@ static nsIPresShell* GetPresShell(nsIWid
}
return nullptr;
}
void
nsBaseWidget::NotifyWindowDestroyed()
{
- nsCOMPtr<nsIBaseWindow> window(do_QueryInterface(static_cast<nsISupports *>(mClientData)));
- if (window) {
- window->Destroy();
+ if (!mWidgetListener)
+ return;
+
+ nsCOMPtr<nsIXULWindow> window = mWidgetListener->GetXULWindow();
+ nsCOMPtr<nsIBaseWindow> xulWindow(do_QueryInterface(window));
+ if (xulWindow) {
+ xulWindow->Destroy();
}
}
void
nsBaseWidget::NotifySizeMoveDone()
{
nsIPresShell* presShell = GetPresShell(this, nullptr);
if (presShell) {
@@ -1405,33 +1409,32 @@ nsBaseWidget::NotifyThemeChanged()
presShell->ThemeChanged();
}
}
void
nsBaseWidget::NotifyUIStateChanged(UIStateChangeType aShowAccelerators,
UIStateChangeType aShowFocusRings)
{
- nsCOMPtr<nsIPresShell> presShell = GetPresShell(this, mClientData);
-
+ nsIPresShell* presShell = GetPresShell(this, mWidgetListener);
nsIDocument* doc = presShell->GetDocument();
if (doc) {
nsPIDOMWindow* win = doc->GetWindow();
if (win) {
win->SetKeyboardIndicators(aShowAccelerators, aShowFocusRings);
}
}
}
#ifdef ACCESSIBILITY
Accessible*
nsBaseWidget::GetAccessible()
{
- nsIPresShell* presShell = GetPresShell(this, mClientData);
+ nsIPresShell* presShell = GetPresShell(this, mWidgetListener);
NS_ENSURE_TRUE(presShell, nullptr);
// If container is null then the presshell is not active. This often happens
// when a preshell is being held onto for fastback.
nsPresContext* presContext = presShell->GetPresContext();
nsCOMPtr<nsISupports> container = presContext->GetContainer();
NS_ENSURE_TRUE(container, nullptr);
@@ -1679,28 +1682,27 @@ nsBaseWidget::debug_DumpEvent(FILE *
(void *) (aWindowID ? aWindowID : 0x0),
aGuiEvent->refPoint.x,
aGuiEvent->refPoint.y);
}
//////////////////////////////////////////////////////////////
/* static */ void
nsBaseWidget::debug_DumpPaintEvent(FILE * aFileOut,
nsIWidget * aWidget,
- nsPaintEvent * aPaintEvent,
+ const nsIntRegion & aRegion,
const nsCAutoString & aWidgetName,
PRInt32 aWindowID)
{
NS_ASSERTION(nullptr != aFileOut,"cmon, null output FILE");
NS_ASSERTION(nullptr != aWidget,"cmon, the widget is null");
- NS_ASSERTION(nullptr != aPaintEvent,"cmon, the paint event is null");
if (!debug_GetCachedBoolPref("nglayout.debug.paint_dumping"))
return;
- nsIntRect rect = aPaintEvent->region.GetBounds();
+ nsIntRect rect = aRegion.GetBounds();
fprintf(aFileOut,
"%4d PAINT widget=%p name=%-12s id=%-8p bounds-rect=%3d,%-3d %3d,%-3d",
_GetPrintCount(),
(void *) aWidget,
aWidgetName.get(),
(void *) aWindowID,
rect.x, rect.y, rect.width, rect.height
);
--- a/widget/xpwidgets/nsBaseWidget.h
+++ b/widget/xpwidgets/nsBaseWidget.h
@@ -59,18 +59,18 @@ protected:
public:
nsBaseWidget();
virtual ~nsBaseWidget();
NS_DECL_ISUPPORTS
// nsIWidget interface
NS_IMETHOD CaptureMouse(bool aCapture);
- NS_IMETHOD GetClientData(void*& aClientData);
- NS_IMETHOD SetClientData(void* aClientData);
+ virtual nsIWidgetListener* GetWidgetListener();
+ virtual void SetWidgetListener(nsIWidgetListener* alistener);
NS_IMETHOD Destroy();
NS_IMETHOD SetParent(nsIWidget* aNewParent);
virtual nsIWidget* GetParent(void);
virtual nsIWidget* GetTopLevelWidget();
virtual nsIWidget* GetSheetWindowParent(void);
virtual float GetDPI();
virtual double GetDefaultScale();
virtual void AddChild(nsIWidget* aChild);
@@ -326,17 +326,17 @@ protected:
* When this function returns, the compositor should not be
* able to access the opengl context anymore.
* 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();
- void* mClientData;
+ nsIWidgetListener* mWidgetListener;
ViewWrapper* mViewWrapperPtr;
EVENT_CALLBACK mEventCallback;
EVENT_CALLBACK mViewCallback;
nsDeviceContext* mContext;
nsRefPtr<LayerManager> mLayerManager;
nsRefPtr<LayerManager> mBasicLayerManager;
nsRefPtr<CompositorChild> mCompositorChild;
nsRefPtr<CompositorParent> mCompositorParent;
@@ -378,17 +378,17 @@ protected:
static void debug_DumpEvent(FILE * aFileOut,
nsIWidget * aWidget,
nsGUIEvent * aGuiEvent,
const nsCAutoString & aWidgetName,
PRInt32 aWindowID);
static void debug_DumpPaintEvent(FILE * aFileOut,
nsIWidget * aWidget,
- nsPaintEvent * aPaintEvent,
+ const nsIntRegion & aPaintEvent,
const nsCAutoString & aWidgetName,
PRInt32 aWindowID);
static bool debug_GetCachedBoolPref(const char* aPrefName);
#endif
};
// A situation can occur when a mouse event occurs over a menu label while the
--- a/xpfe/appshell/src/nsWebShellWindow.cpp
+++ b/xpfe/appshell/src/nsWebShellWindow.cpp
@@ -25,16 +25,17 @@
#include "nsIWebNavigation.h"
#include "nsIWindowWatcher.h"
#include "nsIDOMXULElement.h"
#include "nsGUIEvent.h"
#include "nsWidgetsCID.h"
#include "nsIWidget.h"
+#include "nsIWidgetListener.h"
#include "nsIDOMCharacterData.h"
#include "nsIDOMNodeList.h"
#include "nsITimer.h"
#include "nsXULPopupManager.h"
#include "prmem.h"
@@ -154,22 +155,22 @@ nsresult nsWebShellWindow::Initialize(ns
top-level child windows in OSes that do not. Later.
*/
nsCOMPtr<nsIBaseWindow> parentAsWin(do_QueryInterface(aParent));
if (parentAsWin) {
parentAsWin->GetMainWidget(getter_AddRefs(parentWidget));
mParentWindow = do_GetWeakReference(aParent);
}
- mWindow->SetClientData(this);
+ mWindow->SetWidgetListener(this);
mWindow->Create((nsIWidget *)parentWidget, // Parent nsIWidget
- nullptr, // Native parent widget
+ nullptr, // Native parent widget
r, // Widget dimensions
- nsWebShellWindow::HandleEvent, // Event handler function
- nullptr, // Device context
+ 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
mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
@@ -211,218 +212,178 @@ nsresult nsWebShellWindow::Initialize(ns
nullptr,
nullptr);
NS_ENSURE_SUCCESS(rv, rv);
}
return rv;
}
-
-/*
- * Toolbar
- */
-nsresult
-nsWebShellWindow::Toolbar()
+bool
+nsWebShellWindow::WindowMoved(nsIWidget* aWidget, PRInt32 x, PRInt32 y)
{
- nsCOMPtr<nsIXULWindow> kungFuDeathGrip(this);
- nsCOMPtr<nsIWebBrowserChrome> wbc(do_GetInterface(kungFuDeathGrip));
- if (!wbc)
- return NS_ERROR_UNEXPECTED;
+ nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
+ if (pm) {
+ nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(mDocShell);
+ pm->AdjustPopupsOnWindowChange(window);
+ }
- // rjc: don't use "nsIWebBrowserChrome::CHROME_EXTRA"
- // due to components with multiple sidebar components
- // (such as Mail/News, Addressbook, etc)... and frankly,
- // Mac IE, OmniWeb, and other Mac OS X apps all work this way
-
- PRUint32 chromeMask = (nsIWebBrowserChrome::CHROME_TOOLBAR |
- nsIWebBrowserChrome::CHROME_LOCATIONBAR |
- nsIWebBrowserChrome::CHROME_PERSONAL_TOOLBAR);
-
- PRUint32 chromeFlags, newChromeFlags = 0;
- wbc->GetChromeFlags(&chromeFlags);
- newChromeFlags = chromeFlags & chromeMask;
- if (!newChromeFlags) chromeFlags |= chromeMask;
- else chromeFlags &= (~newChromeFlags);
- wbc->SetChromeFlags(chromeFlags);
- return NS_OK;
+ // Persist position, but not immediately, in case this OS is firing
+ // repeated move events as the user drags the window
+ SetPersistenceTimer(PAD_POSITION);
+ return false;
}
-
-/*
- * Event handler function...
- *
- * This function is called to process events for the nsIWidget of the
- * nsWebShellWindow...
- */
-nsEventStatus
-nsWebShellWindow::HandleEvent(nsGUIEvent *aEvent)
+bool
+nsWebShellWindow::WindowResized(nsIWidget* aWidget, PRInt32 aWidth, PRInt32 aHeight)
{
- nsEventStatus result = nsEventStatus_eIgnore;
- nsIDocShell* docShell = nullptr;
- nsWebShellWindow *eventWindow = nullptr;
+ nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
+ if (pm) {
+ nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(mDocShell);
+ pm->AdjustPopupsOnWindowChange(window);
+ }
+
+ nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(mDocShell));
+ shellAsWin->SetPositionAndSize(0, 0, aWidth, aHeight, false);
+ // Persist size, but not immediately, in case this OS is firing
+ // repeated size events as the user drags the sizing handle
+ if (!IsLocked())
+ SetPersistenceTimer(PAD_POSITION | PAD_SIZE | PAD_MISC);
+ return true;
+}
- // Get the WebShell instance...
- if (nullptr != aEvent->widget) {
- void* data;
+bool
+nsWebShellWindow::RequestWindowClose(nsIWidget* aWidget)
+{
+ // Maintain a reference to this as it is about to get destroyed.
+ nsCOMPtr<nsIXULWindow> xulWindow(this);
+
+ nsCOMPtr<nsPIDOMWindow> window(do_GetInterface(mDocShell));
+ nsCOMPtr<nsIDOMEventTarget> eventTarget = do_QueryInterface(window);
- aEvent->widget->GetClientData(data);
- if (data != nullptr) {
- eventWindow = reinterpret_cast<nsWebShellWindow *>(data);
- docShell = eventWindow->mDocShell;
- }
+ nsCOMPtr<nsIPresShell> presShell;
+ mDocShell->GetPresShell(getter_AddRefs(presShell));
+
+ if (eventTarget) {
+ nsRefPtr<nsPresContext> presContext = presShell->GetPresContext();
+
+ nsEventStatus status = nsEventStatus_eIgnore;
+ nsMouseEvent event(true, NS_XUL_CLOSE, nullptr, nsMouseEvent::eReal);
+ if (NS_SUCCEEDED(eventTarget->DispatchDOMEvent(&event, nullptr, presContext, &status)) &&
+ status == nsEventStatus_eConsumeNoDefault)
+ return false;
}
- if (docShell) {
- switch(aEvent->message) {
- /*
- * For size events, the DocShell must be resized to fill the entire
- * client area of the window...
- */
- case NS_MOVE: {
- // Adjust any child popups so that their widget offsets and coordinates
- // are correct with respect to the new position of the window
- nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
- if (pm) {
- nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(docShell);
- pm->AdjustPopupsOnWindowChange(window);
- }
+ Destroy();
+ return false;
+}
+
+void
+nsWebShellWindow::SizeModeChanged(nsSizeMode sizeMode)
+{
+ // An alwaysRaised (or higher) window will hide any newly opened normal
+ // browser windows, so here we just drop a raised window to the normal
+ // zlevel if it's maximized. We make no provision for automatically
+ // re-raising it when restored.
+ if (sizeMode == nsSizeMode_Maximized || sizeMode == nsSizeMode_Fullscreen) {
+ PRUint32 zLevel;
+ GetZLevel(&zLevel);
+ if (zLevel > nsIXULWindow::normalZ)
+ SetZLevel(nsIXULWindow::normalZ);
+ }
+ mWindow->SetSizeMode(sizeMode);
- // persist position, but not immediately, in case this OS is firing
- // repeated move events as the user drags the window
- eventWindow->SetPersistenceTimer(PAD_POSITION);
- break;
- }
- case NS_SIZE: {
- nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
- if (pm) {
- nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(docShell);
- pm->AdjustPopupsOnWindowChange(window);
- }
-
- nsSizeEvent* sizeEvent = (nsSizeEvent*)aEvent;
- nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(docShell));
- shellAsWin->SetPositionAndSize(0, 0, sizeEvent->windowSize->width,
- sizeEvent->windowSize->height, false);
- // persist size, but not immediately, in case this OS is firing
- // repeated size events as the user drags the sizing handle
- if (!eventWindow->IsLocked())
- eventWindow->SetPersistenceTimer(PAD_POSITION | PAD_SIZE | PAD_MISC);
- result = nsEventStatus_eConsumeNoDefault;
- break;
- }
- case NS_SIZEMODE: {
- nsSizeModeEvent* modeEvent = (nsSizeModeEvent*)aEvent;
+ // Persist mode, but not immediately, because in many (all?)
+ // cases this will merge with the similar call in NS_SIZE and
+ // write the attribute values only once.
+ SetPersistenceTimer(PAD_MISC);
+ nsCOMPtr<nsPIDOMWindow> ourWindow = do_GetInterface(mDocShell);
+ if (ourWindow) {
+ // Let the application know if it's in fullscreen mode so it
+ // can update its UI.
+ if (sizeMode == nsSizeMode_Fullscreen) {
+ ourWindow->SetFullScreen(true);
+ }
+ else if (sizeMode != nsSizeMode_Minimized) {
+ ourWindow->SetFullScreen(false);
+ }
- // an alwaysRaised (or higher) window will hide any newly opened
- // normal browser windows. here we just drop a raised window
- // to the normal zlevel if it's maximized. we make no provision
- // for automatically re-raising it when restored.
- if (modeEvent->mSizeMode == nsSizeMode_Maximized ||
- modeEvent->mSizeMode == nsSizeMode_Fullscreen) {
- PRUint32 zLevel;
- eventWindow->GetZLevel(&zLevel);
- if (zLevel > nsIXULWindow::normalZ)
- eventWindow->SetZLevel(nsIXULWindow::normalZ);
- }
-
- aEvent->widget->SetSizeMode(modeEvent->mSizeMode);
+ // And always fire a user-defined sizemodechange event on the window
+ ourWindow->DispatchCustomEvent("sizemodechange");
+ }
- // persist mode, but not immediately, because in many (all?)
- // cases this will merge with the similar call in NS_SIZE and
- // write the attribute values only once.
- eventWindow->SetPersistenceTimer(PAD_MISC);
- result = nsEventStatus_eConsumeDoDefault;
+ // Note the current implementation of SetSizeMode just stores
+ // the new state; it doesn't actually resize. So here we store
+ // the state and pass the event on to the OS. The day is coming
+ // when we'll handle the event here, and the return result will
+ // then need to be different.
+}
- nsCOMPtr<nsPIDOMWindow> ourWindow = do_GetInterface(docShell);
- if (ourWindow) {
- // Let the application know if it's in fullscreen mode so it
- // can update its UI.
- if (modeEvent->mSizeMode == nsSizeMode_Fullscreen) {
- ourWindow->SetFullScreen(true);
- }
- else if (modeEvent->mSizeMode != nsSizeMode_Minimized) {
- ourWindow->SetFullScreen(false);
- }
+void
+nsWebShellWindow::OSToolbarButtonPressed()
+{
+ // Keep a reference as setting the chrome flags can fire events.
+ nsCOMPtr<nsIXULWindow> xulWindow(this);
- // And always fire a user-defined sizemodechange event on the window
- ourWindow->DispatchCustomEvent("sizemodechange");
- }
+ // rjc: don't use "nsIWebBrowserChrome::CHROME_EXTRA"
+ // due to components with multiple sidebar components
+ // (such as Mail/News, Addressbook, etc)... and frankly,
+ // Mac IE, OmniWeb, and other Mac OS X apps all work this way
+ PRUint32 chromeMask = (nsIWebBrowserChrome::CHROME_TOOLBAR |
+ nsIWebBrowserChrome::CHROME_LOCATIONBAR |
+ nsIWebBrowserChrome::CHROME_PERSONAL_TOOLBAR);
+
+ nsCOMPtr<nsIWebBrowserChrome> wbc(do_GetInterface(xulWindow));
+ if (!wbc)
+ return;
- // Note the current implementation of SetSizeMode just stores
- // the new state; it doesn't actually resize. So here we store
- // the state and pass the event on to the OS. The day is coming
- // when we'll handle the event here, and the return result will
- // then need to be different.
- break;
- }
- case NS_OS_TOOLBAR: {
- nsCOMPtr<nsIXULWindow> kungFuDeathGrip(eventWindow);
- eventWindow->Toolbar();
- break;
- }
- case NS_XUL_CLOSE: {
- // Calling ExecuteCloseHandler may actually close the window
- // (it probably shouldn't, but you never know what the users JS
- // code will do). Therefore we add a death-grip to the window
- // for the duration of the close handler.
- nsCOMPtr<nsIXULWindow> kungFuDeathGrip(eventWindow);
- if (!eventWindow->ExecuteCloseHandler())
- eventWindow->Destroy();
- break;
- }
+ PRUint32 chromeFlags, newChromeFlags = 0;
+ wbc->GetChromeFlags(&chromeFlags);
+ newChromeFlags = chromeFlags & chromeMask;
+ if (!newChromeFlags) chromeFlags |= chromeMask;
+ else chromeFlags &= (~newChromeFlags);
+ wbc->SetChromeFlags(chromeFlags);
+}
- case NS_SETZLEVEL: {
- nsZLevelEvent *zEvent = (nsZLevelEvent *) aEvent;
-
- zEvent->mAdjusted = eventWindow->ConstrainToZLevel(zEvent->mImmediate,
- &zEvent->mPlacement,
- zEvent->mReqBelow, &zEvent->mActualBelow);
- break;
- }
+bool
+nsWebShellWindow::ZLevelChanged(bool aImmediate, nsWindowZ *aPlacement,
+ nsIWidget* aRequestBelow, nsIWidget** aActualBelow)
+{
+ if (aActualBelow)
+ *aActualBelow = nullptr;
- case NS_ACTIVATE: {
-#if defined(DEBUG_saari) || defined(DEBUG_smaug)
- printf("nsWebShellWindow::NS_ACTIVATE\n");
-#endif
- // focusing the window could cause it to close, so keep a reference to it
- nsCOMPtr<nsIXULWindow> kungFuDeathGrip(eventWindow);
+ return ConstrainToZLevel(aImmediate, aPlacement, aRequestBelow, aActualBelow);
+}
- nsCOMPtr<nsIDOMWindow> window = do_GetInterface(docShell);
- nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
- if (fm && window)
- fm->WindowRaised(window);
+void
+nsWebShellWindow::WindowActivated()
+{
+ nsCOMPtr<nsIXULWindow> xulWindow(this);
- if (eventWindow->mChromeLoaded) {
- eventWindow->PersistentAttributesDirty(
- PAD_POSITION | PAD_SIZE | PAD_MISC);
- eventWindow->SavePersistentAttributes();
- }
+ // focusing the window could cause it to close, so keep a reference to it
+ nsCOMPtr<nsIDOMWindow> window = do_GetInterface(mDocShell);
+ nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
+ if (fm && window)
+ fm->WindowRaised(window);
- break;
- }
-
- case NS_DEACTIVATE: {
-#if defined(DEBUG_saari) || defined(DEBUG_smaug)
- printf("nsWebShellWindow::NS_DEACTIVATE\n");
-#endif
+ if (mChromeLoaded) {
+ PersistentAttributesDirty(PAD_POSITION | PAD_SIZE | PAD_MISC);
+ SavePersistentAttributes();
+ }
+}
- nsCOMPtr<nsIDOMWindow> window = do_GetInterface(docShell);
- nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
- if (fm && window)
- fm->WindowLowered(window);
- break;
- }
-
- default:
- break;
+void
+nsWebShellWindow::WindowDeactivated()
+{
+ nsCOMPtr<nsIXULWindow> xulWindow(this);
- }
- }
- return result;
+ nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(mDocShell);
+ nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
+ if (fm && window)
+ fm->WindowLowered(window);
}
#ifdef USE_NATIVE_MENUS
static void LoadNativeMenus(nsIDOMDocument *aDOMDoc, nsIWidget *aParentWindow)
{
// Find the menubar tag (if there is more than one, we ignore all but
// the first).
nsCOMPtr<nsIDOMNodeList> menubarElements;
--- a/xpfe/appshell/src/nsWebShellWindow.h
+++ b/xpfe/appshell/src/nsWebShellWindow.h
@@ -7,26 +7,28 @@
#define nsWebShellWindow_h__
#include "mozilla/Mutex.h"
#include "nsEvent.h"
#include "nsIWebProgressListener.h"
#include "nsITimer.h"
#include "nsCOMPtr.h"
#include "nsXULWindow.h"
+#include "nsIWidgetListener.h"
/* Forward declarations.... */
class nsIURI;
namespace mozilla {
class WebShellWindowTimerCallback;
} // namespace mozilla
class nsWebShellWindow : public nsXULWindow,
- public nsIWebProgressListener
+ public nsIWebProgressListener,
+ public nsIWidgetListener
{
public:
nsWebShellWindow(PRUint32 aChromeFlags);
// nsISupports interface...
NS_DECL_ISUPPORTS_INHERITED
// nsWebShellWindow methods...
@@ -39,16 +41,29 @@ public:
nsresult Toolbar();
// nsIWebProgressListener
NS_DECL_NSIWEBPROGRESSLISTENER
// nsIBaseWindow
NS_IMETHOD Destroy();
+ // nsIWidgetListener
+ virtual nsIXULWindow* GetXULWindow() { return this; }
+
+ virtual bool WindowMoved(nsIWidget* aWidget, PRInt32 x, PRInt32 y);
+ virtual bool WindowResized(nsIWidget* aWidget, PRInt32 aWidth, PRInt32 aHeight);
+ virtual bool RequestWindowClose(nsIWidget* aWidget);
+ virtual void SizeModeChanged(nsSizeMode sizeMode);
+ virtual void OSToolbarButtonPressed();
+ virtual bool ZLevelChanged(bool aImmediate, nsWindowZ *aPlacement,
+ nsIWidget* aRequestBelow, nsIWidget** aActualBelow);
+ virtual void WindowActivated();
+ virtual void WindowDeactivated();
+
protected:
friend class mozilla::WebShellWindowTimerCallback;
virtual ~nsWebShellWindow();
void LoadContentAreas();
bool ExecuteCloseHandler();
void ConstrainToOpenerScreen(PRInt32* aX, PRInt32* aY);
--- a/xpfe/appshell/src/nsXULWindow.cpp
+++ b/xpfe/appshell/src/nsXULWindow.cpp
@@ -503,17 +503,17 @@ NS_IMETHODIMP nsXULWindow::Destroy()
mPrimaryContentTreeOwner->XULWindow(nullptr);
NS_RELEASE(mPrimaryContentTreeOwner);
}
if (mChromeTreeOwner) {
mChromeTreeOwner->XULWindow(nullptr);
NS_RELEASE(mChromeTreeOwner);
}
if (mWindow) {
- mWindow->SetClientData(0); // nsWebShellWindow hackery
+ mWindow->SetWidgetListener(nullptr); // nsWebShellWindow hackery
mWindow->Destroy();
mWindow = nullptr;
}
if (!mIsHiddenWindow) {
/* Inform appstartup we've destroyed this window and it could
quit now if it wanted. This must happen at least after mDocShell
is destroyed, because onunload handlers fire then, and those being
@@ -1874,21 +1874,17 @@ bool nsXULWindow::ConstrainToZLevel(bool
}
/* CalculateZPosition can tell us to be below nothing, because it tries
not to change something it doesn't recognize. A request to verify
being below an unrecognized window, then, is treated as a request
to come to the top (below null) */
nsCOMPtr<nsIXULWindow> windowAbove;
if (newPosition == nsIWindowMediator::zLevelBelow && *aActualBelow) {
- void *data;
- (*aActualBelow)->GetClientData(data);
- if (data) {
- windowAbove = reinterpret_cast<nsWebShellWindow*>(data);
- }
+ windowAbove = (*aActualBelow)->GetWidgetListener()->GetXULWindow();
}
mediator->SetZPosition(us, newPosition, windowAbove);
}
return altered;
}