1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * vim: set ts=2 sw=2 et tw=78:
3 : * ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is mozilla.org code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Netscape Communications Corporation.
20 : * Portions created by the Initial Developer are Copyright (C) 1998
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Steve Clark <buster@netscape.com>
25 : * HÃ¥kan Waara <hwaara@chello.se>
26 : * Dan Rosen <dr@netscape.com>
27 : * Daniel Glazman <glazman@netscape.com>
28 : * Mats Palmgren <matspal@gmail.com>
29 : * Mihai Sucan <mihai.sucan@gmail.com>
30 : *
31 : * Alternatively, the contents of this file may be used under the terms of
32 : * either of the GNU General Public License Version 2 or later (the "GPL"),
33 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
34 : * in which case the provisions of the GPL or the LGPL are applicable instead
35 : * of those above. If you wish to allow use of your version of this file only
36 : * under the terms of either the GPL or the LGPL, and not to allow others to
37 : * use your version of this file under the terms of the MPL, indicate your
38 : * decision by deleting the provisions above and replace them with the notice
39 : * and other provisions required by the GPL or the LGPL. If you do not delete
40 : * the provisions above, a recipient may use your version of this file under
41 : * the terms of any one of the MPL, the GPL or the LGPL.
42 : *
43 : * ***** END LICENSE BLOCK *****
44 : *
45 : * This Original Code has been modified by IBM Corporation.
46 : * Modifications made by IBM described herein are
47 : * Copyright (c) International Business Machines
48 : * Corporation, 2000
49 : *
50 : * Modifications to Mozilla code or documentation
51 : * identified per MPL Section 3.3
52 : *
53 : * Date Modified by Description of modification
54 : * 05/03/2000 IBM Corp. Observer events for reflow states
55 : */
56 :
57 : /* a presentation of a document, part 2 */
58 :
59 : #ifndef nsPresShell_h_
60 : #define nsPresShell_h_
61 :
62 : #include "nsIPresShell.h"
63 : #include "nsStubDocumentObserver.h"
64 : #include "nsISelectionController.h"
65 : #include "nsIObserver.h"
66 : #include "nsWeakReference.h"
67 : #include "nsCRT.h"
68 : #include "nsAutoPtr.h"
69 : #include "nsIWidget.h"
70 : #include "nsStyleSet.h"
71 : #include "nsPresArena.h"
72 : #include "nsFrameSelection.h"
73 : #include "nsGUIEvent.h"
74 : #include "nsContentUtils.h"
75 : #include "nsRefreshDriver.h"
76 :
77 : class nsRange;
78 : class nsIDragService;
79 : class nsCSSStyleSheet;
80 :
81 : struct RangePaintInfo;
82 : struct nsCallbackEventRequest;
83 : #ifdef MOZ_REFLOW_PERF
84 : class ReflowCountMgr;
85 : #endif
86 :
87 : #define STACK_ARENA_MARK_INCREMENT 50
88 : /* a bit under 4096, for malloc overhead */
89 : #define STACK_ARENA_BLOCK_INCREMENT 4044
90 :
91 : /**A block of memory that the stack will
92 : * chop up and hand out
93 : */
94 : struct StackBlock {
95 :
96 : // a block of memory. Note that this must be first so that it will
97 : // be aligned.
98 : char mBlock[STACK_ARENA_BLOCK_INCREMENT];
99 :
100 : // another block of memory that would only be created
101 : // if our stack overflowed. Yes we have the ability
102 : // to grow on a stack overflow
103 : StackBlock* mNext;
104 :
105 0 : StackBlock() : mNext(nsnull) { }
106 0 : ~StackBlock() { }
107 : };
108 :
109 : /* we hold an array of marks. A push pushes a mark on the stack
110 : * a pop pops it off.
111 : */
112 : struct StackMark {
113 : // the block of memory we are currently handing out chunks of
114 : StackBlock* mBlock;
115 :
116 : // our current position in the memory
117 : size_t mPos;
118 : };
119 :
120 :
121 : /* A stack arena allows a stack based interface to a block of memory.
122 : * It should be used when you need to allocate some temporary memory that
123 : * you will immediately return.
124 : */
125 : class StackArena {
126 : public:
127 : StackArena();
128 : ~StackArena();
129 :
130 0 : nsresult Init() { return mBlocks ? NS_OK : NS_ERROR_OUT_OF_MEMORY; }
131 :
132 : // Memory management functions
133 : void* Allocate(size_t aSize);
134 : void Push();
135 : void Pop();
136 :
137 0 : size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
138 0 : size_t n = 0;
139 0 : StackBlock *block = mBlocks;
140 0 : while (block) {
141 0 : n += aMallocSizeOf(block);
142 0 : block = block->mNext;
143 : }
144 0 : n += aMallocSizeOf(mMarks);
145 0 : return n;
146 : }
147 :
148 : private:
149 : // our current position in memory
150 : size_t mPos;
151 :
152 : // a list of memory block. Usually there is only one
153 : // but if we overrun our stack size we can get more memory.
154 : StackBlock* mBlocks;
155 :
156 : // the current block of memory we are passing our chucks of
157 : StackBlock* mCurBlock;
158 :
159 : // our stack of mark where push has been called
160 : StackMark* mMarks;
161 :
162 : // the current top of the mark list
163 : PRUint32 mStackTop;
164 :
165 : // the size of the mark array
166 : PRUint32 mMarkLength;
167 : };
168 :
169 : class nsPresShellEventCB;
170 : class nsAutoCauseReflowNotifier;
171 :
172 : class PresShell : public nsIPresShell,
173 : public nsStubDocumentObserver,
174 : public nsISelectionController, public nsIObserver,
175 : public nsSupportsWeakReference
176 : {
177 : public:
178 : PresShell();
179 :
180 0 : NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
181 :
182 : // nsISupports
183 : NS_DECL_ISUPPORTS
184 :
185 : // nsIPresShell
186 : virtual NS_HIDDEN_(nsresult) Init(nsIDocument* aDocument,
187 : nsPresContext* aPresContext,
188 : nsIViewManager* aViewManager,
189 : nsStyleSet* aStyleSet,
190 : nsCompatibility aCompatMode);
191 : virtual NS_HIDDEN_(void) Destroy();
192 :
193 : virtual NS_HIDDEN_(void*) AllocateFrame(nsQueryFrame::FrameIID aCode,
194 : size_t aSize);
195 : virtual NS_HIDDEN_(void) FreeFrame(nsQueryFrame::FrameIID aCode,
196 : void* aChunk);
197 :
198 : virtual NS_HIDDEN_(void*) AllocateMisc(size_t aSize);
199 : virtual NS_HIDDEN_(void) FreeMisc(size_t aSize, void* aChunk);
200 :
201 : // Dynamic stack memory allocation
202 : virtual NS_HIDDEN_(void) PushStackMemory();
203 : virtual NS_HIDDEN_(void) PopStackMemory();
204 : virtual NS_HIDDEN_(void*) AllocateStackMemory(size_t aSize);
205 :
206 : virtual NS_HIDDEN_(nsresult) SetPreferenceStyleRules(bool aForceReflow);
207 :
208 : NS_IMETHOD GetSelection(SelectionType aType, nsISelection** aSelection);
209 : virtual nsISelection* GetCurrentSelection(SelectionType aType);
210 :
211 : NS_IMETHOD SetDisplaySelection(PRInt16 aToggle);
212 : NS_IMETHOD GetDisplaySelection(PRInt16 *aToggle);
213 : NS_IMETHOD ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion,
214 : PRInt16 aFlags);
215 : NS_IMETHOD RepaintSelection(SelectionType aType);
216 :
217 : virtual NS_HIDDEN_(void) BeginObservingDocument();
218 : virtual NS_HIDDEN_(void) EndObservingDocument();
219 : virtual NS_HIDDEN_(nsresult) InitialReflow(nscoord aWidth, nscoord aHeight);
220 : virtual NS_HIDDEN_(nsresult) ResizeReflow(nscoord aWidth, nscoord aHeight);
221 : virtual NS_HIDDEN_(nsresult) ResizeReflowOverride(nscoord aWidth, nscoord aHeight);
222 : virtual NS_HIDDEN_(void) StyleChangeReflow();
223 : virtual NS_HIDDEN_(nsIPageSequenceFrame*) GetPageSequenceFrame() const;
224 : virtual NS_HIDDEN_(nsIFrame*) GetRealPrimaryFrameFor(nsIContent* aContent) const;
225 :
226 : virtual NS_HIDDEN_(nsIFrame*) GetPlaceholderFrameFor(nsIFrame* aFrame) const;
227 : virtual NS_HIDDEN_(void) FrameNeedsReflow(nsIFrame *aFrame, IntrinsicDirty aIntrinsicDirty,
228 : nsFrameState aBitToAdd);
229 : virtual NS_HIDDEN_(void) FrameNeedsToContinueReflow(nsIFrame *aFrame);
230 : virtual NS_HIDDEN_(void) CancelAllPendingReflows();
231 : virtual NS_HIDDEN_(bool) IsSafeToFlush() const;
232 : virtual NS_HIDDEN_(void) FlushPendingNotifications(mozFlushType aType);
233 :
234 : /**
235 : * Recreates the frames for a node
236 : */
237 : virtual NS_HIDDEN_(nsresult) RecreateFramesFor(nsIContent* aContent);
238 :
239 : /**
240 : * Post a callback that should be handled after reflow has finished.
241 : */
242 : virtual NS_HIDDEN_(nsresult) PostReflowCallback(nsIReflowCallback* aCallback);
243 : virtual NS_HIDDEN_(void) CancelReflowCallback(nsIReflowCallback* aCallback);
244 :
245 : virtual NS_HIDDEN_(void) ClearFrameRefs(nsIFrame* aFrame);
246 : virtual NS_HIDDEN_(already_AddRefed<nsRenderingContext>) GetReferenceRenderingContext();
247 : virtual NS_HIDDEN_(nsresult) GoToAnchor(const nsAString& aAnchorName, bool aScroll);
248 : virtual NS_HIDDEN_(nsresult) ScrollToAnchor();
249 :
250 : virtual NS_HIDDEN_(nsresult) ScrollContentIntoView(nsIContent* aContent,
251 : PRIntn aVPercent,
252 : PRIntn aHPercent,
253 : PRUint32 aFlags);
254 : virtual bool ScrollFrameRectIntoView(nsIFrame* aFrame,
255 : const nsRect& aRect,
256 : PRIntn aVPercent,
257 : PRIntn aHPercent,
258 : PRUint32 aFlags);
259 : virtual nsRectVisibility GetRectVisibility(nsIFrame *aFrame,
260 : const nsRect &aRect,
261 : nscoord aMinTwips) const;
262 :
263 : virtual NS_HIDDEN_(void) SetIgnoreFrameDestruction(bool aIgnore);
264 : virtual NS_HIDDEN_(void) NotifyDestroyingFrame(nsIFrame* aFrame);
265 :
266 : virtual NS_HIDDEN_(nsresult) GetLinkLocation(nsIDOMNode* aNode, nsAString& aLocationString) const;
267 :
268 : virtual NS_HIDDEN_(nsresult) CaptureHistoryState(nsILayoutHistoryState** aLayoutHistoryState, bool aLeavingPage);
269 :
270 : virtual NS_HIDDEN_(void) UnsuppressPainting();
271 :
272 : virtual nsresult GetAgentStyleSheets(nsCOMArray<nsIStyleSheet>& aSheets);
273 : virtual nsresult SetAgentStyleSheets(const nsCOMArray<nsIStyleSheet>& aSheets);
274 :
275 : virtual nsresult AddOverrideStyleSheet(nsIStyleSheet *aSheet);
276 : virtual nsresult RemoveOverrideStyleSheet(nsIStyleSheet *aSheet);
277 :
278 : virtual NS_HIDDEN_(nsresult) HandleEventWithTarget(nsEvent* aEvent, nsIFrame* aFrame,
279 : nsIContent* aContent,
280 : nsEventStatus* aStatus);
281 : virtual NS_HIDDEN_(nsIFrame*) GetEventTargetFrame();
282 : virtual NS_HIDDEN_(already_AddRefed<nsIContent>) GetEventTargetContent(nsEvent* aEvent);
283 :
284 :
285 : virtual nsresult ReconstructFrames(void);
286 : virtual void Freeze();
287 : virtual void Thaw();
288 : virtual void FireOrClearDelayedEvents(bool aFireEvents);
289 :
290 : virtual nsIFrame* GetFrameForPoint(nsIFrame* aFrame, nsPoint aPt);
291 :
292 : virtual NS_HIDDEN_(nsresult) RenderDocument(const nsRect& aRect, PRUint32 aFlags,
293 : nscolor aBackgroundColor,
294 : gfxContext* aThebesContext);
295 :
296 : virtual already_AddRefed<gfxASurface> RenderNode(nsIDOMNode* aNode,
297 : nsIntRegion* aRegion,
298 : nsIntPoint& aPoint,
299 : nsIntRect* aScreenRect);
300 :
301 : virtual already_AddRefed<gfxASurface> RenderSelection(nsISelection* aSelection,
302 : nsIntPoint& aPoint,
303 : nsIntRect* aScreenRect);
304 :
305 : virtual already_AddRefed<nsPIDOMWindow> GetRootWindow();
306 :
307 : virtual LayerManager* GetLayerManager();
308 :
309 : virtual void SetIgnoreViewportScrolling(bool aIgnore);
310 :
311 : virtual void SetDisplayPort(const nsRect& aDisplayPort);
312 :
313 : virtual nsresult SetResolution(float aXResolution, float aYResolution);
314 :
315 : //nsIViewObserver interface
316 :
317 : virtual void Paint(nsIView* aViewToPaint, nsIWidget* aWidget,
318 : const nsRegion& aDirtyRegion, const nsIntRegion& aIntDirtyRegion,
319 : bool aWillSendDidPaint);
320 : virtual nsresult HandleEvent(nsIFrame* aFrame,
321 : nsGUIEvent* aEvent,
322 : bool aDontRetargetEvents,
323 : nsEventStatus* aEventStatus);
324 : virtual NS_HIDDEN_(nsresult) HandleDOMEventWithTarget(nsIContent* aTargetContent,
325 : nsEvent* aEvent,
326 : nsEventStatus* aStatus);
327 : virtual NS_HIDDEN_(nsresult) HandleDOMEventWithTarget(nsIContent* aTargetContent,
328 : nsIDOMEvent* aEvent,
329 : nsEventStatus* aStatus);
330 : virtual bool ShouldIgnoreInvalidation();
331 : virtual void WillPaint(bool aWillSendDidPaint);
332 : virtual void DidPaint();
333 : virtual void ScheduleViewManagerFlush();
334 : virtual void DispatchSynthMouseMove(nsGUIEvent *aEvent, bool aFlushOnHoverChange);
335 : virtual void ClearMouseCaptureOnView(nsIView* aView);
336 : virtual bool IsVisible();
337 :
338 : // caret handling
339 : virtual NS_HIDDEN_(already_AddRefed<nsCaret>) GetCaret() const;
340 : virtual NS_HIDDEN_(void) MaybeInvalidateCaretPosition();
341 : NS_IMETHOD SetCaretEnabled(bool aInEnable);
342 : NS_IMETHOD SetCaretReadOnly(bool aReadOnly);
343 : NS_IMETHOD GetCaretEnabled(bool *aOutEnabled);
344 : NS_IMETHOD SetCaretVisibilityDuringSelection(bool aVisibility);
345 : NS_IMETHOD GetCaretVisible(bool *_retval);
346 : virtual void SetCaret(nsCaret *aNewCaret);
347 : virtual void RestoreCaret();
348 :
349 : NS_IMETHOD SetSelectionFlags(PRInt16 aInEnable);
350 : NS_IMETHOD GetSelectionFlags(PRInt16 *aOutEnable);
351 :
352 : // nsISelectionController
353 :
354 : NS_IMETHOD CharacterMove(bool aForward, bool aExtend);
355 : NS_IMETHOD CharacterExtendForDelete();
356 : NS_IMETHOD CharacterExtendForBackspace();
357 : NS_IMETHOD WordMove(bool aForward, bool aExtend);
358 : NS_IMETHOD WordExtendForDelete(bool aForward);
359 : NS_IMETHOD LineMove(bool aForward, bool aExtend);
360 : NS_IMETHOD IntraLineMove(bool aForward, bool aExtend);
361 : NS_IMETHOD PageMove(bool aForward, bool aExtend);
362 : NS_IMETHOD ScrollPage(bool aForward);
363 : NS_IMETHOD ScrollLine(bool aForward);
364 : NS_IMETHOD ScrollCharacter(bool aRight);
365 : NS_IMETHOD CompleteScroll(bool aForward);
366 : NS_IMETHOD CompleteMove(bool aForward, bool aExtend);
367 : NS_IMETHOD SelectAll();
368 : NS_IMETHOD CheckVisibility(nsIDOMNode *node, PRInt16 startOffset, PRInt16 EndOffset, bool *_retval);
369 : virtual nsresult CheckVisibilityContent(nsIContent* aNode, PRInt16 aStartOffset,
370 : PRInt16 aEndOffset, bool* aRetval);
371 :
372 : // nsIDocumentObserver
373 : NS_DECL_NSIDOCUMENTOBSERVER_BEGINUPDATE
374 : NS_DECL_NSIDOCUMENTOBSERVER_ENDUPDATE
375 : NS_DECL_NSIDOCUMENTOBSERVER_BEGINLOAD
376 : NS_DECL_NSIDOCUMENTOBSERVER_ENDLOAD
377 : NS_DECL_NSIDOCUMENTOBSERVER_CONTENTSTATECHANGED
378 : NS_DECL_NSIDOCUMENTOBSERVER_DOCUMENTSTATESCHANGED
379 : NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETADDED
380 : NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETREMOVED
381 : NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETAPPLICABLESTATECHANGED
382 : NS_DECL_NSIDOCUMENTOBSERVER_STYLERULECHANGED
383 : NS_DECL_NSIDOCUMENTOBSERVER_STYLERULEADDED
384 : NS_DECL_NSIDOCUMENTOBSERVER_STYLERULEREMOVED
385 :
386 : // nsIMutationObserver
387 : NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
388 : NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE
389 : NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
390 : NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
391 : NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
392 : NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
393 :
394 : NS_DECL_NSIOBSERVER
395 :
396 : #ifdef MOZ_REFLOW_PERF
397 : virtual NS_HIDDEN_(void) DumpReflows();
398 : virtual NS_HIDDEN_(void) CountReflows(const char * aName, nsIFrame * aFrame);
399 : virtual NS_HIDDEN_(void) PaintCount(const char * aName,
400 : nsRenderingContext* aRenderingContext,
401 : nsPresContext* aPresContext,
402 : nsIFrame * aFrame,
403 : const nsPoint& aOffset,
404 : PRUint32 aColor);
405 : virtual NS_HIDDEN_(void) SetPaintFrameCount(bool aOn);
406 : virtual bool IsPaintingFrameCounts();
407 : #endif
408 :
409 : #ifdef DEBUG
410 : virtual void ListStyleContexts(nsIFrame *aRootFrame, FILE *out,
411 : PRInt32 aIndent = 0);
412 :
413 : virtual void ListStyleSheets(FILE *out, PRInt32 aIndent = 0);
414 : virtual void VerifyStyleTree();
415 : #endif
416 :
417 : #ifdef PR_LOGGING
418 : static PRLogModuleInfo* gLog;
419 : #endif
420 :
421 : virtual NS_HIDDEN_(void) DisableNonTestMouseEvents(bool aDisable);
422 :
423 : virtual void UpdateCanvasBackground();
424 :
425 : virtual nsresult AddCanvasBackgroundColorItem(nsDisplayListBuilder& aBuilder,
426 : nsDisplayList& aList,
427 : nsIFrame* aFrame,
428 : const nsRect& aBounds,
429 : nscolor aBackstopColor,
430 : PRUint32 aFlags);
431 :
432 : virtual nsresult AddPrintPreviewBackgroundItem(nsDisplayListBuilder& aBuilder,
433 : nsDisplayList& aList,
434 : nsIFrame* aFrame,
435 : const nsRect& aBounds);
436 :
437 : virtual nscolor ComputeBackstopColor(nsIView* aDisplayRoot);
438 :
439 : virtual NS_HIDDEN_(nsresult) SetIsActive(bool aIsActive);
440 :
441 0 : virtual bool GetIsViewportOverridden() { return mViewportOverridden; }
442 :
443 0 : virtual bool IsLayoutFlushObserver()
444 : {
445 : return GetPresContext()->RefreshDriver()->
446 0 : IsLayoutFlushObserver(this);
447 : }
448 :
449 : protected:
450 : virtual ~PresShell();
451 :
452 : void HandlePostedReflowCallbacks(bool aInterruptible);
453 : void CancelPostedReflowCallbacks();
454 :
455 : void UnsuppressAndInvalidate();
456 :
457 0 : void WillCauseReflow() {
458 0 : nsContentUtils::AddScriptBlocker();
459 0 : ++mChangeNestCount;
460 0 : }
461 : nsresult DidCauseReflow();
462 : friend class nsAutoCauseReflowNotifier;
463 :
464 : bool TouchesAreEqual(nsIDOMTouch *aTouch1, nsIDOMTouch *aTouch2);
465 : void DispatchTouchEvent(nsEvent *aEvent,
466 : nsEventStatus* aStatus,
467 : nsPresShellEventCB* aEventCB,
468 : bool aTouchIsNew);
469 :
470 : void WillDoReflow();
471 : void DidDoReflow(bool aInterruptible);
472 : // ProcessReflowCommands returns whether we processed all our dirty roots
473 : // without interruptions.
474 : bool ProcessReflowCommands(bool aInterruptible);
475 : // MaybeScheduleReflow checks if posting a reflow is needed, then checks if
476 : // the last reflow was interrupted. In the interrupted case ScheduleReflow is
477 : // called off a timer, otherwise it is called directly.
478 : void MaybeScheduleReflow();
479 : // Actually schedules a reflow. This should only be called by
480 : // MaybeScheduleReflow and the reflow timer ScheduleReflowOffTimer
481 : // sets up.
482 : void ScheduleReflow();
483 :
484 : // Reflow regardless of whether the override bit has been set.
485 : nsresult ResizeReflowIgnoreOverride(nscoord aWidth, nscoord aHeight);
486 :
487 : // DoReflow returns whether the reflow finished without interruption
488 : bool DoReflow(nsIFrame* aFrame, bool aInterruptible);
489 : #ifdef DEBUG
490 : void DoVerifyReflow();
491 : void VerifyHasDirtyRootAncestor(nsIFrame* aFrame);
492 : #endif
493 :
494 : // Helper for ScrollContentIntoView
495 : void DoScrollContentIntoView(nsIContent* aContent,
496 : PRIntn aVPercent,
497 : PRIntn aHPercent,
498 : PRUint32 aFlags);
499 :
500 : friend struct AutoRenderingStateSaveRestore;
501 : friend struct RenderingState;
502 :
503 : struct RenderingState {
504 0 : RenderingState(PresShell* aPresShell)
505 : : mRenderFlags(aPresShell->mRenderFlags)
506 : , mXResolution(aPresShell->mXResolution)
507 0 : , mYResolution(aPresShell->mYResolution)
508 0 : { }
509 : PRUint32 mRenderFlags;
510 : float mXResolution;
511 : float mYResolution;
512 : };
513 :
514 : struct AutoSaveRestoreRenderingState {
515 0 : AutoSaveRestoreRenderingState(PresShell* aPresShell)
516 : : mPresShell(aPresShell)
517 0 : , mOldState(aPresShell)
518 0 : {}
519 :
520 0 : ~AutoSaveRestoreRenderingState()
521 : {
522 0 : mPresShell->mRenderFlags = mOldState.mRenderFlags;
523 0 : mPresShell->mXResolution = mOldState.mXResolution;
524 0 : mPresShell->mYResolution = mOldState.mYResolution;
525 0 : }
526 :
527 : PresShell* mPresShell;
528 : RenderingState mOldState;
529 : };
530 :
531 : void SetRenderingState(const RenderingState& aState);
532 :
533 : friend class nsPresShellEventCB;
534 :
535 : bool mCaretEnabled;
536 : #ifdef NS_DEBUG
537 : nsStyleSet* CloneStyleSet(nsStyleSet* aSet);
538 : bool VerifyIncrementalReflow();
539 : bool mInVerifyReflow;
540 : void ShowEventTargetDebug();
541 : #endif
542 :
543 : /**
544 : * methods that manage rules that are used to implement the associated preferences
545 : * - initially created for bugs 31816, 20760, 22963
546 : */
547 : nsresult ClearPreferenceStyleRules(void);
548 : nsresult CreatePreferenceStyleSheet(void);
549 : nsresult SetPrefLinkRules(void);
550 : nsresult SetPrefFocusRules(void);
551 : nsresult SetPrefNoScriptRule();
552 : nsresult SetPrefNoFramesRule(void);
553 :
554 : // methods for painting a range to an offscreen buffer
555 :
556 : // given a display list, clip the items within the list to
557 : // the range
558 : nsRect ClipListToRange(nsDisplayListBuilder *aBuilder,
559 : nsDisplayList* aList,
560 : nsRange* aRange);
561 :
562 : // create a RangePaintInfo for the range aRange containing the
563 : // display list needed to paint the range to a surface
564 : RangePaintInfo* CreateRangePaintInfo(nsIDOMRange* aRange,
565 : nsRect& aSurfaceRect,
566 : bool aForPrimarySelection);
567 :
568 : /*
569 : * Paint the items to a new surface and return it.
570 : *
571 : * aSelection - selection being painted, if any
572 : * aRegion - clip region, if any
573 : * aArea - area that the surface occupies, relative to the root frame
574 : * aPoint - reference point, typically the mouse position
575 : * aScreenRect - [out] set to the area of the screen the painted area should
576 : * be displayed at
577 : */
578 : already_AddRefed<gfxASurface>
579 : PaintRangePaintInfo(nsTArray<nsAutoPtr<RangePaintInfo> >* aItems,
580 : nsISelection* aSelection,
581 : nsIntRegion* aRegion,
582 : nsRect aArea,
583 : nsIntPoint& aPoint,
584 : nsIntRect* aScreenRect);
585 :
586 : /**
587 : * Methods to handle changes to user and UA sheet lists that we get
588 : * notified about.
589 : */
590 : void AddUserSheet(nsISupports* aSheet);
591 : void AddAgentSheet(nsISupports* aSheet);
592 : void RemoveSheet(nsStyleSet::sheetType aType, nsISupports* aSheet);
593 :
594 : // Hide a view if it is a popup
595 : void HideViewIfPopup(nsIView* aView);
596 :
597 : // Utility method to restore the root scrollframe state
598 : void RestoreRootScrollPosition();
599 :
600 0 : void MaybeReleaseCapturingContent()
601 : {
602 0 : nsRefPtr<nsFrameSelection> frameSelection = FrameSelection();
603 0 : if (frameSelection) {
604 0 : frameSelection->SetMouseDownState(false);
605 : }
606 0 : if (gCaptureInfo.mContent &&
607 0 : gCaptureInfo.mContent->OwnerDoc() == mDocument) {
608 0 : SetCapturingContent(nsnull, 0);
609 : }
610 0 : }
611 :
612 0 : nsresult HandleRetargetedEvent(nsEvent* aEvent, nsEventStatus* aStatus, nsIContent* aTarget)
613 : {
614 0 : PushCurrentEventInfo(nsnull, nsnull);
615 0 : mCurrentEventContent = aTarget;
616 0 : nsresult rv = NS_OK;
617 0 : if (GetCurrentEventFrame()) {
618 0 : rv = HandleEventInternal(aEvent, aStatus);
619 : }
620 0 : PopCurrentEventInfo();
621 0 : return rv;
622 : }
623 :
624 : nsRefPtr<nsCSSStyleSheet> mPrefStyleSheet; // mStyleSet owns it but we
625 : // maintain a ref, may be null
626 : #ifdef DEBUG
627 : PRUint32 mUpdateCount;
628 : #endif
629 : // reflow roots that need to be reflowed, as both a queue and a hashtable
630 : nsTArray<nsIFrame*> mDirtyRoots;
631 :
632 : bool mDocumentLoading;
633 :
634 : bool mIgnoreFrameDestruction;
635 : bool mHaveShutDown;
636 :
637 : bool mViewportOverridden;
638 :
639 : bool mLastRootReflowHadUnconstrainedHeight;
640 :
641 : // This is used to protect ourselves from triggering reflow while in the
642 : // middle of frame construction and the like... it really shouldn't be
643 : // needed, one hopes, but it is for now.
644 : PRUint32 mChangeNestCount;
645 :
646 : nsIFrame* mCurrentEventFrame;
647 : nsCOMPtr<nsIContent> mCurrentEventContent;
648 : nsTArray<nsIFrame*> mCurrentEventFrameStack;
649 : nsCOMArray<nsIContent> mCurrentEventContentStack;
650 :
651 : nsCOMPtr<nsIContent> mLastAnchorScrolledTo;
652 : nscoord mLastAnchorScrollPositionY;
653 : nsRefPtr<nsCaret> mCaret;
654 : nsRefPtr<nsCaret> mOriginalCaret;
655 : nsPresArena mFrameArena;
656 : StackArena mStackArena;
657 : nsCOMPtr<nsIDragService> mDragService;
658 :
659 : #ifdef DEBUG
660 : // The reflow root under which we're currently reflowing. Null when
661 : // not in reflow.
662 : nsIFrame* mCurrentReflowRoot;
663 : #endif
664 :
665 : // Set of frames that we should mark with NS_FRAME_HAS_DIRTY_CHILDREN after
666 : // we finish reflowing mCurrentReflowRoot.
667 : nsTHashtable< nsPtrHashKey<nsIFrame> > mFramesToDirty;
668 :
669 : // Information needed to properly handle scrolling content into view if the
670 : // pre-scroll reflow flush can be interrupted. mContentToScrollTo is
671 : // non-null between the initial scroll attempt and the first time we finish
672 : // processing all our dirty roots. mContentScrollVPosition and
673 : // mContentScrollHPosition are only used when it's non-null.
674 : nsCOMPtr<nsIContent> mContentToScrollTo;
675 : PRIntn mContentScrollVPosition;
676 : PRIntn mContentScrollHPosition;
677 : PRUint32 mContentToScrollToFlags;
678 :
679 : class nsDelayedEvent
680 0 : {
681 : public:
682 0 : virtual ~nsDelayedEvent() {};
683 0 : virtual void Dispatch(PresShell* aShell) {}
684 : };
685 :
686 : class nsDelayedInputEvent : public nsDelayedEvent
687 0 : {
688 : public:
689 0 : virtual void Dispatch(PresShell* aShell)
690 : {
691 0 : if (mEvent && mEvent->widget) {
692 0 : nsCOMPtr<nsIWidget> w = mEvent->widget;
693 : nsEventStatus status;
694 0 : w->DispatchEvent(mEvent, status);
695 : }
696 0 : }
697 :
698 : protected:
699 0 : void Init(nsInputEvent* aEvent)
700 : {
701 0 : mEvent->time = aEvent->time;
702 0 : mEvent->refPoint = aEvent->refPoint;
703 0 : mEvent->isShift = aEvent->isShift;
704 0 : mEvent->isControl = aEvent->isControl;
705 0 : mEvent->isAlt = aEvent->isAlt;
706 0 : mEvent->isMeta = aEvent->isMeta;
707 0 : }
708 :
709 0 : nsDelayedInputEvent()
710 0 : : nsDelayedEvent(), mEvent(nsnull) {}
711 :
712 : nsInputEvent* mEvent;
713 : };
714 :
715 : class nsDelayedMouseEvent : public nsDelayedInputEvent
716 : {
717 : public:
718 0 : nsDelayedMouseEvent(nsMouseEvent* aEvent) : nsDelayedInputEvent()
719 : {
720 : mEvent = new nsMouseEvent(NS_IS_TRUSTED_EVENT(aEvent),
721 : aEvent->message,
722 : aEvent->widget,
723 : aEvent->reason,
724 0 : aEvent->context);
725 0 : Init(aEvent);
726 0 : static_cast<nsMouseEvent*>(mEvent)->clickCount = aEvent->clickCount;
727 0 : }
728 :
729 0 : virtual ~nsDelayedMouseEvent()
730 0 : {
731 0 : delete static_cast<nsMouseEvent*>(mEvent);
732 0 : }
733 : };
734 :
735 : class nsDelayedKeyEvent : public nsDelayedInputEvent
736 : {
737 : public:
738 0 : nsDelayedKeyEvent(nsKeyEvent* aEvent) : nsDelayedInputEvent()
739 : {
740 : mEvent = new nsKeyEvent(NS_IS_TRUSTED_EVENT(aEvent),
741 : aEvent->message,
742 0 : aEvent->widget);
743 0 : Init(aEvent);
744 0 : static_cast<nsKeyEvent*>(mEvent)->keyCode = aEvent->keyCode;
745 0 : static_cast<nsKeyEvent*>(mEvent)->charCode = aEvent->charCode;
746 : static_cast<nsKeyEvent*>(mEvent)->alternativeCharCodes =
747 0 : aEvent->alternativeCharCodes;
748 0 : static_cast<nsKeyEvent*>(mEvent)->isChar = aEvent->isChar;
749 0 : }
750 :
751 0 : virtual ~nsDelayedKeyEvent()
752 0 : {
753 0 : delete static_cast<nsKeyEvent*>(mEvent);
754 0 : }
755 : };
756 :
757 : bool mNoDelayedMouseEvents;
758 : bool mNoDelayedKeyEvents;
759 : nsTArray<nsAutoPtr<nsDelayedEvent> > mDelayedEvents;
760 :
761 : nsCallbackEventRequest* mFirstCallbackEventRequest;
762 : nsCallbackEventRequest* mLastCallbackEventRequest;
763 :
764 : bool mIsDocumentGone; // We've been disconnected from the document.
765 : // We will refuse to paint the document until either
766 : // (a) our timer fires or (b) all frames are constructed.
767 : bool mShouldUnsuppressPainting; // Indicates that it is safe to unlock painting once all pending
768 : // reflows have been processed.
769 : nsCOMPtr<nsITimer> mPaintSuppressionTimer; // This timer controls painting suppression. Until it fires
770 : // or all frames are constructed, we won't paint anything but
771 : // our <body> background and scrollbars.
772 : #define PAINTLOCK_EVENT_DELAY 250 // 250ms. This is actually
773 : // pref-controlled, but we use this
774 : // value if we fail to get the pref
775 : // for any reason.
776 :
777 : static void sPaintSuppressionCallback(nsITimer* aTimer, void* aPresShell); // A callback for the timer.
778 :
779 : // At least on Win32 and Mac after interupting a reflow we need to post
780 : // the resume reflow event off a timer to avoid event starvation because
781 : // posted messages are processed before other messages when the modal
782 : // moving/sizing loop is running, see bug 491700 for details.
783 : nsCOMPtr<nsITimer> mReflowContinueTimer;
784 : static void sReflowContinueCallback(nsITimer* aTimer, void* aPresShell);
785 : bool ScheduleReflowOffTimer();
786 :
787 : #ifdef MOZ_REFLOW_PERF
788 : ReflowCountMgr * mReflowCountMgr;
789 : #endif
790 :
791 : static bool sDisableNonTestMouseEvents;
792 :
793 : private:
794 :
795 : bool InZombieDocument(nsIContent *aContent);
796 : already_AddRefed<nsIPresShell> GetParentPresShell();
797 : nsresult RetargetEventToParent(nsGUIEvent* aEvent,
798 : nsEventStatus* aEventStatus);
799 :
800 : //helper funcs for event handling
801 : protected:
802 : //protected because nsPresShellEventCB needs this.
803 : nsIFrame* GetCurrentEventFrame();
804 : private:
805 : void PushCurrentEventInfo(nsIFrame* aFrame, nsIContent* aContent);
806 : void PopCurrentEventInfo();
807 : nsresult HandleEventInternal(nsEvent* aEvent, nsEventStatus *aStatus);
808 : nsresult HandlePositionedEvent(nsIFrame* aTargetFrame,
809 : nsGUIEvent* aEvent,
810 : nsEventStatus* aEventStatus);
811 : // This returns the focused DOM window under our top level window.
812 : // I.e., when we are deactive, this returns the *last* focused DOM window.
813 : already_AddRefed<nsPIDOMWindow> GetFocusedDOMWindowInOurWindow();
814 :
815 : /*
816 : * This and the next two helper methods are used to target and position the
817 : * context menu when the keyboard shortcut is used to open it.
818 : *
819 : * If another menu is open, the context menu is opened relative to the
820 : * active menuitem within the menu, or the menu itself if no item is active.
821 : * Otherwise, if the caret is visible, the menu is opened near the caret.
822 : * Otherwise, if a selectable list such as a listbox is focused, the
823 : * current item within the menu is opened relative to this item.
824 : * Otherwise, the context menu is opened at the topleft corner of the
825 : * view.
826 : *
827 : * Returns true if the context menu event should fire and false if it should
828 : * not.
829 : */
830 : bool AdjustContextMenuKeyEvent(nsMouseEvent* aEvent);
831 :
832 : //
833 : bool PrepareToUseCaretPosition(nsIWidget* aEventWidget, nsIntPoint& aTargetPt);
834 :
835 : // Get the selected item and coordinates in device pixels relative to root
836 : // document's root view for element, first ensuring the element is onscreen
837 : void GetCurrentItemAndPositionForElement(nsIDOMElement *aCurrentEl,
838 : nsIContent **aTargetToUse,
839 : nsIntPoint& aTargetPt,
840 : nsIWidget *aRootWidget);
841 :
842 : void FireResizeEvent();
843 : void FireBeforeResizeEvent();
844 : static void AsyncResizeEventCallback(nsITimer* aTimer, void* aPresShell);
845 : nsRevocableEventPtr<nsRunnableMethod<PresShell> > mResizeEvent;
846 : nsCOMPtr<nsITimer> mAsyncResizeEventTimer;
847 : bool mAsyncResizeTimerIsActive;
848 : bool mInResize;
849 :
850 : virtual void SynthesizeMouseMove(bool aFromScroll);
851 :
852 : // Check if aEvent is a mouse event and record the mouse location for later
853 : // synth mouse moves.
854 : void RecordMouseLocation(nsGUIEvent* aEvent);
855 : // This is used for synthetic mouse events that are sent when what is under
856 : // the mouse pointer may have changed without the mouse moving (eg scrolling,
857 : // change to the document contents).
858 : // It is set only on a presshell for a root document, this value represents
859 : // the last observed location of the mouse relative to that root document. It
860 : // is set to (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if the mouse isn't
861 : // over our window or there is no last observed mouse location for some
862 : // reason.
863 : nsPoint mMouseLocation;
864 : class nsSynthMouseMoveEvent : public nsARefreshObserver {
865 : public:
866 0 : nsSynthMouseMoveEvent(PresShell* aPresShell, bool aFromScroll)
867 0 : : mPresShell(aPresShell), mFromScroll(aFromScroll) {
868 0 : NS_ASSERTION(mPresShell, "null parameter");
869 0 : }
870 0 : ~nsSynthMouseMoveEvent() {
871 0 : Revoke();
872 0 : }
873 :
874 0 : NS_INLINE_DECL_REFCOUNTING(nsSynthMouseMoveEvent)
875 :
876 0 : void Revoke() {
877 0 : if (mPresShell) {
878 : mPresShell->GetPresContext()->RefreshDriver()->
879 0 : RemoveRefreshObserver(this, Flush_Display);
880 0 : mPresShell = nsnull;
881 : }
882 0 : }
883 0 : virtual void WillRefresh(mozilla::TimeStamp aTime) {
884 0 : if (mPresShell)
885 0 : mPresShell->ProcessSynthMouseMoveEvent(mFromScroll);
886 0 : }
887 : private:
888 : PresShell* mPresShell;
889 : bool mFromScroll;
890 : };
891 : nsRevocableEventPtr<nsSynthMouseMoveEvent> mSynthMouseMoveEvent;
892 : void ProcessSynthMouseMoveEvent(bool aFromScroll);
893 :
894 : PresShell* GetRootPresShell();
895 :
896 : private:
897 : #ifdef DEBUG
898 : // Ensure that every allocation from the PresArena is eventually freed.
899 : PRUint32 mPresArenaAllocCount;
900 : #endif
901 :
902 : public:
903 :
904 : void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
905 : size_t *aArenasSize,
906 : size_t *aStyleSetsSize,
907 : size_t *aTextRunsSize) const;
908 : size_t SizeOfTextRuns(nsMallocSizeOfFun aMallocSizeOf) const;
909 :
910 : protected:
911 : void QueryIsActive();
912 : nsresult UpdateImageLockingState();
913 :
914 : private:
915 : nscolor GetDefaultBackgroundColorToDraw();
916 : };
917 :
918 : #endif /* !defined(nsPresShell_h_) */
|