Attachment #805978: Frame manager support for display:contents for bug #907396

View | Details | Raw Unified | Return to bug 907396
Collapse All | Expand All

(-)a/layout/base/nsFrameManager.cpp (-4 / +162 lines)
Line     Link Here 
 Lines 34-51    Link Here 
34
#include "ChildIterator.h"
34
#include "ChildIterator.h"
35
35
36
#include "nsFrameManager.h"
36
#include "nsFrameManager.h"
37
#include "GeckoProfiler.h"
37
#include "GeckoProfiler.h"
38
#include "nsIStatefulFrame.h"
38
#include "nsIStatefulFrame.h"
39
39
40
  #ifdef DEBUG
40
  #ifdef DEBUG
41
    //#define DEBUG_UNDISPLAYED_MAP
41
    //#define DEBUG_UNDISPLAYED_MAP
42
    //#define DEBUG_DISPLAYCONTENTS_MAP
42
  #else
43
  #else
43
    #undef DEBUG_UNDISPLAYED_MAP
44
    #undef DEBUG_UNDISPLAYED_MAP
45
    #undef DEBUG_DISPLAYCONTENTS_MAP
44
  #endif
46
  #endif
45
47
46
using namespace mozilla;
48
using namespace mozilla;
47
using namespace mozilla::dom;
49
using namespace mozilla::dom;
48
50
49
//----------------------------------------------------------------------
51
//----------------------------------------------------------------------
50
52
51
struct PlaceholderMapEntry : public PLDHashEntryHdr {
53
struct PlaceholderMapEntry : public PLDHashEntryHdr {
 Lines 90-105   public: Link Here 
90
92
91
  NS_HIDDEN_(nsresult) AddNodeFor(nsIContent* aParentContent,
93
  NS_HIDDEN_(nsresult) AddNodeFor(nsIContent* aParentContent,
92
                                  nsIContent* aChild, nsStyleContext* aStyle);
94
                                  nsIContent* aChild, nsStyleContext* aStyle);
93
95
94
  NS_HIDDEN_(void) RemoveNodeFor(nsIContent* aParentContent,
96
  NS_HIDDEN_(void) RemoveNodeFor(nsIContent* aParentContent,
95
                                 UndisplayedNode* aNode);
97
                                 UndisplayedNode* aNode);
96
98
97
  NS_HIDDEN_(void) RemoveNodesFor(nsIContent* aParentContent);
99
  NS_HIDDEN_(void) RemoveNodesFor(nsIContent* aParentContent);
100
  NS_HIDDEN_(UndisplayedNode*) UnlinkNodesFor(nsIContent* aParentContent);
98
101
99
  // Removes all entries from the hash table
102
  // Removes all entries from the hash table
100
  NS_HIDDEN_(void)  Clear(void);
103
  NS_HIDDEN_(void)  Clear(void);
101
104
102
protected:
105
protected:
103
  /**
106
  /**
104
   * Gets the entry for the provided parent content. If the content
107
   * Gets the entry for the provided parent content. If the content
105
   * is a <xbl:children> element, |**aParentContent| is set to
108
   * is a <xbl:children> element, |**aParentContent| is set to
 Lines 133-148   nsFrameManager::Destroy() Link Here 
133
136
134
  if (mRootFrame) {
137
  if (mRootFrame) {
135
    mRootFrame->Destroy();
138
    mRootFrame->Destroy();
136
    mRootFrame = nullptr;
139
    mRootFrame = nullptr;
137
  }
140
  }
138
  
141
  
139
  delete mUndisplayedMap;
142
  delete mUndisplayedMap;
140
  mUndisplayedMap = nullptr;
143
  mUndisplayedMap = nullptr;
144
  delete mDisplayContentsMap;
145
  mDisplayContentsMap = nullptr;
141
146
142
  mPresShell = nullptr;
147
  mPresShell = nullptr;
143
}
148
}
144
149
145
//----------------------------------------------------------------------
150
//----------------------------------------------------------------------
146
151
147
// Placeholder frame functions
152
// Placeholder frame functions
148
nsPlaceholderFrame*
153
nsPlaceholderFrame*
 Lines 318-333   nsFrameManager::ClearUndisplayedContentI Link Here 
318
        nsStyleContext *context = GetUndisplayedContent(aContent);
323
        nsStyleContext *context = GetUndisplayedContent(aContent);
319
        NS_ASSERTION(context == nullptr, "Found more undisplayed content data after removal");
324
        NS_ASSERTION(context == nullptr, "Found more undisplayed content data after removal");
320
#endif
325
#endif
321
        return;
326
        return;
322
      }
327
      }
323
      node = node->mNext;
328
      node = node->mNext;
324
    }
329
    }
325
  }
330
  }
331
#ifdef DEBUG_UNDISPLAYED_MAP
332
  printf( "not found.\n");
333
#endif
326
}
334
}
327
335
328
void
336
void
329
nsFrameManager::ClearAllUndisplayedContentIn(nsIContent* aParentContent)
337
nsFrameManager::ClearAllUndisplayedContentIn(nsIContent* aParentContent)
330
{
338
{
331
#ifdef DEBUG_UNDISPLAYED_MAP
339
#ifdef DEBUG_UNDISPLAYED_MAP
332
  static int i = 0;
340
  static int i = 0;
333
  printf("ClearAllUndisplayedContentIn(%d): parent=%p \n", i++, (void*)aParentContent);
341
  printf("ClearAllUndisplayedContentIn(%d): parent=%p \n", i++, (void*)aParentContent);
 Lines 345-360   nsFrameManager::ClearAllUndisplayedConte Link Here 
345
  for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
353
  for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
346
    if (child->GetParent() != aParentContent) {
354
    if (child->GetParent() != aParentContent) {
347
      ClearUndisplayedContentIn(child, child->GetParent());
355
      ClearUndisplayedContentIn(child, child->GetParent());
348
    }
356
    }
349
  }
357
  }
350
}
358
}
351
359
352
//----------------------------------------------------------------------
360
//----------------------------------------------------------------------
361
362
nsStyleContext*
363
nsFrameManager::GetDisplayContents(nsIContent* aContent)
364
{
365
  if (!aContent || !mDisplayContentsMap) {
366
    return nullptr;
367
  }
368
  nsIContent* parent = aContent->GetParent();
369
  for (UndisplayedNode* node = mDisplayContentsMap->GetFirstNode(parent);
370
         node; node = node->mNext) {
371
    if (node->mContent == aContent) {
372
      return node->mStyle;
373
    }
374
  }
375
  return nullptr;
376
}
377
378
UndisplayedNode*
379
nsFrameManager::GetAllDisplayContentsIn(nsIContent* aParentContent)
380
{
381
  return mDisplayContentsMap ? mDisplayContentsMap->GetFirstNode(aParentContent)
382
    : nullptr;
383
}
384
385
void
386
nsFrameManager::SetDisplayContents(nsIContent* aContent, 
387
                                   nsStyleContext* aStyleContext)
388
{
389
  NS_PRECONDITION(!aStyleContext->GetPseudo(),
390
                  "Should only have actual elements here");
391
392
#ifdef DEBUG_DISPLAYCONTENTS_MAP
393
  static int i = 0;
394
  printf("SetDisplayContents(%d): aContent=%p \n", i++, (void *)aContent);
395
#endif
396
397
  NS_ASSERTION(!GetDisplayContents(aContent),
398
               "Already have an undisplayed context entry for aContent");
399
400
  if (!mDisplayContentsMap) {
401
    mDisplayContentsMap = new UndisplayedMap;
402
  }
403
  nsIContent* parent = aContent->GetParent();
404
  NS_ASSERTION(parent || (mPresShell && mPresShell->GetDocument() &&
405
               mPresShell->GetDocument()->GetRootElement() == aContent),
406
               "undisplayed content must have a parent, unless it's the root "
407
               "element");
408
  mDisplayContentsMap->AddNodeFor(parent, aContent, aStyleContext);
409
}
410
411
void
412
nsFrameManager::ChangeDisplayContents(nsIContent* aContent, 
413
                                      nsStyleContext* aStyleContext)
414
{
415
  NS_ASSERTION(mDisplayContentsMap, "no existing display:contents content");
416
  
417
#ifdef DEBUG_DISPLAYCONTENTS_MAP
418
   static int i = 0;
419
   printf("ChangeDisplayContents(%d): aContent=%p \n", i++, (void *)aContent);
420
#endif
421
422
  for (UndisplayedNode* node = mDisplayContentsMap->GetFirstNode(aContent->GetParent());
423
         node; node = node->mNext) {
424
    if (node->mContent == aContent) {
425
      node->mStyle = aStyleContext;
426
      return;
427
    }
428
  }
429
430
  NS_NOTREACHED("no existing display:contents content");
431
}
432
433
void
434
nsFrameManager::ClearDisplayContentsIn(nsIContent* aContent,
435
                                       nsIContent* aParentContent)
436
{
437
#ifdef DEBUG_DISPLAYCONTENTS_MAP
438
  static int i = 0;
439
  printf("ClearDisplayContents(%d): content=%p parent=%p --> ", i++, (void *)aContent, (void*)aParentContent);
440
#endif
441
  
442
  if (mDisplayContentsMap) {
443
    UndisplayedNode* node = mDisplayContentsMap->GetFirstNode(aParentContent);
444
    while (node) {
445
      if (node->mContent == aContent) {
446
        mDisplayContentsMap->RemoveNodeFor(aParentContent, node);
447
448
#ifdef DEBUG_DISPLAYCONTENTS_MAP
449
        printf( "REMOVED!\n");
450
#endif
451
#ifdef DEBUG
452
        // make sure that there are no more entries for the same content
453
        nsStyleContext* context = GetDisplayContents(aContent);
454
        NS_ASSERTION(context == nullptr, "Found more entries for aContent after removal");
455
#endif
456
        ClearAllDisplayContentsIn(aContent);
457
        ClearAllUndisplayedContentIn(aContent);
458
        return;
459
      }
460
      node = node->mNext;
461
    }
462
  }
463
#ifdef DEBUG_DISPLAYCONTENTS_MAP
464
  printf( "not found.\n");
465
#endif
466
}
467
468
void
469
nsFrameManager::ClearAllDisplayContentsIn(nsIContent* aParentContent)
470
{
471
#ifdef DEBUG_DISPLAYCONTENTS_MAP
472
  static int i = 0;
473
  printf("ClearAllDisplayContentsIn(%d): parent=%p \n", i++, (void*)aParentContent);
474
#endif
475
476
  if (mDisplayContentsMap) {
477
    UndisplayedNode* cur = mDisplayContentsMap->UnlinkNodesFor(aParentContent);
478
    while (cur) {
479
      UndisplayedNode* next = cur->mNext;
480
      cur->mNext = nullptr;
481
      ClearAllDisplayContentsIn(cur->mContent);
482
      ClearAllUndisplayedContentIn(cur->mContent);
483
      delete cur;
484
      cur = next;
485
    }
486
  }
487
488
  // Need to look at aParentContent's content list due to XBL insertions.
489
  // Nodes in aParentContent's content list do not have aParentContent as a
490
  // parent, but are treated as children of aParentContent. We iterate over
491
  // the flattened content list and just ignore any nodes we don't care about.
492
  FlattenedChildIterator iter(aParentContent);
493
  for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
494
    if (child->GetParent() != aParentContent) {
495
      ClearDisplayContentsIn(child, child->GetParent());
496
      ClearUndisplayedContentIn(child, child->GetParent());
497
    }
498
  }
499
}
500
501
//----------------------------------------------------------------------
353
nsresult
502
nsresult
354
nsFrameManager::AppendFrames(nsIFrame*       aParentFrame,
503
nsFrameManager::AppendFrames(nsIFrame*       aParentFrame,
355
                             ChildListID     aListID,
504
                             ChildListID     aListID,
356
                             nsFrameList&    aFrameList)
505
                             nsFrameList&    aFrameList)
357
{
506
{
358
  if (aParentFrame->IsAbsoluteContainer() &&
507
  if (aParentFrame->IsAbsoluteContainer() &&
359
      aListID == aParentFrame->GetAbsoluteListID()) {
508
      aListID == aParentFrame->GetAbsoluteListID()) {
360
    return aParentFrame->GetAbsoluteContainingBlock()->
509
    return aParentFrame->GetAbsoluteContainingBlock()->
 Lines 424-439   nsFrameManager::RemoveFrame(ChildListID Link Here 
424
//----------------------------------------------------------------------
573
//----------------------------------------------------------------------
425
574
426
void
575
void
427
nsFrameManager::NotifyDestroyingFrame(nsIFrame* aFrame)
576
nsFrameManager::NotifyDestroyingFrame(nsIFrame* aFrame)
428
{
577
{
429
  nsIContent* content = aFrame->GetContent();
578
  nsIContent* content = aFrame->GetContent();
430
  if (content && content->GetPrimaryFrame() == aFrame) {
579
  if (content && content->GetPrimaryFrame() == aFrame) {
431
    ClearAllUndisplayedContentIn(content);
580
    ClearAllUndisplayedContentIn(content);
581
    ClearAllDisplayContentsIn(content);
432
  }
582
  }
433
}
583
}
434
584
435
// Capture state for a given frame.
585
// Capture state for a given frame.
436
// Accept a content id here, in some cases we may not have content (scroll position)
586
// Accept a content id here, in some cases we may not have content (scroll position)
437
void
587
void
438
nsFrameManager::CaptureFrameStateFor(nsIFrame* aFrame,
588
nsFrameManager::CaptureFrameStateFor(nsIFrame* aFrame,
439
                                     nsILayoutHistoryState* aState)
589
                                     nsILayoutHistoryState* aState)
 Lines 700-727   nsFrameManagerBase::UndisplayedMap::Remo Link Here 
700
        }
850
        }
701
        node = node->mNext;
851
        node = node->mNext;
702
      }
852
      }
703
    }
853
    }
704
  }
854
  }
705
  delete aNode;
855
  delete aNode;
706
}
856
}
707
857
708
void
858
709
nsFrameManagerBase::UndisplayedMap::RemoveNodesFor(nsIContent* aParentContent)
859
UndisplayedNode*
860
nsFrameManagerBase::UndisplayedMap::UnlinkNodesFor(nsIContent* aParentContent)
710
{
861
{
711
  PLHashEntry** entry = GetEntryFor(&aParentContent);
862
  PLHashEntry** entry = GetEntryFor(&aParentContent);
712
  NS_ASSERTION(entry, "content not in map");
863
  NS_ASSERTION(entry, "content not in map");
713
  if (*entry) {
864
  if (*entry) {
714
    UndisplayedNode*  node = (UndisplayedNode*)((*entry)->value);
865
    UndisplayedNode* node = (UndisplayedNode*)((*entry)->value);
715
    NS_ASSERTION(node, "null node for non-null entry in UndisplayedMap");
866
    NS_ASSERTION(node, "null node for non-null entry in UndisplayedMap");
716
    delete node;
717
    PL_HashTableRawRemove(mTable, entry, *entry);
867
    PL_HashTableRawRemove(mTable, entry, *entry);
718
    mLastLookup = nullptr; // hashtable may have shifted bucket out from under us
868
    mLastLookup = nullptr; // hashtable may have shifted bucket out from under us
869
    return node;
719
  }
870
  }
871
  return nullptr;
872
}
873
874
void
875
nsFrameManagerBase::UndisplayedMap::RemoveNodesFor(nsIContent* aParentContent)
876
{
877
  delete UnlinkNodesFor(aParentContent);
720
}
878
}
721
879
722
static int
880
static int
723
RemoveUndisplayedEntry(PLHashEntry* he, int i, void* arg)
881
RemoveUndisplayedEntry(PLHashEntry* he, int i, void* arg)
724
{
882
{
725
  UndisplayedNode*  node = (UndisplayedNode*)(he->value);
883
  UndisplayedNode*  node = (UndisplayedNode*)(he->value);
726
  delete node;
884
  delete node;
727
  // Remove and free this entry and continue enumerating
885
  // Remove and free this entry and continue enumerating
(-)a/layout/base/nsFrameManager.h (+12 lines)
Line     Link Here 
 Lines 105-120   public: Link Here 
105
  NS_HIDDEN_(void) SetUndisplayedContent(nsIContent* aContent,
105
  NS_HIDDEN_(void) SetUndisplayedContent(nsIContent* aContent,
106
                                         nsStyleContext* aStyleContext);
106
                                         nsStyleContext* aStyleContext);
107
  NS_HIDDEN_(void) ChangeUndisplayedContent(nsIContent* aContent,
107
  NS_HIDDEN_(void) ChangeUndisplayedContent(nsIContent* aContent,
108
                                            nsStyleContext* aStyleContext);
108
                                            nsStyleContext* aStyleContext);
109
  NS_HIDDEN_(void) ClearUndisplayedContentIn(nsIContent* aContent,
109
  NS_HIDDEN_(void) ClearUndisplayedContentIn(nsIContent* aContent,
110
                                             nsIContent* aParentContent);
110
                                             nsIContent* aParentContent);
111
  NS_HIDDEN_(void) ClearAllUndisplayedContentIn(nsIContent* aParentContent);
111
  NS_HIDDEN_(void) ClearAllUndisplayedContentIn(nsIContent* aParentContent);
112
112
113
  // Mapping display:contents content
114
  NS_HIDDEN_(nsStyleContext*) GetDisplayContents(nsIContent* aContent);
115
  NS_HIDDEN_(mozilla::UndisplayedNode*)
116
    GetAllDisplayContentsIn(nsIContent* aParentContent);
117
  NS_HIDDEN_(void) SetDisplayContents(nsIContent* aContent,
118
                                         nsStyleContext* aStyleContext);
119
  NS_HIDDEN_(void) ChangeDisplayContents(nsIContent* aContent,
120
                                            nsStyleContext* aStyleContext);
121
  NS_HIDDEN_(void) ClearDisplayContentsIn(nsIContent* aContent,
122
                                             nsIContent* aParentContent);
123
  NS_HIDDEN_(void) ClearAllDisplayContentsIn(nsIContent* aParentContent);
124
113
  // Functions for manipulating the frame model
125
  // Functions for manipulating the frame model
114
  NS_HIDDEN_(nsresult) AppendFrames(nsIFrame*       aParentFrame,
126
  NS_HIDDEN_(nsresult) AppendFrames(nsIFrame*       aParentFrame,
115
                                    ChildListID     aListID,
127
                                    ChildListID     aListID,
116
                                    nsFrameList&    aFrameList);
128
                                    nsFrameList&    aFrameList);
117
129
118
  NS_HIDDEN_(nsresult) InsertFrames(nsIFrame*       aParentFrame,
130
  NS_HIDDEN_(nsresult) InsertFrames(nsIFrame*       aParentFrame,
119
                                    ChildListID     aListID,
131
                                    ChildListID     aListID,
120
                                    nsIFrame*       aPrevFrame,
132
                                    nsIFrame*       aPrevFrame,
(-)a/layout/base/nsFrameManagerBase.h (+1 lines)
Line     Link Here 
 Lines 60-75   protected: Link Here 
60
60
61
  // weak link, because the pres shell owns us
61
  // weak link, because the pres shell owns us
62
  nsIPresShell*                   mPresShell;
62
  nsIPresShell*                   mPresShell;
63
  // the pres shell owns the style set
63
  // the pres shell owns the style set
64
  nsStyleSet*                     mStyleSet;
64
  nsStyleSet*                     mStyleSet;
65
  nsIFrame*                       mRootFrame;
65
  nsIFrame*                       mRootFrame;
66
  PLDHashTable                    mPlaceholderMap;
66
  PLDHashTable                    mPlaceholderMap;
67
  UndisplayedMap*                 mUndisplayedMap;
67
  UndisplayedMap*                 mUndisplayedMap;
68
  UndisplayedMap*                 mDisplayContentsMap;
68
  bool                            mIsDestroyingFrames;  // The frame manager is destroying some frame(s).
69
  bool                            mIsDestroyingFrames;  // The frame manager is destroying some frame(s).
69
70
70
  // The frame tree generation number
71
  // The frame tree generation number
71
  // We use this to avoid unnecessary screenshotting
72
  // We use this to avoid unnecessary screenshotting
72
  // on Android. Unfortunately, this is static to match
73
  // on Android. Unfortunately, this is static to match
73
  // the single consumer which is also static. Keeping
74
  // the single consumer which is also static. Keeping
74
  // this the same greatly simplifies lifetime issues and
75
  // this the same greatly simplifies lifetime issues and
75
  // makes sure we always using the correct number.
76
  // makes sure we always using the correct number.

Return to bug 907396