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