1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: sw=2 ts=8 et : 3 */ 4 /* This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 7 8 /** 9 * This "puppet widget" isn't really a platform widget. It's intended 10 * to be used in widgetless rendering contexts, such as sandboxed 11 * content processes. If any "real" widgetry is needed, the request 12 * is forwarded to and/or data received from elsewhere. 13 */ 14 15 #ifndef mozilla_widget_PuppetWidget_h__ 16 #define mozilla_widget_PuppetWidget_h__ 17 18 #include "mozilla/gfx/2D.h" 19 #include "mozilla/RefPtr.h" 20 #include "nsBaseScreen.h" 21 #include "nsBaseWidget.h" 22 #include "nsCOMArray.h" 23 #include "nsIKeyEventInPluginCallback.h" 24 #include "nsIScreenManager.h" 25 #include "nsThreadUtils.h" 26 #include "mozilla/Attributes.h" 27 #include "mozilla/ContentCache.h" 28 #include "mozilla/EventForwards.h" 29 30 namespace mozilla { 31 32 namespace dom { 33 class TabChild; 34 } // namespace dom 35 36 namespace widget { 37 38 struct AutoCacheNativeKeyCommands; 39 40 class PuppetWidget : public nsBaseWidget 41 { 42 typedef mozilla::dom::TabChild TabChild; 43 typedef mozilla::gfx::DrawTarget DrawTarget; 44 typedef nsBaseWidget Base; 45 typedef mozilla::CSSRect CSSRect; 46 47 // The width and height of the "widget" are clamped to this. 48 static const size_t kMaxDimension; 49 50 public: 51 explicit PuppetWidget(TabChild* aTabChild); 52 53 protected: 54 virtual ~PuppetWidget(); 55 56 public: 57 NS_DECL_ISUPPORTS_INHERITED 58 59 // PuppetWidget creation is infallible, hence InfallibleCreate(), which 60 // Create() calls. 61 using nsBaseWidget::Create; // for Create signature not overridden here 62 virtual nsresult Create(nsIWidget* aParent, 63 nsNativeWidget aNativeParent, 64 const LayoutDeviceIntRect& aRect, 65 nsWidgetInitData* aInitData = nullptr) 66 override; 67 void InfallibleCreate(nsIWidget* aParent, 68 nsNativeWidget aNativeParent, 69 const LayoutDeviceIntRect& aRect, 70 nsWidgetInitData* aInitData = nullptr); 71 72 void InitIMEState(); 73 74 virtual already_AddRefed<nsIWidget> 75 CreateChild(const LayoutDeviceIntRect& aRect, 76 nsWidgetInitData* aInitData = nullptr, 77 bool aForceUseIWidgetParent = false) override; 78 79 virtual void Destroy() override; 80 81 NS_IMETHOD Show(bool aState) override; 82 IsVisible()83 virtual bool IsVisible() const override 84 { return mVisible; } 85 ConstrainPosition(bool,int32_t * aX,int32_t * aY)86 virtual void ConstrainPosition(bool /*ignored aAllowSlop*/, 87 int32_t* aX, 88 int32_t* aY) override 89 { *aX = kMaxDimension; *aY = kMaxDimension; } 90 91 // Widget position is controlled by the parent process via TabChild. Move(double aX,double aY)92 NS_IMETHOD Move(double aX, double aY) override 93 { return NS_OK; } 94 95 NS_IMETHOD Resize(double aWidth, 96 double aHeight, 97 bool aRepaint) override; Resize(double aX,double aY,double aWidth,double aHeight,bool aRepaint)98 NS_IMETHOD Resize(double aX, 99 double aY, 100 double aWidth, 101 double aHeight, 102 bool aRepaint) override 103 { 104 if (mBounds.x != aX || mBounds.y != aY) { 105 NotifyWindowMoved(aX, aY); 106 } 107 mBounds.x = aX; 108 mBounds.y = aY; 109 return Resize(aWidth, aHeight, aRepaint); 110 } 111 112 // XXX/cjones: copying gtk behavior here; unclear what disabling a 113 // widget is supposed to entail Enable(bool aState)114 NS_IMETHOD Enable(bool aState) override 115 { mEnabled = aState; return NS_OK; } IsEnabled()116 virtual bool IsEnabled() const override 117 { return mEnabled; } 118 119 NS_IMETHOD SetFocus(bool aRaise = false) override; 120 121 virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations) override; 122 123 NS_IMETHOD Invalidate(const LayoutDeviceIntRect& aRect) override; 124 125 // PuppetWidgets don't have native data, as they're purely nonnative. 126 virtual void* GetNativeData(uint32_t aDataType) override; 127 #if defined(XP_WIN) 128 void SetNativeData(uint32_t aDataType, uintptr_t aVal) override; 129 #endif 130 131 // PuppetWidgets don't have any concept of titles. SetTitle(const nsAString & aTitle)132 NS_IMETHOD SetTitle(const nsAString& aTitle) override 133 { return NS_ERROR_UNEXPECTED; } 134 WidgetToScreenOffset()135 virtual LayoutDeviceIntPoint WidgetToScreenOffset() override 136 { return LayoutDeviceIntPoint::FromUnknownPoint(GetWindowPosition() + GetChromeDimensions()); } 137 138 int32_t RoundsWidgetCoordinatesTo() override; 139 140 void InitEvent(WidgetGUIEvent& aEvent, 141 LayoutDeviceIntPoint* aPoint = nullptr); 142 143 NS_IMETHOD DispatchEvent(WidgetGUIEvent* aEvent, nsEventStatus& aStatus) override; 144 nsEventStatus DispatchInputEvent(WidgetInputEvent* aEvent) override; 145 void SetConfirmedTargetAPZC(uint64_t aInputBlockId, 146 const nsTArray<ScrollableLayerGuid>& aTargets) const override; 147 void UpdateZoomConstraints(const uint32_t& aPresShellId, 148 const FrameMetrics::ViewID& aViewId, 149 const mozilla::Maybe<ZoomConstraints>& aConstraints) override; 150 bool AsyncPanZoomEnabled() const override; 151 152 NS_IMETHOD_(bool) 153 ExecuteNativeKeyBinding(NativeKeyBindingsType aType, 154 const mozilla::WidgetKeyboardEvent& aEvent, 155 DoCommandCallback aCallback, 156 void* aCallbackData) override; 157 158 friend struct AutoCacheNativeKeyCommands; 159 160 // 161 // nsBaseWidget methods we override 162 // 163 164 // Documents loaded in child processes are always subdocuments of 165 // other docs in an ancestor process. To ensure that the 166 // backgrounds of those documents are painted like those of 167 // same-process subdocuments, we force the widget here to be 168 // transparent, which in turn will cause layout to use a transparent 169 // backstop background color. GetTransparencyMode()170 virtual nsTransparencyMode GetTransparencyMode() override 171 { return eTransparencyTransparent; } 172 173 virtual LayerManager* 174 GetLayerManager(PLayerTransactionChild* aShadowManager = nullptr, 175 LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE, 176 LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT) override; 177 178 // This is used after a compositor reset. 179 LayerManager* RecreateLayerManager(PLayerTransactionChild* aShadowManager); 180 181 NS_IMETHOD_(void) SetInputContext(const InputContext& aContext, 182 const InputContextAction& aAction) override; 183 NS_IMETHOD_(InputContext) GetInputContext() override; 184 NS_IMETHOD_(NativeIMEContext) GetNativeIMEContext() override; 185 virtual nsIMEUpdatePreference GetIMEUpdatePreference() override; 186 187 NS_IMETHOD SetCursor(nsCursor aCursor) override; 188 NS_IMETHOD SetCursor(imgIContainer* aCursor, 189 uint32_t aHotspotX, uint32_t aHotspotY) override; 190 191 virtual void ClearCachedCursor() override; 192 193 // Gets the DPI of the screen corresponding to this widget. 194 // Contacts the parent process which gets the DPI from the 195 // proper widget there. TODO: Handle DPI changes that happen 196 // later on. 197 virtual float GetDPI() override; 198 virtual double GetDefaultScaleInternal() override; 199 200 virtual bool NeedsPaint() override; 201 202 // Paint the widget immediately if any paints are queued up. 203 void PaintNowIfNeeded(); 204 GetOwningTabChild()205 virtual TabChild* GetOwningTabChild() override { return mTabChild; } 206 UpdateBackingScaleCache(float aDpi,int32_t aRounding,double aScale)207 void UpdateBackingScaleCache(float aDpi, int32_t aRounding, double aScale) 208 { 209 mDPI = aDpi; 210 mRounding = aRounding; 211 mDefaultScale = aScale; 212 } 213 214 nsIntSize GetScreenDimensions(); 215 216 // Get the size of the chrome of the window that this tab belongs to. 217 nsIntPoint GetChromeDimensions(); 218 219 // Get the screen position of the application window. 220 nsIntPoint GetWindowPosition(); 221 222 virtual LayoutDeviceIntRect GetScreenBounds() override; 223 224 NS_IMETHOD StartPluginIME(const mozilla::WidgetKeyboardEvent& aKeyboardEvent, 225 int32_t aPanelX, int32_t aPanelY, 226 nsString& aCommitted) override; 227 228 virtual void SetPluginFocused(bool& aFocused) override; 229 virtual void DefaultProcOfPluginEvent( 230 const mozilla::WidgetPluginEvent& aEvent) override; 231 232 virtual nsresult SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout, 233 int32_t aNativeKeyCode, 234 uint32_t aModifierFlags, 235 const nsAString& aCharacters, 236 const nsAString& aUnmodifiedCharacters, 237 nsIObserver* aObserver) override; 238 virtual nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, 239 uint32_t aNativeMessage, 240 uint32_t aModifierFlags, 241 nsIObserver* aObserver) override; 242 virtual nsresult SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint, 243 nsIObserver* aObserver) override; 244 virtual nsresult SynthesizeNativeMouseScrollEvent(LayoutDeviceIntPoint aPoint, 245 uint32_t aNativeMessage, 246 double aDeltaX, 247 double aDeltaY, 248 double aDeltaZ, 249 uint32_t aModifierFlags, 250 uint32_t aAdditionalFlags, 251 nsIObserver* aObserver) override; 252 virtual nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId, 253 TouchPointerState aPointerState, 254 LayoutDeviceIntPoint aPoint, 255 double aPointerPressure, 256 uint32_t aPointerOrientation, 257 nsIObserver* aObserver) override; 258 virtual nsresult SynthesizeNativeTouchTap(LayoutDeviceIntPoint aPoint, 259 bool aLongTap, 260 nsIObserver* aObserver) override; 261 virtual nsresult ClearNativeTouchSequence(nsIObserver* aObserver) override; 262 virtual uint32_t GetMaxTouchPoints() const override; 263 264 virtual void StartAsyncScrollbarDrag(const AsyncDragMetrics& aDragMetrics) override; 265 266 virtual void SetCandidateWindowForPlugin( 267 const CandidateWindowPosition& aPosition) override; 268 269 virtual void ZoomToRect(const uint32_t& aPresShellId, 270 const FrameMetrics::ViewID& aViewId, 271 const CSSRect& aRect, 272 const uint32_t& aFlags) override; 273 274 virtual bool HasPendingInputEvent() override; 275 276 void HandledWindowedPluginKeyEvent(const NativeEventData& aKeyEventData, 277 bool aIsConsumed); 278 virtual nsresult OnWindowedPluginKeyEvent( 279 const NativeEventData& aKeyEventData, 280 nsIKeyEventInPluginCallback* aCallback) override; 281 282 virtual void LookUpDictionary( 283 const nsAString& aText, 284 const nsTArray<mozilla::FontRange>& aFontRangeArray, 285 const bool aIsVertical, 286 const LayoutDeviceIntPoint& aPoint) override; 287 288 protected: 289 virtual nsresult NotifyIMEInternal( 290 const IMENotification& aIMENotification) override; 291 292 private: 293 nsresult Paint(); 294 295 void SetChild(PuppetWidget* aChild); 296 297 nsresult RequestIMEToCommitComposition(bool aCancel); 298 nsresult NotifyIMEOfFocusChange(const IMENotification& aIMENotification); 299 nsresult NotifyIMEOfSelectionChange(const IMENotification& aIMENotification); 300 nsresult NotifyIMEOfCompositionUpdate(const IMENotification& aIMENotification); 301 nsresult NotifyIMEOfTextChange(const IMENotification& aIMENotification); 302 nsresult NotifyIMEOfMouseButtonEvent(const IMENotification& aIMENotification); 303 nsresult NotifyIMEOfPositionChange(const IMENotification& aIMENotification); 304 305 bool CacheEditorRect(); 306 bool CacheCompositionRects(uint32_t& aStartOffset, 307 nsTArray<LayoutDeviceIntRect>& aRectArray, 308 uint32_t& aTargetCauseOffset); 309 bool GetCaretRect(LayoutDeviceIntRect& aCaretRect, uint32_t aCaretOffset); 310 uint32_t GetCaretOffset(); 311 312 nsIWidgetListener* GetCurrentWidgetListener(); 313 314 class PaintTask : public Runnable { 315 public: 316 NS_DECL_NSIRUNNABLE PaintTask(PuppetWidget * widget)317 explicit PaintTask(PuppetWidget* widget) : mWidget(widget) {} Revoke()318 void Revoke() { mWidget = nullptr; } 319 private: 320 PuppetWidget* mWidget; 321 }; 322 323 class MemoryPressureObserver : public nsIObserver { 324 public: 325 NS_DECL_ISUPPORTS 326 NS_DECL_NSIOBSERVER MemoryPressureObserver(PuppetWidget * aWidget)327 explicit MemoryPressureObserver(PuppetWidget* aWidget) : mWidget(aWidget) {} 328 void Remove(); 329 private: ~MemoryPressureObserver()330 virtual ~MemoryPressureObserver() {} 331 PuppetWidget* mWidget; 332 }; 333 friend class MemoryPressureObserver; 334 335 // TabChild normally holds a strong reference to this PuppetWidget 336 // or its root ancestor, but each PuppetWidget also needs a 337 // reference back to TabChild (e.g. to delegate nsIWidget IME calls 338 // to chrome) So we hold a weak reference to TabChild here. Since 339 // it's possible for TabChild to outlive the PuppetWidget, we clear 340 // this weak reference in Destroy() 341 TabChild* mTabChild; 342 // The "widget" to which we delegate events if we don't have an 343 // event handler. 344 RefPtr<PuppetWidget> mChild; 345 LayoutDeviceIntRegion mDirtyRegion; 346 nsRevocableEventPtr<PaintTask> mPaintTask; 347 RefPtr<MemoryPressureObserver> mMemoryPressureObserver; 348 // XXX/cjones: keeping this around until we teach LayerManager to do 349 // retained-content-only transactions 350 RefPtr<DrawTarget> mDrawTarget; 351 // IME 352 nsIMEUpdatePreference mIMEPreferenceOfParent; 353 InputContext mInputContext; 354 // mNativeIMEContext is initialized when this dispatches every composition 355 // event both from parent process's widget and TextEventDispatcher in same 356 // process. If it hasn't been started composition yet, this isn't necessary 357 // for XP code since there is no TextComposition instance which is caused by 358 // the PuppetWidget instance. 359 NativeIMEContext mNativeIMEContext; 360 ContentCacheInChild mContentCache; 361 362 // The DPI of the screen corresponding to this widget 363 float mDPI; 364 int32_t mRounding; 365 double mDefaultScale; 366 367 // Precomputed answers for ExecuteNativeKeyBinding 368 InfallibleTArray<mozilla::CommandInt> mSingleLineCommands; 369 InfallibleTArray<mozilla::CommandInt> mMultiLineCommands; 370 InfallibleTArray<mozilla::CommandInt> mRichTextCommands; 371 372 nsCOMPtr<imgIContainer> mCustomCursor; 373 uint32_t mCursorHotspotX, mCursorHotspotY; 374 375 nsCOMArray<nsIKeyEventInPluginCallback> mKeyEventInPluginCallbacks; 376 377 protected: 378 bool mEnabled; 379 bool mVisible; 380 381 private: 382 bool mNeedIMEStateInit; 383 bool mNativeKeyCommandsValid; 384 }; 385 386 struct AutoCacheNativeKeyCommands 387 { AutoCacheNativeKeyCommandsAutoCacheNativeKeyCommands388 explicit AutoCacheNativeKeyCommands(PuppetWidget* aWidget) 389 : mWidget(aWidget) 390 { 391 mSavedValid = mWidget->mNativeKeyCommandsValid; 392 mSavedSingleLine = mWidget->mSingleLineCommands; 393 mSavedMultiLine = mWidget->mMultiLineCommands; 394 mSavedRichText = mWidget->mRichTextCommands; 395 } 396 CacheAutoCacheNativeKeyCommands397 void Cache(const InfallibleTArray<mozilla::CommandInt>& aSingleLineCommands, 398 const InfallibleTArray<mozilla::CommandInt>& aMultiLineCommands, 399 const InfallibleTArray<mozilla::CommandInt>& aRichTextCommands) 400 { 401 mWidget->mNativeKeyCommandsValid = true; 402 mWidget->mSingleLineCommands = aSingleLineCommands; 403 mWidget->mMultiLineCommands = aMultiLineCommands; 404 mWidget->mRichTextCommands = aRichTextCommands; 405 } 406 CacheNoCommandsAutoCacheNativeKeyCommands407 void CacheNoCommands() 408 { 409 mWidget->mNativeKeyCommandsValid = true; 410 mWidget->mSingleLineCommands.Clear(); 411 mWidget->mMultiLineCommands.Clear(); 412 mWidget->mRichTextCommands.Clear(); 413 } 414 ~AutoCacheNativeKeyCommandsAutoCacheNativeKeyCommands415 ~AutoCacheNativeKeyCommands() 416 { 417 mWidget->mNativeKeyCommandsValid = mSavedValid; 418 mWidget->mSingleLineCommands = mSavedSingleLine; 419 mWidget->mMultiLineCommands = mSavedMultiLine; 420 mWidget->mRichTextCommands = mSavedRichText; 421 } 422 423 private: 424 PuppetWidget* mWidget; 425 bool mSavedValid; 426 InfallibleTArray<mozilla::CommandInt> mSavedSingleLine; 427 InfallibleTArray<mozilla::CommandInt> mSavedMultiLine; 428 InfallibleTArray<mozilla::CommandInt> mSavedRichText; 429 }; 430 431 class PuppetScreen : public nsBaseScreen 432 { 433 public: 434 explicit PuppetScreen(void* nativeScreen); 435 ~PuppetScreen(); 436 437 NS_IMETHOD GetId(uint32_t* aId) override; 438 NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight) override; 439 NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight) override; 440 NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) override; 441 NS_IMETHOD GetColorDepth(int32_t* aColorDepth) override; 442 NS_IMETHOD GetRotation(uint32_t* aRotation) override; 443 NS_IMETHOD SetRotation(uint32_t aRotation) override; 444 }; 445 446 class PuppetScreenManager final : public nsIScreenManager 447 { 448 ~PuppetScreenManager(); 449 450 public: 451 PuppetScreenManager(); 452 453 NS_DECL_ISUPPORTS 454 NS_DECL_NSISCREENMANAGER 455 456 protected: 457 nsCOMPtr<nsIScreen> mOneScreen; 458 }; 459 460 } // namespace widget 461 } // namespace mozilla 462 463 #endif // mozilla_widget_PuppetWidget_h__ 464