nsView.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #ifndef nsView_h__
  6. #define nsView_h__
  7. #include "nsCoord.h"
  8. #include "nsRect.h"
  9. #include "nsPoint.h"
  10. #include "nsRegion.h"
  11. #include "nsCRT.h"
  12. #include "nsCOMPtr.h"
  13. #include "nsWidgetInitData.h" // for nsWindowType
  14. #include "nsIWidgetListener.h"
  15. #include "Units.h"
  16. #include "mozilla/EventForwards.h"
  17. class nsViewManager;
  18. class nsIWidget;
  19. class nsIFrame;
  20. // Enumerated type to indicate the visibility of a layer.
  21. // hide - the layer is not shown.
  22. // show - the layer is shown irrespective of the visibility of
  23. // the layer's parent.
  24. enum nsViewVisibility {
  25. nsViewVisibility_kHide = 0,
  26. nsViewVisibility_kShow = 1
  27. };
  28. // Public view flags
  29. // Indicates that the view is using auto z-indexing
  30. #define NS_VIEW_FLAG_AUTO_ZINDEX 0x0004
  31. // Indicates that the view is a floating view.
  32. #define NS_VIEW_FLAG_FLOATING 0x0008
  33. //----------------------------------------------------------------------
  34. /**
  35. * View interface
  36. *
  37. * Views are NOT reference counted. Use the Destroy() member function to
  38. * destroy a view.
  39. *
  40. * The lifetime of the view hierarchy is bounded by the lifetime of the
  41. * view manager that owns the views.
  42. *
  43. * Most of the methods here are read-only. To set the corresponding properties
  44. * of a view, go through nsViewManager.
  45. */
  46. class nsView final : public nsIWidgetListener
  47. {
  48. public:
  49. friend class nsViewManager;
  50. typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect;
  51. typedef mozilla::LayoutDeviceIntRegion LayoutDeviceIntRegion;
  52. NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
  53. /**
  54. * Get the view manager which "owns" the view.
  55. * This method might require some expensive traversal work in the future. If you can get the
  56. * view manager from somewhere else, do that instead.
  57. * @result the view manager
  58. */
  59. nsViewManager* GetViewManager() const { return mViewManager; }
  60. /**
  61. * Find the view for the given widget, if there is one.
  62. * @return the view the widget belongs to, or null if the widget doesn't
  63. * belong to any view.
  64. */
  65. static nsView* GetViewFor(nsIWidget* aWidget);
  66. /**
  67. * Destroy the view.
  68. *
  69. * The view destroys its child views, and destroys and releases its
  70. * widget (if it has one).
  71. *
  72. * Also informs the view manager that the view is destroyed by calling
  73. * SetRootView(NULL) if the view is the root view and calling RemoveChild()
  74. * otherwise.
  75. */
  76. void Destroy();
  77. /**
  78. * Called to get the position of a view.
  79. * The specified coordinates are relative to the parent view's origin, but
  80. * are in appunits of this.
  81. * This is the (0, 0) origin of the coordinate space established by this view.
  82. * @param x out parameter for x position
  83. * @param y out parameter for y position
  84. */
  85. nsPoint GetPosition() const {
  86. NS_ASSERTION(!IsRoot() || (mPosX == 0 && mPosY == 0),
  87. "root views should always have explicit position of (0,0)");
  88. return nsPoint(mPosX, mPosY);
  89. }
  90. /**
  91. * Called to get the dimensions and position of the view's bounds.
  92. * The view's bounds (x,y) are relative to the origin of the parent view, but
  93. * are in appunits of this.
  94. * The view's bounds (x,y) might not be the same as the view's position,
  95. * if the view has content above or to the left of its origin.
  96. * @param aBounds out parameter for bounds
  97. */
  98. nsRect GetBounds() const { return mDimBounds; }
  99. /**
  100. * The bounds of this view relative to this view. So this is the same as
  101. * GetBounds except this is relative to this view instead of the parent view.
  102. */
  103. nsRect GetDimensions() const {
  104. nsRect r = mDimBounds; r.MoveBy(-mPosX, -mPosY); return r;
  105. }
  106. /**
  107. * Get the offset between the coordinate systems of |this| and aOther.
  108. * Adding the return value to a point in the coordinate system of |this|
  109. * will transform the point to the coordinate system of aOther.
  110. *
  111. * The offset is expressed in appunits of |this|. So if you are getting the
  112. * offset between views in different documents that might have different
  113. * appunits per devpixel ratios you need to be careful how you use the
  114. * result.
  115. *
  116. * If aOther is null, this will return the offset of |this| from the
  117. * root of the viewmanager tree.
  118. *
  119. * This function is fastest when aOther is an ancestor of |this|.
  120. *
  121. * NOTE: this actually returns the offset from aOther to |this|, but
  122. * that offset is added to transform _coordinates_ from |this| to aOther.
  123. */
  124. nsPoint GetOffsetTo(const nsView* aOther) const;
  125. /**
  126. * Get the offset between the origin of |this| and the origin of aWidget.
  127. * Adding the return value to a point in the coordinate system of |this|
  128. * will transform the point to the coordinate system of aWidget.
  129. *
  130. * The offset is expressed in appunits of |this|.
  131. */
  132. nsPoint GetOffsetToWidget(nsIWidget* aWidget) const;
  133. /**
  134. * Takes a point aPt that is in the coordinate system of |this|'s parent view
  135. * and converts it to be in the coordinate system of |this| taking into
  136. * account the offset and any app unit per dev pixel ratio differences.
  137. */
  138. nsPoint ConvertFromParentCoords(nsPoint aPt) const;
  139. /**
  140. * Called to query the visibility state of a view.
  141. * @result current visibility state
  142. */
  143. nsViewVisibility GetVisibility() const { return mVis; }
  144. /**
  145. * Get whether the view "floats" above all other views,
  146. * which tells the compositor not to consider higher views in
  147. * the view hierarchy that would geometrically intersect with
  148. * this view. This is a hack, but it fixes some problems with
  149. * views that need to be drawn in front of all other views.
  150. * @result true if the view floats, false otherwise.
  151. */
  152. bool GetFloating() const { return (mVFlags & NS_VIEW_FLAG_FLOATING) != 0; }
  153. /**
  154. * Called to query the parent of the view.
  155. * @result view's parent
  156. */
  157. nsView* GetParent() const { return mParent; }
  158. /**
  159. * The view's first child is the child which is earliest in document order.
  160. * @result first child
  161. */
  162. nsView* GetFirstChild() const { return mFirstChild; }
  163. /**
  164. * Called to query the next sibling of the view.
  165. * @result view's next sibling
  166. */
  167. nsView* GetNextSibling() const { return mNextSibling; }
  168. /**
  169. * Set the view's frame.
  170. */
  171. void SetFrame(nsIFrame* aRootFrame) { mFrame = aRootFrame; }
  172. /**
  173. * Retrieve the view's frame.
  174. */
  175. nsIFrame* GetFrame() const { return mFrame; }
  176. /**
  177. * Get the nearest widget in this view or a parent of this view and
  178. * the offset from the widget's origin to this view's origin
  179. * @param aOffset - if non-null the offset from this view's origin to the
  180. * widget's origin (usually positive) expressed in appunits of this will be
  181. * returned in aOffset.
  182. * @return the widget closest to this view; can be null because some view trees
  183. * don't have widgets at all (e.g., printing), but if any view in the view tree
  184. * has a widget, then it's safe to assume this will not return null
  185. */
  186. nsIWidget* GetNearestWidget(nsPoint* aOffset) const;
  187. /**
  188. * Create a widget to associate with this view. This variant of
  189. * CreateWidget*() will look around in the view hierarchy for an
  190. * appropriate parent widget for the view.
  191. *
  192. * @param aWidgetInitData data used to initialize this view's widget before
  193. * its create is called.
  194. * @return error status
  195. */
  196. nsresult CreateWidget(nsWidgetInitData *aWidgetInitData = nullptr,
  197. bool aEnableDragDrop = true,
  198. bool aResetVisibility = true);
  199. /**
  200. * Create a widget for this view with an explicit parent widget.
  201. * |aParentWidget| must be nonnull. The other params are the same
  202. * as for |CreateWidget()|.
  203. */
  204. nsresult CreateWidgetForParent(nsIWidget* aParentWidget,
  205. nsWidgetInitData *aWidgetInitData = nullptr,
  206. bool aEnableDragDrop = true,
  207. bool aResetVisibility = true);
  208. /**
  209. * Create a popup widget for this view. Pass |aParentWidget| to
  210. * explicitly set the popup's parent. If it's not passed, the view
  211. * hierarchy will be searched for an appropriate parent widget. The
  212. * other params are the same as for |CreateWidget()|, except that
  213. * |aWidgetInitData| must be nonnull.
  214. */
  215. nsresult CreateWidgetForPopup(nsWidgetInitData *aWidgetInitData,
  216. nsIWidget* aParentWidget = nullptr,
  217. bool aEnableDragDrop = true,
  218. bool aResetVisibility = true);
  219. /**
  220. * Destroys the associated widget for this view. If this method is
  221. * not called explicitly, the widget when be destroyed when its
  222. * view gets destroyed.
  223. */
  224. void DestroyWidget();
  225. /**
  226. * Attach/detach a top level widget from this view. When attached, the view
  227. * updates the widget's device context and allows the view to begin receiving
  228. * gecko events. The underlying base window associated with the widget will
  229. * continues to receive events it expects.
  230. *
  231. * An attached widget will not be destroyed when the view is destroyed,
  232. * allowing the recycling of a single top level widget over multiple views.
  233. *
  234. * @param aWidget The widget to attach to / detach from.
  235. */
  236. nsresult AttachToTopLevelWidget(nsIWidget* aWidget);
  237. nsresult DetachFromTopLevelWidget();
  238. /**
  239. * Returns a flag indicating whether the view owns it's widget
  240. * or is attached to an existing top level widget.
  241. */
  242. bool IsAttachedToTopLevel() const { return mWidgetIsTopLevel; }
  243. /**
  244. * In 4.0, the "cutout" nature of a view is queryable.
  245. * If we believe that all cutout view have a native widget, this
  246. * could be a replacement.
  247. * @param aWidget out parameter for widget that this view contains,
  248. * or nullptr if there is none.
  249. */
  250. nsIWidget* GetWidget() const { return mWindow; }
  251. /**
  252. * The widget which we have attached a listener to can also have a "previous"
  253. * listener set on it. This is to keep track of the last nsView when navigating
  254. * to a new one so that we can continue to paint that if the new one isn't ready
  255. * yet.
  256. */
  257. void SetPreviousWidget(nsIWidget* aWidget) { mPreviousWindow = aWidget; }
  258. /**
  259. * Returns true if the view has a widget associated with it.
  260. */
  261. bool HasWidget() const { return mWindow != nullptr; }
  262. void SetForcedRepaint(bool aForceRepaint) {
  263. mForcedRepaint = aForceRepaint;
  264. }
  265. void SetNeedsWindowPropertiesSync();
  266. /**
  267. * Make aWidget direct its events to this view.
  268. * The caller must call DetachWidgetEventHandler before this view
  269. * is destroyed.
  270. */
  271. void AttachWidgetEventHandler(nsIWidget* aWidget);
  272. /**
  273. * Stop aWidget directing its events to this view.
  274. */
  275. void DetachWidgetEventHandler(nsIWidget* aWidget);
  276. #ifdef DEBUG
  277. /**
  278. * Output debug info to FILE
  279. * @param out output file handle
  280. * @param aIndent indentation depth
  281. * NOTE: virtual so that debugging tools not linked into gklayout can access it
  282. */
  283. virtual void List(FILE* out, int32_t aIndent = 0) const;
  284. #endif // DEBUG
  285. /**
  286. * @result true iff this is the root view for its view manager
  287. */
  288. bool IsRoot() const;
  289. LayoutDeviceIntRect CalcWidgetBounds(nsWindowType aType);
  290. // This is an app unit offset to add when converting view coordinates to
  291. // widget coordinates. It is the offset in view coordinates from widget
  292. // origin (unlike views, widgets can't extend above or to the left of their
  293. // origin) to view origin expressed in appunits of this.
  294. nsPoint ViewToWidgetOffset() const { return mViewToWidgetOffset; }
  295. /**
  296. * Called to indicate that the position of the view has been changed.
  297. * The specified coordinates are in the parent view's coordinate space.
  298. * @param x new x position
  299. * @param y new y position
  300. */
  301. void SetPosition(nscoord aX, nscoord aY);
  302. /**
  303. * Called to indicate that the z-index of a view has been changed.
  304. * The z-index is relative to all siblings of the view.
  305. * @param aAuto Indicate that the z-index of a view is "auto". An "auto" z-index
  306. * means that the view does not define a new stacking context,
  307. * which means that the z-indicies of the view's children are
  308. * relative to the view's siblings.
  309. * @param zindex new z depth
  310. */
  311. void SetZIndex(bool aAuto, int32_t aZIndex);
  312. bool GetZIndexIsAuto() const { return (mVFlags & NS_VIEW_FLAG_AUTO_ZINDEX) != 0; }
  313. int32_t GetZIndex() const { return mZIndex; }
  314. void SetParent(nsView *aParent) { mParent = aParent; }
  315. void SetNextSibling(nsView *aSibling)
  316. {
  317. NS_ASSERTION(aSibling != this, "Can't be our own sibling!");
  318. mNextSibling = aSibling;
  319. }
  320. nsRegion* GetDirtyRegion() {
  321. if (!mDirtyRegion) {
  322. NS_ASSERTION(!mParent || GetFloating(),
  323. "Only display roots should have dirty regions");
  324. mDirtyRegion = new nsRegion();
  325. NS_ASSERTION(mDirtyRegion, "Out of memory!");
  326. }
  327. return mDirtyRegion;
  328. }
  329. // nsIWidgetListener
  330. virtual nsIPresShell* GetPresShell() override;
  331. virtual nsView* GetView() override { return this; }
  332. virtual bool WindowMoved(nsIWidget* aWidget, int32_t x, int32_t y) override;
  333. virtual bool WindowResized(nsIWidget* aWidget, int32_t aWidth, int32_t aHeight) override;
  334. virtual bool RequestWindowClose(nsIWidget* aWidget) override;
  335. virtual void WillPaintWindow(nsIWidget* aWidget) override;
  336. virtual bool PaintWindow(nsIWidget* aWidget,
  337. LayoutDeviceIntRegion aRegion) override;
  338. virtual void DidPaintWindow() override;
  339. virtual void DidCompositeWindow(uint64_t aTransactionId,
  340. const mozilla::TimeStamp& aCompositeStart,
  341. const mozilla::TimeStamp& aCompositeEnd) override;
  342. virtual void RequestRepaint() override;
  343. virtual nsEventStatus HandleEvent(mozilla::WidgetGUIEvent* aEvent,
  344. bool aUseAttachedEvents) override;
  345. virtual ~nsView();
  346. nsPoint GetOffsetTo(const nsView* aOther, const int32_t aAPD) const;
  347. nsIWidget* GetNearestWidget(nsPoint* aOffset, const int32_t aAPD) const;
  348. bool IsPrimaryFramePaintSuppressed();
  349. private:
  350. explicit nsView(nsViewManager* aViewManager = nullptr,
  351. nsViewVisibility aVisibility = nsViewVisibility_kShow);
  352. bool ForcedRepaint() { return mForcedRepaint; }
  353. // Do the actual work of ResetWidgetBounds, unconditionally. Don't
  354. // call this method if we have no widget.
  355. void DoResetWidgetBounds(bool aMoveOnly, bool aInvalidateChangedSize);
  356. void InitializeWindow(bool aEnableDragDrop, bool aResetVisibility);
  357. bool IsEffectivelyVisible();
  358. /**
  359. * Called to indicate that the dimensions of the view have been changed.
  360. * The x and y coordinates may be < 0, indicating that the view extends above
  361. * or to the left of its origin position. The term 'dimensions' indicates it
  362. * is relative to this view.
  363. */
  364. void SetDimensions(const nsRect &aRect, bool aPaint = true,
  365. bool aResizeWidget = true);
  366. /**
  367. * Called to indicate that the visibility of a view has been
  368. * changed.
  369. * @param visibility new visibility state
  370. */
  371. void SetVisibility(nsViewVisibility visibility);
  372. /**
  373. * Set/Get whether the view "floats" above all other views,
  374. * which tells the compositor not to consider higher views in
  375. * the view hierarchy that would geometrically intersect with
  376. * this view. This is a hack, but it fixes some problems with
  377. * views that need to be drawn in front of all other views.
  378. * @result true if the view floats, false otherwise.
  379. */
  380. void SetFloating(bool aFloatingView);
  381. // Helper function to get mouse grabbing off this view (by moving it to the
  382. // parent, if we can)
  383. void DropMouseGrabbing();
  384. // Same as GetBounds but converts to parent appunits if they are different.
  385. nsRect GetBoundsInParentUnits() const;
  386. bool HasNonEmptyDirtyRegion() {
  387. return mDirtyRegion && !mDirtyRegion->IsEmpty();
  388. }
  389. void InsertChild(nsView *aChild, nsView *aSibling);
  390. void RemoveChild(nsView *aChild);
  391. void ResetWidgetBounds(bool aRecurse, bool aForceSync);
  392. void AssertNoWindow();
  393. void NotifyEffectiveVisibilityChanged(bool aEffectivelyVisible);
  394. // Update the cached RootViewManager for all view manager descendents.
  395. void InvalidateHierarchy();
  396. nsViewManager *mViewManager;
  397. nsView *mParent;
  398. nsCOMPtr<nsIWidget> mWindow;
  399. nsCOMPtr<nsIWidget> mPreviousWindow;
  400. nsView *mNextSibling;
  401. nsView *mFirstChild;
  402. nsIFrame *mFrame;
  403. nsRegion *mDirtyRegion;
  404. int32_t mZIndex;
  405. nsViewVisibility mVis;
  406. // position relative our parent view origin but in our appunits
  407. nscoord mPosX, mPosY;
  408. // relative to parent, but in our appunits
  409. nsRect mDimBounds;
  410. // in our appunits
  411. nsPoint mViewToWidgetOffset;
  412. uint32_t mVFlags;
  413. bool mWidgetIsTopLevel;
  414. bool mForcedRepaint;
  415. bool mNeedsWindowPropertiesSync;
  416. };
  417. #endif