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