Bug 743975 - use a widget listener interface instead of the remaining events that don't need an event, r=tn,jmathies,netzen,smichaud,karlt,blassey,chrisjones

This commit is contained in:
Neil Deakin 2012-08-15 14:52:42 -04:00
parent 193db1ca6c
commit 0413e44a55
29 changed files with 924 additions and 1105 deletions

View File

@ -70,6 +70,7 @@
#include "nsIFrame.h"
#include "nsCanvasFrame.h"
#include "nsIWidget.h"
#include "nsIWidgetListener.h"
#include "nsIBaseWindow.h"
#include "nsDeviceSensors.h"
#include "nsIContent.h"
@ -7708,10 +7709,11 @@ nsGlobalWindow::ActivateOrDeactivate(bool aActivate)
// 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) {

View File

@ -92,7 +92,7 @@ NS_IMETHODIMP nsWebBrowser::InternalDestroy()
{
if (mInternalWidget) {
mInternalWidget->SetClientData(0);
mInternalWidget->SetWidgetListener(nullptr);
mInternalWidget->Destroy();
mInternalWidget = nullptr; // Force release here.
}
@ -1118,8 +1118,8 @@ NS_IMETHODIMP nsWebBrowser::Create()
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);
}
@ -1659,69 +1659,45 @@ static void DrawThebesLayer(ThebesLayer* aLayer,
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");
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;
}
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());
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
browser->Activate();
break;
}
Activate();
}
case NS_DEACTIVATE: {
void nsWebBrowser::WindowLowered(nsIWidget* aWidget)
{
#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());
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
browser->Deactivate();
break;
Deactivate();
}
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);
}
default:
break;
}
return nsEventStatus_eIgnore;
layerManager->EndTransaction(DrawThebesLayer, &mBackgroundColor);
return true;
}
NS_IMETHODIMP nsWebBrowser::GetPrimaryContentWindow(nsIDOMWindow** aDOMWindow)

View File

@ -36,6 +36,7 @@
#include "nsIWindowWatcher.h"
#include "nsIPrintSettings.h"
#include "nsEmbedStream.h"
#include "nsIWidgetListener.h"
#include "nsTArray.h"
#include "nsWeakPtr.h"
@ -84,6 +85,7 @@ class nsWebBrowser : public nsIWebBrowser,
public nsIWebBrowserFocus,
public nsIWebProgressListener,
public nsIWebBrowserStream,
public nsIWidgetListener,
public nsSupportsWeakReference
{
friend class nsDocShellTreeOwner;
@ -119,7 +121,10 @@ protected:
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;

View File

@ -7,27 +7,34 @@
#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)
@ -39,6 +46,75 @@ class ViewWrapper MOZ_FINAL : public nsIInterfaceRequestor
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)
@ -93,23 +169,7 @@ NS_IMETHODIMP ViewWrapper::GetInterface(REFNSIID aIID, void** aInstancePtr)
*/
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
@ -256,7 +316,7 @@ void nsView::DestroyWidget()
mWindow->SetAttachedViewPtr(nullptr);
}
else {
mWindow->SetClientData(nullptr);
mWindow->SetWidgetListener(nullptr);
mWindow->Destroy();
}
@ -788,7 +848,7 @@ nsView::InitializeWindow(bool aEnableDragDrop, bool aResetVisibility)
ViewWrapper* wrapper = new ViewWrapper(this);
NS_ADDREF(wrapper); // Will be released in ~nsView
mWindow->SetClientData(wrapper);
mWindow->SetWidgetListener(wrapper);
if (aEnableDragDrop) {
mWindow->EnableDragDrop(true);
@ -879,7 +939,7 @@ void nsView::AssertNoWindow()
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);
}
@ -891,16 +951,14 @@ void nsView::AssertNoWindow()
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;
}
@ -909,7 +967,7 @@ 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

View File

@ -645,252 +645,125 @@ void nsViewManager::InvalidateViews(nsView *aView)
}
}
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);
}
}
return false;
// 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();
}
NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent,
nsIView* aView, nsEventStatus *aStatus)
{
NS_ASSERTION(!aView || static_cast<nsView*>(aView)->GetViewManager() == this,
"wrong view manager");
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 true;
}
void nsViewManager::DidPaintWindow()
{
if (!IsRefreshDriverPaintingEnabled()) {
mRootViewManager->CallDidPaintOnObserver();
}
}
nsresult nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsIView* aView, nsEventStatus* aStatus)
{
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);
}
// 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;
}

View File

@ -168,6 +168,11 @@ public: // NOT in nsIViewManager, so private to the view module
// 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();

View File

@ -72,6 +72,7 @@ EXPORTS = \
nsINativeKeyBindings.h \
nsIDeviceContextSpec.h \
nsIRollupListener.h \
nsIWidgetListener.h \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)

View File

@ -22,6 +22,7 @@ using mozilla::unused;
#include "nsWindow.h"
#include "nsIObserverService.h"
#include "nsFocusManager.h"
#include "nsIWidgetListener.h"
#include "nsRenderingContext.h"
#include "nsIDOMSimpleGestureEvent.h"
@ -570,8 +571,10 @@ nsWindow::BringToFront()
gTopLevelWindows.InsertElementAt(0, this);
if (oldTop) {
nsGUIEvent event(true, NS_DEACTIVATE, oldTop);
DispatchEvent(&event);
nsIWidgetListener* listener = oldTop->GetWidgetListener();
if (listener) {
listener->WindowDeactivated();
}
}
if (Destroyed()) {
@ -583,8 +586,9 @@ nsWindow::BringToFront()
newTop = gTopLevelWindows[0];
}
nsGUIEvent event(true, NS_ACTIVATE, newTop);
DispatchEvent(&event);
if (mWidgetListener) {
mWidgetListener->WindowActivated();
}
// force a window resize
nsAppShell::gAppShell->ResendLastResizeEvent(newTop);
@ -964,11 +968,10 @@ 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
@ -984,8 +987,8 @@ nsWindow::DrawTo(gfxASurface *targetSurface, const nsIntRect &invalidRect)
// 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: {
@ -997,13 +1000,13 @@ nsWindow::DrawTo(gfxASurface *targetSurface, const nsIntRect &invalidRect)
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
@ -1017,7 +1020,7 @@ nsWindow::DrawTo(gfxASurface *targetSurface, const nsIntRect &invalidRect)
static_cast<mozilla::layers::LayerManagerOGL*>(GetLayerManager(nullptr))->
SetClippingRegion(nsIntRegion(boundsRect));
status = DispatchEvent(&event);
painted = mWidgetListener->PaintWindow(this, region, false, false);
break;
}
@ -1227,24 +1230,14 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
void
nsWindow::OnSizeChanged(const gfxIntSize& aSize)
{
int w = aSize.width;
int h = aSize.height;
ALOG("nsWindow: %p OnSizeChanged [%d %d]", (void*)this, aSize.width, aSize.height);
ALOG("nsWindow: %p OnSizeChanged [%d %d]", (void*)this, w, h);
mBounds.width = aSize.width;
mBounds.height = aSize.height;
nsRefPtr<nsWindow> kungFuDeathGrip(this);
nsSizeEvent event(true, NS_SIZE, this);
InitEvent(event);
nsIntRect wsz(0, 0, w, h);
event.windowSize = &wsz;
event.mWinWidth = w;
event.mWinHeight = h;
mBounds.width = w;
mBounds.height = h;
DispatchEvent(&event);
if (mWidgetListener) {
mWidgetListener->WindowResized(this, aSize.width, aSize.height);
}
}
void

View File

@ -479,7 +479,9 @@ public:
// Mac specific methods
virtual bool DispatchWindowEvent(nsGUIEvent& event);
bool PaintWindow(nsIntRegion aRegion);
#ifdef ACCESSIBILITY
already_AddRefed<Accessible> GetDocumentAccessible();
#endif
@ -519,8 +521,8 @@ public:
protected:
bool ReportMoveEvent();
bool ReportSizeEvent();
void ReportMoveEvent();
void ReportSizeEvent();
// override to create different kinds of child views. Autoreleases, so
// caller must retain.

View File

@ -31,6 +31,7 @@
#include "nsIDOMSimpleGestureEvent.h"
#include "nsNPAPIPluginInstance.h"
#include "nsThemeConstants.h"
#include "nsIWidgetListener.h"
#include "nsDragService.h"
#include "nsClipboard.h"
@ -1466,23 +1467,18 @@ NS_IMETHODIMP nsChildView::DispatchEvent(nsGUIEvent* event, nsEventStatus& aStat
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;
}
@ -1493,25 +1489,44 @@ bool nsChildView::DispatchWindowEvent(nsGUIEvent &event)
return ConvertStatus(status);
}
#pragma mark -
bool nsChildView::ReportMoveEvent()
bool nsChildView::PaintWindow(nsIntRegion aRegion)
{
nsGUIEvent moveEvent(true, NS_MOVE, this);
moveEvent.refPoint.x = mBounds.x;
moveEvent.refPoint.y = mBounds.y;
moveEvent.time = PR_IntervalNow();
return DispatchWindowEvent(moveEvent);
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;
}
bool nsChildView::ReportSizeEvent()
#pragma mark -
void nsChildView::ReportMoveEvent()
{
nsSizeEvent sizeEvent(true, NS_SIZE, this);
sizeEvent.time = PR_IntervalNow();
sizeEvent.windowSize = &mBounds;
sizeEvent.mWinWidth = mBounds.width;
sizeEvent.mWinHeight = mBounds.height;
return DispatchWindowEvent(sizeEvent);
if (mWidgetListener)
mWidgetListener->WindowMoved(this, mBounds.x, mBounds.y);
}
void nsChildView::ReportSizeEvent()
{
if (mWidgetListener)
mWidgetListener->WindowResized(this, mBounds.width, mBounds.height);
}
#pragma mark -
@ -2493,9 +2508,7 @@ NSEvent* gLastDragMouseDownEvent = nil;
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);
@ -2506,12 +2519,11 @@ NSEvent* gLastDragMouseDownEvent = nil;
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
@ -2524,8 +2536,7 @@ NSEvent* gLastDragMouseDownEvent = nil;
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
@ -2535,7 +2546,7 @@ NSEvent* gLastDragMouseDownEvent = nil;
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) {
@ -2545,7 +2556,7 @@ NSEvent* gLastDragMouseDownEvent = nil;
[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.
@ -2566,7 +2577,7 @@ NSEvent* gLastDragMouseDownEvent = nil;
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();
@ -2581,7 +2592,7 @@ NSEvent* gLastDragMouseDownEvent = nil;
{
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
@ -2641,7 +2652,7 @@ NSEvent* gLastDragMouseDownEvent = nil;
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
@ -2663,8 +2674,11 @@ NSEvent* gLastDragMouseDownEvent = nil;
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];
}
@ -4288,7 +4302,9 @@ static PRInt32 RoundUp(double aDouble)
if (isMozWindow)
[[self window] setSuppressMakeKeyFront:YES];
[self sendFocusEvent:NS_ACTIVATE];
nsIWidgetListener* listener = mGeckoChild->GetWidgetListener();
if (listener)
listener->WindowActivated();
if (isMozWindow)
[[self window] setSuppressMakeKeyFront:NO];
@ -4303,7 +4319,9 @@ static PRInt32 RoundUp(double aDouble)
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::

View File

@ -151,7 +151,6 @@ typedef struct _nsCocoaWindowList {
+ (void)paintMenubarForWindow:(NSWindow*)aWindow;
- (id)initWithGeckoWindow:(nsCocoaWindow*)geckoWind;
- (void)windowDidResize:(NSNotification*)aNotification;
- (void)sendFocusEvent:(PRUint32)eventType;
- (nsCocoaWindow*)geckoWidget;
- (bool)toplevelActiveState;
- (void)sendToplevelActivateEvents;

View File

@ -29,6 +29,7 @@
#include "nsChildView.h"
#include "nsCocoaFeatures.h"
#include "nsIScreenManager.h"
#include "nsIWidgetListener.h"
#include "gfxPlatform.h"
#include "qcms.h"
@ -1407,17 +1408,10 @@ bool nsCocoaWindow::DragEvent(unsigned int aMessage, Point aMouseGlobal, UInt16
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;
}
@ -1517,12 +1511,8 @@ nsCocoaWindow::ReportMoveEvent()
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;
@ -1546,12 +1536,9 @@ nsCocoaWindow::DispatchSizeModeEvent()
}
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
@ -1561,17 +1548,11 @@ nsCocoaWindow::ReportSizeEvent()
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;
}
@ -2136,11 +2117,9 @@ bool nsCocoaWindow::ShouldFocusPlugin()
- (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
}
@ -2175,17 +2154,6 @@ bool nsCocoaWindow::ShouldFocusPlugin()
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;
@ -2217,16 +2185,20 @@ bool nsCocoaWindow::ShouldFocusPlugin()
- (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;
}
}
@ -2677,10 +2649,10 @@ static const NSString* kStateShowsToolbarButton = @"showsToolbarButton";
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;

View File

@ -34,6 +34,7 @@
#include "nsScreenManagerGonk.h"
#include "nsTArray.h"
#include "nsWindow.h"
#include "nsIWidgetListener.h"
#include "cutils/properties.h"
#include "BasicLayers.h"
@ -105,16 +106,12 @@ public:
{}
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;
@ -236,16 +233,17 @@ nsWindow::DoDraw(void)
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;
@ -257,19 +255,21 @@ nsWindow::DoDraw(void)
{
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");
@ -393,16 +393,9 @@ nsWindow::Resize(PRInt32 aX,
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 = &rect;
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);
@ -624,15 +617,15 @@ 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);
}

View File

@ -20,6 +20,7 @@
#include "nsWidgetsCID.h"
#include "nsDragService.h"
#include "nsIWidgetListener.h"
#include "nsGtkKeyUtils.h"
#include "nsGtkCursors.h"
@ -419,21 +420,6 @@ nsWindow::CommonCreate(nsIWidget *aParent, bool 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)
{
@ -443,17 +429,16 @@ nsWindow::DispatchActivateEvent(void)
#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();
@ -1084,11 +1069,10 @@ nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, bool aRepaint)
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;
@ -1153,10 +1137,8 @@ nsWindow::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight,
NotifyRollupGeometryChange(gRollupListener);
if (mIsTopLevel || mListenForResizes) {
// synthesize a resize event
nsIntRect rect(aX, aY, aWidth, aHeight);
nsEventStatus status;
DispatchResizeEvent(rect, status);
if (mWidgetListener)
mWidgetListener->WindowResized(this, aWidth, aHeight);
}
return NS_OK;
@ -1453,7 +1435,7 @@ nsWindow::SetFocus(bool aRaise)
// 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;
@ -2021,14 +2003,6 @@ gdk_window_flash(GdkWindow * aGdkWindow,
#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)
@ -2045,23 +2019,18 @@ nsWindow::OnExposeEvent(cairo_t *cr)
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 (mWidgetListener)
mWidgetListener->WillPaintWindow(this, true);
// If the window has been destroyed during WILL_PAINT, there is
// nothing left to do.
// 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;
@ -2093,6 +2062,8 @@ nsWindow::OnExposeEvent(cairo_t *cr)
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;
@ -2102,15 +2073,14 @@ nsWindow::OnExposeEvent(cairo_t *cr)
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) {
@ -2126,14 +2096,14 @@ nsWindow::OnExposeEvent(cairo_t *cr)
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
@ -2151,24 +2121,28 @@ nsWindow::OnExposeEvent(cairo_t *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);
manager->SetClippingRegion(region);
nsEventStatus status;
DispatchEvent(&event, status);
if (mWidgetListener)
mWidgetListener->PaintWindow(this, region, true, true);
g_free(rects);
DispatchDidPaint(this);
if (mWidgetListener)
mWidgetListener->DidPaintWindow();
return TRUE;
}
@ -2188,11 +2162,11 @@ nsWindow::OnExposeEvent(cairo_t *cr)
// 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();
@ -2226,18 +2200,20 @@ nsWindow::OnExposeEvent(cairo_t *cr)
#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 =
@ -2281,7 +2257,8 @@ nsWindow::OnExposeEvent(cairo_t *cr)
cairo_rectangle_list_destroy(rects);
#endif
DispatchDidPaint(this);
if (mWidgetListener)
mWidgetListener->DidPaintWindow();
// Synchronously flush any new dirty areas
#if defined(MOZ_WIDGET_GTK2)
@ -2357,7 +2334,7 @@ nsWindow::OnConfigureEvent(GtkWidget *aWidget, GdkEventConfigure *aEvent)
// 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.
@ -2366,14 +2343,10 @@ nsWindow::OnConfigureEvent(GtkWidget *aWidget, GdkEventConfigure *aEvent)
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;
}
@ -2418,20 +2391,15 @@ nsWindow::OnSizeAllocate(GtkWidget *aWidget, GtkAllocation *aAllocation)
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
@ -2830,15 +2798,15 @@ nsWindow::OnContainerFocusInEvent(GtkWidget *aWidget, GdkEventFocus *aEvent)
// 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();
@ -3214,8 +3182,6 @@ nsWindow::OnWindowStateEvent(GtkWidget *aWidget, GdkEventWindowState *aEvent)
}
// 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
@ -3227,7 +3193,6 @@ nsWindow::OnWindowStateEvent(GtkWidget *aWidget, GdkEventWindowState *aEvent)
if (aEvent->new_window_state & GDK_WINDOW_STATE_ICONIFIED) {
LOG(("\tIconified\n"));
event.mSizeMode = nsSizeMode_Minimized;
mSizeState = nsSizeMode_Minimized;
#ifdef ACCESSIBILITY
DispatchMinimizeEventAccessible();
@ -3235,12 +3200,10 @@ nsWindow::OnWindowStateEvent(GtkWidget *aWidget, GdkEventWindowState *aEvent)
}
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();
@ -3248,15 +3211,14 @@ nsWindow::OnWindowStateEvent(GtkWidget *aWidget, GdkEventWindowState *aEvent)
}
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
@ -5850,8 +5812,6 @@ nsWindow::DispatchEventToRootAccessible(PRUint32 aEventType)
}
}
// XXXndeakin what is all this for? Accessibility should be receiving these
// notifications of gtk the same as other platforms.
void
nsWindow::DispatchActivateEventAccessible(void)
{

View File

@ -85,7 +85,6 @@ public:
// event handling code
void DispatchActivateEvent(void);
void DispatchDeactivateEvent(void);
void DispatchResizeEvent(nsIntRect &aRect, nsEventStatus &aStatus);
virtual nsresult DispatchEvent(nsGUIEvent *aEvent, nsEventStatus &aStatus);
@ -363,7 +362,7 @@ private:
mIsFullyObscured : 1,
mRetryPointerGrab : 1;
GtkWindow *mTransientParent;
PRInt32 mSizeState;
nsSizeMode mSizeState;
PluginType mPluginType;
PRInt32 mTransparencyBitmapWidth;

View File

@ -35,6 +35,7 @@ class imgIContainer;
class gfxASurface;
class nsIContent;
class ViewWrapper;
class nsIWidgetListener;
namespace mozilla {
namespace dom {
@ -87,8 +88,8 @@ typedef nsEventStatus (* EVENT_CALLBACK)(nsGUIEvent *event);
#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
@ -493,12 +494,12 @@ class nsIWidget : public nsISupports {
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;
//@}
/**

129
widget/nsIWidgetListener.h Normal file
View File

@ -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

View File

@ -68,6 +68,7 @@ using namespace QtMobility;
#include "nsQtKeyUtils.h"
#include "mozilla/Services.h"
#include "mozilla/Preferences.h"
#include "nsIWidgetListener.h"
#include "nsIStringBundle.h"
#include "nsGfxCIID.h"
@ -659,6 +660,8 @@ nsWindow::SetFocus(bool aRaise)
else
realFocusItem->setFocus(Qt::OtherFocusReason);
// XXXndeakin why is this here? It should dispatch only when the OS
// notifies us.
DispatchActivateEvent();
return NS_OK;
@ -992,34 +995,23 @@ GetSurfaceForQWidget(QWidget* aDrawable)
}
#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)
@ -1033,7 +1025,7 @@ nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption, Q
if (!mDirtyScrollArea.isEmpty())
mDirtyScrollArea = QRegion();
nsEventStatus status;
bool painted = false;
nsIntRect rect(r.x(), r.y(), r.width(), r.height());
nsFastStartup* startup = nsFastStartup::GetSingleton();
@ -1043,13 +1035,9 @@ nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption, Q
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()));
@ -1061,10 +1049,12 @@ nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption, Q
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();
@ -1074,7 +1064,7 @@ nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption, Q
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;
@ -1084,13 +1074,13 @@ nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption, Q
#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);
@ -1113,24 +1103,22 @@ nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption, Q
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;
return painted;
if (status == nsEventStatus_eIgnore)
return status;
if (!painted)
return false;
LOGDRAW(("[%p] draw done\n", this));
@ -1193,10 +1181,11 @@ nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption, Q
ctx = nullptr;
targetSurface = nullptr;
DispatchDidPaint(this);
if (mWidgetListener)
mWidgetListener->DidPaintWindow();
// check the return value!
return status;
return painted;
}
nsEventStatus
@ -1206,7 +1195,7 @@ nsWindow::OnMoveEvent(QGraphicsSceneHoverEvent *aEvent)
aEvent->pos().x(), aEvent->pos().y()));
// can we shortcut?
if (!mWidget)
if (!mWidget || !mWidgetListener)
return nsEventStatus_eIgnore;
if ((mBounds.x == aEvent->pos().x() &&
@ -1215,14 +1204,8 @@ nsWindow::OnMoveEvent(QGraphicsSceneHoverEvent *aEvent)
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
@ -1247,12 +1230,10 @@ nsWindow::OnResizeEvent(QGraphicsSceneResizeEvent *aEvent)
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
@ -2846,17 +2827,15 @@ nsWindow::GetDPI()
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
@ -2878,16 +2857,10 @@ nsWindow::DispatchDeactivateEventOnTopLevelWindow(void)
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

View File

@ -82,7 +82,7 @@ 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();

View File

@ -115,6 +115,7 @@
#include "WinTaskbar.h"
#include "WinUtils.h"
#include "WidgetUtils.h"
#include "nsIWidgetListener.h"
#ifdef MOZ_ENABLE_D3D9_LAYER
#include "LayerManagerD3D9.h"
@ -1587,10 +1588,9 @@ NS_IMETHODIMP nsWindow::SetSizeMode(PRInt32 aMode) {
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;
}
@ -2700,11 +2700,8 @@ nsWindow::MakeFullScreen(bool aFullScreen)
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;
}
@ -3489,28 +3486,11 @@ NS_IMETHODIMP nsWindow::DispatchEvent(nsGUIEvent* event, nsEventStatus & aStatus
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);
}
@ -3947,12 +3927,18 @@ bool nsWindow::DispatchMouseEvent(PRUint32 aEventType, WPARAM wParam,
return result;
}
bool nsWindow::DispatchFocusToTopLevelWindow(PRUint32 aEventType)
void nsWindow::DispatchFocusToTopLevelWindow(bool aIsActivate)
{
if (aEventType == NS_ACTIVATE)
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;
@ -3972,47 +3958,13 @@ bool nsWindow::DispatchFocusToTopLevelWindow(PRUint32 aEventType)
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;
if (win) {
if (aIsActivate)
mWidgetListener->WindowActivated();
else
mWidgetListener->WindowDeactivated();
}
event.pluginEvent = (void *)&pluginEvent;
return DispatchWindowEvent(&event);
}
return false;
}
bool nsWindow::IsTopLevelMouseExit(HWND aWnd)
@ -4687,7 +4639,8 @@ bool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam,
break;
case WM_CLOSE: // close request
DispatchStandardEvent(NS_XUL_CLOSE);
if (mWidgetListener)
mWidgetListener->RequestWindowClose(this);
result = true; // abort window closure
break;
@ -4976,18 +4929,17 @@ bool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam,
// 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;
@ -5054,13 +5006,13 @@ bool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam,
ForgetRedirectedKeyDownMessage();
}
if (sJustGotActivate) {
result = DispatchFocusToTopLevelWindow(NS_ACTIVATE);
DispatchFocusToTopLevelWindow(true);
}
break;
case WM_KILLFOCUS:
if (sJustGotDeactivate) {
result = DispatchFocusToTopLevelWindow(NS_DEACTIVATE);
DispatchFocusToTopLevelWindow(false);
}
break;
@ -5314,7 +5266,7 @@ bool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam,
} else {
// WM_KILLFOCUS was received by the child process.
if (sJustGotDeactivate) {
DispatchFocusToTopLevelWindow(NS_DEACTIVATE);
DispatchFocusToTopLevelWindow(false);
}
}
}
@ -5930,36 +5882,32 @@ void nsWindow::OnWindowPosChanged(WINDOWPOS *wp, bool& result)
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
@ -5982,15 +5930,14 @@ void nsWindow::OnWindowPosChanged(WINDOWPOS *wp, bool& result)
};
#endif
InitEvent(event);
if (mWidgetListener)
mWidgetListener->SizeModeChanged(mSizeMode);
result = DispatchWindowEvent(&event);
// If window was restored, NS_ACTIVATE dispatch was bypassed during the
// 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)
@ -6117,7 +6064,7 @@ void nsWindow::OnWindowPosChanging(LPWINDOWPOS& info)
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)
@ -6127,11 +6074,8 @@ void nsWindow::OnWindowPosChanging(LPWINDOWPOS& info)
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);
}
@ -6139,37 +6083,32 @@ void nsWindow::OnWindowPosChanging(LPWINDOWPOS& info)
// 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);
nsWindow *aboveWindow = 0;
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)
@ -7073,12 +7012,7 @@ 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
@ -7091,31 +7025,8 @@ bool nsWindow::OnResize(nsIntRect &aWindowRect)
}
#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)

View File

@ -329,8 +329,7 @@ protected:
* 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);

View File

@ -34,6 +34,7 @@ using mozilla::plugins::PluginInstanceParent;
#include "nsRenderingContext.h"
#include "prmem.h"
#include "WinUtils.h"
#include "nsIWidgetListener.h"
#include "mozilla/unused.h"
#include "LayerManagerOGL.h"
@ -234,13 +235,12 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32 aNestingLevel)
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))
@ -277,20 +277,13 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32 aNestingLevel)
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
@ -298,7 +291,7 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32 aNestingLevel)
#ifdef WIDGET_DEBUG_OUTPUT
debug_DumpPaintEvent(stdout,
this,
&event,
region,
nsCAutoString("noname"),
(PRInt32) mWnd);
#endif // WIDGET_DEBUG_OUTPUT
@ -385,7 +378,7 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32 aNestingLevel)
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);
}
@ -422,7 +415,7 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32 aNestingLevel)
{
AutoLayerManagerSetup
setupLayerManager(this, thebesContext, doubleBuffering);
result = DispatchWindowEvent(&event, eventStatus);
result = mWidgetListener->PaintWindow(this, region, true, true);
}
#ifdef MOZ_XUL
@ -536,16 +529,16 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32 aNestingLevel)
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;
@ -565,7 +558,7 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32 aNestingLevel)
if (layerManagerD3D10->device() != gfxWindowsPlatform::GetPlatform()->GetD3D10Device()) {
Invalidate();
} else {
result = DispatchWindowEvent(&event, eventStatus);
result = mWidgetListener->PaintWindow(this, region, true, true);
}
}
break;
@ -589,7 +582,7 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32 aNestingLevel)
// 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);
@ -602,8 +595,8 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32 aNestingLevel)
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);

View File

@ -17,6 +17,7 @@
#include "mozilla/layers/CompositorChild.h"
#include "mozilla/layers/PLayersChild.h"
#include "PuppetWidget.h"
#include "nsIWidgetListener.h"
using namespace mozilla::dom;
using namespace mozilla::hal;
@ -184,8 +185,11 @@ PuppetWidget::Resize(PRInt32 aWidth,
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;
@ -476,63 +480,43 @@ PuppetWidget::SetCursor(nsCursor aCursor)
}
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 = &rect;
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)
{
@ -547,7 +531,7 @@ NS_IMETHODIMP
PuppetWidget::PaintTask::Run()
{
if (mWidget) {
mWidget->DispatchPaintEvent();
mWidget->Paint();
}
return NS_OK;
}

View File

@ -166,8 +166,7 @@ public:
virtual float GetDPI();
private:
nsresult DispatchPaintEvent();
nsresult DispatchResizeEvent();
nsresult Paint();
void SetChild(PuppetWidget* aChild);

View File

@ -28,6 +28,7 @@
#include "nsView.h"
#include "nsIViewManager.h"
#include "nsEventStateManager.h"
#include "nsIWidgetListener.h"
#include "nsIGfxInfo.h"
#include "npapi.h"
#include "base/thread.h"
@ -86,7 +87,7 @@ nsAutoRollup::~nsAutoRollup()
//-------------------------------------------------------------------------
nsBaseWidget::nsBaseWidget()
: mClientData(nullptr)
: mWidgetListener(nullptr)
, mViewWrapperPtr(nullptr)
, mEventCallback(nullptr)
, mViewCallback(nullptr)
@ -232,16 +233,14 @@ NS_IMETHODIMP nsBaseWidget::CaptureMouse(bool aCapture)
//
//-------------------------------------------------------------------------
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>
@ -1346,11 +1345,12 @@ 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));
@ -1373,9 +1373,13 @@ static nsIPresShell* GetPresShell(nsIWidget* aWidget, void* clientData)
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();
}
}
@ -1410,8 +1414,7 @@ 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();
@ -1426,7 +1429,7 @@ nsBaseWidget::NotifyUIStateChanged(UIStateChangeType aShowAccelerators,
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
@ -1684,18 +1687,17 @@ nsBaseWidget::debug_DumpEvent(FILE * aFileOut,
/* 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(),

View File

@ -64,8 +64,8 @@ public:
// 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);
@ -331,7 +331,7 @@ protected:
*/
void DestroyCompositor();
void* mClientData;
nsIWidgetListener* mWidgetListener;
ViewWrapper* mViewWrapperPtr;
EVENT_CALLBACK mEventCallback;
EVENT_CALLBACK mViewCallback;
@ -383,7 +383,7 @@ protected:
static void debug_DumpPaintEvent(FILE * aFileOut,
nsIWidget * aWidget,
nsPaintEvent * aPaintEvent,
const nsIntRegion & aPaintEvent,
const nsCAutoString & aWidgetName,
PRInt32 aWindowID);

View File

@ -30,6 +30,7 @@
#include "nsGUIEvent.h"
#include "nsWidgetsCID.h"
#include "nsIWidget.h"
#include "nsIWidgetListener.h"
#include "nsIDOMCharacterData.h"
#include "nsIDOMNodeList.h"
@ -159,12 +160,12 @@ nsresult nsWebShellWindow::Initialize(nsIXULWindow* aParent,
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
@ -216,208 +217,168 @@ nsresult nsWebShellWindow::Initialize(nsIXULWindow* aParent,
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;
// Get the WebShell instance...
if (nullptr != aEvent->widget) {
void* data;
aEvent->widget->GetClientData(data);
if (data != nullptr) {
eventWindow = reinterpret_cast<nsWebShellWindow *>(data);
docShell = eventWindow->mDocShell;
}
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
if (pm) {
nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(mDocShell);
pm->AdjustPopupsOnWindowChange(window);
}
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);
}
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;
}
// 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;
bool
nsWebShellWindow::RequestWindowClose(nsIWidget* aWidget)
{
// Maintain a reference to this as it is about to get destroyed.
nsCOMPtr<nsIXULWindow> xulWindow(this);
// 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);
}
nsCOMPtr<nsPIDOMWindow> window(do_GetInterface(mDocShell));
nsCOMPtr<nsIDOMEventTarget> eventTarget = do_QueryInterface(window);
aEvent->widget->SetSizeMode(modeEvent->mSizeMode);
nsCOMPtr<nsIPresShell> presShell;
mDocShell->GetPresShell(getter_AddRefs(presShell));
// 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;
if (eventTarget) {
nsRefPtr<nsPresContext> presContext = presShell->GetPresContext();
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);
}
// And always fire a user-defined sizemodechange event on the window
ourWindow->DispatchCustomEvent("sizemodechange");
}
// 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;
}
case NS_SETZLEVEL: {
nsZLevelEvent *zEvent = (nsZLevelEvent *) aEvent;
zEvent->mAdjusted = eventWindow->ConstrainToZLevel(zEvent->mImmediate,
&zEvent->mPlacement,
zEvent->mReqBelow, &zEvent->mActualBelow);
break;
}
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);
nsCOMPtr<nsIDOMWindow> window = do_GetInterface(docShell);
nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
if (fm && window)
fm->WindowRaised(window);
if (eventWindow->mChromeLoaded) {
eventWindow->PersistentAttributesDirty(
PAD_POSITION | PAD_SIZE | PAD_MISC);
eventWindow->SavePersistentAttributes();
}
break;
}
case NS_DEACTIVATE: {
#if defined(DEBUG_saari) || defined(DEBUG_smaug)
printf("nsWebShellWindow::NS_DEACTIVATE\n");
#endif
nsCOMPtr<nsIDOMWindow> window = do_GetInterface(docShell);
nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
if (fm && window)
fm->WindowLowered(window);
break;
}
default:
break;
}
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;
}
return result;
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 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);
}
// And always fire a user-defined sizemodechange event on the window
ourWindow->DispatchCustomEvent("sizemodechange");
}
// 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.
}
void
nsWebShellWindow::OSToolbarButtonPressed()
{
// Keep a reference as setting the chrome flags can fire events.
nsCOMPtr<nsIXULWindow> xulWindow(this);
// 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;
PRUint32 chromeFlags, newChromeFlags = 0;
wbc->GetChromeFlags(&chromeFlags);
newChromeFlags = chromeFlags & chromeMask;
if (!newChromeFlags) chromeFlags |= chromeMask;
else chromeFlags &= (~newChromeFlags);
wbc->SetChromeFlags(chromeFlags);
}
bool
nsWebShellWindow::ZLevelChanged(bool aImmediate, nsWindowZ *aPlacement,
nsIWidget* aRequestBelow, nsIWidget** aActualBelow)
{
if (aActualBelow)
*aActualBelow = nullptr;
return ConstrainToZLevel(aImmediate, aPlacement, aRequestBelow, aActualBelow);
}
void
nsWebShellWindow::WindowActivated()
{
nsCOMPtr<nsIXULWindow> xulWindow(this);
// 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);
if (mChromeLoaded) {
PersistentAttributesDirty(PAD_POSITION | PAD_SIZE | PAD_MISC);
SavePersistentAttributes();
}
}
void
nsWebShellWindow::WindowDeactivated()
{
nsCOMPtr<nsIXULWindow> xulWindow(this);
nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(mDocShell);
nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
if (fm && window)
fm->WindowLowered(window);
}
#ifdef USE_NATIVE_MENUS

View File

@ -12,6 +12,7 @@
#include "nsITimer.h"
#include "nsCOMPtr.h"
#include "nsXULWindow.h"
#include "nsIWidgetListener.h"
/* Forward declarations.... */
class nsIURI;
@ -21,7 +22,8 @@ class WebShellWindowTimerCallback;
} // namespace mozilla
class nsWebShellWindow : public nsXULWindow,
public nsIWebProgressListener
public nsIWebProgressListener,
public nsIWidgetListener
{
public:
nsWebShellWindow(PRUint32 aChromeFlags);
@ -44,6 +46,19 @@ public:
// 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;

View File

@ -508,7 +508,7 @@ NS_IMETHODIMP nsXULWindow::Destroy()
NS_RELEASE(mChromeTreeOwner);
}
if (mWindow) {
mWindow->SetClientData(0); // nsWebShellWindow hackery
mWindow->SetWidgetListener(nullptr); // nsWebShellWindow hackery
mWindow->Destroy();
mWindow = nullptr;
}
@ -1879,11 +1879,7 @@ bool nsXULWindow::ConstrainToZLevel(bool aImmediate,
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);