michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "mozilla/ArrayUtils.h" michael@0: michael@0: #include "mozilla/layers/CompositorChild.h" michael@0: #include "mozilla/layers/CompositorParent.h" michael@0: #include "mozilla/layers/ImageBridgeChild.h" michael@0: #include "nsBaseWidget.h" michael@0: #include "nsDeviceContext.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsGfxCIID.h" michael@0: #include "nsWidgetsCID.h" michael@0: #include "nsServiceManagerUtils.h" michael@0: #include "nsIScreenManager.h" michael@0: #include "nsAppDirectoryServiceDefs.h" michael@0: #include "nsISimpleEnumerator.h" michael@0: #include "nsIContent.h" michael@0: #include "nsIDocument.h" michael@0: #include "nsIPresShell.h" michael@0: #include "nsIServiceManager.h" michael@0: #include "mozilla/Preferences.h" michael@0: #include "BasicLayers.h" michael@0: #include "ClientLayerManager.h" michael@0: #include "mozilla/layers/Compositor.h" michael@0: #include "nsIXULRuntime.h" michael@0: #include "nsIXULWindow.h" michael@0: #include "nsIBaseWindow.h" michael@0: #include "nsXULPopupManager.h" michael@0: #include "nsIWidgetListener.h" michael@0: #include "nsIGfxInfo.h" michael@0: #include "npapi.h" michael@0: #include "base/thread.h" michael@0: #include "prdtoa.h" michael@0: #include "prenv.h" michael@0: #include "mozilla/Attributes.h" michael@0: #include "mozilla/unused.h" michael@0: #include "nsContentUtils.h" michael@0: #include "gfxPrefs.h" michael@0: #include "mozilla/gfx/2D.h" michael@0: #include "mozilla/MouseEvents.h" michael@0: #include "GLConsts.h" michael@0: #include "LayerScope.h" michael@0: #include "mozilla/unused.h" michael@0: michael@0: #ifdef ACCESSIBILITY michael@0: #include "nsAccessibilityService.h" michael@0: #endif michael@0: michael@0: #ifdef DEBUG michael@0: #include "nsIObserver.h" michael@0: michael@0: static void debug_RegisterPrefCallbacks(); michael@0: michael@0: #endif michael@0: michael@0: #ifdef NOISY_WIDGET_LEAKS michael@0: static int32_t gNumWidgets; michael@0: #endif michael@0: michael@0: #ifdef XP_MACOSX michael@0: #include "nsCocoaFeatures.h" michael@0: #endif michael@0: michael@0: nsIRollupListener* nsBaseWidget::gRollupListener = nullptr; michael@0: michael@0: using namespace mozilla::layers; michael@0: using namespace mozilla::ipc; michael@0: using namespace mozilla; michael@0: using base::Thread; michael@0: michael@0: nsIContent* nsBaseWidget::mLastRollup = nullptr; michael@0: // Global user preference for disabling native theme. Used michael@0: // in NativeWindowTheme. michael@0: bool gDisableNativeTheme = false; michael@0: michael@0: // Async pump timer during injected long touch taps michael@0: #define TOUCH_INJECT_PUMP_TIMER_MSEC 50 michael@0: #define TOUCH_INJECT_LONG_TAP_DEFAULT_MSEC 1500 michael@0: int32_t nsIWidget::sPointerIdCounter = 0; michael@0: michael@0: // nsBaseWidget michael@0: NS_IMPL_ISUPPORTS(nsBaseWidget, nsIWidget) michael@0: michael@0: michael@0: nsAutoRollup::nsAutoRollup() michael@0: { michael@0: // remember if mLastRollup was null, and only clear it upon destruction michael@0: // if so. This prevents recursive usage of nsAutoRollup from clearing michael@0: // mLastRollup when it shouldn't. michael@0: wasClear = !nsBaseWidget::mLastRollup; michael@0: } michael@0: michael@0: nsAutoRollup::~nsAutoRollup() michael@0: { michael@0: if (nsBaseWidget::mLastRollup && wasClear) { michael@0: NS_RELEASE(nsBaseWidget::mLastRollup); michael@0: } michael@0: } michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // nsBaseWidget constructor michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: michael@0: nsBaseWidget::nsBaseWidget() michael@0: : mWidgetListener(nullptr) michael@0: , mAttachedWidgetListener(nullptr) michael@0: , mContext(nullptr) michael@0: , mCursor(eCursor_standard) michael@0: , mBorderStyle(eBorderStyle_none) michael@0: , mUseLayersAcceleration(false) michael@0: , mForceLayersAcceleration(false) michael@0: , mTemporarilyUseBasicLayerManager(false) michael@0: , mUseAttachedEvents(false) michael@0: , mContextInitialized(false) michael@0: , mBounds(0,0,0,0) michael@0: , mOriginalBounds(nullptr) michael@0: , mClipRectCount(0) michael@0: , mSizeMode(nsSizeMode_Normal) michael@0: , mPopupLevel(ePopupLevelTop) michael@0: , mPopupType(ePopupTypeAny) michael@0: { michael@0: #ifdef NOISY_WIDGET_LEAKS michael@0: gNumWidgets++; michael@0: printf("WIDGETS+ = %d\n", gNumWidgets); michael@0: #endif michael@0: michael@0: #ifdef DEBUG michael@0: debug_RegisterPrefCallbacks(); michael@0: #endif michael@0: michael@0: mShutdownObserver = new WidgetShutdownObserver(this); michael@0: nsContentUtils::RegisterShutdownObserver(mShutdownObserver); michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS(WidgetShutdownObserver, nsIObserver) michael@0: michael@0: NS_IMETHODIMP michael@0: WidgetShutdownObserver::Observe(nsISupports *aSubject, michael@0: const char *aTopic, michael@0: const char16_t *aData) michael@0: { michael@0: if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0 && michael@0: mWidget) { michael@0: mWidget->Shutdown(); michael@0: nsContentUtils::UnregisterShutdownObserver(this); michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: void michael@0: nsBaseWidget::Shutdown() michael@0: { michael@0: DestroyCompositor(); michael@0: mShutdownObserver = nullptr; michael@0: } michael@0: michael@0: static void DeferredDestroyCompositor(CompositorParent* aCompositorParent, michael@0: CompositorChild* aCompositorChild) michael@0: { michael@0: // Bug 848949 needs to be fixed before michael@0: // we can close the channel properly michael@0: //aCompositorChild->Close(); michael@0: aCompositorParent->Release(); michael@0: aCompositorChild->Release(); michael@0: } michael@0: michael@0: void nsBaseWidget::DestroyCompositor() michael@0: { michael@0: LayerScope::DestroyServerSocket(); michael@0: michael@0: if (mCompositorChild) { michael@0: mCompositorChild->SendWillStop(); michael@0: mCompositorChild->Destroy(); michael@0: michael@0: // The call just made to SendWillStop can result in IPC from the michael@0: // CompositorParent to the CompositorChild (e.g. caused by the destruction michael@0: // of shared memory). We need to ensure this gets processed by the michael@0: // CompositorChild before it gets destroyed. It suffices to ensure that michael@0: // events already in the MessageLoop get processed before the michael@0: // CompositorChild is destroyed, so we add a task to the MessageLoop to michael@0: // handle compositor desctruction. michael@0: MessageLoop::current()->PostTask(FROM_HERE, michael@0: NewRunnableFunction(DeferredDestroyCompositor, mCompositorParent, michael@0: mCompositorChild)); michael@0: // The DestroyCompositor task we just added to the MessageLoop will handle michael@0: // releasing mCompositorParent and mCompositorChild. michael@0: unused << mCompositorParent.forget(); michael@0: unused << mCompositorChild.forget(); michael@0: } michael@0: } michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // nsBaseWidget destructor michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: nsBaseWidget::~nsBaseWidget() michael@0: { michael@0: if (mLayerManager && michael@0: mLayerManager->GetBackendType() == LayersBackend::LAYERS_BASIC) { michael@0: static_cast(mLayerManager.get())->ClearRetainerWidget(); michael@0: } michael@0: michael@0: if (mLayerManager) { michael@0: mLayerManager->Destroy(); michael@0: mLayerManager = nullptr; michael@0: } michael@0: michael@0: if (mShutdownObserver) { michael@0: // If the shutdown observer is currently processing observers, michael@0: // then UnregisterShutdownObserver won't stop our Observer michael@0: // function from being called. Make sure we don't try michael@0: // to reference the dead widget. michael@0: mShutdownObserver->mWidget = nullptr; michael@0: nsContentUtils::UnregisterShutdownObserver(mShutdownObserver); michael@0: } michael@0: michael@0: DestroyCompositor(); michael@0: michael@0: #ifdef NOISY_WIDGET_LEAKS michael@0: gNumWidgets--; michael@0: printf("WIDGETS- = %d\n", gNumWidgets); michael@0: #endif michael@0: michael@0: NS_IF_RELEASE(mContext); michael@0: delete mOriginalBounds; michael@0: } michael@0: michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // Basic create. michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: void nsBaseWidget::BaseCreate(nsIWidget *aParent, michael@0: const nsIntRect &aRect, michael@0: nsDeviceContext *aContext, michael@0: nsWidgetInitData *aInitData) michael@0: { michael@0: static bool gDisableNativeThemeCached = false; michael@0: if (!gDisableNativeThemeCached) { michael@0: Preferences::AddBoolVarCache(&gDisableNativeTheme, michael@0: "mozilla.widget.disable-native-theme", michael@0: gDisableNativeTheme); michael@0: gDisableNativeThemeCached = true; michael@0: } michael@0: michael@0: // keep a reference to the device context michael@0: if (aContext) { michael@0: mContext = aContext; michael@0: NS_ADDREF(mContext); michael@0: } michael@0: else { michael@0: mContext = new nsDeviceContext(); michael@0: NS_ADDREF(mContext); michael@0: mContext->Init(nullptr); michael@0: } michael@0: michael@0: if (nullptr != aInitData) { michael@0: mWindowType = aInitData->mWindowType; michael@0: mBorderStyle = aInitData->mBorderStyle; michael@0: mPopupLevel = aInitData->mPopupLevel; michael@0: mPopupType = aInitData->mPopupHint; michael@0: mRequireOffMainThreadCompositing = aInitData->mRequireOffMainThreadCompositing; michael@0: } michael@0: michael@0: if (aParent) { michael@0: aParent->AddChild(this); michael@0: } michael@0: } michael@0: michael@0: NS_IMETHODIMP nsBaseWidget::CaptureMouse(bool aCapture) michael@0: { michael@0: return NS_OK; michael@0: } michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // Accessor functions to get/set the client data michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: michael@0: nsIWidgetListener* nsBaseWidget::GetWidgetListener() michael@0: { michael@0: return mWidgetListener; michael@0: } michael@0: michael@0: void nsBaseWidget::SetWidgetListener(nsIWidgetListener* aWidgetListener) michael@0: { michael@0: mWidgetListener = aWidgetListener; michael@0: } michael@0: michael@0: already_AddRefed michael@0: nsBaseWidget::CreateChild(const nsIntRect &aRect, michael@0: nsDeviceContext *aContext, michael@0: nsWidgetInitData *aInitData, michael@0: bool aForceUseIWidgetParent) michael@0: { michael@0: nsIWidget* parent = this; michael@0: nsNativeWidget nativeParent = nullptr; michael@0: michael@0: if (!aForceUseIWidgetParent) { michael@0: // Use only either parent or nativeParent, not both, to match michael@0: // existing code. Eventually Create() should be divested of its michael@0: // nativeWidget parameter. michael@0: nativeParent = parent ? parent->GetNativeData(NS_NATIVE_WIDGET) : nullptr; michael@0: parent = nativeParent ? nullptr : parent; michael@0: NS_ABORT_IF_FALSE(!parent || !nativeParent, "messed up logic"); michael@0: } michael@0: michael@0: nsCOMPtr widget; michael@0: if (aInitData && aInitData->mWindowType == eWindowType_popup) { michael@0: widget = AllocateChildPopupWidget(); michael@0: } else { michael@0: static NS_DEFINE_IID(kCChildCID, NS_CHILD_CID); michael@0: widget = do_CreateInstance(kCChildCID); michael@0: } michael@0: michael@0: if (widget && michael@0: NS_SUCCEEDED(widget->Create(parent, nativeParent, aRect, michael@0: aContext, aInitData))) { michael@0: return widget.forget(); michael@0: } michael@0: michael@0: return nullptr; michael@0: } michael@0: michael@0: // Attach a view to our widget which we'll send events to. michael@0: NS_IMETHODIMP michael@0: nsBaseWidget::AttachViewToTopLevel(bool aUseAttachedEvents, michael@0: nsDeviceContext *aContext) michael@0: { michael@0: NS_ASSERTION((mWindowType == eWindowType_toplevel || michael@0: mWindowType == eWindowType_dialog || michael@0: mWindowType == eWindowType_invisible || michael@0: mWindowType == eWindowType_child), michael@0: "Can't attach to window of that type"); michael@0: michael@0: mUseAttachedEvents = aUseAttachedEvents; michael@0: michael@0: if (aContext) { michael@0: if (mContext) { michael@0: NS_IF_RELEASE(mContext); michael@0: } michael@0: mContext = aContext; michael@0: NS_ADDREF(mContext); michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsIWidgetListener* nsBaseWidget::GetAttachedWidgetListener() michael@0: { michael@0: return mAttachedWidgetListener; michael@0: } michael@0: michael@0: void nsBaseWidget::SetAttachedWidgetListener(nsIWidgetListener* aListener) michael@0: { michael@0: mAttachedWidgetListener = aListener; michael@0: } michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // Close this nsBaseWidget michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: NS_METHOD nsBaseWidget::Destroy() michael@0: { michael@0: // Just in case our parent is the only ref to us michael@0: nsCOMPtr kungFuDeathGrip(this); michael@0: // disconnect from the parent michael@0: nsIWidget *parent = GetParent(); michael@0: if (parent) { michael@0: parent->RemoveChild(this); michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // Set this nsBaseWidget's parent michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: NS_IMETHODIMP nsBaseWidget::SetParent(nsIWidget* aNewParent) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // Get this nsBaseWidget parent michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: nsIWidget* nsBaseWidget::GetParent(void) michael@0: { michael@0: return nullptr; michael@0: } michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // Get this nsBaseWidget top level widget michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: nsIWidget* nsBaseWidget::GetTopLevelWidget() michael@0: { michael@0: nsIWidget *topLevelWidget = nullptr, *widget = this; michael@0: while (widget) { michael@0: topLevelWidget = widget; michael@0: widget = widget->GetParent(); michael@0: } michael@0: return topLevelWidget; michael@0: } michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // Get this nsBaseWidget's top (non-sheet) parent (if it's a sheet) michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: nsIWidget* nsBaseWidget::GetSheetWindowParent(void) michael@0: { michael@0: return nullptr; michael@0: } michael@0: michael@0: float nsBaseWidget::GetDPI() michael@0: { michael@0: return 96.0f; michael@0: } michael@0: michael@0: CSSToLayoutDeviceScale nsIWidget::GetDefaultScale() michael@0: { michael@0: double devPixelsPerCSSPixel = DefaultScaleOverride(); michael@0: michael@0: if (devPixelsPerCSSPixel <= 0.0) { michael@0: devPixelsPerCSSPixel = GetDefaultScaleInternal(); michael@0: } michael@0: michael@0: return CSSToLayoutDeviceScale(devPixelsPerCSSPixel); michael@0: } michael@0: michael@0: /* static */ michael@0: double nsIWidget::DefaultScaleOverride() michael@0: { michael@0: // The number of device pixels per CSS pixel. A value <= 0 means choose michael@0: // automatically based on the DPI. A positive value is used as-is. This effectively michael@0: // controls the size of a CSS "px". michael@0: double devPixelsPerCSSPixel = -1.0; michael@0: michael@0: nsAdoptingCString prefString = Preferences::GetCString("layout.css.devPixelsPerPx"); michael@0: if (!prefString.IsEmpty()) { michael@0: devPixelsPerCSSPixel = PR_strtod(prefString, nullptr); michael@0: } michael@0: michael@0: return devPixelsPerCSSPixel; michael@0: } michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // Add a child to the list of children michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: void nsBaseWidget::AddChild(nsIWidget* aChild) michael@0: { michael@0: NS_PRECONDITION(!aChild->GetNextSibling() && !aChild->GetPrevSibling(), michael@0: "aChild not properly removed from its old child list"); michael@0: michael@0: if (!mFirstChild) { michael@0: mFirstChild = mLastChild = aChild; michael@0: } else { michael@0: // append to the list michael@0: NS_ASSERTION(mLastChild, "Bogus state"); michael@0: NS_ASSERTION(!mLastChild->GetNextSibling(), "Bogus state"); michael@0: mLastChild->SetNextSibling(aChild); michael@0: aChild->SetPrevSibling(mLastChild); michael@0: mLastChild = aChild; michael@0: } michael@0: } michael@0: michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // Remove a child from the list of children michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: void nsBaseWidget::RemoveChild(nsIWidget* aChild) michael@0: { michael@0: #ifdef DEBUG michael@0: #ifdef XP_MACOSX michael@0: // nsCocoaWindow doesn't implement GetParent, so in that case parent will be michael@0: // null and we'll just have to do without this assertion. michael@0: nsIWidget* parent = aChild->GetParent(); michael@0: NS_ASSERTION(!parent || parent == this, "Not one of our kids!"); michael@0: #else michael@0: NS_ASSERTION(aChild->GetParent() == this, "Not one of our kids!"); michael@0: #endif michael@0: #endif michael@0: michael@0: if (mLastChild == aChild) { michael@0: mLastChild = mLastChild->GetPrevSibling(); michael@0: } michael@0: if (mFirstChild == aChild) { michael@0: mFirstChild = mFirstChild->GetNextSibling(); michael@0: } michael@0: michael@0: // Now remove from the list. Make sure that we pass ownership of the tail michael@0: // of the list correctly before we have aChild let go of it. michael@0: nsIWidget* prev = aChild->GetPrevSibling(); michael@0: nsIWidget* next = aChild->GetNextSibling(); michael@0: if (prev) { michael@0: prev->SetNextSibling(next); michael@0: } michael@0: if (next) { michael@0: next->SetPrevSibling(prev); michael@0: } michael@0: michael@0: aChild->SetNextSibling(nullptr); michael@0: aChild->SetPrevSibling(nullptr); michael@0: } michael@0: michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // Sets widget's position within its parent's child list. michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: void nsBaseWidget::SetZIndex(int32_t aZIndex) michael@0: { michael@0: // Hold a ref to ourselves just in case, since we're going to remove michael@0: // from our parent. michael@0: nsCOMPtr kungFuDeathGrip(this); michael@0: michael@0: mZIndex = aZIndex; michael@0: michael@0: // reorder this child in its parent's list. michael@0: nsBaseWidget* parent = static_cast(GetParent()); michael@0: if (parent) { michael@0: parent->RemoveChild(this); michael@0: // Scope sib outside the for loop so we can check it afterward michael@0: nsIWidget* sib = parent->GetFirstChild(); michael@0: for ( ; sib; sib = sib->GetNextSibling()) { michael@0: int32_t childZIndex = GetZIndex(); michael@0: if (aZIndex < childZIndex) { michael@0: // Insert ourselves before sib michael@0: nsIWidget* prev = sib->GetPrevSibling(); michael@0: mNextSibling = sib; michael@0: mPrevSibling = prev; michael@0: sib->SetPrevSibling(this); michael@0: if (prev) { michael@0: prev->SetNextSibling(this); michael@0: } else { michael@0: NS_ASSERTION(sib == parent->mFirstChild, "Broken child list"); michael@0: // We've taken ownership of sib, so it's safe to have parent let michael@0: // go of it michael@0: parent->mFirstChild = this; michael@0: } michael@0: PlaceBehind(eZPlacementBelow, sib, false); michael@0: break; michael@0: } michael@0: } michael@0: // were we added to the list? michael@0: if (!sib) { michael@0: parent->AddChild(this); michael@0: } michael@0: } michael@0: } michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // Places widget behind the given widget (platforms must override) michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: NS_IMETHODIMP nsBaseWidget::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement, michael@0: nsIWidget *aWidget, bool aActivate) michael@0: { michael@0: return NS_OK; michael@0: } michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // Maximize, minimize or restore the window. The BaseWidget implementation michael@0: // merely stores the state. michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: NS_IMETHODIMP nsBaseWidget::SetSizeMode(int32_t aMode) michael@0: { michael@0: if (aMode == nsSizeMode_Normal || michael@0: aMode == nsSizeMode_Minimized || michael@0: aMode == nsSizeMode_Maximized || michael@0: aMode == nsSizeMode_Fullscreen) { michael@0: michael@0: mSizeMode = (nsSizeMode) aMode; michael@0: return NS_OK; michael@0: } michael@0: return NS_ERROR_ILLEGAL_VALUE; michael@0: } michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // Get this component cursor michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: nsCursor nsBaseWidget::GetCursor() michael@0: { michael@0: return mCursor; michael@0: } michael@0: michael@0: NS_METHOD nsBaseWidget::SetCursor(nsCursor aCursor) michael@0: { michael@0: mCursor = aCursor; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsBaseWidget::SetCursor(imgIContainer* aCursor, michael@0: uint32_t aHotspotX, uint32_t aHotspotY) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // Window transparency methods michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: michael@0: void nsBaseWidget::SetTransparencyMode(nsTransparencyMode aMode) { michael@0: } michael@0: michael@0: nsTransparencyMode nsBaseWidget::GetTransparencyMode() { michael@0: return eTransparencyOpaque; michael@0: } michael@0: michael@0: bool michael@0: nsBaseWidget::StoreWindowClipRegion(const nsTArray& aRects) michael@0: { michael@0: if (mClipRects && mClipRectCount == aRects.Length() && michael@0: memcmp(mClipRects, aRects.Elements(), sizeof(nsIntRect)*mClipRectCount) == 0) michael@0: return false; michael@0: michael@0: mClipRectCount = aRects.Length(); michael@0: mClipRects = new nsIntRect[mClipRectCount]; michael@0: if (mClipRects) { michael@0: memcpy(mClipRects, aRects.Elements(), sizeof(nsIntRect)*mClipRectCount); michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: void michael@0: nsBaseWidget::GetWindowClipRegion(nsTArray* aRects) michael@0: { michael@0: if (mClipRects) { michael@0: aRects->AppendElements(mClipRects.get(), mClipRectCount); michael@0: } else { michael@0: aRects->AppendElement(nsIntRect(0, 0, mBounds.width, mBounds.height)); michael@0: } michael@0: } michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // Set window shadow style michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: michael@0: NS_IMETHODIMP nsBaseWidget::SetWindowShadowStyle(int32_t aMode) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // Hide window borders/decorations for this widget michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: NS_IMETHODIMP nsBaseWidget::HideWindowChrome(bool aShouldHide) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // Put the window into full-screen mode michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: NS_IMETHODIMP nsBaseWidget::MakeFullScreen(bool aFullScreen) michael@0: { michael@0: HideWindowChrome(aFullScreen); michael@0: michael@0: if (aFullScreen) { michael@0: if (!mOriginalBounds) michael@0: mOriginalBounds = new nsIntRect(); michael@0: GetScreenBounds(*mOriginalBounds); michael@0: // convert dev pix to display pix for window manipulation michael@0: CSSToLayoutDeviceScale scale = GetDefaultScale(); michael@0: mOriginalBounds->x = NSToIntRound(mOriginalBounds->x / scale.scale); michael@0: mOriginalBounds->y = NSToIntRound(mOriginalBounds->y / scale.scale); michael@0: mOriginalBounds->width = NSToIntRound(mOriginalBounds->width / scale.scale); michael@0: mOriginalBounds->height = NSToIntRound(mOriginalBounds->height / scale.scale); michael@0: michael@0: // Move to top-left corner of screen and size to the screen dimensions michael@0: nsCOMPtr screenManager; michael@0: screenManager = do_GetService("@mozilla.org/gfx/screenmanager;1"); michael@0: NS_ASSERTION(screenManager, "Unable to grab screenManager."); michael@0: if (screenManager) { michael@0: nsCOMPtr screen; michael@0: screenManager->ScreenForRect(mOriginalBounds->x, michael@0: mOriginalBounds->y, michael@0: mOriginalBounds->width, michael@0: mOriginalBounds->height, michael@0: getter_AddRefs(screen)); michael@0: if (screen) { michael@0: int32_t left, top, width, height; michael@0: if (NS_SUCCEEDED(screen->GetRectDisplayPix(&left, &top, &width, &height))) { michael@0: Resize(left, top, width, height, true); michael@0: } michael@0: } michael@0: } michael@0: michael@0: } else if (mOriginalBounds) { michael@0: Resize(mOriginalBounds->x, mOriginalBounds->y, mOriginalBounds->width, michael@0: mOriginalBounds->height, true); michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsBaseWidget::AutoLayerManagerSetup::AutoLayerManagerSetup( michael@0: nsBaseWidget* aWidget, gfxContext* aTarget, michael@0: BufferMode aDoubleBuffering, ScreenRotation aRotation) michael@0: : mWidget(aWidget) michael@0: { michael@0: mLayerManager = static_cast(mWidget->GetLayerManager()); michael@0: if (mLayerManager) { michael@0: NS_ASSERTION(mLayerManager->GetBackendType() == LayersBackend::LAYERS_BASIC, michael@0: "AutoLayerManagerSetup instantiated for non-basic layer backend!"); michael@0: mLayerManager->SetDefaultTarget(aTarget); michael@0: mLayerManager->SetDefaultTargetConfiguration(aDoubleBuffering, aRotation); michael@0: } michael@0: } michael@0: michael@0: nsBaseWidget::AutoLayerManagerSetup::~AutoLayerManagerSetup() michael@0: { michael@0: if (mLayerManager) { michael@0: NS_ASSERTION(mLayerManager->GetBackendType() == LayersBackend::LAYERS_BASIC, michael@0: "AutoLayerManagerSetup instantiated for non-basic layer backend!"); michael@0: mLayerManager->SetDefaultTarget(nullptr); michael@0: mLayerManager->SetDefaultTargetConfiguration(mozilla::layers::BufferMode::BUFFER_NONE, ROTATION_0); michael@0: } michael@0: } michael@0: michael@0: nsBaseWidget::AutoUseBasicLayerManager::AutoUseBasicLayerManager(nsBaseWidget* aWidget) michael@0: : mWidget(aWidget) michael@0: { michael@0: mPreviousTemporarilyUseBasicLayerManager = michael@0: mWidget->mTemporarilyUseBasicLayerManager; michael@0: mWidget->mTemporarilyUseBasicLayerManager = true; michael@0: } michael@0: michael@0: nsBaseWidget::AutoUseBasicLayerManager::~AutoUseBasicLayerManager() michael@0: { michael@0: mWidget->mTemporarilyUseBasicLayerManager = michael@0: mPreviousTemporarilyUseBasicLayerManager; michael@0: } michael@0: michael@0: bool michael@0: nsBaseWidget::ComputeShouldAccelerate(bool aDefault) michael@0: { michael@0: #if defined(XP_WIN) || defined(ANDROID) || \ michael@0: defined(MOZ_GL_PROVIDER) || defined(XP_MACOSX) || defined(MOZ_WIDGET_QT) michael@0: bool accelerateByDefault = true; michael@0: #else michael@0: bool accelerateByDefault = false; michael@0: #endif michael@0: michael@0: #ifdef XP_MACOSX michael@0: // 10.6.2 and lower have a bug involving textures and pixel buffer objects michael@0: // that caused bug 629016, so we don't allow OpenGL-accelerated layers on michael@0: // those versions of the OS. michael@0: // This will still let full-screen video be accelerated on OpenGL, because michael@0: // that XUL widget opts in to acceleration, but that's probably OK. michael@0: SInt32 major = nsCocoaFeatures::OSXVersionMajor(); michael@0: SInt32 minor = nsCocoaFeatures::OSXVersionMinor(); michael@0: SInt32 bugfix = nsCocoaFeatures::OSXVersionBugFix(); michael@0: if (major == 10 && minor == 6 && bugfix <= 2) { michael@0: accelerateByDefault = false; michael@0: } michael@0: #endif michael@0: michael@0: // we should use AddBoolPrefVarCache michael@0: bool disableAcceleration = gfxPrefs::LayersAccelerationDisabled(); michael@0: mForceLayersAcceleration = gfxPrefs::LayersAccelerationForceEnabled(); michael@0: michael@0: const char *acceleratedEnv = PR_GetEnv("MOZ_ACCELERATED"); michael@0: accelerateByDefault = accelerateByDefault || michael@0: (acceleratedEnv && (*acceleratedEnv != '0')); michael@0: michael@0: nsCOMPtr xr = do_GetService("@mozilla.org/xre/runtime;1"); michael@0: bool safeMode = false; michael@0: if (xr) michael@0: xr->GetInSafeMode(&safeMode); michael@0: michael@0: bool whitelisted = false; michael@0: michael@0: nsCOMPtr gfxInfo = do_GetService("@mozilla.org/gfx/info;1"); michael@0: if (gfxInfo) { michael@0: // bug 655578: on X11 at least, we must always call GetData (even if we don't need that information) michael@0: // as that's what causes GfxInfo initialization which kills the zombie 'glxtest' process. michael@0: // initially we relied on the fact that GetFeatureStatus calls GetData for us, but bug 681026 showed michael@0: // that assumption to be unsafe. michael@0: gfxInfo->GetData(); michael@0: michael@0: int32_t status; michael@0: if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_OPENGL_LAYERS, &status))) { michael@0: if (status == nsIGfxInfo::FEATURE_NO_INFO) { michael@0: whitelisted = true; michael@0: } michael@0: } michael@0: } michael@0: michael@0: if (disableAcceleration || safeMode) michael@0: return false; michael@0: michael@0: if (mForceLayersAcceleration) michael@0: return true; michael@0: michael@0: if (!whitelisted) { michael@0: static int tell_me_once = 0; michael@0: if (!tell_me_once) { michael@0: NS_WARNING("OpenGL-accelerated layers are not supported on this system"); michael@0: tell_me_once = 1; michael@0: } michael@0: #ifdef MOZ_ANDROID_OMTC michael@0: NS_RUNTIMEABORT("OpenGL-accelerated layers are a hard requirement on this platform. " michael@0: "Cannot continue without support for them"); michael@0: #endif michael@0: return false; michael@0: } michael@0: michael@0: if (accelerateByDefault) michael@0: return true; michael@0: michael@0: /* use the window acceleration flag */ michael@0: return aDefault; michael@0: } michael@0: michael@0: CompositorParent* nsBaseWidget::NewCompositorParent(int aSurfaceWidth, michael@0: int aSurfaceHeight) michael@0: { michael@0: return new CompositorParent(this, false, aSurfaceWidth, aSurfaceHeight); michael@0: } michael@0: michael@0: void nsBaseWidget::CreateCompositor() michael@0: { michael@0: nsIntRect rect; michael@0: GetBounds(rect); michael@0: CreateCompositor(rect.width, rect.height); michael@0: } michael@0: michael@0: void michael@0: nsBaseWidget::GetPreferredCompositorBackends(nsTArray& aHints) michael@0: { michael@0: if (mUseLayersAcceleration) { michael@0: aHints.AppendElement(LayersBackend::LAYERS_OPENGL); michael@0: } michael@0: michael@0: aHints.AppendElement(LayersBackend::LAYERS_BASIC); michael@0: } michael@0: michael@0: static void michael@0: CheckForBasicBackends(nsTArray& aHints) michael@0: { michael@0: for (size_t i = 0; i < aHints.Length(); ++i) { michael@0: if (aHints[i] == LayersBackend::LAYERS_BASIC && michael@0: !Preferences::GetBool("layers.offmainthreadcomposition.force-basic", false)) { michael@0: // basic compositor is not stable enough for regular use michael@0: aHints[i] = LayersBackend::LAYERS_NONE; michael@0: } michael@0: } michael@0: } michael@0: michael@0: void nsBaseWidget::CreateCompositor(int aWidth, int aHeight) michael@0: { michael@0: // Recreating this is tricky, as we may still have an old and we need michael@0: // to make sure it's properly destroyed by calling DestroyCompositor! michael@0: michael@0: // If we've already received a shutdown notification, don't try michael@0: // create a new compositor. michael@0: if (!mShutdownObserver) { michael@0: return; michael@0: } michael@0: michael@0: // The server socket has to be created on the main thread. michael@0: LayerScope::CreateServerSocket(); michael@0: michael@0: mCompositorParent = NewCompositorParent(aWidth, aHeight); michael@0: MessageChannel *parentChannel = mCompositorParent->GetIPCChannel(); michael@0: ClientLayerManager* lm = new ClientLayerManager(this); michael@0: MessageLoop *childMessageLoop = CompositorParent::CompositorLoop(); michael@0: mCompositorChild = new CompositorChild(lm); michael@0: mCompositorChild->Open(parentChannel, childMessageLoop, ipc::ChildSide); michael@0: michael@0: TextureFactoryIdentifier textureFactoryIdentifier; michael@0: PLayerTransactionChild* shadowManager = nullptr; michael@0: nsTArray backendHints; michael@0: GetPreferredCompositorBackends(backendHints); michael@0: michael@0: if (!mRequireOffMainThreadCompositing) { michael@0: CheckForBasicBackends(backendHints); michael@0: } michael@0: michael@0: bool success = false; michael@0: if (!backendHints.IsEmpty()) { michael@0: shadowManager = mCompositorChild->SendPLayerTransactionConstructor( michael@0: backendHints, 0, &textureFactoryIdentifier, &success); michael@0: } michael@0: michael@0: if (success) { michael@0: ShadowLayerForwarder* lf = lm->AsShadowForwarder(); michael@0: if (!lf) { michael@0: delete lm; michael@0: mCompositorChild = nullptr; michael@0: return; michael@0: } michael@0: lf->SetShadowManager(shadowManager); michael@0: lf->IdentifyTextureHost(textureFactoryIdentifier); michael@0: ImageBridgeChild::IdentifyCompositorTextureHost(textureFactoryIdentifier); michael@0: WindowUsesOMTC(); michael@0: michael@0: mLayerManager = lm; michael@0: return; michael@0: } michael@0: michael@0: NS_WARNING("Failed to create an OMT compositor."); michael@0: DestroyCompositor(); michael@0: // Compositor child had the only reference to LayerManager and will have michael@0: // deallocated it when being freed. michael@0: } michael@0: michael@0: bool nsBaseWidget::ShouldUseOffMainThreadCompositing() michael@0: { michael@0: return CompositorParent::CompositorLoop(); michael@0: } michael@0: michael@0: LayerManager* nsBaseWidget::GetLayerManager(PLayerTransactionChild* aShadowManager, michael@0: LayersBackend aBackendHint, michael@0: LayerManagerPersistence aPersistence, michael@0: bool* aAllowRetaining) michael@0: { michael@0: if (!mLayerManager) { michael@0: michael@0: mUseLayersAcceleration = ComputeShouldAccelerate(mUseLayersAcceleration); michael@0: michael@0: // Try to use an async compositor first, if possible michael@0: if (ShouldUseOffMainThreadCompositing()) { michael@0: // e10s uses the parameter to pass in the shadow manager from the TabChild michael@0: // so we don't expect to see it there since this doesn't support e10s. michael@0: NS_ASSERTION(aShadowManager == nullptr, "Async Compositor not supported with e10s"); michael@0: CreateCompositor(); michael@0: } michael@0: michael@0: if (!mLayerManager) { michael@0: mLayerManager = CreateBasicLayerManager(); michael@0: } michael@0: } michael@0: if (mTemporarilyUseBasicLayerManager && !mBasicLayerManager) { michael@0: mBasicLayerManager = CreateBasicLayerManager(); michael@0: } michael@0: LayerManager* usedLayerManager = mTemporarilyUseBasicLayerManager ? michael@0: mBasicLayerManager : mLayerManager; michael@0: if (aAllowRetaining) { michael@0: *aAllowRetaining = (usedLayerManager == mLayerManager); michael@0: } michael@0: return usedLayerManager; michael@0: } michael@0: michael@0: LayerManager* nsBaseWidget::CreateBasicLayerManager() michael@0: { michael@0: return new BasicLayerManager(this); michael@0: } michael@0: michael@0: CompositorChild* nsBaseWidget::GetRemoteRenderer() michael@0: { michael@0: return mCompositorChild; michael@0: } michael@0: michael@0: TemporaryRef nsBaseWidget::StartRemoteDrawing() michael@0: { michael@0: return nullptr; michael@0: } michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // Return the used device context michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: nsDeviceContext* nsBaseWidget::GetDeviceContext() michael@0: { michael@0: if (!mContextInitialized) { michael@0: mContext->Init(this); michael@0: mContextInitialized = true; michael@0: } michael@0: return mContext; michael@0: } michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // Get the thebes surface michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: gfxASurface *nsBaseWidget::GetThebesSurface() michael@0: { michael@0: // in theory we should get our parent's surface, michael@0: // clone it, and set a device offset before returning michael@0: return nullptr; michael@0: } michael@0: michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // Destroy the window michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: void nsBaseWidget::OnDestroy() michael@0: { michael@0: // release references to device context and app shell michael@0: NS_IF_RELEASE(mContext); michael@0: } michael@0: michael@0: NS_METHOD nsBaseWidget::SetWindowClass(const nsAString& xulWinType) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_METHOD nsBaseWidget::MoveClient(double aX, double aY) michael@0: { michael@0: nsIntPoint clientOffset(GetClientOffset()); michael@0: michael@0: // GetClientOffset returns device pixels; scale back to display pixels michael@0: // if that's what this widget uses for the Move/Resize APIs michael@0: CSSToLayoutDeviceScale scale = BoundsUseDisplayPixels() michael@0: ? GetDefaultScale() michael@0: : CSSToLayoutDeviceScale(1.0); michael@0: aX -= clientOffset.x * 1.0 / scale.scale; michael@0: aY -= clientOffset.y * 1.0 / scale.scale; michael@0: michael@0: return Move(aX, aY); michael@0: } michael@0: michael@0: NS_METHOD nsBaseWidget::ResizeClient(double aWidth, michael@0: double aHeight, michael@0: bool aRepaint) michael@0: { michael@0: NS_ASSERTION((aWidth >=0) , "Negative width passed to ResizeClient"); michael@0: NS_ASSERTION((aHeight >=0), "Negative height passed to ResizeClient"); michael@0: michael@0: nsIntRect clientBounds; michael@0: GetClientBounds(clientBounds); michael@0: michael@0: // GetClientBounds and mBounds are device pixels; scale back to display pixels michael@0: // if that's what this widget uses for the Move/Resize APIs michael@0: CSSToLayoutDeviceScale scale = BoundsUseDisplayPixels() michael@0: ? GetDefaultScale() michael@0: : CSSToLayoutDeviceScale(1.0); michael@0: double invScale = 1.0 / scale.scale; michael@0: aWidth = mBounds.width * invScale + (aWidth - clientBounds.width * invScale); michael@0: aHeight = mBounds.height * invScale + (aHeight - clientBounds.height * invScale); michael@0: michael@0: return Resize(aWidth, aHeight, aRepaint); michael@0: } michael@0: michael@0: NS_METHOD nsBaseWidget::ResizeClient(double aX, michael@0: double aY, michael@0: double aWidth, michael@0: double aHeight, michael@0: bool aRepaint) michael@0: { michael@0: NS_ASSERTION((aWidth >=0) , "Negative width passed to ResizeClient"); michael@0: NS_ASSERTION((aHeight >=0), "Negative height passed to ResizeClient"); michael@0: michael@0: nsIntRect clientBounds; michael@0: GetClientBounds(clientBounds); michael@0: michael@0: double scale = BoundsUseDisplayPixels() ? 1.0 / GetDefaultScale().scale : 1.0; michael@0: aWidth = mBounds.width * scale + (aWidth - clientBounds.width * scale); michael@0: aHeight = mBounds.height * scale + (aHeight - clientBounds.height * scale); michael@0: michael@0: nsIntPoint clientOffset(GetClientOffset()); michael@0: aX -= clientOffset.x * scale; michael@0: aY -= clientOffset.y * scale; michael@0: michael@0: return Resize(aX, aY, aWidth, aHeight, aRepaint); michael@0: } michael@0: michael@0: //------------------------------------------------------------------------- michael@0: // michael@0: // Bounds michael@0: // michael@0: //------------------------------------------------------------------------- michael@0: michael@0: /** michael@0: * If the implementation of nsWindow supports borders this method MUST be overridden michael@0: * michael@0: **/ michael@0: NS_METHOD nsBaseWidget::GetClientBounds(nsIntRect &aRect) michael@0: { michael@0: return GetBounds(aRect); michael@0: } michael@0: michael@0: /** michael@0: * If the implementation of nsWindow supports borders this method MUST be overridden michael@0: * michael@0: **/ michael@0: NS_METHOD nsBaseWidget::GetBounds(nsIntRect &aRect) michael@0: { michael@0: aRect = mBounds; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /** michael@0: * If the implementation of nsWindow uses a local coordinate system within the window, michael@0: * this method must be overridden michael@0: * michael@0: **/ michael@0: NS_METHOD nsBaseWidget::GetScreenBounds(nsIntRect &aRect) michael@0: { michael@0: return GetBounds(aRect); michael@0: } michael@0: michael@0: nsIntPoint nsBaseWidget::GetClientOffset() michael@0: { michael@0: return nsIntPoint(0, 0); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsBaseWidget::GetNonClientMargins(nsIntMargin &margins) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsBaseWidget::SetNonClientMargins(nsIntMargin &margins) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_METHOD nsBaseWidget::EnableDragDrop(bool aEnable) michael@0: { michael@0: return NS_OK; michael@0: } michael@0: michael@0: uint32_t nsBaseWidget::GetMaxTouchPoints() const michael@0: { michael@0: return 0; michael@0: } michael@0: michael@0: NS_METHOD nsBaseWidget::SetModal(bool aModal) michael@0: { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsBaseWidget::GetAttention(int32_t aCycleCount) { michael@0: return NS_OK; michael@0: } michael@0: michael@0: bool michael@0: nsBaseWidget::HasPendingInputEvent() michael@0: { michael@0: return false; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsBaseWidget::SetIcon(const nsAString&) michael@0: { michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsBaseWidget::SetWindowTitlebarColor(nscolor aColor, bool aActive) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: bool michael@0: nsBaseWidget::ShowsResizeIndicator(nsIntRect* aResizerRect) michael@0: { michael@0: return false; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsBaseWidget::SetLayersAcceleration(bool aEnabled) michael@0: { michael@0: if (mUseLayersAcceleration == aEnabled) { michael@0: return NS_OK; michael@0: } michael@0: michael@0: bool usedAcceleration = mUseLayersAcceleration; michael@0: michael@0: mUseLayersAcceleration = ComputeShouldAccelerate(aEnabled); michael@0: // ComputeShouldAccelerate may have set mUseLayersAcceleration to a value michael@0: // different from aEnabled. michael@0: if (usedAcceleration == mUseLayersAcceleration) { michael@0: return NS_OK; michael@0: } michael@0: if (mLayerManager) { michael@0: mLayerManager->Destroy(); michael@0: } michael@0: mLayerManager = nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_METHOD nsBaseWidget::RegisterTouchWindow() michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_METHOD nsBaseWidget::UnregisterTouchWindow() michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsBaseWidget::OverrideSystemMouseScrollSpeed(double aOriginalDeltaX, michael@0: double aOriginalDeltaY, michael@0: double& aOverriddenDeltaX, michael@0: double& aOverriddenDeltaY) michael@0: { michael@0: aOverriddenDeltaX = aOriginalDeltaX; michael@0: aOverriddenDeltaY = aOriginalDeltaY; michael@0: michael@0: static bool sInitialized = false; michael@0: static bool sIsOverrideEnabled = false; michael@0: static int32_t sIntFactorX = 0; michael@0: static int32_t sIntFactorY = 0; michael@0: michael@0: if (!sInitialized) { michael@0: Preferences::AddBoolVarCache(&sIsOverrideEnabled, michael@0: "mousewheel.system_scroll_override_on_root_content.enabled", false); michael@0: Preferences::AddIntVarCache(&sIntFactorX, michael@0: "mousewheel.system_scroll_override_on_root_content.horizontal.factor", 0); michael@0: Preferences::AddIntVarCache(&sIntFactorY, michael@0: "mousewheel.system_scroll_override_on_root_content.vertical.factor", 0); michael@0: sIntFactorX = std::max(sIntFactorX, 0); michael@0: sIntFactorY = std::max(sIntFactorY, 0); michael@0: sInitialized = true; michael@0: } michael@0: michael@0: if (!sIsOverrideEnabled) { michael@0: return NS_OK; michael@0: } michael@0: michael@0: // The pref value must be larger than 100, otherwise, we don't override the michael@0: // delta value. michael@0: if (sIntFactorX > 100) { michael@0: double factor = static_cast(sIntFactorX) / 100; michael@0: aOverriddenDeltaX *= factor; michael@0: } michael@0: if (sIntFactorY > 100) { michael@0: double factor = static_cast(sIntFactorY) / 100; michael@0: aOverriddenDeltaY *= factor; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: michael@0: /** michael@0: * Modifies aFile to point at an icon file with the given name and suffix. The michael@0: * suffix may correspond to a file extension with leading '.' if appropriate. michael@0: * Returns true if the icon file exists and can be read. michael@0: */ michael@0: static bool michael@0: ResolveIconNameHelper(nsIFile *aFile, michael@0: const nsAString &aIconName, michael@0: const nsAString &aIconSuffix) michael@0: { michael@0: aFile->Append(NS_LITERAL_STRING("icons")); michael@0: aFile->Append(NS_LITERAL_STRING("default")); michael@0: aFile->Append(aIconName + aIconSuffix); michael@0: michael@0: bool readable; michael@0: return NS_SUCCEEDED(aFile->IsReadable(&readable)) && readable; michael@0: } michael@0: michael@0: /** michael@0: * Resolve the given icon name into a local file object. This method is michael@0: * intended to be called by subclasses of nsBaseWidget. aIconSuffix is a michael@0: * platform specific icon file suffix (e.g., ".ico" under Win32). michael@0: * michael@0: * If no file is found matching the given parameters, then null is returned. michael@0: */ michael@0: void michael@0: nsBaseWidget::ResolveIconName(const nsAString &aIconName, michael@0: const nsAString &aIconSuffix, michael@0: nsIFile **aResult) michael@0: { michael@0: *aResult = nullptr; michael@0: michael@0: nsCOMPtr dirSvc = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID); michael@0: if (!dirSvc) michael@0: return; michael@0: michael@0: // first check auxilary chrome directories michael@0: michael@0: nsCOMPtr dirs; michael@0: dirSvc->Get(NS_APP_CHROME_DIR_LIST, NS_GET_IID(nsISimpleEnumerator), michael@0: getter_AddRefs(dirs)); michael@0: if (dirs) { michael@0: bool hasMore; michael@0: while (NS_SUCCEEDED(dirs->HasMoreElements(&hasMore)) && hasMore) { michael@0: nsCOMPtr element; michael@0: dirs->GetNext(getter_AddRefs(element)); michael@0: if (!element) michael@0: continue; michael@0: nsCOMPtr file = do_QueryInterface(element); michael@0: if (!file) michael@0: continue; michael@0: if (ResolveIconNameHelper(file, aIconName, aIconSuffix)) { michael@0: NS_ADDREF(*aResult = file); michael@0: return; michael@0: } michael@0: } michael@0: } michael@0: michael@0: // then check the main app chrome directory michael@0: michael@0: nsCOMPtr file; michael@0: dirSvc->Get(NS_APP_CHROME_DIR, NS_GET_IID(nsIFile), michael@0: getter_AddRefs(file)); michael@0: if (file && ResolveIconNameHelper(file, aIconName, aIconSuffix)) michael@0: NS_ADDREF(*aResult = file); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsBaseWidget::BeginResizeDrag(WidgetGUIEvent* aEvent, michael@0: int32_t aHorizontal, michael@0: int32_t aVertical) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsBaseWidget::BeginMoveDrag(WidgetMouseEvent* aEvent) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: uint32_t michael@0: nsBaseWidget::GetGLFrameBufferFormat() michael@0: { michael@0: return LOCAL_GL_RGBA; michael@0: } michael@0: michael@0: void nsBaseWidget::SetSizeConstraints(const SizeConstraints& aConstraints) michael@0: { michael@0: mSizeConstraints = aConstraints; michael@0: // We can't ensure that the size is honored at this point because we're michael@0: // probably in the middle of a reflow. michael@0: } michael@0: michael@0: const widget::SizeConstraints& nsBaseWidget::GetSizeConstraints() const michael@0: { michael@0: return mSizeConstraints; michael@0: } michael@0: michael@0: // static michael@0: nsIRollupListener* michael@0: nsBaseWidget::GetActiveRollupListener() michael@0: { michael@0: // If set, then this is likely an dropdown. michael@0: if (gRollupListener) michael@0: return gRollupListener; michael@0: michael@0: return nsXULPopupManager::GetInstance(); michael@0: } michael@0: michael@0: void michael@0: nsBaseWidget::NotifyWindowDestroyed() michael@0: { michael@0: if (!mWidgetListener) michael@0: return; michael@0: michael@0: nsCOMPtr window = mWidgetListener->GetXULWindow(); michael@0: nsCOMPtr xulWindow(do_QueryInterface(window)); michael@0: if (xulWindow) { michael@0: xulWindow->Destroy(); michael@0: } michael@0: } michael@0: michael@0: void michael@0: nsBaseWidget::NotifySizeMoveDone() michael@0: { michael@0: if (!mWidgetListener || mWidgetListener->GetXULWindow()) michael@0: return; michael@0: michael@0: nsIPresShell* presShell = mWidgetListener->GetPresShell(); michael@0: if (presShell) { michael@0: presShell->WindowSizeMoveDone(); michael@0: } michael@0: } michael@0: michael@0: void michael@0: nsBaseWidget::NotifyWindowMoved(int32_t aX, int32_t aY) michael@0: { michael@0: if (mWidgetListener) { michael@0: mWidgetListener->WindowMoved(this, aX, aY); michael@0: } michael@0: michael@0: if (GetIMEUpdatePreference().WantPositionChanged()) { michael@0: NotifyIME(IMENotification(IMEMessage::NOTIFY_IME_OF_POSITION_CHANGE)); michael@0: } michael@0: } michael@0: michael@0: void michael@0: nsBaseWidget::NotifySysColorChanged() michael@0: { michael@0: if (!mWidgetListener || mWidgetListener->GetXULWindow()) michael@0: return; michael@0: michael@0: nsIPresShell* presShell = mWidgetListener->GetPresShell(); michael@0: if (presShell) { michael@0: presShell->SysColorChanged(); michael@0: } michael@0: } michael@0: michael@0: void michael@0: nsBaseWidget::NotifyThemeChanged() michael@0: { michael@0: if (!mWidgetListener || mWidgetListener->GetXULWindow()) michael@0: return; michael@0: michael@0: nsIPresShell* presShell = mWidgetListener->GetPresShell(); michael@0: if (presShell) { michael@0: presShell->ThemeChanged(); michael@0: } michael@0: } michael@0: michael@0: void michael@0: nsBaseWidget::NotifyUIStateChanged(UIStateChangeType aShowAccelerators, michael@0: UIStateChangeType aShowFocusRings) michael@0: { michael@0: if (!mWidgetListener) michael@0: return; michael@0: michael@0: nsIPresShell* presShell = mWidgetListener->GetPresShell(); michael@0: if (!presShell) michael@0: return; michael@0: michael@0: nsIDocument* doc = presShell->GetDocument(); michael@0: if (doc) { michael@0: nsPIDOMWindow* win = doc->GetWindow(); michael@0: if (win) { michael@0: win->SetKeyboardIndicators(aShowAccelerators, aShowFocusRings); michael@0: } michael@0: } michael@0: } michael@0: michael@0: #ifdef ACCESSIBILITY michael@0: michael@0: a11y::Accessible* michael@0: nsBaseWidget::GetRootAccessible() michael@0: { michael@0: NS_ENSURE_TRUE(mWidgetListener, nullptr); michael@0: michael@0: nsIPresShell* presShell = mWidgetListener->GetPresShell(); michael@0: NS_ENSURE_TRUE(presShell, nullptr); michael@0: michael@0: // If container is null then the presshell is not active. This often happens michael@0: // when a preshell is being held onto for fastback. michael@0: nsPresContext* presContext = presShell->GetPresContext(); michael@0: NS_ENSURE_TRUE(presContext->GetContainerWeak(), nullptr); michael@0: michael@0: // Accessible creation might be not safe so use IsSafeToRunScript to michael@0: // make sure it's not created at unsafe times. michael@0: nsCOMPtr accService = michael@0: services::GetAccessibilityService(); michael@0: if (accService) { michael@0: return accService->GetRootDocumentAccessible(presShell, nsContentUtils::IsSafeToRunScript()); michael@0: } michael@0: michael@0: return nullptr; michael@0: } michael@0: michael@0: #endif // ACCESSIBILITY michael@0: michael@0: nsresult michael@0: nsIWidget::SynthesizeNativeTouchTap(nsIntPoint aPointerScreenPoint, bool aLongTap) michael@0: { michael@0: if (sPointerIdCounter > TOUCH_INJECT_MAX_POINTS) { michael@0: sPointerIdCounter = 0; michael@0: } michael@0: int pointerId = sPointerIdCounter; michael@0: sPointerIdCounter++; michael@0: nsresult rv = SynthesizeNativeTouchPoint(pointerId, TOUCH_CONTACT, michael@0: aPointerScreenPoint, 1.0, 90); michael@0: if (NS_FAILED(rv)) { michael@0: return rv; michael@0: } michael@0: michael@0: if (!aLongTap) { michael@0: nsresult rv = SynthesizeNativeTouchPoint(pointerId, TOUCH_REMOVE, michael@0: aPointerScreenPoint, 0, 0); michael@0: return rv; michael@0: } michael@0: michael@0: // initiate a long tap michael@0: int elapse = Preferences::GetInt("ui.click_hold_context_menus.delay", michael@0: TOUCH_INJECT_LONG_TAP_DEFAULT_MSEC); michael@0: if (!mLongTapTimer) { michael@0: mLongTapTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv); michael@0: if (NS_FAILED(rv)) { michael@0: SynthesizeNativeTouchPoint(pointerId, TOUCH_CANCEL, michael@0: aPointerScreenPoint, 0, 0); michael@0: return NS_ERROR_UNEXPECTED; michael@0: } michael@0: // Windows requires recuring events, so we set this to a smaller window michael@0: // than the pref value. michael@0: int timeout = elapse; michael@0: if (timeout > TOUCH_INJECT_PUMP_TIMER_MSEC) { michael@0: timeout = TOUCH_INJECT_PUMP_TIMER_MSEC; michael@0: } michael@0: mLongTapTimer->InitWithFuncCallback(OnLongTapTimerCallback, this, michael@0: timeout, michael@0: nsITimer::TYPE_REPEATING_SLACK); michael@0: } michael@0: michael@0: // If we already have a long tap pending, cancel it. We only allow one long michael@0: // tap to be active at a time. michael@0: if (mLongTapTouchPoint) { michael@0: SynthesizeNativeTouchPoint(mLongTapTouchPoint->mPointerId, TOUCH_CANCEL, michael@0: mLongTapTouchPoint->mPosition, 0, 0); michael@0: } michael@0: michael@0: mLongTapTouchPoint = new LongTapInfo(pointerId, aPointerScreenPoint, michael@0: TimeDuration::FromMilliseconds(elapse)); michael@0: return NS_OK; michael@0: } michael@0: michael@0: // static michael@0: void michael@0: nsIWidget::OnLongTapTimerCallback(nsITimer* aTimer, void* aClosure) michael@0: { michael@0: nsIWidget *self = static_cast(aClosure); michael@0: michael@0: if ((self->mLongTapTouchPoint->mStamp + self->mLongTapTouchPoint->mDuration) > michael@0: TimeStamp::Now()) { michael@0: #ifdef XP_WIN michael@0: // Windows needs us to keep pumping feedback to the digitizer, so update michael@0: // the pointer id with the same position. michael@0: self->SynthesizeNativeTouchPoint(self->mLongTapTouchPoint->mPointerId, michael@0: TOUCH_CONTACT, michael@0: self->mLongTapTouchPoint->mPosition, michael@0: 1.0, 90); michael@0: #endif michael@0: return; michael@0: } michael@0: michael@0: // finished, remove the touch point michael@0: self->mLongTapTimer->Cancel(); michael@0: self->mLongTapTimer = nullptr; michael@0: self->SynthesizeNativeTouchPoint(self->mLongTapTouchPoint->mPointerId, michael@0: TOUCH_REMOVE, michael@0: self->mLongTapTouchPoint->mPosition, michael@0: 0, 0); michael@0: self->mLongTapTouchPoint = nullptr; michael@0: } michael@0: michael@0: nsresult michael@0: nsIWidget::ClearNativeTouchSequence() michael@0: { michael@0: if (!mLongTapTimer) { michael@0: return NS_OK; michael@0: } michael@0: mLongTapTimer->Cancel(); michael@0: mLongTapTimer = nullptr; michael@0: SynthesizeNativeTouchPoint(mLongTapTouchPoint->mPointerId, TOUCH_CANCEL, michael@0: mLongTapTouchPoint->mPosition, 0, 0); michael@0: mLongTapTouchPoint = nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: #ifdef DEBUG michael@0: ////////////////////////////////////////////////////////////// michael@0: // michael@0: // Convert a GUI event message code to a string. michael@0: // Makes it a lot easier to debug events. michael@0: // michael@0: // See gtk/nsWidget.cpp and windows/nsWindow.cpp michael@0: // for a DebugPrintEvent() function that uses michael@0: // this. michael@0: // michael@0: ////////////////////////////////////////////////////////////// michael@0: /* static */ nsAutoString michael@0: nsBaseWidget::debug_GuiEventToString(WidgetGUIEvent* aGuiEvent) michael@0: { michael@0: NS_ASSERTION(nullptr != aGuiEvent,"cmon, null gui event."); michael@0: michael@0: nsAutoString eventName(NS_LITERAL_STRING("UNKNOWN")); michael@0: michael@0: #define _ASSIGN_eventName(_value,_name)\ michael@0: case _value: eventName.AssignLiteral(_name) ; break michael@0: michael@0: switch(aGuiEvent->message) michael@0: { michael@0: _ASSIGN_eventName(NS_BLUR_CONTENT,"NS_BLUR_CONTENT"); michael@0: _ASSIGN_eventName(NS_DRAGDROP_GESTURE,"NS_DND_GESTURE"); michael@0: _ASSIGN_eventName(NS_DRAGDROP_DROP,"NS_DND_DROP"); michael@0: _ASSIGN_eventName(NS_DRAGDROP_ENTER,"NS_DND_ENTER"); michael@0: _ASSIGN_eventName(NS_DRAGDROP_EXIT,"NS_DND_EXIT"); michael@0: _ASSIGN_eventName(NS_DRAGDROP_OVER,"NS_DND_OVER"); michael@0: _ASSIGN_eventName(NS_EDITOR_INPUT,"NS_EDITOR_INPUT"); michael@0: _ASSIGN_eventName(NS_FOCUS_CONTENT,"NS_FOCUS_CONTENT"); michael@0: _ASSIGN_eventName(NS_FORM_SELECTED,"NS_FORM_SELECTED"); michael@0: _ASSIGN_eventName(NS_FORM_CHANGE,"NS_FORM_CHANGE"); michael@0: _ASSIGN_eventName(NS_FORM_RESET,"NS_FORM_RESET"); michael@0: _ASSIGN_eventName(NS_FORM_SUBMIT,"NS_FORM_SUBMIT"); michael@0: _ASSIGN_eventName(NS_IMAGE_ABORT,"NS_IMAGE_ABORT"); michael@0: _ASSIGN_eventName(NS_LOAD_ERROR,"NS_LOAD_ERROR"); michael@0: _ASSIGN_eventName(NS_KEY_DOWN,"NS_KEY_DOWN"); michael@0: _ASSIGN_eventName(NS_KEY_PRESS,"NS_KEY_PRESS"); michael@0: _ASSIGN_eventName(NS_KEY_UP,"NS_KEY_UP"); michael@0: _ASSIGN_eventName(NS_MOUSE_ENTER,"NS_MOUSE_ENTER"); michael@0: _ASSIGN_eventName(NS_MOUSE_EXIT,"NS_MOUSE_EXIT"); michael@0: _ASSIGN_eventName(NS_MOUSE_BUTTON_DOWN,"NS_MOUSE_BUTTON_DOWN"); michael@0: _ASSIGN_eventName(NS_MOUSE_BUTTON_UP,"NS_MOUSE_BUTTON_UP"); michael@0: _ASSIGN_eventName(NS_MOUSE_CLICK,"NS_MOUSE_CLICK"); michael@0: _ASSIGN_eventName(NS_MOUSE_DOUBLECLICK,"NS_MOUSE_DBLCLICK"); michael@0: _ASSIGN_eventName(NS_MOUSE_MOVE,"NS_MOUSE_MOVE"); michael@0: _ASSIGN_eventName(NS_LOAD,"NS_LOAD"); michael@0: _ASSIGN_eventName(NS_POPSTATE,"NS_POPSTATE"); michael@0: _ASSIGN_eventName(NS_BEFORE_SCRIPT_EXECUTE,"NS_BEFORE_SCRIPT_EXECUTE"); michael@0: _ASSIGN_eventName(NS_AFTER_SCRIPT_EXECUTE,"NS_AFTER_SCRIPT_EXECUTE"); michael@0: _ASSIGN_eventName(NS_PAGE_UNLOAD,"NS_PAGE_UNLOAD"); michael@0: _ASSIGN_eventName(NS_HASHCHANGE,"NS_HASHCHANGE"); michael@0: _ASSIGN_eventName(NS_READYSTATECHANGE,"NS_READYSTATECHANGE"); michael@0: _ASSIGN_eventName(NS_XUL_BROADCAST, "NS_XUL_BROADCAST"); michael@0: _ASSIGN_eventName(NS_XUL_COMMAND_UPDATE, "NS_XUL_COMMAND_UPDATE"); michael@0: michael@0: #undef _ASSIGN_eventName michael@0: michael@0: default: michael@0: { michael@0: char buf[32]; michael@0: michael@0: sprintf(buf,"UNKNOWN: %d",aGuiEvent->message); michael@0: michael@0: CopyASCIItoUTF16(buf, eventName); michael@0: } michael@0: break; michael@0: } michael@0: michael@0: return nsAutoString(eventName); michael@0: } michael@0: ////////////////////////////////////////////////////////////// michael@0: // michael@0: // Code to deal with paint and event debug prefs. michael@0: // michael@0: ////////////////////////////////////////////////////////////// michael@0: struct PrefPair michael@0: { michael@0: const char * name; michael@0: bool value; michael@0: }; michael@0: michael@0: static PrefPair debug_PrefValues[] = michael@0: { michael@0: { "nglayout.debug.crossing_event_dumping", false }, michael@0: { "nglayout.debug.event_dumping", false }, michael@0: { "nglayout.debug.invalidate_dumping", false }, michael@0: { "nglayout.debug.motion_event_dumping", false }, michael@0: { "nglayout.debug.paint_dumping", false }, michael@0: { "nglayout.debug.paint_flashing", false } michael@0: }; michael@0: michael@0: ////////////////////////////////////////////////////////////// michael@0: bool michael@0: nsBaseWidget::debug_GetCachedBoolPref(const char * aPrefName) michael@0: { michael@0: NS_ASSERTION(nullptr != aPrefName,"cmon, pref name is null."); michael@0: michael@0: for (uint32_t i = 0; i < ArrayLength(debug_PrefValues); i++) michael@0: { michael@0: if (strcmp(debug_PrefValues[i].name, aPrefName) == 0) michael@0: { michael@0: return debug_PrefValues[i].value; michael@0: } michael@0: } michael@0: michael@0: return false; michael@0: } michael@0: ////////////////////////////////////////////////////////////// michael@0: static void debug_SetCachedBoolPref(const char * aPrefName,bool aValue) michael@0: { michael@0: NS_ASSERTION(nullptr != aPrefName,"cmon, pref name is null."); michael@0: michael@0: for (uint32_t i = 0; i < ArrayLength(debug_PrefValues); i++) michael@0: { michael@0: if (strcmp(debug_PrefValues[i].name, aPrefName) == 0) michael@0: { michael@0: debug_PrefValues[i].value = aValue; michael@0: michael@0: return; michael@0: } michael@0: } michael@0: michael@0: NS_ASSERTION(false, "cmon, this code is not reached dude."); michael@0: } michael@0: michael@0: ////////////////////////////////////////////////////////////// michael@0: class Debug_PrefObserver MOZ_FINAL : public nsIObserver { michael@0: public: michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIOBSERVER michael@0: }; michael@0: michael@0: NS_IMPL_ISUPPORTS(Debug_PrefObserver, nsIObserver) michael@0: michael@0: NS_IMETHODIMP michael@0: Debug_PrefObserver::Observe(nsISupports* subject, const char* topic, michael@0: const char16_t* data) michael@0: { michael@0: NS_ConvertUTF16toUTF8 prefName(data); michael@0: michael@0: bool value = Preferences::GetBool(prefName.get(), false); michael@0: debug_SetCachedBoolPref(prefName.get(), value); michael@0: return NS_OK; michael@0: } michael@0: michael@0: ////////////////////////////////////////////////////////////// michael@0: /* static */ void michael@0: debug_RegisterPrefCallbacks() michael@0: { michael@0: static bool once = true; michael@0: michael@0: if (!once) { michael@0: return; michael@0: } michael@0: michael@0: once = false; michael@0: michael@0: nsCOMPtr obs(new Debug_PrefObserver()); michael@0: for (uint32_t i = 0; i < ArrayLength(debug_PrefValues); i++) { michael@0: // Initialize the pref values michael@0: debug_PrefValues[i].value = michael@0: Preferences::GetBool(debug_PrefValues[i].name, false); michael@0: michael@0: if (obs) { michael@0: // Register callbacks for when these change michael@0: Preferences::AddStrongObserver(obs, debug_PrefValues[i].name); michael@0: } michael@0: } michael@0: } michael@0: ////////////////////////////////////////////////////////////// michael@0: static int32_t michael@0: _GetPrintCount() michael@0: { michael@0: static int32_t sCount = 0; michael@0: michael@0: return ++sCount; michael@0: } michael@0: ////////////////////////////////////////////////////////////// michael@0: /* static */ bool michael@0: nsBaseWidget::debug_WantPaintFlashing() michael@0: { michael@0: return debug_GetCachedBoolPref("nglayout.debug.paint_flashing"); michael@0: } michael@0: ////////////////////////////////////////////////////////////// michael@0: /* static */ void michael@0: nsBaseWidget::debug_DumpEvent(FILE * aFileOut, michael@0: nsIWidget * aWidget, michael@0: WidgetGUIEvent* aGuiEvent, michael@0: const nsAutoCString & aWidgetName, michael@0: int32_t aWindowID) michael@0: { michael@0: if (aGuiEvent->message == NS_MOUSE_MOVE) michael@0: { michael@0: if (!debug_GetCachedBoolPref("nglayout.debug.motion_event_dumping")) michael@0: return; michael@0: } michael@0: michael@0: if (aGuiEvent->message == NS_MOUSE_ENTER || michael@0: aGuiEvent->message == NS_MOUSE_EXIT) michael@0: { michael@0: if (!debug_GetCachedBoolPref("nglayout.debug.crossing_event_dumping")) michael@0: return; michael@0: } michael@0: michael@0: if (!debug_GetCachedBoolPref("nglayout.debug.event_dumping")) michael@0: return; michael@0: michael@0: NS_LossyConvertUTF16toASCII tempString(debug_GuiEventToString(aGuiEvent).get()); michael@0: michael@0: fprintf(aFileOut, michael@0: "%4d %-26s widget=%-8p name=%-12s id=0x%-6x refpt=%d,%d\n", michael@0: _GetPrintCount(), michael@0: tempString.get(), michael@0: (void *) aWidget, michael@0: aWidgetName.get(), michael@0: aWindowID, michael@0: aGuiEvent->refPoint.x, michael@0: aGuiEvent->refPoint.y); michael@0: } michael@0: ////////////////////////////////////////////////////////////// michael@0: /* static */ void michael@0: nsBaseWidget::debug_DumpPaintEvent(FILE * aFileOut, michael@0: nsIWidget * aWidget, michael@0: const nsIntRegion & aRegion, michael@0: const nsAutoCString & aWidgetName, michael@0: int32_t aWindowID) michael@0: { michael@0: NS_ASSERTION(nullptr != aFileOut,"cmon, null output FILE"); michael@0: NS_ASSERTION(nullptr != aWidget,"cmon, the widget is null"); michael@0: michael@0: if (!debug_GetCachedBoolPref("nglayout.debug.paint_dumping")) michael@0: return; michael@0: michael@0: nsIntRect rect = aRegion.GetBounds(); michael@0: fprintf(aFileOut, michael@0: "%4d PAINT widget=%p name=%-12s id=0x%-6x bounds-rect=%3d,%-3d %3d,%-3d", michael@0: _GetPrintCount(), michael@0: (void *) aWidget, michael@0: aWidgetName.get(), michael@0: aWindowID, michael@0: rect.x, rect.y, rect.width, rect.height michael@0: ); michael@0: michael@0: fprintf(aFileOut,"\n"); michael@0: } michael@0: ////////////////////////////////////////////////////////////// michael@0: /* static */ void michael@0: nsBaseWidget::debug_DumpInvalidate(FILE * aFileOut, michael@0: nsIWidget * aWidget, michael@0: const nsIntRect * aRect, michael@0: const nsAutoCString & aWidgetName, michael@0: int32_t aWindowID) michael@0: { michael@0: if (!debug_GetCachedBoolPref("nglayout.debug.invalidate_dumping")) michael@0: return; michael@0: michael@0: NS_ASSERTION(nullptr != aFileOut,"cmon, null output FILE"); michael@0: NS_ASSERTION(nullptr != aWidget,"cmon, the widget is null"); michael@0: michael@0: fprintf(aFileOut, michael@0: "%4d Invalidate widget=%p name=%-12s id=0x%-6x", michael@0: _GetPrintCount(), michael@0: (void *) aWidget, michael@0: aWidgetName.get(), michael@0: aWindowID); michael@0: michael@0: if (aRect) michael@0: { michael@0: fprintf(aFileOut, michael@0: " rect=%3d,%-3d %3d,%-3d", michael@0: aRect->x, michael@0: aRect->y, michael@0: aRect->width, michael@0: aRect->height); michael@0: } michael@0: else michael@0: { michael@0: fprintf(aFileOut, michael@0: " rect=%-15s", michael@0: "none"); michael@0: } michael@0: michael@0: fprintf(aFileOut,"\n"); michael@0: } michael@0: ////////////////////////////////////////////////////////////// michael@0: michael@0: #endif // DEBUG michael@0: