diff -r 000000000000 -r 6474c204b198 widget/xpwidgets/nsBaseWidget.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/widget/xpwidgets/nsBaseWidget.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,478 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef nsBaseWidget_h__ +#define nsBaseWidget_h__ + +#include "mozilla/EventForwards.h" +#include "mozilla/WidgetUtils.h" +#include "nsRect.h" +#include "nsIWidget.h" +#include "nsWidgetsCID.h" +#include "nsIFile.h" +#include "nsString.h" +#include "nsCOMPtr.h" +#include "nsAutoPtr.h" +#include "nsIRollupListener.h" +#include "nsIObserver.h" +#include "nsIWidgetListener.h" +#include "nsPIDOMWindow.h" +#include +class nsIContent; +class nsAutoRollup; +class gfxContext; + +namespace mozilla { +#ifdef ACCESSIBILITY +namespace a11y { +class Accessible; +} +#endif + +namespace layers { +class BasicLayerManager; +class CompositorChild; +class CompositorParent; +} +} + +namespace base { +class Thread; +} + +// Windows specific constant indicating the maximum number of touch points the +// inject api will allow. This also sets the maximum numerical value for touch +// ids we can use when injecting touch points on Windows. +#define TOUCH_INJECT_MAX_POINTS 256 + +class nsBaseWidget; + +class WidgetShutdownObserver MOZ_FINAL : public nsIObserver +{ +public: + WidgetShutdownObserver(nsBaseWidget* aWidget) + : mWidget(aWidget) + { } + + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER + + nsBaseWidget *mWidget; +}; + +/** + * Common widget implementation used as base class for native + * or crossplatform implementations of Widgets. + * All cross-platform behavior that all widgets need to implement + * should be placed in this class. + * (Note: widget implementations are not required to use this + * class, but it gives them a head start.) + */ + +class nsBaseWidget : public nsIWidget +{ + friend class nsAutoRollup; + +protected: + typedef base::Thread Thread; + typedef mozilla::layers::BasicLayerManager BasicLayerManager; + typedef mozilla::layers::BufferMode BufferMode; + typedef mozilla::layers::CompositorChild CompositorChild; + typedef mozilla::layers::CompositorParent CompositorParent; + typedef mozilla::ScreenRotation ScreenRotation; + +public: + nsBaseWidget(); + virtual ~nsBaseWidget(); + + NS_DECL_ISUPPORTS + + // nsIWidget interface + NS_IMETHOD CaptureMouse(bool aCapture); + virtual nsIWidgetListener* GetWidgetListener(); + virtual void SetWidgetListener(nsIWidgetListener* alistener); + NS_IMETHOD Destroy(); + NS_IMETHOD SetParent(nsIWidget* aNewParent); + virtual nsIWidget* GetParent(void); + virtual nsIWidget* GetTopLevelWidget(); + virtual nsIWidget* GetSheetWindowParent(void); + virtual float GetDPI(); + virtual void AddChild(nsIWidget* aChild); + virtual void RemoveChild(nsIWidget* aChild); + + void SetZIndex(int32_t aZIndex); + NS_IMETHOD PlaceBehind(nsTopLevelWidgetZPlacement aPlacement, + nsIWidget *aWidget, bool aActivate); + + NS_IMETHOD SetSizeMode(int32_t aMode); + virtual int32_t SizeMode() MOZ_OVERRIDE + { + return mSizeMode; + } + + virtual nsCursor GetCursor(); + NS_IMETHOD SetCursor(nsCursor aCursor); + NS_IMETHOD SetCursor(imgIContainer* aCursor, + uint32_t aHotspotX, uint32_t aHotspotY); + virtual void SetTransparencyMode(nsTransparencyMode aMode); + virtual nsTransparencyMode GetTransparencyMode(); + virtual void GetWindowClipRegion(nsTArray* aRects); + NS_IMETHOD SetWindowShadowStyle(int32_t aStyle); + virtual void SetShowsToolbarButton(bool aShow) {} + virtual void SetShowsFullScreenButton(bool aShow) {} + virtual void SetWindowAnimationType(WindowAnimationType aType) {} + NS_IMETHOD HideWindowChrome(bool aShouldHide); + NS_IMETHOD MakeFullScreen(bool aFullScreen); + virtual nsDeviceContext* GetDeviceContext(); + virtual LayerManager* GetLayerManager(PLayerTransactionChild* aShadowManager = nullptr, + LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE, + LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT, + bool* aAllowRetaining = nullptr); + + virtual CompositorParent* NewCompositorParent(int aSurfaceWidth, int aSurfaceHeight); + virtual void CreateCompositor(); + virtual void CreateCompositor(int aWidth, int aHeight); + virtual void PrepareWindowEffects() {} + virtual void CleanupWindowEffects() {} + virtual bool PreRender(LayerManagerComposite* aManager) { return true; } + virtual void PostRender(LayerManagerComposite* aManager) {} + virtual void DrawWindowUnderlay(LayerManagerComposite* aManager, nsIntRect aRect) {} + virtual void DrawWindowOverlay(LayerManagerComposite* aManager, nsIntRect aRect) {} + virtual mozilla::TemporaryRef StartRemoteDrawing(); + virtual void EndRemoteDrawing() { }; + virtual void CleanupRemoteDrawing() { }; + virtual void UpdateThemeGeometries(const nsTArray& aThemeGeometries) {} + virtual gfxASurface* GetThebesSurface(); + NS_IMETHOD SetModal(bool aModal); + virtual uint32_t GetMaxTouchPoints() const; + NS_IMETHOD SetWindowClass(const nsAString& xulWinType); + // Return whether this widget interprets parameters to Move and Resize APIs + // as "global display pixels" rather than "device pixels", and therefore + // applies its GetDefaultScale() value to them before using them as mBounds + // etc (which are always stored in device pixels). + // Note that APIs that -get- the widget's position/size/bounds, rather than + // -setting- them (i.e. moving or resizing the widget) will always return + // values in the widget's device pixels. + bool BoundsUseDisplayPixels() const { + return mWindowType <= eWindowType_popup; + } + NS_IMETHOD MoveClient(double aX, double aY); + NS_IMETHOD ResizeClient(double aWidth, double aHeight, bool aRepaint); + NS_IMETHOD ResizeClient(double aX, double aY, double aWidth, double aHeight, bool aRepaint); + NS_IMETHOD GetBounds(nsIntRect &aRect); + NS_IMETHOD GetClientBounds(nsIntRect &aRect); + NS_IMETHOD GetScreenBounds(nsIntRect &aRect); + NS_IMETHOD GetNonClientMargins(nsIntMargin &margins); + NS_IMETHOD SetNonClientMargins(nsIntMargin &margins); + virtual nsIntPoint GetClientOffset(); + NS_IMETHOD EnableDragDrop(bool aEnable); + NS_IMETHOD GetAttention(int32_t aCycleCount); + virtual bool HasPendingInputEvent(); + NS_IMETHOD SetIcon(const nsAString &anIconSpec); + NS_IMETHOD SetWindowTitlebarColor(nscolor aColor, bool aActive); + virtual void SetDrawsInTitlebar(bool aState) {} + virtual bool ShowsResizeIndicator(nsIntRect* aResizerRect); + virtual void FreeNativeData(void * data, uint32_t aDataType) {} + NS_IMETHOD BeginResizeDrag(mozilla::WidgetGUIEvent* aEvent, + int32_t aHorizontal, + int32_t aVertical); + NS_IMETHOD BeginMoveDrag(mozilla::WidgetMouseEvent* aEvent); + virtual nsresult ActivateNativeMenuItemAt(const nsAString& indexString) { return NS_ERROR_NOT_IMPLEMENTED; } + virtual nsresult ForceUpdateNativeMenuAt(const nsAString& indexString) { return NS_ERROR_NOT_IMPLEMENTED; } + NS_IMETHOD NotifyIME(const IMENotification& aIMENotification) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; } + NS_IMETHOD AttachNativeKeyEvent(mozilla::WidgetKeyboardEvent& aEvent) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; } + NS_IMETHOD_(bool) ExecuteNativeKeyBinding( + NativeKeyBindingsType aType, + const mozilla::WidgetKeyboardEvent& aEvent, + DoCommandCallback aCallback, + void* aCallbackData) MOZ_OVERRIDE { return false; } + NS_IMETHOD SetLayersAcceleration(bool aEnabled); + virtual bool GetLayersAcceleration() { return mUseLayersAcceleration; } + virtual bool ComputeShouldAccelerate(bool aDefault); + NS_IMETHOD GetToggledKeyState(uint32_t aKeyCode, bool* aLEDState) { return NS_ERROR_NOT_IMPLEMENTED; } + virtual nsIMEUpdatePreference GetIMEUpdatePreference() MOZ_OVERRIDE { return nsIMEUpdatePreference(); } + NS_IMETHOD OnDefaultButtonLoaded(const nsIntRect &aButtonRect) { return NS_ERROR_NOT_IMPLEMENTED; } + NS_IMETHOD OverrideSystemMouseScrollSpeed(double aOriginalDeltaX, + double aOriginalDeltaY, + double& aOverriddenDeltaX, + double& aOverriddenDeltaY); + virtual already_AddRefed + CreateChild(const nsIntRect &aRect, + nsDeviceContext *aContext, + nsWidgetInitData *aInitData = nullptr, + bool aForceUseIWidgetParent = false); + NS_IMETHOD AttachViewToTopLevel(bool aUseAttachedEvents, nsDeviceContext *aContext); + virtual nsIWidgetListener* GetAttachedWidgetListener(); + virtual void SetAttachedWidgetListener(nsIWidgetListener* aListener); + NS_IMETHOD RegisterTouchWindow(); + NS_IMETHOD UnregisterTouchWindow(); + + void NotifyWindowDestroyed(); + void NotifySizeMoveDone(); + void NotifyWindowMoved(int32_t aX, int32_t aY); + + // Should be called by derived implementations to notify on system color and + // theme changes. + void NotifySysColorChanged(); + void NotifyThemeChanged(); + void NotifyUIStateChanged(UIStateChangeType aShowAccelerators, + UIStateChangeType aShowFocusRings); + +#ifdef ACCESSIBILITY + // Get the accessible for the window. + mozilla::a11y::Accessible* GetRootAccessible(); +#endif + + nsPopupLevel PopupLevel() { return mPopupLevel; } + + virtual nsIntSize ClientToWindowSize(const nsIntSize& aClientSize) + { + return aClientSize; + } + + // return true if this is a popup widget with a native titlebar + bool IsPopupWithTitleBar() const + { + return (mWindowType == eWindowType_popup && + mBorderStyle != eBorderStyle_default && + mBorderStyle & eBorderStyle_title); + } + + NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent) = 0; + + virtual uint32_t GetGLFrameBufferFormat() MOZ_OVERRIDE; + + virtual const SizeConstraints& GetSizeConstraints() const; + virtual void SetSizeConstraints(const SizeConstraints& aConstraints); + + /** + * Use this when GetLayerManager() returns a BasicLayerManager + * (nsBaseWidget::GetLayerManager() does). This sets up the widget's + * layer manager to temporarily render into aTarget. + * + * |aNaturalWidgetBounds| is the un-rotated bounds of |aWidget|. + * |aRotation| is the "virtual rotation" to apply when rendering to + * the target. When |aRotation| is ROTATION_0, + * |aNaturalWidgetBounds| is not used. + */ + class AutoLayerManagerSetup { + public: + AutoLayerManagerSetup(nsBaseWidget* aWidget, gfxContext* aTarget, + BufferMode aDoubleBuffering, + ScreenRotation aRotation = mozilla::ROTATION_0); + ~AutoLayerManagerSetup(); + private: + nsBaseWidget* mWidget; + nsRefPtr mLayerManager; + }; + friend class AutoLayerManagerSetup; + + class AutoUseBasicLayerManager { + public: + AutoUseBasicLayerManager(nsBaseWidget* aWidget); + ~AutoUseBasicLayerManager(); + private: + nsBaseWidget* mWidget; + bool mPreviousTemporarilyUseBasicLayerManager; + }; + friend class AutoUseBasicLayerManager; + + virtual bool ShouldUseOffMainThreadCompositing(); + + static nsIRollupListener* GetActiveRollupListener(); + + void Shutdown(); + +protected: + + virtual void ResolveIconName(const nsAString &aIconName, + const nsAString &aIconSuffix, + nsIFile **aResult); + virtual void OnDestroy(); + virtual void BaseCreate(nsIWidget *aParent, + const nsIntRect &aRect, + nsDeviceContext *aContext, + nsWidgetInitData *aInitData); + + virtual nsIContent* GetLastRollup() + { + return mLastRollup; + } + + virtual nsresult SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout, + int32_t aNativeKeyCode, + uint32_t aModifierFlags, + const nsAString& aCharacters, + const nsAString& aUnmodifiedCharacters) + { return NS_ERROR_UNEXPECTED; } + + virtual nsresult SynthesizeNativeMouseEvent(nsIntPoint aPoint, + uint32_t aNativeMessage, + uint32_t aModifierFlags) + { return NS_ERROR_UNEXPECTED; } + + virtual nsresult SynthesizeNativeMouseMove(nsIntPoint aPoint) + { return NS_ERROR_UNEXPECTED; } + + virtual nsresult SynthesizeNativeMouseScrollEvent(nsIntPoint aPoint, + uint32_t aNativeMessage, + double aDeltaX, + double aDeltaY, + double aDeltaZ, + uint32_t aModifierFlags, + uint32_t aAdditionalFlags) + { return NS_ERROR_UNEXPECTED; } + + virtual nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId, + TouchPointerState aPointerState, + nsIntPoint aPointerScreenPoint, + double aPointerPressure, + uint32_t aPointerOrientation) + { return NS_ERROR_UNEXPECTED; } + +protected: + // Stores the clip rectangles in aRects into mClipRects. Returns true + // if the new rectangles are different from the old rectangles. + bool StoreWindowClipRegion(const nsTArray& aRects); + + virtual already_AddRefed + AllocateChildPopupWidget() + { + static NS_DEFINE_IID(kCPopUpCID, NS_CHILD_CID); + nsCOMPtr widget = do_CreateInstance(kCPopUpCID); + return widget.forget(); + } + + LayerManager* CreateBasicLayerManager(); + + nsPopupType PopupType() const { return mPopupType; } + + void NotifyRollupGeometryChange() + { + // XULPopupManager isn't interested in this notification, so only + // send it if gRollupListener is set. + if (gRollupListener) { + gRollupListener->NotifyGeometryChange(); + } + } + + /** + * Apply the current size constraints to the given size. + * + * @param aWidth width to constrain + * @param aHeight height to constrain + */ + void ConstrainSize(int32_t* aWidth, int32_t* aHeight) const + { + *aWidth = std::max(mSizeConstraints.mMinSize.width, + std::min(mSizeConstraints.mMaxSize.width, *aWidth)); + *aHeight = std::max(mSizeConstraints.mMinSize.height, + std::min(mSizeConstraints.mMaxSize.height, *aHeight)); + } + + virtual CompositorChild* GetRemoteRenderer() MOZ_OVERRIDE; + + virtual void GetPreferredCompositorBackends(nsTArray& aHints); + + /** + * Notify the widget that this window is being used with OMTC. + */ + virtual void WindowUsesOMTC() {} + +protected: + /** + * Starts the OMTC compositor destruction sequence. + * + * When this function returns, the compositor should not be + * able to access the opengl context anymore. + * It is safe to call it several times if platform implementations + * require the compositor to be destroyed before ~nsBaseWidget is + * reached (This is the case with gtk2 for instance). + */ + void DestroyCompositor(); + + nsIWidgetListener* mWidgetListener; + nsIWidgetListener* mAttachedWidgetListener; + nsDeviceContext* mContext; + nsRefPtr mLayerManager; + nsRefPtr mBasicLayerManager; + nsRefPtr mCompositorChild; + nsRefPtr mCompositorParent; + nsRefPtr mShutdownObserver; + nsCursor mCursor; + nsBorderStyle mBorderStyle; + bool mUseLayersAcceleration; + bool mForceLayersAcceleration; + bool mTemporarilyUseBasicLayerManager; + // Windows with out-of-process tabs always require OMTC. This flag designates + // such windows. + bool mRequireOffMainThreadCompositing; + bool mUseAttachedEvents; + bool mContextInitialized; + nsIntRect mBounds; + nsIntRect* mOriginalBounds; + // When this pointer is null, the widget is not clipped + nsAutoArrayPtr mClipRects; + uint32_t mClipRectCount; + nsSizeMode mSizeMode; + nsPopupLevel mPopupLevel; + nsPopupType mPopupType; + SizeConstraints mSizeConstraints; + + static nsIRollupListener* gRollupListener; + + // the last rolled up popup. Only set this when an nsAutoRollup is in scope, + // so it can be cleared automatically. + static nsIContent* mLastRollup; + +#ifdef DEBUG +protected: + static nsAutoString debug_GuiEventToString(mozilla::WidgetGUIEvent* aGuiEvent); + static bool debug_WantPaintFlashing(); + + static void debug_DumpInvalidate(FILE * aFileOut, + nsIWidget * aWidget, + const nsIntRect * aRect, + const nsAutoCString & aWidgetName, + int32_t aWindowID); + + static void debug_DumpEvent(FILE* aFileOut, + nsIWidget* aWidget, + mozilla::WidgetGUIEvent* aGuiEvent, + const nsAutoCString& aWidgetName, + int32_t aWindowID); + + static void debug_DumpPaintEvent(FILE * aFileOut, + nsIWidget * aWidget, + const nsIntRegion & aPaintEvent, + const nsAutoCString & aWidgetName, + int32_t aWindowID); + + static bool debug_GetCachedBoolPref(const char* aPrefName); +#endif +}; + +// A situation can occur when a mouse event occurs over a menu label while the +// menu popup is already open. The expected behaviour is to close the popup. +// This happens by calling nsIRollupListener::Rollup before the mouse event is +// processed. However, in cases where the mouse event is not consumed, this +// event will then get targeted at the menu label causing the menu to open +// again. To prevent this, we store in mLastRollup a reference to the popup +// that was closed during the Rollup call, and prevent this popup from +// reopening while processing the mouse event. +// mLastRollup should only be set while an nsAutoRollup is in scope; +// when it goes out of scope mLastRollup is cleared automatically. +// As mLastRollup is static, it can be retrieved by calling +// nsIWidget::GetLastRollup on any widget. +class nsAutoRollup +{ + bool wasClear; + + public: + + nsAutoRollup(); + ~nsAutoRollup(); +}; + +#endif // nsBaseWidget_h__