Bug 1895153 - Implement "Find in page..." menu functionality r=android-reviewers...
[gecko.git] / view / nsViewManager.h
blob66c9d09d659b52818c0fe18ab43ace1f1d7815a0
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___
9 #include "nscore.h"
10 #include "nsView.h"
11 #include "nsCOMPtr.h"
12 #include "nsCRT.h"
13 #include "nsTArray.h"
14 #include "nsDeviceContext.h"
15 #include "nsTArray.h"
16 #include "mozilla/Attributes.h"
17 #include "mozilla/AlreadyAddRefed.h"
18 #include "mozilla/EventForwards.h"
20 class nsIWidget;
21 struct nsRect;
22 class nsRegion;
23 class nsDeviceContext;
25 namespace mozilla {
26 class PresShell;
27 } // namespace mozilla
29 class nsViewManager final {
30 ~nsViewManager();
32 public:
33 friend class nsView;
35 typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect;
36 typedef mozilla::LayoutDeviceIntRegion LayoutDeviceIntRegion;
38 NS_INLINE_DECL_REFCOUNTING(nsViewManager)
40 nsViewManager();
42 /**
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);
50 /**
51 * Create an ordinary view
52 * @param aBounds initial bounds for view
53 * XXX We should eliminate this parameter; you can set the bounds
54 * after CreateView
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
61 * CreateView
62 * @result The new view. Never null.
64 nsView* CreateView(const nsRect& aBounds, nsView* aParent,
65 ViewVisibility aVisibilityFlag = ViewVisibility::Show);
67 /**
68 * Get the root of the view tree.
69 * @result the root view
71 nsView* GetRootView() { return mRootView; }
73 /**
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);
81 /**
82 * Get the dimensions of the root window. The dimensions are in
83 * twips
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);
89 /**
90 * Set the dimensions of the root window.
91 * Called if the root window is resized. The dimensions are in
92 * twips
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);
99 /**
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
128 * event system.
129 * @param aEvent event to dispatch
130 * @param aViewTarget dispatch the event to this view
131 * @param aStatus event handling status
133 MOZ_CAN_RUN_SCRIPT
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,
153 bool aAfter);
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
158 * dirty regions.
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
179 * coordinate system.
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
184 void ResizeView(nsView* aView, const nsRect& aRect);
187 * Set the visibility of a view. Hidden views have the effect of hiding
188 * their descendants as well. This does not affect painting, so layout
189 * is responsible for ensuring that content in hidden views is not
190 * painted nor handling events. It does affect the visibility of widgets;
191 * if a view is hidden, descendant views with widgets have their widgets
192 * hidden.
193 * The view manager generates the appropriate dirty regions.
194 * @param aView view to change visibility state of
195 * @param visible new visibility state
197 void SetViewVisibility(nsView* aView, ViewVisibility aVisible);
200 * Set whether the view "floats" above all other views,
201 * which tells the compositor not to consider higher views in
202 * the view hierarchy that would geometrically intersect with
203 * this view. This is a hack, but it fixes some problems with
204 * views that need to be drawn in front of all other views.
206 void SetViewFloating(nsView* aView, bool aFloatingView);
209 * Set the presshell associated with this manager
210 * @param aPresShell - new presshell
212 void SetPresShell(mozilla::PresShell* aPresShell) { mPresShell = aPresShell; }
215 * Get the pres shell associated with this manager
217 mozilla::PresShell* GetPresShell() const { return mPresShell; }
220 * Get the device context associated with this manager
222 nsDeviceContext* GetDeviceContext() const { return mContext; }
225 * A stack class for disallowing changes that would enter painting. For
226 * example, popup widgets shouldn't be resized during reflow, since doing so
227 * might cause synchronous painting inside reflow which is forbidden.
228 * While refresh is disabled, widget geometry changes are deferred and will
229 * be handled later, either from the refresh driver or from an NS_WILL_PAINT
230 * event.
231 * We don't want to defer widget geometry changes all the time. Resizing a
232 * popup from script doesn't need to be deferred, for example, especially
233 * since popup widget geometry is observable from script and expected to
234 * update synchronously.
236 class MOZ_STACK_CLASS AutoDisableRefresh {
237 public:
238 explicit AutoDisableRefresh(nsViewManager* aVM) {
239 if (aVM) {
240 mRootVM = aVM->IncrementDisableRefreshCount();
243 ~AutoDisableRefresh() {
244 if (mRootVM) {
245 mRootVM->DecrementDisableRefreshCount();
249 private:
250 AutoDisableRefresh(const AutoDisableRefresh& aOther);
251 const AutoDisableRefresh& operator=(const AutoDisableRefresh& aOther);
253 RefPtr<nsViewManager> mRootVM;
256 private:
257 friend class AutoDisableRefresh;
259 nsViewManager* IncrementDisableRefreshCount();
260 void DecrementDisableRefreshCount();
262 public:
264 * Retrieve the widget at the root of the nearest enclosing
265 * view manager whose root view has a widget.
267 nsIWidget* GetRootWidget() const;
270 * Indicate whether the viewmanager is currently painting
272 * @param aPainting true if the viewmanager is painting
273 * false otherwise
275 void IsPainting(bool& aIsPainting);
278 * Retrieve the time of the last user event. User events
279 * include mouse and keyboard events. The viewmanager
280 * saves the time of the last user event.
282 * @param aTime Last user event time in microseconds
284 void GetLastUserEventTime(uint32_t& aTime);
287 * Find the nearest display root view for the view aView. This is the view for
288 * the nearest enclosing popup or the root view for the root document.
290 static nsView* GetDisplayRootFor(nsView* aView);
293 * Flush the accumulated dirty region to the widget and update widget
294 * geometry.
296 MOZ_CAN_RUN_SCRIPT void ProcessPendingUpdates();
299 * Just update widget geometry without flushing the dirty region
301 MOZ_CAN_RUN_SCRIPT void UpdateWidgetGeometry();
303 int32_t AppUnitsPerDevPixel() const {
304 return mContext->AppUnitsPerDevPixel();
307 private:
308 static uint32_t gLastUserEventTime;
310 /* Update the cached RootViewManager pointer on this view manager. */
311 void InvalidateHierarchy();
312 void FlushPendingInvalidates();
314 MOZ_CAN_RUN_SCRIPT
315 void ProcessPendingUpdatesForView(nsView* aView,
316 bool aFlushDirtyRegion = true);
317 void ProcessPendingUpdatesRecurse(
318 nsView* aView, AutoTArray<nsCOMPtr<nsIWidget>, 1>& aWidgets);
319 MOZ_CAN_RUN_SCRIPT
320 void ProcessPendingUpdatesPaint(nsIWidget* aWidget);
322 void FlushDirtyRegionToWidget(nsView* aView);
324 * Call WillPaint() on all view observers under this vm root.
326 MOZ_CAN_RUN_SCRIPT_BOUNDARY void CallWillPaintOnObservers();
327 static void CollectVMsForWillPaint(nsView* aView, nsViewManager* aParentVM,
328 nsTArray<RefPtr<nsViewManager>>& aVMs);
330 void ReparentChildWidgets(nsView* aView, nsIWidget* aNewWidget);
331 void ReparentWidgets(nsView* aView, nsView* aParent);
332 void InvalidateWidgetArea(nsView* aWidgetView,
333 const nsRegion& aDamagedRegion);
335 void InvalidateViews(nsView* aView);
337 // aView is the view for aWidget and aRegion is relative to aWidget.
338 MOZ_CAN_RUN_SCRIPT
339 void Refresh(nsView* aView, const LayoutDeviceIntRegion& aRegion);
341 // Utilities
343 bool IsViewInserted(nsView* aView);
346 * Intersects aRect with aView's bounds and then transforms it from aView's
347 * coordinate system to the coordinate system of the widget attached to
348 * aView.
350 LayoutDeviceIntRect ViewToWidget(nsView* aView, const nsRect& aRect) const;
352 MOZ_CAN_RUN_SCRIPT_BOUNDARY
353 void DoSetWindowDimensions(nscoord aWidth, nscoord aHeight);
354 bool ShouldDelayResize() const;
356 bool IsPainting() const { return RootViewManager()->mPainting; }
358 void SetPainting(bool aPainting) { RootViewManager()->mPainting = aPainting; }
360 void InvalidateView(nsView* aView, const nsRect& aRect);
362 nsViewManager* RootViewManager() const {
363 return mRootViewManager ? mRootViewManager.get()
364 : const_cast<nsViewManager*>(this);
366 bool IsRootVM() const { return !mRootViewManager; }
368 // Whether synchronous painting is allowed at the moment. For example,
369 // widget geometry changes can cause synchronous painting, so they need to
370 // be deferred while refresh is disabled.
371 bool IsPaintingAllowed() {
372 return RootViewManager()->mRefreshDisableCount == 0;
375 MOZ_CAN_RUN_SCRIPT void WillPaintWindow(nsIWidget* aWidget);
376 MOZ_CAN_RUN_SCRIPT
377 bool PaintWindow(nsIWidget* aWidget, const LayoutDeviceIntRegion& aRegion);
378 MOZ_CAN_RUN_SCRIPT void DidPaintWindow();
380 // Call this when you need to let the viewmanager know that it now has
381 // pending updates.
382 void PostPendingUpdate();
384 RefPtr<nsDeviceContext> mContext;
385 mozilla::PresShell* mPresShell;
387 // The size for a resize that we delayed until the root view becomes
388 // visible again.
389 nsSize mDelayedResize;
391 nsView* mRootView;
393 // mRootViewManager is a strong reference to the root view manager, unless
394 // |this| is the root, in which case mRootViewManager is null. Callers
395 // should use RootViewManager() (which handles that case) rather than using
396 // mRootViewManager directly.
397 RefPtr<nsViewManager> mRootViewManager;
399 // The following members should not be accessed directly except by
400 // the root view manager. Some have accessor functions to enforce
401 // this, as noted.
403 int32_t mRefreshDisableCount;
404 // Use IsPainting() and SetPainting() to access mPainting.
405 bool mPainting;
406 bool mRecursiveRefreshPending;
407 bool mHasPendingWidgetGeometryChanges;
409 // from here to public should be static and locked... MMP
413 Invalidation model:
415 1) Callers call into the view manager and ask it to invalidate a view.
417 2) The view manager finds the "right" widget for the view, henceforth called
418 the root widget.
420 3) The view manager traverses descendants of the root widget and for each
421 one that needs invalidation stores the rect to invalidate on the widget's
422 view (batching).
424 4) The dirty region is flushed to the right widget when
425 ProcessPendingUpdates is called from the RefreshDriver.
427 It's important to note that widgets associated to views outside this view
428 manager can end up being invalidated during step 3. Therefore, the end of a
429 view update batch really needs to traverse the entire view tree, to ensure
430 that those invalidates happen.
432 To cope with this, invalidation processing and should only happen on the
433 root viewmanager.
436 #endif // nsViewManager_h___