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/. */
6 #ifndef nsViewManager_h___
7 #define nsViewManager_h___
14 #include "nsDeviceContext.h"
16 #include "mozilla/Attributes.h"
17 #include "mozilla/AlreadyAddRefed.h"
18 #include "mozilla/EventForwards.h"
23 class nsDeviceContext
;
27 } // namespace mozilla
29 class nsViewManager final
{
35 typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect
;
36 typedef mozilla::LayoutDeviceIntRegion LayoutDeviceIntRegion
;
38 NS_INLINE_DECL_REFCOUNTING(nsViewManager
)
43 * Initialize the ViewManager
44 * Note: this instance does not hold a reference to the presshell
45 * because it holds a reference to this instance.
46 * @result The result of the initialization, NS_OK if no errors
48 nsresult
Init(nsDeviceContext
* aContext
);
51 * Create an ordinary view
52 * @param aBounds initial bounds for view
53 * XXX We should eliminate this parameter; you can set the bounds
55 * @param aParent intended parent for view. this is not actually set in the
56 * nsView through this method. it is only used by the initialization
57 * code to walk up the view tree, if necessary, to find resources.
58 * XXX We should eliminate this parameter!
59 * @param aVisibilityFlag initial visibility state of view
60 * XXX We should eliminate this parameter; you can set it after
62 * @result The new view. Never null.
64 nsView
* CreateView(const nsRect
& aBounds
, nsView
* aParent
,
65 ViewVisibility aVisibilityFlag
= ViewVisibility::Show
);
68 * Get the root of the view tree.
69 * @result the root view
71 nsView
* GetRootView() { return mRootView
; }
74 * Set the root of the view tree. Does not destroy the current root view.
75 * aView may have a parent view managed by a different view manager.
76 * aView may have a widget (anything but printing) or may not (printing).
77 * @param aView view to set as root
79 void SetRootView(nsView
* aView
);
82 * Get the dimensions of the root window. The dimensions are in
84 * @param aWidth out parameter for width of window in twips
85 * @param aHeight out parameter for height of window in twips
87 void GetWindowDimensions(nscoord
* aWidth
, nscoord
* aHeight
);
90 * Set the dimensions of the root window.
91 * Called if the root window is resized. The dimensions are in
93 * @param aWidth of window in twips
94 * @param aHeight of window in twips
96 void SetWindowDimensions(nscoord aWidth
, nscoord aHeight
,
97 bool aDelayResize
= false);
100 * Do any resizes that are pending.
102 void FlushDelayedResize();
105 * Called to inform the view manager that the entire area of a view
106 * is dirty and needs to be redrawn.
107 * @param aView view to paint. should be root view
109 void InvalidateView(nsView
* aView
);
112 * Called to inform the view manager that some portion of a view is dirty and
113 * needs to be redrawn. The rect passed in should be in the view's coordinate
114 * space. Does not check for paint suppression.
115 * @param aView view to paint. should be root view
116 * @param rect rect to mark as damaged
118 void InvalidateViewNoSuppression(nsView
* aView
, const nsRect
& aRect
);
121 * Called to inform the view manager that it should invalidate all views.
123 void InvalidateAllViews();
126 * Called to dispatch an event to the appropriate view. Often called
127 * as a result of receiving a mouse or keyboard event from the widget
129 * @param aEvent event to dispatch
130 * @param aViewTarget dispatch the event to this view
131 * @param aStatus event handling status
134 void DispatchEvent(mozilla::WidgetGUIEvent
* aEvent
, nsView
* aViewTarget
,
135 nsEventStatus
* aStatus
);
138 * Given a parent view, insert another view as its child.
139 * aSibling and aAbove control the "document order" for the insertion.
140 * If aSibling is null, the view is inserted at the end of the document order
141 * if aAfter is true, otherwise it is inserted at the beginning.
142 * If aSibling is non-null, then if aAfter is true, the view is inserted
143 * after the sibling in document order (appearing above the sibling unless
144 * overriden by z-order).
145 * If it is false, the view is inserted before the sibling.
146 * The view manager generates the appopriate dirty regions.
147 * @param aParent parent view
148 * @param aChild child view
149 * @param aSibling sibling view
150 * @param aAfter after or before in the document order
152 void InsertChild(nsView
* aParent
, nsView
* aChild
, nsView
* aSibling
,
156 * Remove a specific child view from its parent. This will NOT remove its
157 * placeholder if there is one. The view manager generates the appropriate
159 * @param aParent parent view
160 * @param aChild child view
162 void RemoveChild(nsView
* aChild
);
165 * Move a view to the specified position, provided in parent coordinates.
166 * The new position is the (0, 0) origin for the view's coordinate system.
167 * The view's bounds may extend above or to the left of this point.
168 * The view manager generates the appropriate dirty regions.
169 * @param aView view to move
170 * @param aX x value for new view position
171 * @param aY y value for new view position
173 void MoveViewTo(nsView
* aView
, nscoord aX
, nscoord aY
);
176 * Resize a view. In addition to setting the width and height, you can
177 * set the x and y of its bounds relative to its position. Negative x and y
178 * will let the view extend above and to the left of the (0,0) point in its
180 * The view manager generates the appropriate dirty regions.
181 * @param aView view to move
182 * @param the new bounds relative to the current position
183 * @param RepaintExposedAreaOnly
184 * if true Repaint only the expanded or contracted region,
185 * if false Repaint the union of the old and new rectangles.
187 void ResizeView(nsView
* aView
, const nsRect
& aRect
,
188 bool aRepaintExposedAreaOnly
= false);
191 * Set the visibility of a view. Hidden views have the effect of hiding
192 * their descendants as well. This does not affect painting, so layout
193 * is responsible for ensuring that content in hidden views is not
194 * painted nor handling events. It does affect the visibility of widgets;
195 * if a view is hidden, descendant views with widgets have their widgets
197 * The view manager generates the appropriate dirty regions.
198 * @param aView view to change visibility state of
199 * @param visible new visibility state
201 void SetViewVisibility(nsView
* aView
, ViewVisibility aVisible
);
204 * Set the z-index of a view. Positive z-indices mean that a view
205 * is above its parent in z-order. Negative z-indices mean that a
206 * view is below its parent.
207 * The view manager generates the appropriate dirty regions.
208 * @param aAutoZIndex indicate that the z-index of a view is "auto". An
209 * "auto" z-index means that the view does not define a new stacking
210 * context, which means that the z-indicies of the view's children are
211 * relative to the view's siblings.
212 * @param aView view to change z depth of
213 * @param aZindex explicit z depth
215 void SetViewZIndex(nsView
* aView
, bool aAutoZIndex
, int32_t aZindex
);
218 * Set whether the view "floats" above all other views,
219 * which tells the compositor not to consider higher views in
220 * the view hierarchy that would geometrically intersect with
221 * this view. This is a hack, but it fixes some problems with
222 * views that need to be drawn in front of all other views.
224 void SetViewFloating(nsView
* aView
, bool aFloatingView
);
227 * Set the presshell associated with this manager
228 * @param aPresShell - new presshell
230 void SetPresShell(mozilla::PresShell
* aPresShell
) { mPresShell
= aPresShell
; }
233 * Get the pres shell associated with this manager
235 mozilla::PresShell
* GetPresShell() const { return mPresShell
; }
238 * Get the device context associated with this manager
240 nsDeviceContext
* GetDeviceContext() const { return mContext
; }
243 * A stack class for disallowing changes that would enter painting. For
244 * example, popup widgets shouldn't be resized during reflow, since doing so
245 * might cause synchronous painting inside reflow which is forbidden.
246 * While refresh is disabled, widget geometry changes are deferred and will
247 * be handled later, either from the refresh driver or from an NS_WILL_PAINT
249 * We don't want to defer widget geometry changes all the time. Resizing a
250 * popup from script doesn't need to be deferred, for example, especially
251 * since popup widget geometry is observable from script and expected to
252 * update synchronously.
254 class MOZ_STACK_CLASS AutoDisableRefresh
{
256 explicit AutoDisableRefresh(nsViewManager
* aVM
) {
258 mRootVM
= aVM
->IncrementDisableRefreshCount();
261 ~AutoDisableRefresh() {
263 mRootVM
->DecrementDisableRefreshCount();
268 AutoDisableRefresh(const AutoDisableRefresh
& aOther
);
269 const AutoDisableRefresh
& operator=(const AutoDisableRefresh
& aOther
);
271 RefPtr
<nsViewManager
> mRootVM
;
275 friend class AutoDisableRefresh
;
277 nsViewManager
* IncrementDisableRefreshCount();
278 void DecrementDisableRefreshCount();
282 * Retrieve the widget at the root of the nearest enclosing
283 * view manager whose root view has a widget.
285 nsIWidget
* GetRootWidget() const;
288 * Indicate whether the viewmanager is currently painting
290 * @param aPainting true if the viewmanager is painting
293 void IsPainting(bool& aIsPainting
);
296 * Retrieve the time of the last user event. User events
297 * include mouse and keyboard events. The viewmanager
298 * saves the time of the last user event.
300 * @param aTime Last user event time in microseconds
302 void GetLastUserEventTime(uint32_t& aTime
);
305 * Find the nearest display root view for the view aView. This is the view for
306 * the nearest enclosing popup or the root view for the root document.
308 static nsView
* GetDisplayRootFor(nsView
* aView
);
311 * Flush the accumulated dirty region to the widget and update widget
314 MOZ_CAN_RUN_SCRIPT
void ProcessPendingUpdates();
317 * Just update widget geometry without flushing the dirty region
319 MOZ_CAN_RUN_SCRIPT
void UpdateWidgetGeometry();
321 int32_t AppUnitsPerDevPixel() const {
322 return mContext
->AppUnitsPerDevPixel();
326 static uint32_t gLastUserEventTime
;
328 /* Update the cached RootViewManager pointer on this view manager. */
329 void InvalidateHierarchy();
330 void FlushPendingInvalidates();
333 void ProcessPendingUpdatesForView(nsView
* aView
,
334 bool aFlushDirtyRegion
= true);
335 void ProcessPendingUpdatesRecurse(
336 nsView
* aView
, AutoTArray
<nsCOMPtr
<nsIWidget
>, 1>& aWidgets
);
338 void ProcessPendingUpdatesPaint(nsIWidget
* aWidget
);
340 void FlushDirtyRegionToWidget(nsView
* aView
);
342 * Call WillPaint() on all view observers under this vm root.
344 MOZ_CAN_RUN_SCRIPT_BOUNDARY
void CallWillPaintOnObservers();
345 void ReparentChildWidgets(nsView
* aView
, nsIWidget
* aNewWidget
);
346 void ReparentWidgets(nsView
* aView
, nsView
* aParent
);
347 void InvalidateWidgetArea(nsView
* aWidgetView
,
348 const nsRegion
& aDamagedRegion
);
350 void InvalidateViews(nsView
* aView
);
352 // aView is the view for aWidget and aRegion is relative to aWidget.
354 void Refresh(nsView
* aView
, const LayoutDeviceIntRegion
& aRegion
);
358 bool IsViewInserted(nsView
* aView
);
361 * Intersects aRect with aView's bounds and then transforms it from aView's
362 * coordinate system to the coordinate system of the widget attached to
365 LayoutDeviceIntRect
ViewToWidget(nsView
* aView
, const nsRect
& aRect
) const;
367 MOZ_CAN_RUN_SCRIPT_BOUNDARY
368 void DoSetWindowDimensions(nscoord aWidth
, nscoord aHeight
);
369 bool ShouldDelayResize() const;
371 bool IsPainting() const { return RootViewManager()->mPainting
; }
373 void SetPainting(bool aPainting
) { RootViewManager()->mPainting
= aPainting
; }
375 void InvalidateView(nsView
* aView
, const nsRect
& aRect
);
377 nsViewManager
* RootViewManager() const {
378 return mRootViewManager
? mRootViewManager
.get()
379 : const_cast<nsViewManager
*>(this);
381 bool IsRootVM() const { return !mRootViewManager
; }
383 // Whether synchronous painting is allowed at the moment. For example,
384 // widget geometry changes can cause synchronous painting, so they need to
385 // be deferred while refresh is disabled.
386 bool IsPaintingAllowed() {
387 return RootViewManager()->mRefreshDisableCount
== 0;
390 MOZ_CAN_RUN_SCRIPT
void WillPaintWindow(nsIWidget
* aWidget
);
392 bool PaintWindow(nsIWidget
* aWidget
, const LayoutDeviceIntRegion
& aRegion
);
393 MOZ_CAN_RUN_SCRIPT
void DidPaintWindow();
395 // Call this when you need to let the viewmanager know that it now has
397 void PostPendingUpdate();
399 RefPtr
<nsDeviceContext
> mContext
;
400 mozilla::PresShell
* mPresShell
;
402 // The size for a resize that we delayed until the root view becomes
404 nsSize mDelayedResize
;
408 // mRootViewManager is a strong reference to the root view manager, unless
409 // |this| is the root, in which case mRootViewManager is null. Callers
410 // should use RootViewManager() (which handles that case) rather than using
411 // mRootViewManager directly.
412 RefPtr
<nsViewManager
> mRootViewManager
;
414 // The following members should not be accessed directly except by
415 // the root view manager. Some have accessor functions to enforce
418 int32_t mRefreshDisableCount
;
419 // Use IsPainting() and SetPainting() to access mPainting.
421 bool mRecursiveRefreshPending
;
422 bool mHasPendingWidgetGeometryChanges
;
424 // from here to public should be static and locked... MMP
426 // list of view managers
427 static mozilla::StaticAutoPtr
<nsTArray
<nsViewManager
*>> gViewManagers
;
433 1) Callers call into the view manager and ask it to invalidate a view.
435 2) The view manager finds the "right" widget for the view, henceforth called
438 3) The view manager traverses descendants of the root widget and for each
439 one that needs invalidation stores the rect to invalidate on the widget's
442 4) The dirty region is flushed to the right widget when
443 ProcessPendingUpdates is called from the RefreshDriver.
445 It's important to note that widgets associated to views outside this view
446 manager can end up being invalidated during step 3. Therefore, the end of a
447 view update batch really needs to traverse the entire view tree, to ensure
448 that those invalidates happen.
450 To cope with this, invalidation processing and should only happen on the
454 #endif // nsViewManager_h___