1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #ifndef nsViewManager_h___
39 #define nsViewManager_h___
41 #include "nsIViewManager.h"
43 #include "nsIWidget.h"
47 #include "nsVoidArray.h"
48 #include "nsThreadUtils.h"
49 #include "nsIScrollableView.h"
50 #include "nsIRegion.h"
52 #include "nsIViewObserver.h"
54 //Uncomment the following line to enable generation of viewmanager performance data.
55 #ifdef MOZ_PERF_METRICS
56 //#define NS_VM_PERF_METRICS 1
59 #ifdef NS_VM_PERF_METRICS
66 1) Callers call into the view manager and ask it to update a view.
68 2) The view manager finds the "right" widget for the view, henceforth called
71 3) The view manager traverses descendants of the root widget and for each
72 one that needs invalidation either
74 a) Calls Invalidate() on the widget (no batching)
76 b) Stores the rect to invalidate on the widget's view (batching)
78 // XXXbz we want to change this a bit. See bug 243726
80 4) When batching, the call to end the batch either processes the pending
81 Invalidate() calls on the widgets or posts an event to do so.
83 It's important to note that widgets associated to views outside this view
84 manager can end up being invalidated during step 3. Therefore, the end of a
85 view update batch really needs to traverse the entire view tree, to ensure
86 that those invalidates happen.
88 To cope with this, invalidate event processing and view update batch
89 handling should only happen on the root viewmanager. This means the root
90 view manager is the only thing keeping track of mUpdateCnt. As a result,
91 Composite() calls should also be forwarded to the root view manager.
94 class nsViewManagerEvent
: public nsRunnable
{
96 nsViewManagerEvent(class nsViewManager
*vm
) : mViewManager(vm
) {
97 NS_ASSERTION(mViewManager
, "null parameter");
99 void Revoke() { mViewManager
= nsnull
; }
101 class nsViewManager
*mViewManager
;
104 class nsViewManager
: public nsIViewManager
{
108 NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
112 NS_IMETHOD
Init(nsIDeviceContext
* aContext
);
114 NS_IMETHOD_(nsIView
*) CreateView(const nsRect
& aBounds
,
115 const nsIView
* aParent
,
116 nsViewVisibility aVisibilityFlag
= nsViewVisibility_kShow
);
118 NS_IMETHOD_(nsIScrollableView
*) CreateScrollableView(const nsRect
& aBounds
,
119 const nsIView
* aParent
);
121 NS_IMETHOD
GetRootView(nsIView
*&aView
);
122 NS_IMETHOD
SetRootView(nsIView
*aView
);
124 NS_IMETHOD
GetWindowDimensions(nscoord
*width
, nscoord
*height
);
125 NS_IMETHOD
SetWindowDimensions(nscoord width
, nscoord height
);
126 NS_IMETHOD
FlushDelayedResize();
128 NS_IMETHOD
Composite(void);
130 NS_IMETHOD
UpdateView(nsIView
*aView
, PRUint32 aUpdateFlags
);
131 NS_IMETHOD
UpdateView(nsIView
*aView
, const nsRect
&aRect
, PRUint32 aUpdateFlags
);
132 NS_IMETHOD
UpdateAllViews(PRUint32 aUpdateFlags
);
134 NS_IMETHOD
DispatchEvent(nsGUIEvent
*aEvent
, nsEventStatus
* aStatus
);
136 NS_IMETHOD
GrabMouseEvents(nsIView
*aView
, PRBool
&aResult
);
138 NS_IMETHOD
GetMouseEventGrabber(nsIView
*&aView
);
140 NS_IMETHOD
InsertChild(nsIView
*parent
, nsIView
*child
, nsIView
*sibling
,
143 NS_IMETHOD
InsertChild(nsIView
*parent
, nsIView
*child
,
146 NS_IMETHOD
RemoveChild(nsIView
*parent
);
148 NS_IMETHOD
MoveViewBy(nsIView
*aView
, nscoord aX
, nscoord aY
);
150 NS_IMETHOD
MoveViewTo(nsIView
*aView
, nscoord aX
, nscoord aY
);
152 NS_IMETHOD
ResizeView(nsIView
*aView
, const nsRect
&aRect
, PRBool aRepaintExposedAreaOnly
= PR_FALSE
);
154 NS_IMETHOD
SetViewFloating(nsIView
*aView
, PRBool aFloating
);
156 NS_IMETHOD
SetViewVisibility(nsIView
*aView
, nsViewVisibility aVisible
);
158 NS_IMETHOD
SetViewZIndex(nsIView
*aView
, PRBool aAuto
, PRInt32 aZIndex
, PRBool aTopMost
=PR_FALSE
);
160 NS_IMETHOD
SetViewObserver(nsIViewObserver
*aObserver
);
161 NS_IMETHOD
GetViewObserver(nsIViewObserver
*&aObserver
);
163 NS_IMETHOD
GetDeviceContext(nsIDeviceContext
*&aContext
);
165 NS_IMETHOD
DisableRefresh(void);
166 NS_IMETHOD
EnableRefresh(PRUint32 aUpdateFlags
);
168 virtual nsIViewManager
* BeginUpdateViewBatch(void);
169 NS_IMETHOD
EndUpdateViewBatch(PRUint32 aUpdateFlags
);
171 NS_IMETHOD
SetRootScrollableView(nsIScrollableView
*aScrollable
);
172 NS_IMETHOD
GetRootScrollableView(nsIScrollableView
**aScrollable
);
174 NS_IMETHOD
GetWidget(nsIWidget
**aWidget
);
175 nsIWidget
* GetWidget() { return mRootView
? mRootView
->GetWidget() : nsnull
; }
176 NS_IMETHOD
ForceUpdate();
178 NS_IMETHOD
IsPainting(PRBool
& aIsPainting
);
179 NS_IMETHOD
SetDefaultBackgroundColor(nscolor aColor
);
180 NS_IMETHOD
GetDefaultBackgroundColor(nscolor
* aColor
);
181 NS_IMETHOD
GetLastUserEventTime(PRUint32
& aTime
);
182 void ProcessInvalidateEvent();
183 static PRUint32 gLastUserEventTime
;
186 * Determine if a rectangle specified in the view's coordinate system
187 * is completely, or partially visible.
188 * @param aView view that aRect coordinates are specified relative to
189 * @param aRect rectangle in twips to test for visibility
190 * @param aMinTwips is the min. pixel rows or cols at edge of screen
191 * needed for object to be counted visible
192 * @param aRectVisibility returns eVisible if the rect is visible,
193 * otherwise it returns an enum indicating why not
195 NS_IMETHOD
GetRectVisibility(nsIView
*aView
, const nsRect
&aRect
,
197 nsRectVisibility
*aRectVisibility
);
199 NS_IMETHOD
SynthesizeMouseMove(PRBool aFromScroll
);
200 void ProcessSynthMouseMoveEvent(PRBool aFromScroll
);
202 /* Update the cached RootViewManager pointer on this view manager. */
203 void InvalidateHierarchy();
206 * Enables/disables focus/blur event suppression.
207 * Enabling stops focus/blur events from reaching the widgets.
208 * This should be enabled when we're messing with the frame tree,
209 * so focus/blur handlers don't mess with stuff while we are.
211 * Disabling "reboots" the focus by sending a blur to what was focused
212 * before suppression began, and by sending a focus event to what should
213 * be currently focused. Note this can run arbitrary code, and could
214 * even destroy the view manager.
217 static void SuppressFocusEvents(PRBool aSuppress
);
219 PRBool
IsFocusSuppressed()
221 return sFocusSuppressed
;
224 static void SetCurrentlyFocusedView(nsView
*aView
)
226 sCurrentlyFocusView
= aView
;
229 static nsView
* GetCurrentlyFocusedView()
231 return sCurrentlyFocusView
;
234 static void SetViewFocusedBeforeSuppression(nsView
*aView
)
236 sViewFocusedBeforeSuppression
= aView
;
239 static nsView
* GetViewFocusedBeforeSuppression()
241 return sViewFocusedBeforeSuppression
;
245 virtual ~nsViewManager();
249 static nsView
*sCurrentlyFocusView
;
250 static nsView
*sViewFocusedBeforeSuppression
;
251 static PRBool sFocusSuppressed
;
253 void FlushPendingInvalidates();
254 void ProcessPendingUpdates(nsView
*aView
, PRBool aDoInvalidate
);
255 void ReparentChildWidgets(nsIView
* aView
, nsIWidget
*aNewWidget
);
256 void ReparentWidgets(nsIView
* aView
, nsIView
*aParent
);
257 already_AddRefed
<nsIRenderingContext
> CreateRenderingContext(nsView
&aView
);
258 void UpdateWidgetArea(nsView
*aWidgetView
, const nsRegion
&aDamagedRegion
,
259 nsView
* aIgnoreWidgetView
);
261 void UpdateViews(nsView
*aView
, PRUint32 aUpdateFlags
);
263 void Refresh(nsView
*aView
, nsIRenderingContext
*aContext
,
264 nsIRegion
*region
, PRUint32 aUpdateFlags
);
266 * Refresh aView (which must be non-null) with our default background color
268 void DefaultRefresh(nsView
* aView
, nsIRenderingContext
*aContext
, const nsRect
* aRect
);
269 void RenderViews(nsView
*aRootView
, nsIRenderingContext
& aRC
,
270 const nsRegion
& aRegion
);
272 void InvalidateRectDifference(nsView
*aView
, const nsRect
& aRect
, const nsRect
& aCutOut
, PRUint32 aUpdateFlags
);
273 void InvalidateHorizontalBandDifference(nsView
*aView
, const nsRect
& aRect
, const nsRect
& aCutOut
,
274 PRUint32 aUpdateFlags
, nscoord aY1
, nscoord aY2
, PRBool aInCutOut
);
276 void AddCoveringWidgetsToOpaqueRegion(nsRegion
&aRgn
, nsIDeviceContext
* aContext
,
281 PRBool
IsViewInserted(nsView
*aView
);
284 * Function to recursively call Update() on all widgets belonging to
285 * a view or its kids.
287 void UpdateWidgetsForView(nsView
* aView
);
290 * Transforms a rectangle from aView's coordinate system to the coordinate
291 * system of the widget attached to aWidgetView, which should be an ancestor
294 void ViewToWidget(nsView
*aView
, nsView
* aWidgetView
, nsRect
&aRect
) const;
297 * Transforms a rectangle from specified view's coordinate system to
298 * an absolute coordinate rectangle which can be compared against the
299 * rectangle returned by GetVisibleRect to determine visibility.
300 * @param aView view that aRect coordinates are specified relative to
301 * @param aRect rectangle in twips to convert to absolute coordinates
302 * @param aAbsRect rectangle in absolute coorindates.
303 * @returns NS_OK if successful otherwise, NS_ERROR_FAILURE
306 nsresult
GetAbsoluteRect(nsView
*aView
, const nsRect
&aRect
,
309 * Determine the visible rect
310 * @param aVisibleRect visible rectangle in twips
311 * @returns NS_OK if successful, otherwise NS_ERROR_FAILURE.
314 nsresult
GetVisibleRect(nsRect
& aVisibleRect
);
316 void DoSetWindowDimensions(nscoord aWidth
, nscoord aHeight
)
319 nsRect
newDim(0, 0, aWidth
, aHeight
);
320 mRootView
->GetDimensions(oldDim
);
321 // We care about resizes even when one dimension is already zero.
322 if (!oldDim
.IsExactEqual(newDim
)) {
323 // Don't resize the widget. It is already being set elsewhere.
324 mRootView
->SetDimensions(newDim
, PR_TRUE
, PR_FALSE
);
326 mObserver
->ResizeReflow(mRootView
, aWidth
, aHeight
);
331 void IncrementUpdateCount() {
332 NS_ASSERTION(IsRootVM(),
333 "IncrementUpdateCount called on non-root viewmanager");
337 void DecrementUpdateCount() {
338 NS_ASSERTION(IsRootVM(),
339 "DecrementUpdateCount called on non-root viewmanager");
343 PRInt32
UpdateCount() const {
344 NS_ASSERTION(IsRootVM(),
345 "DecrementUpdateCount called on non-root viewmanager");
349 void ClearUpdateCount() {
350 NS_ASSERTION(IsRootVM(),
351 "DecrementUpdateCount called on non-root viewmanager");
355 PRBool
IsPainting() const {
356 return RootViewManager()->mPainting
;
359 void SetPainting(PRBool aPainting
) {
360 RootViewManager()->mPainting
= aPainting
;
363 public: // NOT in nsIViewManager, so private to the view module
364 nsView
* GetRootView() const { return mRootView
; }
365 nsView
* GetMouseEventGrabber() const {
366 return RootViewManager()->mMouseGrabber
;
368 nsViewManager
* RootViewManager() const { return mRootViewManager
; }
369 PRBool
IsRootVM() const { return this == RootViewManager(); }
371 nsEventStatus
HandleEvent(nsView
* aView
, nsPoint aPoint
, nsGUIEvent
* aEvent
,
375 * Called to inform the view manager that a view is about to bit-blit.
376 * @param aView the view that will bit-blit
377 * @param aScrollAmount how much aView will scroll by
378 * @return always returns NS_OK
380 * This method used to return void, but MSVC 6.0 SP5 (without the
381 * Processor Pack) and SP6, and the MS eMbedded Visual C++ 4.0 SP4
382 * (for WINCE) hit an internal compiler error when compiling this
387 fatal error C1001: INTERNAL COMPILER ERROR
388 (compiler file 'E:\8966\vc98\p2\src\P2\main.c', line 494)
392 * Making the method return nsresult worked around the internal
393 * compiler error. See Bugzilla bug 281158. (The WINCE internal
394 * compiler error was addressed by the patch in bug 291229 comment
395 * 14 although the bug report did not mention the problem.)
397 nsresult
WillBitBlit(nsView
* aView
, nsPoint aScrollAmount
);
400 * Called to inform the view manager that a view has scrolled via a
402 * The view manager will invalidate any widgets which may need
404 * @param aView view to paint. should be the nsScrollPortView that
406 * @param aUpdateRegion ensure that this part of the view is repainted
408 void UpdateViewAfterScroll(nsView
*aView
, const nsRegion
& aUpdateRegion
);
411 * Asks whether we can scroll a view using bitblt. If we say 'yes', we
412 * return in aUpdateRegion an area that must be updated (relative to aView
413 * after it has been scrolled).
415 PRBool
CanScrollWithBitBlt(nsView
* aView
, nsPoint aDelta
, nsRegion
* aUpdateRegion
);
417 nsresult
CreateRegion(nsIRegion
* *result
);
419 PRBool
IsRefreshEnabled() { return RootViewManager()->mRefreshEnabled
; }
421 nsIViewObserver
* GetViewObserver() { return mObserver
; }
423 // Call this when you need to let the viewmanager know that it now has
425 void PostPendingUpdate() { RootViewManager()->mHasPendingUpdates
= PR_TRUE
; }
427 nsIDeviceContext
*mContext
;
428 nsIViewObserver
*mObserver
;
429 nsIScrollableView
*mRootScrollable
;
430 nscolor mDefaultBackgroundColor
;
431 nsPoint mMouseLocation
; // device units, relative to mRootView
433 // The size for a resize that we delayed until the root view becomes
435 nsSize mDelayedResize
;
437 nsCOMPtr
<nsIFactory
> mRegionFactory
;
439 // mRootViewManager is a strong ref unless it equals |this|. It's
440 // never null (if we have no ancestors, it will be |this|).
441 nsViewManager
*mRootViewManager
;
443 nsRevocableEventPtr
<nsViewManagerEvent
> mSynthMouseMoveEvent
;
444 nsRevocableEventPtr
<nsViewManagerEvent
> mInvalidateEvent
;
446 // The following members should not be accessed directly except by
447 // the root view manager. Some have accessor functions to enforce
450 // Use GrabMouseEvents() and GetMouseEventGrabber() to access mMouseGrabber.
451 nsView
*mMouseGrabber
;
452 // Use IncrementUpdateCount(), DecrementUpdateCount(), UpdateCount(),
453 // ClearUpdateCount() on the root viewmanager to access mUpdateCnt.
455 PRInt32 mUpdateBatchCnt
;
456 PRUint32 mUpdateBatchFlags
;
458 // Use IsRefreshEnabled() to check the value of mRefreshEnabled.
459 PRPackedBool mRefreshEnabled
;
460 // Use IsPainting() and SetPainting() to access mPainting.
461 PRPackedBool mPainting
;
462 PRPackedBool mRecursiveRefreshPending
;
463 PRPackedBool mHasPendingUpdates
;
464 PRPackedBool mInScroll
;
466 //from here to public should be static and locked... MMP
467 static PRInt32 mVMCount
; //number of viewmanagers
469 //Rendering context used to cleanup the blending buffers
470 static nsIRenderingContext
* gCleanupContext
;
472 //list of view managers
473 static nsVoidArray
*gViewManagers
;
475 void PostInvalidateEvent();
477 #ifdef NS_VM_PERF_METRICS
478 MOZ_TIMER_DECLARE(mWatch
) // Measures compositing+paint time for current document
482 //when the refresh happens, should it be double buffered?
483 #define NS_VMREFRESH_DOUBLE_BUFFER 0x0001
485 #endif /* nsViewManager_h___ */