PresShell.cpp 398 KB
Newer Older
1
2
3
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6

7
8
/* a presentation of a document, part 2 */

9
#include "mozilla/PresShell.h"
10

11
#include "Units.h"
12
#include "mozilla/dom/FontFaceSet.h"
13
#include "mozilla/ArrayUtils.h"
14
#include "mozilla/Attributes.h"
15
#include "mozilla/AutoRestore.h"
16
#include "mozilla/ContentIterator.h"
17
#include "mozilla/EventDispatcher.h"
18
#include "mozilla/EventStateManager.h"
19
#include "mozilla/EventStates.h"
20
#include "mozilla/GeckoMVMContext.h"
21
#include "mozilla/IMEStateManager.h"
22
#include "mozilla/MemoryReporting.h"
23
#include "mozilla/dom/BrowserChild.h"
24
#include "mozilla/Likely.h"
25
#include "mozilla/Logging.h"
26
#include "mozilla/MouseEvents.h"
27
#include "mozilla/PerfStats.h"
28
#include "mozilla/PresShellInlines.h"
29
#include "mozilla/RangeUtils.h"
30
#include "mozilla/Sprintf.h"
31
32
#include "mozilla/StaticPrefs_apz.h"
#include "mozilla/StaticPrefs_dom.h"
33
#include "mozilla/StaticPrefs_font.h"
34
#include "mozilla/StaticPrefs_layout.h"
35
#include "mozilla/TextEvents.h"
36
#include "mozilla/TimeStamp.h"
37
#include "mozilla/TouchEvents.h"
38
#include "mozilla/UniquePtr.h"
39
#include "mozilla/Unused.h"
40
#include "mozilla/ViewportUtils.h"
41
#include <algorithm>
42

43
#ifdef XP_WIN
44
#  include "winuser.h"
45
46
#endif

47
#include "gfxContext.h"
48
#include "gfxUserFontSet.h"
49
#include "nsContentList.h"
50
#include "nsPresContext.h"
kipp's avatar
kipp committed
51
#include "nsIContent.h"
52
#include "mozilla/dom/BrowserBridgeChild.h"
53
#include "mozilla/dom/BrowsingContext.h"
54
#include "mozilla/dom/Element.h"
55
#include "mozilla/dom/PointerEventHandler.h"
56
#include "mozilla/dom/PopupBlocker.h"
57
#include "mozilla/dom/Document.h"
58
#include "mozilla/dom/DocumentInlines.h"
59
#include "mozilla/dom/UserActivation.h"
60
#include "nsAnimationManager.h"
61
#include "nsNameSpaceManager.h"  // for Pref-related rule management (bugs 22963,20760,31816)
62
#include "nsFlexContainerFrame.h"
kipp's avatar
kipp committed
63
#include "nsFrame.h"
64
#include "FrameLayerBuilder.h"
65
#include "nsViewManager.h"
66
#include "nsView.h"
67
#include "nsCRTGlue.h"
68
#include "prinrval.h"
69
#include "nsTArray.h"
70
#include "nsCOMArray.h"
71
#include "nsContainerFrame.h"
72
#include "mozilla/dom/Selection.h"
73
#include "nsGkAtoms.h"
74
#include "nsRange.h"
75
#include "nsWindowSizes.h"
76
#include "nsCOMPtr.h"
77
#include "nsReadableUtils.h"
78
#include "nsPageSequenceFrame.h"
79
#include "nsCaret.h"
80
#include "mozilla/AccessibleCaretEventHub.h"
81
#include "nsFrameManager.h"
82
#include "nsXPCOM.h"
83
#include "nsILayoutHistoryState.h"
84
#include "nsILineIterator.h"  // for ScrollContentIntoView
85
#include "PLDHashTable.h"
86
#include "mozilla/dom/Touch.h"
87
#include "mozilla/dom/TouchEvent.h"
88
#include "mozilla/dom/PointerEventBinding.h"
89
#include "mozilla/dom/ShadowIncludingTreeIterator.h"
90
#include "nsIObserverService.h"
91
#include "nsDocShell.h"  // for reflow observation
92
#include "nsIBaseWindow.h"
93
#include "nsError.h"
94
#include "nsLayoutUtils.h"
95
#include "nsViewportInfo.h"
96
#include "nsCSSRendering.h"
97
// for |#ifdef DEBUG| code
98
#include "prenv.h"
99
100
#include "nsDisplayList.h"
#include "nsRegion.h"
101
#include "nsAutoLayoutPhase.h"
102
#ifdef MOZ_GECKO_PROFILER
103
#  include "AutoProfilerStyleMarker.h"
104
#endif
105
#ifdef MOZ_REFLOW_PERF
106
#  include "nsFontMetrics.h"
107
#endif
108
#include "MobileViewportManager.h"
109
#include "OverflowChangedTracker.h"
110
#include "PositionedEventTargeting.h"
111

hyatt%netscape.com's avatar
hyatt%netscape.com committed
112
113
#include "nsIReflowCallback.h"

114
#include "nsPIDOMWindow.h"
115
#include "nsFocusManager.h"
116
#include "nsIObjectFrame.h"
117
#include "nsIObjectLoadingContent.h"
118
#include "nsNetUtil.h"
119
#include "nsThreadUtils.h"
120
#include "nsStyleSheetService.h"
121
#include "gfxUtils.h"
122
#include "mozilla/SMILAnimationController.h"
123
#include "SVGContentUtils.h"
124
#include "SVGObserverUtils.h"
125
#include "SVGFragmentIdentifier.h"
126
#include "nsFrameSelection.h"
127

128
#include "mozilla/dom/Performance.h"
129
#include "nsRefreshDriver.h"
130
#include "nsDOMNavigationTiming.h"
131

132
// Drag & Drop, Clipboard
133
#include "nsIDocShellTreeItem.h"
134
#include "nsIURI.h"
135
#include "nsIScrollableFrame.h"
136
#include "nsITimer.h"
137
#ifdef ACCESSIBILITY
138
139
140
141
142
#  include "nsAccessibilityService.h"
#  include "mozilla/a11y/DocAccessible.h"
#  ifdef DEBUG
#    include "mozilla/a11y/Logging.h"
#  endif
143
#endif
144

145
146
// For style data reconstruction
#include "nsStyleChangeList.h"
147
#include "nsCSSFrameConstructor.h"
148
#ifdef MOZ_XUL
149
150
151
152
153
154
155
156
157
#  include "nsMenuFrame.h"
#  include "nsTreeBodyFrame.h"
#  include "XULTreeElement.h"
#  include "nsMenuPopupFrame.h"
#  include "nsTreeColumns.h"
#  include "nsIDOMXULMultSelectCntrlEl.h"
#  include "nsIDOMXULSelectCntrlItemEl.h"
#  include "nsIDOMXULMenuListElement.h"
#  include "nsXULElement.h"
158
#endif  // MOZ_XUL
159

160
#include "mozilla/layers/CompositorBridgeChild.h"
161
#include "ClientLayerManager.h"
162
#include "GeckoProfiler.h"
163
#include "gfxPlatform.h"
164
#include "Layers.h"
165
#include "LayerTreeInvalidation.h"
166
#include "mozilla/css/ImageLoader.h"
167
#include "mozilla/dom/DocumentTimeline.h"
168
#include "mozilla/dom/ScriptSettings.h"
169
#include "mozilla/ErrorResult.h"
170
171
172
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"
#include "nsCanvasFrame.h"
173
#include "nsImageFrame.h"
174
175
176
177
#include "nsIScreen.h"
#include "nsIScreenManager.h"
#include "nsPlaceholderFrame.h"
#include "nsTransitionManager.h"
178
#include "ChildIterator.h"
179
#include "mozilla/RestyleManager.h"
180
#include "nsIDragSession.h"
181
#include "nsIFrameInlines.h"
182
#include "mozilla/gfx/2D.h"
183
#include "nsNetUtil.h"
184
#include "nsSubDocumentFrame.h"
185
#include "nsQueryObject.h"
186
#include "mozilla/GlobalStyleSheetCache.h"
187
#include "mozilla/layers/InputAPZContext.h"
188
#include "mozilla/layers/FocusTarget.h"
189
190
#include "mozilla/layers/WebRenderLayerManager.h"
#include "mozilla/layers/WebRenderUserData.h"
191
#include "mozilla/layout/ScrollAnchorContainer.h"
192
#include "mozilla/ScrollTypes.h"
193
#include "mozilla/ServoBindings.h"
194
#include "mozilla/ServoStyleSet.h"
195
196
#include "mozilla/StyleSheet.h"
#include "mozilla/StyleSheetInlines.h"
197
#include "mozilla/dom/ImageTracker.h"
198
#include "nsIDocShellTreeOwner.h"
199
200
#include "nsClassHashtable.h"
#include "nsHashKeys.h"
201
#include "VisualViewport.h"
202
#include "ZoomConstraintsClient.h"
203

204
#ifdef MOZ_TASK_TRACER
205
#  include "GeckoTaskTracer.h"
206
207
208
using namespace mozilla::tasktracer;
#endif

209
210
// define the scalfactor of drag and drop images
// relative to the max screen height/width
211
212
#define RELATIVE_SCALEFACTOR 0.0925f

213
using namespace mozilla;
214
using namespace mozilla::css;
215
using namespace mozilla::dom;
216
using namespace mozilla::gfx;
217
using namespace mozilla::layers;
218
using namespace mozilla::gfx;
219
using namespace mozilla::layout;
220
using PaintFrameFlags = nsLayoutUtils::PaintFrameFlags;
221
typedef ScrollableLayerGuid::ViewID ViewID;
222

223
PresShell::CapturingContentInfo PresShell::sCapturingContentInfo;
224

225
226
// RangePaintInfo is used to paint ranges to offscreen buffers
struct RangePaintInfo {
227
  RefPtr<nsRange> mRange;
228
229
230
231
232
233
  nsDisplayListBuilder mBuilder;
  nsDisplayList mList;

  // offset of builder's reference frame to the root frame
  nsPoint mRootOffset;

234
  RangePaintInfo(nsRange* aRange, nsIFrame* aFrame)
235
      : mRange(aRange),
236
        mBuilder(aFrame, nsDisplayListBuilderMode::Painting, false) {
237
    MOZ_COUNT_CTOR(RangePaintInfo);
238
    mBuilder.BeginFrame();
239
240
  }

241
  ~RangePaintInfo() {
242
    mList.DeleteAll(&mBuilder);
243
    mBuilder.EndFrame();
244
    MOZ_COUNT_DTOR(RangePaintInfo);
245
246
247
  }
};

kipp's avatar
kipp committed
248
249
#undef NOISY

250
251
// ----------------------------------------------------------------------

252
#ifdef DEBUG
253
254
255
// Set the environment variable GECKO_VERIFY_REFLOW_FLAGS to one or
// more of the following flags (comma separated) for handy debug
// output.
256
static VerifyReflowFlags gVerifyReflowFlags;
257

258
struct VerifyReflowFlagData {
259
  const char* name;
260
  VerifyReflowFlags bit;
261
262
};

263
static const VerifyReflowFlagData gFlags[] = {
264
    // clang-format off
265
266
267
268
269
270
271
  { "verify",                VerifyReflowFlags::On },
  { "reflow",                VerifyReflowFlags::Noisy },
  { "all",                   VerifyReflowFlags::All },
  { "list-commands",         VerifyReflowFlags::DumpCommands },
  { "noisy-commands",        VerifyReflowFlags::NoisyCommands },
  { "really-noisy-commands", VerifyReflowFlags::ReallyNoisyCommands },
  { "resize",                VerifyReflowFlags::DuringResizeReflow },
272
    // clang-format on
273
274
};

275
#  define NUM_VERIFY_REFLOW_FLAGS (sizeof(gFlags) / sizeof(gFlags[0]))
276

277
static void ShowVerifyReflowFlags() {
278
  printf("Here are the available GECKO_VERIFY_REFLOW_FLAGS:\n");
279
280
  const VerifyReflowFlagData* flag = gFlags;
  const VerifyReflowFlagData* limit = gFlags + NUM_VERIFY_REFLOW_FLAGS;
281
282
283
284
285
286
287
288
289
  while (flag < limit) {
    printf("  %s\n", flag->name);
    ++flag;
  }
  printf("Note: GECKO_VERIFY_REFLOW_FLAGS is a comma separated list of flag\n");
  printf("names (no whitespace)\n");
}
#endif

290
291
//========================================================================
//========================================================================
292
293
294
295
//========================================================================
#ifdef MOZ_REFLOW_PERF
class ReflowCountMgr;

296
static const char kGrandTotalsStr[] = "Grand Totals";
297
298
299

// Counting Class
class ReflowCounter {
300
301
 public:
  explicit ReflowCounter(ReflowCountMgr* aMgr = nullptr);
302
303
304
  ~ReflowCounter();

  void ClearTotals();
305
306
307
  void DisplayTotals(const char* aStr);
  void DisplayDiffTotals(const char* aStr);
  void DisplayHTMLTotals(const char* aStr);
308

309
  void Add() { mTotal++; }
310
  void Add(uint32_t aTotal) { mTotal += aTotal; }
311
312
313
314

  void CalcDiffInTotals();
  void SetTotalsCache();

315
  void SetMgr(ReflowCountMgr* aMgr) { mMgr = aMgr; }
316

317
  uint32_t GetTotal() { return mTotal; }
318

319
320
321
 protected:
  void DisplayTotals(uint32_t aTotal, const char* aTitle);
  void DisplayHTMLTotals(uint32_t aTotal, const char* aTitle);
322

323
324
  uint32_t mTotal;
  uint32_t mCacheTotal;
325

326
  ReflowCountMgr* mMgr;  // weak reference (don't delete)
327
328
};

329
330
// Counting Class
class IndiReflowCounter {
331
332
333
334
335
336
337
 public:
  explicit IndiReflowCounter(ReflowCountMgr* aMgr = nullptr)
      : mFrame(nullptr),
        mCount(0),
        mMgr(aMgr),
        mCounter(aMgr),
        mHasBeenOutput(false) {}
338
  virtual ~IndiReflowCounter() = default;
339
340

  nsAutoString mName;
341
342
  nsIFrame* mFrame;  // weak reference (don't delete)
  int32_t mCount;
343

344
  ReflowCountMgr* mMgr;  // weak reference (don't delete)
345
346

  ReflowCounter mCounter;
347
  bool mHasBeenOutput;
348
349
};

350
//--------------------
351
// Manager Class
352
//--------------------
353
class ReflowCountMgr {
354
 public:
355
  ReflowCountMgr();
356
  virtual ~ReflowCountMgr();
357
358

  void ClearTotals();
359
  void ClearGrandTotals();
360
361
  void DisplayTotals(const char* aStr);
  void DisplayHTMLTotals(const char* aStr);
362
  void DisplayDiffsInTotals();
363

364
365
  void Add(const char* aName, nsIFrame* aFrame);
  ReflowCounter* LookUp(const char* aName);
366

367
368
369
  void PaintCount(const char* aName, gfxContext* aRenderingContext,
                  nsPresContext* aPresContext, nsIFrame* aFrame,
                  const nsPoint& aOffset, uint32_t aColor);
370

371
  FILE* GetOutFile() { return mFD; }
372

373
  void SetPresContext(nsPresContext* aPresContext) {
374
375
    mPresContext = aPresContext;  // weak reference
  }
376
  void SetPresShell(PresShell* aPresShell) {
377
378
    mPresShell = aPresShell;  // weak reference
  }
379

380
381
382
  void SetDumpFrameCounts(bool aVal) { mDumpFrameCounts = aVal; }
  void SetDumpFrameByFrameCounts(bool aVal) { mDumpFrameByFrameCounts = aVal; }
  void SetPaintFrameCounts(bool aVal) { mPaintFrameByFrameCounts = aVal; }
383

384
  bool IsPaintingFrameCounts() { return mPaintFrameByFrameCounts; }
385

386
387
388
 protected:
  void DisplayTotals(uint32_t aTotal, uint32_t* aDupArray, char* aTitle);
  void DisplayHTMLTotals(uint32_t aTotal, uint32_t* aDupArray, char* aTitle);
389
390

  void DoGrandTotals();
391
  void DoIndiTotalsTree();
392
393
394
395

  // HTML Output Methods
  void DoGrandHTMLTotals();

396
397
  nsClassHashtable<nsCharPtrHashKey, ReflowCounter> mCounts;
  nsClassHashtable<nsCharPtrHashKey, IndiReflowCounter> mIndiFrameCounts;
398
  FILE* mFD;
399

400
401
402
  bool mDumpFrameCounts;
  bool mDumpFrameByFrameCounts;
  bool mPaintFrameByFrameCounts;
403

404
  bool mCycledOnce;
405

406
  // Root Frame for Individual Tracking
407
  nsPresContext* mPresContext;
408
  PresShell* mPresShell;
409

410
411
412
413
414
  // ReflowCountMgr gReflowCountMgr;
};
#endif
//========================================================================

415
// comment out to hide caret
416
#define SHOW_CARET
417

418
419
420
421
422
423
// The upper bound on the amount of time to spend reflowing, in
// microseconds.  When this bound is exceeded and reflow commands are
// still queued up, a reflow event is posted.  The idea is for reflow
// to not hog the processor beyond the time specifed in
// gMaxRCProcessingTime.  This data member is initialized from the
// layout.reflow.timeslice pref.
424
#define NS_MAX_REFLOW_TIME 1000000
425
static int32_t gMaxRCProcessingTime = -1;
nisheeth%netscape.com's avatar
nisheeth%netscape.com committed
426

427
struct nsCallbackEventRequest {
hyatt%netscape.com's avatar
hyatt%netscape.com committed
428
429
430
431
  nsIReflowCallback* callback;
  nsCallbackEventRequest* next;
};

432
// ----------------------------------------------------------------------------
433
434
435
436
437
//
// NOTE(emilio): It'd be nice for this to assert that our document isn't in the
// bfcache, but font pref changes don't care about that, and maybe / probably
// shouldn't.
#ifdef DEBUG
438
439
440
441
442
443
444
445
446
447
448
449
#  define ASSERT_REFLOW_SCHEDULED_STATE()                                   \
    {                                                                       \
      if (ObservingLayoutFlushes()) {                                       \
        MOZ_ASSERT(                                                         \
            mDocument->GetBFCacheEntry() ||                                 \
                mPresContext->RefreshDriver()->IsLayoutFlushObserver(this), \
            "Unexpected state");                                            \
      } else {                                                              \
        MOZ_ASSERT(                                                         \
            !mPresContext->RefreshDriver()->IsLayoutFlushObserver(this),    \
            "Unexpected state");                                            \
      }                                                                     \
450
    }
451
#else
452
#  define ASSERT_REFLOW_SCHEDULED_STATE() /* nothing */
453
#endif
454

455
456
class nsAutoCauseReflowNotifier {
 public:
457
  MOZ_CAN_RUN_SCRIPT explicit nsAutoCauseReflowNotifier(PresShell* aPresShell)
458
459
      : mPresShell(aPresShell) {
    mPresShell->WillCauseReflow();
Olli Pettay's avatar
Olli Pettay committed
460
  }
461
  MOZ_CAN_RUN_SCRIPT ~nsAutoCauseReflowNotifier() {
Olli Pettay's avatar
Olli Pettay committed
462
463
    // This check should not be needed. Currently the only place that seem
    // to need it is the code that deals with bug 337586.
464
    if (!mPresShell->mHaveShutDown) {
465
466
      RefPtr<PresShell> presShell(mPresShell);
      presShell->DidCauseReflow();
467
    } else {
Olli Pettay's avatar
Olli Pettay committed
468
469
470
471
      nsContentUtils::RemoveScriptBlocker();
    }
  }

472
  PresShell* mPresShell;
Olli Pettay's avatar
Olli Pettay committed
473
474
};

475
476
class MOZ_STACK_CLASS nsPresShellEventCB : public EventDispatchingCallback {
 public:
477
  explicit nsPresShellEventCB(PresShell* aPresShell) : mPresShell(aPresShell) {}
478

479
  MOZ_CAN_RUN_SCRIPT
480
  virtual void HandleEvent(EventChainPostVisitor& aVisitor) override {
481
    if (aVisitor.mPresContext && aVisitor.mEvent->mClass != eBasicEventClass) {
482
      if (aVisitor.mEvent->mMessage == eMouseDown ||
483
          aVisitor.mEvent->mMessage == eMouseUp) {
484
        // Mouse-up and mouse-down events call nsFrame::HandlePress/Release
485
486
487
        // which call GetContentOffsetsFromPoint which requires up-to-date
        // layout. Bring layout up-to-date now so that GetCurrentEventFrame()
        // below will return a real frame and we don't have to worry about
488
        // destroying it by flushing later.
489
        MOZ_KnownLive(mPresShell)->FlushPendingNotifications(FlushType::Layout);
490
      } else if (aVisitor.mEvent->mMessage == eWheel &&
491
492
493
494
495
496
497
                 aVisitor.mEventStatus != nsEventStatus_eConsumeNoDefault) {
        nsIFrame* frame = mPresShell->GetCurrentEventFrame();
        if (frame) {
          // chrome (including addons) should be able to know if content
          // handles both D3E "wheel" event and legacy mouse scroll events.
          // We should dispatch legacy mouse events before dispatching the
          // "wheel" event into system group.
498
          RefPtr<EventStateManager> esm =
499
500
501
              aVisitor.mPresContext->EventStateManager();
          esm->DispatchLegacyMouseScrollEvents(
              frame, aVisitor.mEvent->AsWheelEvent(), &aVisitor.mEventStatus);
502
        }
503
      }
504
      nsIFrame* frame = mPresShell->GetCurrentEventFrame();
505
506
      if (!frame && (aVisitor.mEvent->mMessage == eMouseUp ||
                     aVisitor.mEvent->mMessage == eTouchEnd)) {
507
508
509
510
        // Redirect BUTTON_UP and TOUCH_END events to the root frame to ensure
        // that capturing is released.
        frame = mPresShell->GetRootFrame();
      }
511
      if (frame) {
512
513
        frame->HandleEvent(MOZ_KnownLive(aVisitor.mPresContext),
                           aVisitor.mEvent->AsGUIEvent(),
514
515
516
517
518
                           &aVisitor.mEventStatus);
      }
    }
  }

519
  RefPtr<PresShell> mPresShell;
520
521
};

522
523
class nsBeforeFirstPaintDispatcher : public Runnable {
 public:
524
  explicit nsBeforeFirstPaintDispatcher(Document* aDocument)
525
526
      : mozilla::Runnable("nsBeforeFirstPaintDispatcher"),
        mDocument(aDocument) {}
527

528
529
530
  // Fires the "before-first-paint" event so that interested parties (right now,
  // the mobile browser) are aware of it.
  NS_IMETHOD Run() override {
531
    nsCOMPtr<nsIObserverService> observerService =
532
        mozilla::services::GetObserverService();
533
    if (observerService) {
534
535
      observerService->NotifyObservers(ToSupports(mDocument),
                                       "before-first-paint", nullptr);
536
537
538
539
    }
    return NS_OK;
  }

540
 private:
541
  RefPtr<Document> mDocument;
542
543
};

544
545
546
// This is a helper class to track whether the targeted frame is destroyed after
// dispatching pointer events. In that case, we need the original targeted
// content so that we can dispatch the mouse events to it.
547
548
549
550
class MOZ_STACK_CLASS AutoPointerEventTargetUpdater final {
 public:
  AutoPointerEventTargetUpdater(PresShell* aShell, WidgetEvent* aEvent,
                                nsIFrame* aFrame, nsIContent** aTargetContent) {
551
552
    MOZ_ASSERT(aEvent);
    if (!aTargetContent || aEvent->mClass != ePointerEventClass) {
553
554
      // Make the destructor happy.
      mTargetContent = nullptr;
555
556
      return;
    }
557
558
    MOZ_ASSERT(aShell);
    MOZ_ASSERT(aFrame);
559
560
561
    MOZ_ASSERT(!aFrame->GetContent() ||
               aShell->GetDocument() == aFrame->GetContent()->OwnerDoc());

562
    MOZ_ASSERT(StaticPrefs::dom_w3c_pointer_events_enabled());
563
564
565
566
567
568
    mShell = aShell;
    mWeakFrame = aFrame;
    mTargetContent = aTargetContent;
    aShell->mPointerEventTarget = aFrame->GetContent();
  }

569
  ~AutoPointerEventTargetUpdater() {
570
571
572
573
574
575
    if (!mTargetContent || !mShell || mWeakFrame.IsAlive()) {
      return;
    }
    mShell->mPointerEventTarget.swap(*mTargetContent);
  }

576
 private:
577
578
579
580
581
  RefPtr<PresShell> mShell;
  AutoWeakFrame mWeakFrame;
  nsIContent** mTargetContent;
};

582
void PresShell::DirtyRootsList::Add(nsIFrame* aFrame) {
583
584
585
586
587
588
589
590
591
  // Is this root already scheduled for reflow?
  // FIXME: This could possibly be changed to a uniqueness assertion, with some
  // work in ResizeReflowIgnoreOverride (and maybe others?)
  if (mList.Contains(aFrame)) {
    // We don't expect frame to change depths.
    MOZ_ASSERT(aFrame->GetDepthInFrameTree() ==
               mList[mList.IndexOf(aFrame)].mDepth);
    return;
  }
592

593
594
595
  mList.InsertElementSorted(
      FrameAndDepth{aFrame, aFrame->GetDepthInFrameTree()},
      FrameAndDepth::CompareByReverseDepth{});
596
597
}

598
void PresShell::DirtyRootsList::Remove(nsIFrame* aFrame) {
599
  mList.RemoveElement(aFrame);
600
601
}

602
nsIFrame* PresShell::DirtyRootsList::PopShallowestRoot() {
603
604
605
606
607
608
609
610
  // List is sorted in order of decreasing depth, so there are no deeper
  // frames than the last one.
  const FrameAndDepth& lastFAD = mList.LastElement();
  nsIFrame* frame = lastFAD.mFrame;
  // We don't expect frame to change depths.
  MOZ_ASSERT(frame->GetDepthInFrameTree() == lastFAD.mDepth);
  mList.RemoveLastElement();
  return frame;
611
612
}

613
void PresShell::DirtyRootsList::Clear() { mList.Clear(); }
614

615
bool PresShell::DirtyRootsList::Contains(nsIFrame* aFrame) const {
616
617
618
  return mList.Contains(aFrame);
}

619
bool PresShell::DirtyRootsList::IsEmpty() const { return mList.IsEmpty(); }
620

621
bool PresShell::DirtyRootsList::FrameIsAncestorOfDirtyRoot(
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
    nsIFrame* aFrame) const {
  MOZ_ASSERT(aFrame);

  // Look for a path from any dirty roots to aFrame, following GetParent().
  // This check mirrors what FrameNeedsReflow() would have done if the reflow
  // root didn't get in the way.
  for (nsIFrame* dirtyFrame : mList) {
    do {
      if (dirtyFrame == aFrame) {
        return true;
      }
      dirtyFrame = dirtyFrame->GetParent();
    } while (dirtyFrame);
  }

  return false;
}
639

640
bool PresShell::sDisableNonTestMouseEvents = false;
641

642
LazyLogModule PresShell::gLog("PresShell");
643

644
645
TimeStamp PresShell::EventHandler::sLastInputCreated;
TimeStamp PresShell::EventHandler::sLastInputProcessed;
646
StaticRefPtr<Element> PresShell::EventHandler::sLastKeyDownEventTargetElement;
647

648
649
bool PresShell::sProcessInteractable = false;

650
static bool gVerifyReflowEnabled;
651

652
bool PresShell::GetVerifyReflowEnable() {
653
#ifdef DEBUG
654
  static bool firstTime = true;
655
  if (firstTime) {
656
    firstTime = false;
657
658
    char* flags = PR_GetEnv("GECKO_VERIFY_REFLOW_FLAGS");
    if (flags) {
659
      bool error = false;
660
661
662

      for (;;) {
        char* comma = PL_strchr(flags, ',');
663
        if (comma) *comma = '\0';
664

665
        bool found = false;
666
667
        const VerifyReflowFlagData* flag = gFlags;
        const VerifyReflowFlagData* limit = gFlags + NUM_VERIFY_REFLOW_FLAGS;
668
669
670
        while (flag < limit) {
          if (PL_strcasecmp(flag->name, flags) == 0) {
            gVerifyReflowFlags |= flag->bit;
671
            found = true;
672
673
674
675
676
            break;
          }
          ++flag;
        }

677
        if (!found) error = true;
678

679
        if (!comma) break;
680
681
682
683
684

        *comma = ',';
        flags = comma + 1;
      }

685
      if (error) ShowVerifyReflowFlags();
686
687
    }

688
    if (VerifyReflowFlags::On & gVerifyReflowFlags) {
689
      gVerifyReflowEnabled = true;
690
691

      printf("Note: verifyreflow is enabled");
692
      if (VerifyReflowFlags::Noisy & gVerifyReflowFlags) {
693
694
        printf(" (noisy)");
      }
695
      if (VerifyReflowFlags::All & gVerifyReflowFlags) {
696
697
        printf(" (all)");
      }
698
      if (VerifyReflowFlags::DumpCommands & gVerifyReflowFlags) {
699
700
        printf(" (show reflow commands)");
      }
701
      if (VerifyReflowFlags::NoisyCommands & gVerifyReflowFlags) {
702
        printf(" (noisy reflow commands)");
703
        if (VerifyReflowFlags::ReallyNoisyCommands & gVerifyReflowFlags) {
704
705
          printf(" (REALLY noisy reflow commands)");
        }
706
      }
707
      printf("\n");
708
    }
kipp's avatar
kipp committed
709
710
  }
#endif
711
  return gVerifyReflowEnabled;
kipp's avatar
kipp committed
712
}
713

714
void PresShell::SetVerifyReflowEnable(bool aEnabled) {
715
  gVerifyReflowEnabled = aEnabled;
kipp's avatar
kipp committed
716
717
}

718
void PresShell::AddAutoWeakFrame(AutoWeakFrame* aWeakFrame) {
719
720
721
722
723
724
725
  if (aWeakFrame->GetFrame()) {
    aWeakFrame->GetFrame()->AddStateBits(NS_FRAME_EXTERNAL_REFERENCE);
  }
  aWeakFrame->SetPreviousWeakFrame(mAutoWeakFrames);
  mAutoWeakFrames = aWeakFrame;
}

726
void PresShell::AddWeakFrame(WeakFrame* aWeakFrame) {
727
728
729
  if (aWeakFrame->GetFrame()) {
    aWeakFrame->GetFrame()->AddStateBits(NS_FRAME_EXTERNAL_REFERENCE);
  }
730
731
  MOZ_ASSERT(!mWeakFrames.GetEntry(aWeakFrame));
  mWeakFrames.PutEntry(aWeakFrame);
732
733
}

734
void PresShell::RemoveAutoWeakFrame(AutoWeakFrame* aWeakFrame) {
735
736
  if (mAutoWeakFrames == aWeakFrame) {
    mAutoWeakFrames = aWeakFrame->GetPreviousWeakFrame();
737
738
    return;
  }
739
  AutoWeakFrame* nextWeak = mAutoWeakFrames;
740
741
742
743
744
745
746
747
  while (nextWeak && nextWeak->GetPreviousWeakFrame() != aWeakFrame) {
    nextWeak = nextWeak->GetPreviousWeakFrame();
  }
  if (nextWeak) {
    nextWeak->SetPreviousWeakFrame(aWeakFrame->GetPreviousWeakFrame());
  }
}

748
void PresShell::RemoveWeakFrame(WeakFrame* aWeakFrame) {