1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/view/public/nsViewManager.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,442 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef nsViewManager_h___ 1.10 +#define nsViewManager_h___ 1.11 + 1.12 +#include "nscore.h" 1.13 +#include "nsView.h" 1.14 +#include "nsCOMPtr.h" 1.15 +#include "nsCRT.h" 1.16 +#include "nsVoidArray.h" 1.17 +#include "nsDeviceContext.h" 1.18 +#include "nsTArray.h" 1.19 +#include "mozilla/EventForwards.h" 1.20 + 1.21 +class nsIWidget; 1.22 +struct nsRect; 1.23 +class nsRegion; 1.24 +class nsDeviceContext; 1.25 +class nsIPresShell; 1.26 + 1.27 +class nsViewManager MOZ_FINAL 1.28 +{ 1.29 +public: 1.30 + friend class nsView; 1.31 + 1.32 + NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW 1.33 + 1.34 + NS_INLINE_DECL_REFCOUNTING(nsViewManager) 1.35 + 1.36 + nsViewManager(); 1.37 + ~nsViewManager(); 1.38 + 1.39 + /** 1.40 + * Initialize the ViewManager 1.41 + * Note: this instance does not hold a reference to the presshell 1.42 + * because it holds a reference to this instance. 1.43 + * @result The result of the initialization, NS_OK if no errors 1.44 + */ 1.45 + nsresult Init(nsDeviceContext* aContext); 1.46 + 1.47 + /** 1.48 + * Create an ordinary view 1.49 + * @param aBounds initial bounds for view 1.50 + * XXX We should eliminate this parameter; you can set the bounds after CreateView 1.51 + * @param aParent intended parent for view. this is not actually set in the 1.52 + * nsView through this method. it is only used by the initialization 1.53 + * code to walk up the view tree, if necessary, to find resources. 1.54 + * XXX We should eliminate this parameter! 1.55 + * @param aVisibilityFlag initial visibility state of view 1.56 + * XXX We should eliminate this parameter; you can set it after CreateView 1.57 + * @result The new view. Never null. 1.58 + */ 1.59 + nsView* CreateView(const nsRect& aBounds, 1.60 + nsView* aParent, 1.61 + nsViewVisibility aVisibilityFlag = nsViewVisibility_kShow); 1.62 + 1.63 + /** 1.64 + * Get the root of the view tree. 1.65 + * @result the root view 1.66 + */ 1.67 + nsView* GetRootView() { return mRootView; } 1.68 + 1.69 + /** 1.70 + * Set the root of the view tree. Does not destroy the current root view. 1.71 + * aView may have a parent view managed by a different view manager. 1.72 + * aView may have a widget (anything but printing) or may not (printing). 1.73 + * @param aView view to set as root 1.74 + */ 1.75 + void SetRootView(nsView *aView); 1.76 + 1.77 + /** 1.78 + * Get the dimensions of the root window. The dimensions are in 1.79 + * twips 1.80 + * @param aWidth out parameter for width of window in twips 1.81 + * @param aHeight out parameter for height of window in twips 1.82 + */ 1.83 + void GetWindowDimensions(nscoord *aWidth, nscoord *aHeight); 1.84 + 1.85 + /** 1.86 + * Set the dimensions of the root window. 1.87 + * Called if the root window is resized. The dimensions are in 1.88 + * twips 1.89 + * @param aWidth of window in twips 1.90 + * @param aHeight of window in twips 1.91 + */ 1.92 + void SetWindowDimensions(nscoord aWidth, nscoord aHeight); 1.93 + 1.94 + /** 1.95 + * Do any resizes that are pending. 1.96 + */ 1.97 + void FlushDelayedResize(bool aDoReflow); 1.98 + 1.99 + /** 1.100 + * Called to inform the view manager that the entire area of a view 1.101 + * is dirty and needs to be redrawn. 1.102 + * @param aView view to paint. should be root view 1.103 + */ 1.104 + void InvalidateView(nsView *aView); 1.105 + 1.106 + /** 1.107 + * Called to inform the view manager that some portion of a view is dirty and 1.108 + * needs to be redrawn. The rect passed in should be in the view's coordinate 1.109 + * space. Does not check for paint suppression. 1.110 + * @param aView view to paint. should be root view 1.111 + * @param rect rect to mark as damaged 1.112 + */ 1.113 + void InvalidateViewNoSuppression(nsView *aView, const nsRect &aRect); 1.114 + 1.115 + /** 1.116 + * Called to inform the view manager that it should invalidate all views. 1.117 + */ 1.118 + void InvalidateAllViews(); 1.119 + 1.120 + /** 1.121 + * Called to dispatch an event to the appropriate view. Often called 1.122 + * as a result of receiving a mouse or keyboard event from the widget 1.123 + * event system. 1.124 + * @param aEvent event to dispatch 1.125 + * @param aViewTarget dispatch the event to this view 1.126 + * @param aStatus event handling status 1.127 + */ 1.128 + void DispatchEvent(mozilla::WidgetGUIEvent *aEvent, 1.129 + nsView* aViewTarget, 1.130 + nsEventStatus* aStatus); 1.131 + 1.132 + /** 1.133 + * Given a parent view, insert another view as its child. 1.134 + * aSibling and aAbove control the "document order" for the insertion. 1.135 + * If aSibling is null, the view is inserted at the end of the document order 1.136 + * if aAfter is true, otherwise it is inserted at the beginning. 1.137 + * If aSibling is non-null, then if aAfter is true, the view is inserted 1.138 + * after the sibling in document order (appearing above the sibling unless 1.139 + * overriden by z-order). 1.140 + * If it is false, the view is inserted before the sibling. 1.141 + * The view manager generates the appopriate dirty regions. 1.142 + * @param aParent parent view 1.143 + * @param aChild child view 1.144 + * @param aSibling sibling view 1.145 + * @param aAfter after or before in the document order 1.146 + */ 1.147 + void InsertChild(nsView *aParent, nsView *aChild, nsView *aSibling, 1.148 + bool aAfter); 1.149 + 1.150 + void InsertChild(nsView *aParent, nsView *aChild, int32_t aZIndex); 1.151 + 1.152 + /** 1.153 + * Remove a specific child view from its parent. This will NOT remove its placeholder 1.154 + * if there is one. 1.155 + * The view manager generates the appropriate dirty regions. 1.156 + * @param aParent parent view 1.157 + * @param aChild child view 1.158 + */ 1.159 + void RemoveChild(nsView *aChild); 1.160 + 1.161 + /** 1.162 + * Move a view to the specified position, provided in parent coordinates. 1.163 + * The new position is the (0, 0) origin for the view's coordinate system. 1.164 + * The view's bounds may extend above or to the left of this point. 1.165 + * The view manager generates the appropriate dirty regions. 1.166 + * @param aView view to move 1.167 + * @param aX x value for new view position 1.168 + * @param aY y value for new view position 1.169 + */ 1.170 + void MoveViewTo(nsView *aView, nscoord aX, nscoord aY); 1.171 + 1.172 + /** 1.173 + * Resize a view. In addition to setting the width and height, you can 1.174 + * set the x and y of its bounds relative to its position. Negative x and y 1.175 + * will let the view extend above and to the left of the (0,0) point in its 1.176 + * coordinate system. 1.177 + * The view manager generates the appropriate dirty regions. 1.178 + * @param aView view to move 1.179 + * @param the new bounds relative to the current position 1.180 + * @param RepaintExposedAreaOnly 1.181 + * if true Repaint only the expanded or contracted region, 1.182 + * if false Repaint the union of the old and new rectangles. 1.183 + */ 1.184 + void ResizeView(nsView *aView, const nsRect &aRect, 1.185 + bool aRepaintExposedAreaOnly = false); 1.186 + 1.187 + /** 1.188 + * Set the visibility of a view. Hidden views have the effect of hiding 1.189 + * their descendants as well. This does not affect painting, so layout 1.190 + * is responsible for ensuring that content in hidden views is not 1.191 + * painted nor handling events. It does affect the visibility of widgets; 1.192 + * if a view is hidden, descendant views with widgets have their widgets 1.193 + * hidden. 1.194 + * The view manager generates the appropriate dirty regions. 1.195 + * @param aView view to change visibility state of 1.196 + * @param visible new visibility state 1.197 + */ 1.198 + void SetViewVisibility(nsView *aView, nsViewVisibility aVisible); 1.199 + 1.200 + /** 1.201 + * Set the z-index of a view. Positive z-indices mean that a view 1.202 + * is above its parent in z-order. Negative z-indices mean that a 1.203 + * view is below its parent. 1.204 + * The view manager generates the appropriate dirty regions. 1.205 + * @param aAutoZIndex indicate that the z-index of a view is "auto". An "auto" z-index 1.206 + * means that the view does not define a new stacking context, 1.207 + * which means that the z-indicies of the view's children are 1.208 + * relative to the view's siblings. 1.209 + * @param aView view to change z depth of 1.210 + * @param aZindex explicit z depth 1.211 + */ 1.212 + void SetViewZIndex(nsView *aView, bool aAutoZIndex, int32_t aZindex); 1.213 + 1.214 + /** 1.215 + * Set whether the view "floats" above all other views, 1.216 + * which tells the compositor not to consider higher views in 1.217 + * the view hierarchy that would geometrically intersect with 1.218 + * this view. This is a hack, but it fixes some problems with 1.219 + * views that need to be drawn in front of all other views. 1.220 + */ 1.221 + void SetViewFloating(nsView *aView, bool aFloatingView); 1.222 + 1.223 + /** 1.224 + * Set the presshell associated with this manager 1.225 + * @param aPresShell - new presshell 1.226 + */ 1.227 + void SetPresShell(nsIPresShell *aPresShell) { mPresShell = aPresShell; } 1.228 + 1.229 + /** 1.230 + * Get the pres shell associated with this manager 1.231 + */ 1.232 + nsIPresShell* GetPresShell() { return mPresShell; } 1.233 + 1.234 + /** 1.235 + * Get the device context associated with this manager 1.236 + */ 1.237 + nsDeviceContext* GetDeviceContext() const 1.238 + { 1.239 + return mContext; 1.240 + } 1.241 + 1.242 + /** 1.243 + * A stack class for disallowing changes that would enter painting. For 1.244 + * example, popup widgets shouldn't be resized during reflow, since doing so 1.245 + * might cause synchronous painting inside reflow which is forbidden. 1.246 + * While refresh is disabled, widget geometry changes are deferred and will 1.247 + * be handled later, either from the refresh driver or from an NS_WILL_PAINT 1.248 + * event. 1.249 + * We don't want to defer widget geometry changes all the time. Resizing a 1.250 + * popup from script doesn't need to be deferred, for example, especially 1.251 + * since popup widget geometry is observable from script and expected to 1.252 + * update synchronously. 1.253 + */ 1.254 + class MOZ_STACK_CLASS AutoDisableRefresh { 1.255 + public: 1.256 + AutoDisableRefresh(nsViewManager* aVM) { 1.257 + if (aVM) { 1.258 + mRootVM = aVM->IncrementDisableRefreshCount(); 1.259 + } 1.260 + } 1.261 + ~AutoDisableRefresh() { 1.262 + if (mRootVM) { 1.263 + mRootVM->DecrementDisableRefreshCount(); 1.264 + } 1.265 + } 1.266 + private: 1.267 + AutoDisableRefresh(const AutoDisableRefresh& aOther); 1.268 + const AutoDisableRefresh& operator=(const AutoDisableRefresh& aOther); 1.269 + 1.270 + nsRefPtr<nsViewManager> mRootVM; 1.271 + }; 1.272 + 1.273 +private: 1.274 + friend class AutoDisableRefresh; 1.275 + 1.276 + nsViewManager* IncrementDisableRefreshCount(); 1.277 + void DecrementDisableRefreshCount(); 1.278 + 1.279 +public: 1.280 + /** 1.281 + * Retrieve the widget at the root of the nearest enclosing 1.282 + * view manager whose root view has a widget. 1.283 + */ 1.284 + void GetRootWidget(nsIWidget **aWidget); 1.285 + 1.286 + /** 1.287 + * Indicate whether the viewmanager is currently painting 1.288 + * 1.289 + * @param aPainting true if the viewmanager is painting 1.290 + * false otherwise 1.291 + */ 1.292 + void IsPainting(bool& aIsPainting); 1.293 + 1.294 + /** 1.295 + * Retrieve the time of the last user event. User events 1.296 + * include mouse and keyboard events. The viewmanager 1.297 + * saves the time of the last user event. 1.298 + * 1.299 + * @param aTime Last user event time in microseconds 1.300 + */ 1.301 + void GetLastUserEventTime(uint32_t& aTime); 1.302 + 1.303 + /** 1.304 + * Find the nearest display root view for the view aView. This is the view for 1.305 + * the nearest enclosing popup or the root view for the root document. 1.306 + */ 1.307 + static nsView* GetDisplayRootFor(nsView* aView); 1.308 + 1.309 + /** 1.310 + * Flush the accumulated dirty region to the widget and update widget 1.311 + * geometry. 1.312 + */ 1.313 + void ProcessPendingUpdates(); 1.314 + 1.315 + /** 1.316 + * Just update widget geometry without flushing the dirty region 1.317 + */ 1.318 + void UpdateWidgetGeometry(); 1.319 + 1.320 + int32_t AppUnitsPerDevPixel() const 1.321 + { 1.322 + return mContext->AppUnitsPerDevPixel(); 1.323 + } 1.324 + 1.325 +private: 1.326 + static uint32_t gLastUserEventTime; 1.327 + 1.328 + /* Update the cached RootViewManager pointer on this view manager. */ 1.329 + void InvalidateHierarchy(); 1.330 + void FlushPendingInvalidates(); 1.331 + 1.332 + void ProcessPendingUpdatesForView(nsView *aView, 1.333 + bool aFlushDirtyRegion = true); 1.334 + void ProcessPendingUpdatesRecurse(nsView* aView, 1.335 + nsTArray<nsCOMPtr<nsIWidget> >& aWidgets); 1.336 + void ProcessPendingUpdatesPaint(nsIWidget* aWidget); 1.337 + 1.338 + void FlushDirtyRegionToWidget(nsView* aView); 1.339 + /** 1.340 + * Call WillPaint() on all view observers under this vm root. 1.341 + */ 1.342 + void CallWillPaintOnObservers(); 1.343 + void ReparentChildWidgets(nsView* aView, nsIWidget *aNewWidget); 1.344 + void ReparentWidgets(nsView* aView, nsView *aParent); 1.345 + void InvalidateWidgetArea(nsView *aWidgetView, const nsRegion &aDamagedRegion); 1.346 + 1.347 + void InvalidateViews(nsView *aView); 1.348 + 1.349 + // aView is the view for aWidget and aRegion is relative to aWidget. 1.350 + void Refresh(nsView *aView, const nsIntRegion& aRegion); 1.351 + 1.352 + // Utilities 1.353 + 1.354 + bool IsViewInserted(nsView *aView); 1.355 + 1.356 + /** 1.357 + * Intersects aRect with aView's bounds and then transforms it from aView's 1.358 + * coordinate system to the coordinate system of the widget attached to 1.359 + * aView. 1.360 + */ 1.361 + nsIntRect ViewToWidget(nsView *aView, const nsRect &aRect) const; 1.362 + 1.363 + void DoSetWindowDimensions(nscoord aWidth, nscoord aHeight); 1.364 + 1.365 + bool IsPainting() const { 1.366 + return RootViewManager()->mPainting; 1.367 + } 1.368 + 1.369 + void SetPainting(bool aPainting) { 1.370 + RootViewManager()->mPainting = aPainting; 1.371 + } 1.372 + 1.373 + void InvalidateView(nsView *aView, const nsRect &aRect); 1.374 + 1.375 + nsViewManager* RootViewManager() const { return mRootViewManager; } 1.376 + bool IsRootVM() const { return this == RootViewManager(); } 1.377 + 1.378 + // Whether synchronous painting is allowed at the moment. For example, 1.379 + // widget geometry changes can cause synchronous painting, so they need to 1.380 + // be deferred while refresh is disabled. 1.381 + bool IsPaintingAllowed() { return RootViewManager()->mRefreshDisableCount == 0; } 1.382 + 1.383 + void WillPaintWindow(nsIWidget* aWidget); 1.384 + bool PaintWindow(nsIWidget* aWidget, nsIntRegion aRegion); 1.385 + void DidPaintWindow(); 1.386 + 1.387 + // Call this when you need to let the viewmanager know that it now has 1.388 + // pending updates. 1.389 + void PostPendingUpdate(); 1.390 + 1.391 + nsRefPtr<nsDeviceContext> mContext; 1.392 + nsIPresShell *mPresShell; 1.393 + 1.394 + // The size for a resize that we delayed until the root view becomes 1.395 + // visible again. 1.396 + nsSize mDelayedResize; 1.397 + 1.398 + nsView *mRootView; 1.399 + // mRootViewManager is a strong ref unless it equals |this|. It's 1.400 + // never null (if we have no ancestors, it will be |this|). 1.401 + nsViewManager *mRootViewManager; 1.402 + 1.403 + // The following members should not be accessed directly except by 1.404 + // the root view manager. Some have accessor functions to enforce 1.405 + // this, as noted. 1.406 + 1.407 + int32_t mRefreshDisableCount; 1.408 + // Use IsPainting() and SetPainting() to access mPainting. 1.409 + bool mPainting; 1.410 + bool mRecursiveRefreshPending; 1.411 + bool mHasPendingWidgetGeometryChanges; 1.412 + bool mInScroll; 1.413 + 1.414 + //from here to public should be static and locked... MMP 1.415 + static int32_t mVMCount; //number of viewmanagers 1.416 + 1.417 + //list of view managers 1.418 + static nsVoidArray *gViewManagers; 1.419 +}; 1.420 + 1.421 +/** 1.422 + Invalidation model: 1.423 + 1.424 + 1) Callers call into the view manager and ask it to invalidate a view. 1.425 + 1.426 + 2) The view manager finds the "right" widget for the view, henceforth called 1.427 + the root widget. 1.428 + 1.429 + 3) The view manager traverses descendants of the root widget and for each 1.430 + one that needs invalidation stores the rect to invalidate on the widget's 1.431 + view (batching). 1.432 + 1.433 + 4) The dirty region is flushed to the right widget when 1.434 + ProcessPendingUpdates is called from the RefreshDriver. 1.435 + 1.436 + It's important to note that widgets associated to views outside this view 1.437 + manager can end up being invalidated during step 3. Therefore, the end of a 1.438 + view update batch really needs to traverse the entire view tree, to ensure 1.439 + that those invalidates happen. 1.440 + 1.441 + To cope with this, invalidation processing and should only happen on the 1.442 + root viewmanager. 1.443 +*/ 1.444 + 1.445 +#endif // nsViewManager_h___