michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * vim: sw=2 ts=8 et : michael@0: */ 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: /** michael@0: * This "puppet widget" isn't really a platform widget. It's intended michael@0: * to be used in widgetless rendering contexts, such as sandboxed michael@0: * content processes. If any "real" widgetry is needed, the request michael@0: * is forwarded to and/or data received from elsewhere. michael@0: */ michael@0: michael@0: #ifndef mozilla_widget_PuppetWidget_h__ michael@0: #define mozilla_widget_PuppetWidget_h__ michael@0: michael@0: #include "nsBaseScreen.h" michael@0: #include "nsBaseWidget.h" michael@0: #include "nsIScreenManager.h" michael@0: #include "nsThreadUtils.h" michael@0: #include "nsWeakReference.h" michael@0: #include "mozilla/Attributes.h" michael@0: #include "mozilla/EventForwards.h" michael@0: michael@0: class gfxASurface; michael@0: michael@0: namespace mozilla { michael@0: michael@0: namespace dom { michael@0: class TabChild; michael@0: } michael@0: michael@0: namespace widget { michael@0: michael@0: class AutoCacheNativeKeyCommands; michael@0: michael@0: class PuppetWidget : public nsBaseWidget, public nsSupportsWeakReference michael@0: { michael@0: typedef mozilla::dom::TabChild TabChild; michael@0: typedef nsBaseWidget Base; michael@0: michael@0: // The width and height of the "widget" are clamped to this. michael@0: static const size_t kMaxDimension; michael@0: michael@0: public: michael@0: PuppetWidget(TabChild* aTabChild); michael@0: virtual ~PuppetWidget(); michael@0: michael@0: NS_DECL_ISUPPORTS_INHERITED michael@0: michael@0: NS_IMETHOD Create(nsIWidget* aParent, michael@0: nsNativeWidget aNativeParent, michael@0: const nsIntRect& aRect, michael@0: nsDeviceContext* aContext, michael@0: nsWidgetInitData* aInitData = nullptr); michael@0: michael@0: void InitIMEState(); michael@0: 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: michael@0: NS_IMETHOD Destroy(); michael@0: michael@0: NS_IMETHOD Show(bool aState); michael@0: michael@0: virtual bool IsVisible() const michael@0: { return mVisible; } michael@0: michael@0: NS_IMETHOD ConstrainPosition(bool /*ignored aAllowSlop*/, michael@0: int32_t* aX, michael@0: int32_t* aY) michael@0: { *aX = kMaxDimension; *aY = kMaxDimension; return NS_OK; } michael@0: michael@0: // We're always at <0, 0>, and so ignore move requests. michael@0: NS_IMETHOD Move(double aX, double aY) michael@0: { return NS_OK; } michael@0: michael@0: NS_IMETHOD Resize(double aWidth, michael@0: double aHeight, michael@0: bool aRepaint); michael@0: NS_IMETHOD Resize(double aX, michael@0: double aY, michael@0: double aWidth, michael@0: double aHeight, michael@0: bool aRepaint) michael@0: // (we're always at <0, 0>) michael@0: { return Resize(aWidth, aHeight, aRepaint); } michael@0: michael@0: // XXX/cjones: copying gtk behavior here; unclear what disabling a michael@0: // widget is supposed to entail michael@0: NS_IMETHOD Enable(bool aState) michael@0: { mEnabled = aState; return NS_OK; } michael@0: virtual bool IsEnabled() const michael@0: { return mEnabled; } michael@0: michael@0: NS_IMETHOD SetFocus(bool aRaise = false); michael@0: michael@0: // PuppetWidgets don't care about children. michael@0: virtual nsresult ConfigureChildren(const nsTArray& aConfigurations) michael@0: { return NS_OK; } michael@0: michael@0: NS_IMETHOD Invalidate(const nsIntRect& aRect); michael@0: michael@0: // This API is going away, steer clear. michael@0: virtual void Scroll(const nsIntPoint& aDelta, michael@0: const nsTArray& aDestRects, michael@0: const nsTArray& aReconfigureChildren) michael@0: { /* dead man walking */ } michael@0: michael@0: // PuppetWidgets don't have native data, as they're purely nonnative. michael@0: virtual void* GetNativeData(uint32_t aDataType); michael@0: NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent) michael@0: { return NS_ERROR_UNEXPECTED; } michael@0: michael@0: // PuppetWidgets don't have any concept of titles. michael@0: NS_IMETHOD SetTitle(const nsAString& aTitle) michael@0: { return NS_ERROR_UNEXPECTED; } michael@0: michael@0: // PuppetWidgets are always at <0, 0>. michael@0: virtual nsIntPoint WidgetToScreenOffset() michael@0: { return nsIntPoint(0, 0); } michael@0: michael@0: void InitEvent(WidgetGUIEvent& aEvent, nsIntPoint* aPoint = nullptr); michael@0: michael@0: NS_IMETHOD DispatchEvent(WidgetGUIEvent* aEvent, nsEventStatus& aStatus); michael@0: michael@0: NS_IMETHOD CaptureRollupEvents(nsIRollupListener* aListener, michael@0: bool aDoCapture) michael@0: { return NS_ERROR_UNEXPECTED; } michael@0: michael@0: NS_IMETHOD_(bool) michael@0: ExecuteNativeKeyBinding(NativeKeyBindingsType aType, michael@0: const mozilla::WidgetKeyboardEvent& aEvent, michael@0: DoCommandCallback aCallback, michael@0: void* aCallbackData) MOZ_OVERRIDE; michael@0: michael@0: friend class AutoCacheNativeKeyCommands; michael@0: michael@0: // michael@0: // nsBaseWidget methods we override michael@0: // michael@0: michael@0: // Documents loaded in child processes are always subdocuments of michael@0: // other docs in an ancestor process. To ensure that the michael@0: // backgrounds of those documents are painted like those of michael@0: // same-process subdocuments, we force the widget here to be michael@0: // transparent, which in turn will cause layout to use a transparent michael@0: // backstop background color. michael@0: virtual nsTransparencyMode GetTransparencyMode() MOZ_OVERRIDE michael@0: { return eTransparencyTransparent; } michael@0: michael@0: virtual LayerManager* michael@0: 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: virtual gfxASurface* GetThebesSurface(); michael@0: michael@0: NS_IMETHOD NotifyIME(const IMENotification& aIMENotification) MOZ_OVERRIDE; michael@0: NS_IMETHOD_(void) SetInputContext(const InputContext& aContext, michael@0: const InputContextAction& aAction); michael@0: NS_IMETHOD_(InputContext) GetInputContext(); michael@0: virtual nsIMEUpdatePreference GetIMEUpdatePreference() MOZ_OVERRIDE; michael@0: michael@0: NS_IMETHOD SetCursor(nsCursor aCursor); michael@0: NS_IMETHOD SetCursor(imgIContainer* aCursor, michael@0: uint32_t aHotspotX, uint32_t aHotspotY) michael@0: { michael@0: return nsBaseWidget::SetCursor(aCursor, aHotspotX, aHotspotY); michael@0: } michael@0: michael@0: // Gets the DPI of the screen corresponding to this widget. michael@0: // Contacts the parent process which gets the DPI from the michael@0: // proper widget there. TODO: Handle DPI changes that happen michael@0: // later on. michael@0: virtual float GetDPI(); michael@0: virtual double GetDefaultScaleInternal(); michael@0: michael@0: virtual bool NeedsPaint() MOZ_OVERRIDE; michael@0: michael@0: virtual TabChild* GetOwningTabChild() MOZ_OVERRIDE { return mTabChild; } michael@0: michael@0: private: michael@0: nsresult Paint(); michael@0: michael@0: void SetChild(PuppetWidget* aChild); michael@0: michael@0: nsresult IMEEndComposition(bool aCancel); michael@0: nsresult NotifyIMEOfFocusChange(bool aFocus); michael@0: nsresult NotifyIMEOfSelectionChange(const IMENotification& aIMENotification); michael@0: nsresult NotifyIMEOfUpdateComposition(); michael@0: nsresult NotifyIMEOfTextChange(const IMENotification& aIMENotification); michael@0: michael@0: class PaintTask : public nsRunnable { michael@0: public: michael@0: NS_DECL_NSIRUNNABLE michael@0: PaintTask(PuppetWidget* widget) : mWidget(widget) {} michael@0: void Revoke() { mWidget = nullptr; } michael@0: private: michael@0: PuppetWidget* mWidget; michael@0: }; michael@0: michael@0: // TabChild normally holds a strong reference to this PuppetWidget michael@0: // or its root ancestor, but each PuppetWidget also needs a michael@0: // reference back to TabChild (e.g. to delegate nsIWidget IME calls michael@0: // to chrome) So we hold a weak reference to TabChild here. Since michael@0: // it's possible for TabChild to outlive the PuppetWidget, we clear michael@0: // this weak reference in Destroy() michael@0: TabChild* mTabChild; michael@0: // The "widget" to which we delegate events if we don't have an michael@0: // event handler. michael@0: nsRefPtr mChild; michael@0: nsIntRegion mDirtyRegion; michael@0: nsRevocableEventPtr mPaintTask; michael@0: bool mEnabled; michael@0: bool mVisible; michael@0: // XXX/cjones: keeping this around until we teach LayerManager to do michael@0: // retained-content-only transactions michael@0: nsRefPtr mSurface; michael@0: // IME michael@0: nsIMEUpdatePreference mIMEPreferenceOfParent; michael@0: bool mIMEComposing; michael@0: // Latest seqno received through events michael@0: uint32_t mIMELastReceivedSeqno; michael@0: // Chrome's seqno value when last blur occurred michael@0: // arriving events with seqno up to this should be discarded michael@0: // Note that if seqno overflows (~50 days at 1 ms increment rate), michael@0: // events will be discarded until new focus/blur occurs michael@0: uint32_t mIMELastBlurSeqno; michael@0: bool mNeedIMEStateInit; michael@0: michael@0: // The DPI of the screen corresponding to this widget michael@0: float mDPI; michael@0: double mDefaultScale; michael@0: michael@0: // Precomputed answers for ExecuteNativeKeyBinding michael@0: bool mNativeKeyCommandsValid; michael@0: InfallibleTArray mSingleLineCommands; michael@0: InfallibleTArray mMultiLineCommands; michael@0: InfallibleTArray mRichTextCommands; michael@0: }; michael@0: michael@0: struct AutoCacheNativeKeyCommands michael@0: { michael@0: AutoCacheNativeKeyCommands(PuppetWidget* aWidget) michael@0: : mWidget(aWidget) michael@0: { michael@0: mSavedValid = mWidget->mNativeKeyCommandsValid; michael@0: mSavedSingleLine = mWidget->mSingleLineCommands; michael@0: mSavedMultiLine = mWidget->mMultiLineCommands; michael@0: mSavedRichText = mWidget->mRichTextCommands; michael@0: } michael@0: michael@0: void Cache(const InfallibleTArray& aSingleLineCommands, michael@0: const InfallibleTArray& aMultiLineCommands, michael@0: const InfallibleTArray& aRichTextCommands) michael@0: { michael@0: mWidget->mNativeKeyCommandsValid = true; michael@0: mWidget->mSingleLineCommands = aSingleLineCommands; michael@0: mWidget->mMultiLineCommands = aMultiLineCommands; michael@0: mWidget->mRichTextCommands = aRichTextCommands; michael@0: } michael@0: michael@0: void CacheNoCommands() michael@0: { michael@0: mWidget->mNativeKeyCommandsValid = true; michael@0: mWidget->mSingleLineCommands.Clear(); michael@0: mWidget->mMultiLineCommands.Clear(); michael@0: mWidget->mRichTextCommands.Clear(); michael@0: } michael@0: michael@0: ~AutoCacheNativeKeyCommands() michael@0: { michael@0: mWidget->mNativeKeyCommandsValid = mSavedValid; michael@0: mWidget->mSingleLineCommands = mSavedSingleLine; michael@0: mWidget->mMultiLineCommands = mSavedMultiLine; michael@0: mWidget->mRichTextCommands = mSavedRichText; michael@0: } michael@0: michael@0: private: michael@0: PuppetWidget* mWidget; michael@0: bool mSavedValid; michael@0: InfallibleTArray mSavedSingleLine; michael@0: InfallibleTArray mSavedMultiLine; michael@0: InfallibleTArray mSavedRichText; michael@0: }; michael@0: michael@0: class PuppetScreen : public nsBaseScreen michael@0: { michael@0: public: michael@0: PuppetScreen(void* nativeScreen); michael@0: ~PuppetScreen(); michael@0: michael@0: NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight) MOZ_OVERRIDE; michael@0: NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight) MOZ_OVERRIDE; michael@0: NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) MOZ_OVERRIDE; michael@0: NS_IMETHOD GetColorDepth(int32_t* aColorDepth) MOZ_OVERRIDE; michael@0: NS_IMETHOD GetRotation(uint32_t* aRotation) MOZ_OVERRIDE; michael@0: NS_IMETHOD SetRotation(uint32_t aRotation) MOZ_OVERRIDE; michael@0: }; michael@0: michael@0: class PuppetScreenManager MOZ_FINAL : public nsIScreenManager michael@0: { michael@0: public: michael@0: PuppetScreenManager(); michael@0: ~PuppetScreenManager(); michael@0: michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSISCREENMANAGER michael@0: michael@0: protected: michael@0: nsCOMPtr mOneScreen; michael@0: }; michael@0: michael@0: } // namespace widget michael@0: } // namespace mozilla michael@0: michael@0: #endif // mozilla_widget_PuppetWidget_h__