1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /* a presentation of a document, part 1 */
8 #include "mozilla/ArrayUtils.h"
9 #include "mozilla/DebugOnly.h"
10 #include "mozilla/EventDispatcher.h"
11 #include "mozilla/EventStateManager.h"
13 #include "base/basictypes.h"
16 #include "nsPresContext.h"
17 #include "nsIPresShell.h"
18 #include "nsDocShell.h"
19 #include "nsIContentViewer.h"
20 #include "nsPIDOMWindow.h"
21 #include "nsStyleSet.h"
22 #include "nsIContent.h"
24 #include "nsIDocument.h"
25 #include "nsIPrintSettings.h"
26 #include "nsILanguageAtomService.h"
27 #include "mozilla/LookAndFeel.h"
28 #include "nsIInterfaceRequestorUtils.h"
29 #include "nsIWeakReferenceUtils.h"
30 #include "nsAutoPtr.h"
31 #include "nsThreadUtils.h"
32 #include "nsFrameManager.h"
33 #include "nsLayoutUtils.h"
34 #include "nsViewManager.h"
35 #include "RestyleManager.h"
36 #include "SurfaceCache.h"
37 #include "nsCSSRuleProcessor.h"
38 #include "nsRuleNode.h"
39 #include "gfxPlatform.h"
40 #include "nsCSSRules.h"
41 #include "nsFontFaceLoader.h"
42 #include "mozilla/EventListenerManager.h"
44 #include "nsObjectFrame.h"
45 #include "nsTransitionManager.h"
46 #include "nsAnimationManager.h"
47 #include "CounterStyleManager.h"
48 #include "mozilla/MemoryReporting.h"
49 #include "mozilla/dom/Element.h"
50 #include "nsIMessageManager.h"
51 #include "mozilla/dom/MediaQueryList.h"
52 #include "nsSMILAnimationController.h"
53 #include "mozilla/css/ImageLoader.h"
54 #include "mozilla/dom/PBrowserParent.h"
55 #include "mozilla/dom/TabChild.h"
56 #include "mozilla/dom/TabParent.h"
57 #include "nsRefreshDriver.h"
59 #include "nsIDOMEvent.h"
61 #include "nsIDOMChromeWindow.h"
62 #include "nsFrameLoader.h"
64 #include "nsContentUtils.h"
65 #include "nsPIWindowRoot.h"
66 #include "mozilla/Preferences.h"
68 // Needed for Start/Stop of Image Animation
69 #include "imgIContainer.h"
70 #include "nsIImageLoadingContent.h"
72 #include "nsCSSParser.h"
73 #include "nsBidiUtils.h"
74 #include "nsServiceManagerUtils.h"
78 using namespace mozilla
;
79 using namespace mozilla::dom
;
80 using namespace mozilla::layers
;
82 uint8_t gNotifySubDocInvalidationData
;
85 * Layer UserData for ContainerLayers that want to be notified
86 * of local invalidations of them and their descendant layers.
87 * Pass a callback to ComputeDifferences to have these called.
89 class ContainerLayerPresContext
: public LayerUserData
{
91 nsPresContext
* mPresContext
;
96 class CharSetChangingRunnable
: public nsRunnable
99 CharSetChangingRunnable(nsPresContext
* aPresContext
,
100 const nsCString
& aCharSet
)
101 : mPresContext(aPresContext
),
108 mPresContext
->DoChangeCharSet(mCharSet
);
113 nsRefPtr
<nsPresContext
> mPresContext
;
117 } // anonymous namespace
120 nsPresContext::MakeColorPref(const nsString
& aColor
)
124 if (!parser
.ParseColorString(aColor
, nullptr, 0, value
)) {
125 // Any better choices?
126 return NS_RGB(0, 0, 0);
130 return nsRuleNode::ComputeColor(value
, this, nullptr, color
)
136 nsPresContext::IsDOMPaintEventPending()
138 if (mFireAfterPaintEvents
) {
141 if (GetDisplayRootPresContext()->GetRootPresContext()->mRefreshDriver
->ViewManagerFlushIsPending()) {
142 // Since we're promising that there will be a MozAfterPaint event
143 // fired, we record an empty invalidation in case display list
144 // invalidation doesn't invalidate anything further.
145 NotifyInvalidation(nsRect(0, 0, 0, 0), 0);
146 NS_ASSERTION(mFireAfterPaintEvents
, "Why aren't we planning to fire the event?");
153 nsPresContext::PrefChangedCallback(const char* aPrefName
, void* instance_data
)
155 nsRefPtr
<nsPresContext
> presContext
=
156 static_cast<nsPresContext
*>(instance_data
);
158 NS_ASSERTION(nullptr != presContext
, "bad instance data");
159 if (nullptr != presContext
) {
160 presContext
->PreferenceChanged(aPrefName
);
165 nsPresContext::PrefChangedUpdateTimerCallback(nsITimer
*aTimer
, void *aClosure
)
167 nsPresContext
* presContext
= (nsPresContext
*)aClosure
;
168 NS_ASSERTION(presContext
!= nullptr, "bad instance data");
170 presContext
->UpdateAfterPreferencesChanged();
174 IsVisualCharset(const nsCString
& aCharset
)
176 if (aCharset
.LowerCaseEqualsLiteral("ibm862") // Hebrew
177 || aCharset
.LowerCaseEqualsLiteral("iso-8859-8") ) { // Hebrew
178 return true; // visual text type
181 return false; // logical text type
185 // NOTE! nsPresContext::operator new() zeroes out all members, so don't
186 // bother initializing members to 0.
188 nsPresContext::nsPresContext(nsIDocument
* aDocument
, nsPresContextType aType
)
189 : mType(aType
), mDocument(aDocument
), mBaseMinFontSize(0),
190 mTextZoom(1.0), mFullZoom(1.0), mLastFontInflationScreenWidth(-1.0),
191 mPageSize(-1, -1), mPPScale(1.0f
),
192 mViewportStyleOverflow(NS_STYLE_OVERFLOW_AUTO
, NS_STYLE_OVERFLOW_AUTO
),
193 mImageAnimationModePref(imgIContainer::kNormalAnimMode
),
194 mAllInvalidated(false),
195 mPaintFlashing(false), mPaintFlashingInitialized(false)
197 // NOTE! nsPresContext::operator new() zeroes out all members, so don't
198 // bother initializing members to 0.
200 mDoScaledTwips
= true;
202 SetBackgroundImageDraw(true); // always draw the background
203 SetBackgroundColorDraw(true);
205 mBackgroundColor
= NS_RGB(0xFF, 0xFF, 0xFF);
207 mUseDocumentColors
= true;
208 mUseDocumentFonts
= true;
210 // the minimum font-size is unconstrained by default
212 mLinkColor
= NS_RGB(0x00, 0x00, 0xEE);
213 mActiveLinkColor
= NS_RGB(0xEE, 0x00, 0x00);
214 mVisitedLinkColor
= NS_RGB(0x55, 0x1A, 0x8B);
215 mUnderlineLinks
= true;
216 mSendAfterPaintToContent
= false;
218 mFocusTextColor
= mDefaultColor
;
219 mFocusBackgroundColor
= mBackgroundColor
;
222 mBodyTextColor
= mDefaultColor
;
224 if (aType
== eContext_Galley
) {
225 mMedium
= nsGkAtoms::screen
;
227 mMedium
= nsGkAtoms::print
;
230 mMediaEmulated
= mMedium
;
233 mImageAnimationMode
= imgIContainer::kDontAnimMode
;
234 mNeverAnimate
= true;
236 mImageAnimationMode
= imgIContainer::kNormalAnimMode
;
237 mNeverAnimate
= false;
239 NS_ASSERTION(mDocument
, "Null document");
240 mUserFontSet
= nullptr;
241 mUserFontSetDirty
= true;
243 mCounterStylesDirty
= true;
245 // if text perf logging enabled, init stats struct
246 PRLogModuleInfo
*log
= gfxPlatform::GetLog(eGfxLog_textperf
);
247 if (log
&& log
->level
>= PR_LOG_WARNING
) {
248 mTextPerf
= new gfxTextPerfMetrics();
251 PR_INIT_CLIST(&mDOMMediaQueryLists
);
254 nsPresContext::~nsPresContext()
256 NS_PRECONDITION(!mShell
, "Presshell forgot to clear our mShell pointer");
259 NS_ABORT_IF_FALSE(PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists
),
260 "must not have media query lists left");
262 // Disconnect the refresh driver *after* the transition manager, which
264 if (mRefreshDriver
&& mRefreshDriver
->PresContext() == this) {
265 mRefreshDriver
->Disconnect();
269 // unclear if these are needed, but can't hurt
270 mEventManager
->NotifyDestroyPresContext(this);
271 mEventManager
->SetPresContext(nullptr);
274 if (mPrefChangedTimer
)
276 mPrefChangedTimer
->Cancel();
277 mPrefChangedTimer
= nullptr;
280 // Unregister preference callbacks
281 Preferences::UnregisterCallback(nsPresContext::PrefChangedCallback
,
284 Preferences::UnregisterCallback(nsPresContext::PrefChangedCallback
,
287 Preferences::UnregisterCallback(nsPresContext::PrefChangedCallback
,
288 "browser.underline_anchors",
290 Preferences::UnregisterCallback(nsPresContext::PrefChangedCallback
,
291 "browser.anchor_color",
293 Preferences::UnregisterCallback(nsPresContext::PrefChangedCallback
,
294 "browser.active_color",
296 Preferences::UnregisterCallback(nsPresContext::PrefChangedCallback
,
297 "browser.visited_color",
299 Preferences::UnregisterCallback(nsPresContext::PrefChangedCallback
,
300 "image.animation_mode",
302 Preferences::UnregisterCallback(nsPresContext::PrefChangedCallback
,
305 Preferences::UnregisterCallback(nsPresContext::PrefChangedCallback
,
306 "dom.send_after_paint_to_content",
308 Preferences::UnregisterCallback(nsPresContext::PrefChangedCallback
,
309 "gfx.font_rendering.",
311 Preferences::UnregisterCallback(nsPresContext::PrefChangedCallback
,
314 Preferences::UnregisterCallback(nsPresContext::PrefChangedCallback
,
315 "layout.css.devPixelsPerPx",
317 Preferences::UnregisterCallback(nsPresContext::PrefChangedCallback
,
318 "nglayout.debug.paint_flashing",
320 Preferences::UnregisterCallback(nsPresContext::PrefChangedCallback
,
321 "nglayout.debug.paint_flashing_chrome",
325 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPresContext
)
326 NS_INTERFACE_MAP_ENTRY(nsISupports
)
327 NS_INTERFACE_MAP_ENTRY(nsIObserver
)
330 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPresContext
)
331 NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(nsPresContext
, LastRelease())
334 nsPresContext::LastRelease()
337 static_cast<nsRootPresContext
*>(this)->CancelDidPaintTimer();
341 NS_IMPL_CYCLE_COLLECTION_CLASS(nsPresContext
)
343 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsPresContext
)
344 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument
);
345 // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mDeviceContext); // not xpcom
346 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventManager
);
347 // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mLanguage); // an atom
349 // We own only the items in mDOMMediaQueryLists that have listeners;
350 // this reference is managed by their AddListener and RemoveListener
352 for (PRCList
*l
= PR_LIST_HEAD(&tmp
->mDOMMediaQueryLists
);
353 l
!= &tmp
->mDOMMediaQueryLists
; l
= PR_NEXT_LINK(l
)) {
354 MediaQueryList
*mql
= static_cast<MediaQueryList
*>(l
);
355 if (mql
->HasListeners()) {
356 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb
, "mDOMMediaQueryLists item");
357 cb
.NoteXPCOMChild(mql
);
361 // NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTheme); // a service
362 // NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLangService); // a service
363 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrintSettings
);
364 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrefChangedTimer
);
365 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
367 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsPresContext
)
368 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument
);
369 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDeviceContext
); // worth bothering?
370 if (tmp
->mEventManager
) {
371 // unclear if these are needed, but can't hurt
372 tmp
->mEventManager
->NotifyDestroyPresContext(tmp
);
373 tmp
->mEventManager
->SetPresContext(nullptr);
374 tmp
->mEventManager
= nullptr;
377 // We own only the items in mDOMMediaQueryLists that have listeners;
378 // this reference is managed by their AddListener and RemoveListener
380 for (PRCList
*l
= PR_LIST_HEAD(&tmp
->mDOMMediaQueryLists
);
381 l
!= &tmp
->mDOMMediaQueryLists
; ) {
382 PRCList
*next
= PR_NEXT_LINK(l
);
383 MediaQueryList
*mql
= static_cast<MediaQueryList
*>(l
);
384 mql
->RemoveAllListeners();
388 // NS_RELEASE(tmp->mLanguage); // an atom
390 // NS_IMPL_CYCLE_COLLECTION_UNLINK(mTheme); // a service
391 // NS_IMPL_CYCLE_COLLECTION_UNLINK(mLangService); // a service
392 NS_IMPL_CYCLE_COLLECTION_UNLINK(mPrintSettings
);
393 if (tmp
->mPrefChangedTimer
)
395 tmp
->mPrefChangedTimer
->Cancel();
396 tmp
->mPrefChangedTimer
= nullptr;
398 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
401 #define MAKE_FONT_PREF_KEY(_pref, _s0, _s1) \
405 static const char* const kGenericFont
[] = {
415 // whether no native theme service exists;
416 // if this gets set to true, we'll stop asking for it.
417 static bool sNoTheme
= false;
419 // Set to true when LookAndFeelChanged needs to be called. This is used
420 // because the look and feel is a service, so there's no need to notify it from
421 // more than one prescontext.
422 static bool sLookAndFeelChanged
;
424 // Set to true when ThemeChanged needs to be called on mTheme. This is used
425 // because mTheme is a service, so there's no need to notify it from more than
427 static bool sThemeChanged
;
429 const nsPresContext::LangGroupFontPrefs
*
430 nsPresContext::GetFontPrefsForLang(nsIAtom
*aLanguage
) const
432 // Get language group for aLanguage:
435 nsIAtom
*langGroupAtom
= nullptr;
437 aLanguage
= mLanguage
;
439 if (aLanguage
&& mLangService
) {
440 langGroupAtom
= mLangService
->GetLanguageGroup(aLanguage
, &rv
);
442 if (NS_FAILED(rv
) || !langGroupAtom
) {
443 langGroupAtom
= nsGkAtoms::x_western
; // Assume x-western is safe...
446 // Look for cached prefs for this lang group.
447 // Most documents will only use one (or very few) language groups. Rather
448 // than have the overhead of a hash lookup, we simply look along what will
449 // typically be a very short (usually of length 1) linked list. There are 31
450 // language groups, so in the worst case scenario we'll need to traverse 31
453 LangGroupFontPrefs
*prefs
=
454 const_cast<LangGroupFontPrefs
*>(&mLangGroupFontPrefs
);
455 if (prefs
->mLangGroup
) { // if initialized
456 DebugOnly
<uint32_t> count
= 0;
458 NS_ASSERTION(++count
< 35, "Lang group count exceeded!!!");
459 if (prefs
->mLangGroup
== langGroupAtom
) {
465 prefs
= prefs
->mNext
;
468 // nothing cached, so go on and fetch the prefs for this lang group:
469 prefs
= prefs
->mNext
= new LangGroupFontPrefs
;
472 prefs
->mLangGroup
= langGroupAtom
;
474 /* Fetch the font prefs to be used -- see bug 61883 for details.
475 Not all prefs are needed upfront. Some are fallback prefs intended
476 for the GFX font sub-system...
478 1) unit : assumed to be the same for all language groups -------------
479 font.size.unit = px | pt XXX could be folded in the size... bug 90440
481 2) attributes for generic fonts --------------------------------------
482 font.default.[langGroup] = serif | sans-serif - fallback generic font
483 font.name.[generic].[langGroup] = current user' selected font on the pref dialog
484 font.name-list.[generic].[langGroup] = fontname1, fontname2, ... [factory pre-built list]
485 font.size.[generic].[langGroup] = integer - settable by the user
486 font.size-adjust.[generic].[langGroup] = "float" - settable by the user
487 font.minimum-size.[langGroup] = integer - settable by the user
490 nsAutoCString langGroup
;
491 langGroupAtom
->ToUTF8String(langGroup
);
493 prefs
->mDefaultVariableFont
.size
= CSSPixelsToAppUnits(16);
494 prefs
->mDefaultFixedFont
.size
= CSSPixelsToAppUnits(13);
498 // get the current applicable font-size unit
499 enum {eUnit_unknown
= -1, eUnit_px
, eUnit_pt
};
500 int32_t unit
= eUnit_px
;
502 nsAdoptingCString cvalue
=
503 Preferences::GetCString("font.size.unit");
505 if (!cvalue
.IsEmpty()) {
506 if (cvalue
.EqualsLiteral("px")) {
509 else if (cvalue
.EqualsLiteral("pt")) {
513 // XXX should really send this warning to the user (Error Console?).
514 // And just default to unit = eUnit_px?
515 NS_WARNING("unexpected font-size unit -- expected: 'px' or 'pt'");
516 unit
= eUnit_unknown
;
520 // get font.minimum-size.[langGroup]
522 MAKE_FONT_PREF_KEY(pref
, "font.minimum-size.", langGroup
);
524 int32_t size
= Preferences::GetInt(pref
.get());
525 if (unit
== eUnit_px
) {
526 prefs
->mMinimumFontSize
= CSSPixelsToAppUnits(size
);
528 else if (unit
== eUnit_pt
) {
529 prefs
->mMinimumFontSize
= CSSPointsToAppUnits(size
);
532 nsFont
* fontTypes
[] = {
533 &prefs
->mDefaultVariableFont
,
534 &prefs
->mDefaultFixedFont
,
535 &prefs
->mDefaultSerifFont
,
536 &prefs
->mDefaultSansSerifFont
,
537 &prefs
->mDefaultMonospaceFont
,
538 &prefs
->mDefaultCursiveFont
,
539 &prefs
->mDefaultFantasyFont
541 static_assert(MOZ_ARRAY_LENGTH(fontTypes
) == eDefaultFont_COUNT
,
542 "FontTypes array count is not correct");
544 // Get attributes specific to each generic font. We do not get the user's
545 // generic-font-name-to-specific-family-name preferences because its the
546 // generic name that should be fed into the cascade. It is up to the GFX
547 // code to look up the font prefs to convert generic names to specific
548 // family names as necessary.
549 nsAutoCString generic_dot_langGroup
;
550 for (uint32_t eType
= 0; eType
< ArrayLength(fontTypes
); ++eType
) {
551 generic_dot_langGroup
.Assign(kGenericFont
[eType
]);
552 generic_dot_langGroup
.Append(langGroup
);
554 nsFont
* font
= fontTypes
[eType
];
556 // set the default variable font (the other fonts are seen as 'generic' fonts
557 // in GFX and will be queried there when hunting for alternative fonts)
558 if (eType
== eDefaultFont_Variable
) {
559 MAKE_FONT_PREF_KEY(pref
, "font.name.variable.", langGroup
);
561 nsAdoptingString value
= Preferences::GetString(pref
.get());
562 if (!value
.IsEmpty()) {
563 FontFamilyName defaultVariableName
= FontFamilyName::Convert(value
);
564 FontFamilyType defaultType
= defaultVariableName
.mType
;
565 NS_ASSERTION(defaultType
== eFamily_serif
||
566 defaultType
== eFamily_sans_serif
,
567 "default type must be serif or sans-serif");
568 prefs
->mDefaultVariableFont
.fontlist
= FontFamilyList(defaultType
);
571 MAKE_FONT_PREF_KEY(pref
, "font.default.", langGroup
);
572 value
= Preferences::GetString(pref
.get());
573 if (!value
.IsEmpty()) {
574 FontFamilyName defaultVariableName
= FontFamilyName::Convert(value
);
575 FontFamilyType defaultType
= defaultVariableName
.mType
;
576 NS_ASSERTION(defaultType
== eFamily_serif
||
577 defaultType
== eFamily_sans_serif
,
578 "default type must be serif or sans-serif");
579 prefs
->mDefaultVariableFont
.fontlist
= FontFamilyList(defaultType
);
584 if (eType
== eDefaultFont_Monospace
) {
585 // This takes care of the confusion whereby people often expect "monospace"
586 // to have the same default font-size as "-moz-fixed" (this tentative
587 // size may be overwritten with the specific value for "monospace" when
588 // "font.size.monospace.[langGroup]" is read -- see below)
589 prefs
->mDefaultMonospaceFont
.size
= prefs
->mDefaultFixedFont
.size
;
591 else if (eType
!= eDefaultFont_Fixed
) {
592 // all the other generic fonts are initialized with the size of the
593 // variable font, but their specific size can supersede later -- see below
594 font
->size
= prefs
->mDefaultVariableFont
.size
;
598 // Bug 84398: for spec purists, a different font-size only applies to the
599 // .variable. and .fixed. fonts and the other fonts should get |font-size-adjust|.
600 // The problem is that only GfxWin has the support for |font-size-adjust|. So for
601 // parity, we enable the ability to set a different font-size on all platforms.
603 // get font.size.[generic].[langGroup]
604 // size=0 means 'Auto', i.e., generic fonts retain the size of the variable font
605 MAKE_FONT_PREF_KEY(pref
, "font.size", generic_dot_langGroup
);
606 size
= Preferences::GetInt(pref
.get());
608 if (unit
== eUnit_px
) {
609 font
->size
= CSSPixelsToAppUnits(size
);
611 else if (unit
== eUnit_pt
) {
612 font
->size
= CSSPointsToAppUnits(size
);
616 // get font.size-adjust.[generic].[langGroup]
617 // XXX only applicable on GFX ports that handle |font-size-adjust|
618 MAKE_FONT_PREF_KEY(pref
, "font.size-adjust", generic_dot_langGroup
);
619 cvalue
= Preferences::GetCString(pref
.get());
620 if (!cvalue
.IsEmpty()) {
621 font
->sizeAdjust
= (float)atof(cvalue
.get());
625 printf("%s Family-list:%s size:%d sizeAdjust:%.2f\n",
626 generic_dot_langGroup
.get(),
627 NS_ConvertUTF16toUTF8(font
->name
).get(), font
->size
,
636 nsPresContext::GetDocumentColorPreferences()
638 // Make sure the preferences are initialized. In the normal run,
639 // they would already be, because gfxPlatform would have been created,
640 // but in some reference tests, that is not the case.
641 gfxPrefs::GetSingleton();
643 int32_t useAccessibilityTheme
= 0;
644 bool usePrefColors
= true;
645 bool isChromeDocShell
= false;
647 nsIDocument
* doc
= mDocument
->GetDisplayDocument();
648 if (doc
&& doc
->GetDocShell()) {
649 isChromeDocShell
= nsIDocShellTreeItem::typeChrome
==
650 doc
->GetDocShell()->ItemType();
652 nsCOMPtr
<nsIDocShellTreeItem
> docShell(mContainer
);
654 isChromeDocShell
= nsIDocShellTreeItem::typeChrome
== docShell
->ItemType();
658 mIsChromeOriginImage
= mDocument
->IsBeingUsedAsImage() &&
659 IsChromeURI(mDocument
->GetDocumentURI());
661 if (isChromeDocShell
|| mIsChromeOriginImage
) {
662 usePrefColors
= false;
664 useAccessibilityTheme
=
665 LookAndFeel::GetInt(LookAndFeel::eIntID_UseAccessibilityTheme
, 0);
666 usePrefColors
= !useAccessibilityTheme
;
670 !Preferences::GetBool("browser.display.use_system_colors", false);
674 nsAdoptingString colorStr
=
675 Preferences::GetString("browser.display.foreground_color");
677 if (!colorStr
.IsEmpty()) {
678 mDefaultColor
= MakeColorPref(colorStr
);
681 colorStr
= Preferences::GetString("browser.display.background_color");
683 if (!colorStr
.IsEmpty()) {
684 mBackgroundColor
= MakeColorPref(colorStr
);
689 LookAndFeel::GetColor(LookAndFeel::eColorID_WindowForeground
,
690 NS_RGB(0x00, 0x00, 0x00));
692 LookAndFeel::GetColor(LookAndFeel::eColorID_WindowBackground
,
693 NS_RGB(0xFF, 0xFF, 0xFF));
696 // Wherever we got the default background color from, ensure it is
698 mBackgroundColor
= NS_ComposeColors(NS_RGB(0xFF, 0xFF, 0xFF),
701 mUseDocumentColors
= !useAccessibilityTheme
&&
702 Preferences::GetBool("browser.display.use_document_colors",
707 nsPresContext::GetUserPreferences()
709 if (!GetPresShell()) {
710 // No presshell means nothing to do here. We'll do this when we
715 mAutoQualityMinFontSizePixelsPref
=
716 Preferences::GetInt("browser.display.auto_quality_min_font_size");
719 GetDocumentColorPreferences();
721 mSendAfterPaintToContent
=
722 Preferences::GetBool("dom.send_after_paint_to_content",
723 mSendAfterPaintToContent
);
727 Preferences::GetBool("browser.underline_anchors", mUnderlineLinks
);
729 nsAdoptingString colorStr
= Preferences::GetString("browser.anchor_color");
731 if (!colorStr
.IsEmpty()) {
732 mLinkColor
= MakeColorPref(colorStr
);
735 colorStr
= Preferences::GetString("browser.active_color");
737 if (!colorStr
.IsEmpty()) {
738 mActiveLinkColor
= MakeColorPref(colorStr
);
741 colorStr
= Preferences::GetString("browser.visited_color");
743 if (!colorStr
.IsEmpty()) {
744 mVisitedLinkColor
= MakeColorPref(colorStr
);
748 Preferences::GetBool("browser.display.use_focus_colors", mUseFocusColors
);
750 mFocusTextColor
= mDefaultColor
;
751 mFocusBackgroundColor
= mBackgroundColor
;
753 colorStr
= Preferences::GetString("browser.display.focus_text_color");
755 if (!colorStr
.IsEmpty()) {
756 mFocusTextColor
= MakeColorPref(colorStr
);
759 colorStr
= Preferences::GetString("browser.display.focus_background_color");
761 if (!colorStr
.IsEmpty()) {
762 mFocusBackgroundColor
= MakeColorPref(colorStr
);
766 Preferences::GetInt("browser.display.focus_ring_width", mFocusRingWidth
);
768 mFocusRingOnAnything
=
769 Preferences::GetBool("browser.display.focus_ring_on_anything",
770 mFocusRingOnAnything
);
773 Preferences::GetInt("browser.display.focus_ring_style", mFocusRingStyle
);
775 mBodyTextColor
= mDefaultColor
;
779 Preferences::GetInt("browser.display.use_document_fonts") != 0;
781 mPrefScrollbarSide
= Preferences::GetInt("layout.scrollbar.side");
783 ResetCachedFontPrefs();
786 const nsAdoptingCString
& animatePref
=
787 Preferences::GetCString("image.animation_mode");
788 if (animatePref
.EqualsLiteral("normal"))
789 mImageAnimationModePref
= imgIContainer::kNormalAnimMode
;
790 else if (animatePref
.EqualsLiteral("none"))
791 mImageAnimationModePref
= imgIContainer::kDontAnimMode
;
792 else if (animatePref
.EqualsLiteral("once"))
793 mImageAnimationModePref
= imgIContainer::kLoopOnceAnimMode
;
794 else // dynamic change to invalid value should act like it does initially
795 mImageAnimationModePref
= imgIContainer::kNormalAnimMode
;
797 uint32_t bidiOptions
= GetBidi();
800 Preferences::GetInt(IBMBIDI_TEXTDIRECTION_STR
,
801 GET_BIDI_OPTION_DIRECTION(bidiOptions
));
802 SET_BIDI_OPTION_DIRECTION(bidiOptions
, prefInt
);
803 mPrefBidiDirection
= prefInt
;
806 Preferences::GetInt(IBMBIDI_TEXTTYPE_STR
,
807 GET_BIDI_OPTION_TEXTTYPE(bidiOptions
));
808 SET_BIDI_OPTION_TEXTTYPE(bidiOptions
, prefInt
);
811 Preferences::GetInt(IBMBIDI_NUMERAL_STR
,
812 GET_BIDI_OPTION_NUMERAL(bidiOptions
));
813 SET_BIDI_OPTION_NUMERAL(bidiOptions
, prefInt
);
816 Preferences::GetInt(IBMBIDI_SUPPORTMODE_STR
,
817 GET_BIDI_OPTION_SUPPORT(bidiOptions
));
818 SET_BIDI_OPTION_SUPPORT(bidiOptions
, prefInt
);
820 // We don't need to force reflow: either we are initializing a new
821 // prescontext or we are being called from UpdateAfterPreferencesChanged()
822 // which triggers a reflow anyway.
823 SetBidi(bidiOptions
, false);
827 nsPresContext::InvalidateThebesLayers()
831 nsIFrame
* rootFrame
= mShell
->FrameManager()->GetRootFrame();
833 // FrameLayerBuilder caches invalidation-related values that depend on the
834 // appunits-per-dev-pixel ratio, so ensure that all ThebesLayer drawing
835 // is completely flushed.
836 rootFrame
->InvalidateFrameSubtree();
841 nsPresContext::AppUnitsPerDevPixelChanged()
843 InvalidateThebesLayers();
845 if (mDeviceContext
) {
846 mDeviceContext
->FlushFontCache();
849 if (HasCachedStyleData()) {
850 // All cached style data must be recomputed.
851 MediaFeatureValuesChanged(eAlwaysRebuildStyle
, NS_STYLE_HINT_REFLOW
);
854 mCurAppUnitsPerDevPixel
= AppUnitsPerDevPixel();
858 nsPresContext::PreferenceChanged(const char* aPrefName
)
860 nsDependentCString
prefName(aPrefName
);
861 if (prefName
.EqualsLiteral("layout.css.dpi") ||
862 prefName
.EqualsLiteral("layout.css.devPixelsPerPx")) {
863 int32_t oldAppUnitsPerDevPixel
= AppUnitsPerDevPixel();
864 if (mDeviceContext
->CheckDPIChange() && mShell
) {
865 nsCOMPtr
<nsIPresShell
> shell
= mShell
;
866 // Re-fetch the view manager's window dimensions in case there's a deferred
867 // resize which hasn't affected our mVisibleArea yet
868 nscoord oldWidthAppUnits
, oldHeightAppUnits
;
869 nsRefPtr
<nsViewManager
> vm
= shell
->GetViewManager();
873 vm
->GetWindowDimensions(&oldWidthAppUnits
, &oldHeightAppUnits
);
874 float oldWidthDevPixels
= oldWidthAppUnits
/oldAppUnitsPerDevPixel
;
875 float oldHeightDevPixels
= oldHeightAppUnits
/oldAppUnitsPerDevPixel
;
877 nscoord width
= NSToCoordRound(oldWidthDevPixels
*AppUnitsPerDevPixel());
878 nscoord height
= NSToCoordRound(oldHeightDevPixels
*AppUnitsPerDevPixel());
879 vm
->SetWindowDimensions(width
, height
);
881 AppUnitsPerDevPixelChanged();
885 if (StringBeginsWith(prefName
, NS_LITERAL_CSTRING("font."))) {
886 // Changes to font family preferences don't change anything in the
887 // computed style data, so the style system won't generate a reflow
888 // hint for us. We need to do that manually.
890 // FIXME We could probably also handle changes to
891 // browser.display.auto_quality_min_font_size here, but that
892 // probably also requires clearing the text run cache, so don't
893 // bother (yet, anyway).
894 mPrefChangePendingNeedsReflow
= true;
896 if (StringBeginsWith(prefName
, NS_LITERAL_CSTRING("bidi."))) {
897 // Changes to bidi prefs need to trigger a reflow (see bug 443629)
898 mPrefChangePendingNeedsReflow
= true;
900 // Changes to bidi.numeral also needs to empty the text run cache.
901 // This is handled in gfxTextRunWordCache.cpp.
903 if (StringBeginsWith(prefName
, NS_LITERAL_CSTRING("gfx.font_rendering."))) {
904 // Changes to font_rendering prefs need to trigger a reflow
905 mPrefChangePendingNeedsReflow
= true;
907 // we use a zero-delay timer to coalesce multiple pref updates
908 if (!mPrefChangedTimer
)
910 mPrefChangedTimer
= do_CreateInstance("@mozilla.org/timer;1");
911 if (!mPrefChangedTimer
)
913 mPrefChangedTimer
->InitWithFuncCallback(nsPresContext::PrefChangedUpdateTimerCallback
, (void*)this, 0, nsITimer::TYPE_ONE_SHOT
);
915 if (prefName
.EqualsLiteral("nglayout.debug.paint_flashing") ||
916 prefName
.EqualsLiteral("nglayout.debug.paint_flashing_chrome")) {
917 mPaintFlashingInitialized
= false;
923 nsPresContext::UpdateAfterPreferencesChanged()
925 mPrefChangedTimer
= nullptr;
927 nsCOMPtr
<nsIDocShellTreeItem
> docShell(mContainer
);
928 if (docShell
&& nsIDocShellTreeItem::typeChrome
== docShell
->ItemType()) {
932 // Initialize our state from the user preferences
933 GetUserPreferences();
935 // update the presShell: tell it to set the preference style rules up
937 mShell
->SetPreferenceStyleRules(true);
940 InvalidateThebesLayers();
941 mDeviceContext
->FlushFontCache();
943 nsChangeHint hint
= nsChangeHint(0);
945 if (mPrefChangePendingNeedsReflow
) {
946 NS_UpdateHint(hint
, NS_STYLE_HINT_REFLOW
);
949 RebuildAllStyleData(hint
);
953 nsPresContext::Init(nsDeviceContext
* aDeviceContext
)
955 NS_ASSERTION(!mInitialized
, "attempt to reinit pres context");
956 NS_ENSURE_ARG(aDeviceContext
);
958 mDeviceContext
= aDeviceContext
;
960 if (mDeviceContext
->SetPixelScale(mFullZoom
))
961 mDeviceContext
->FlushFontCache();
962 mCurAppUnitsPerDevPixel
= AppUnitsPerDevPixel();
964 mEventManager
= new mozilla::EventStateManager();
966 mTransitionManager
= new nsTransitionManager(this);
968 mAnimationManager
= new nsAnimationManager(this);
970 if (mDocument
->GetDisplayDocument()) {
971 NS_ASSERTION(mDocument
->GetDisplayDocument()->GetShell() &&
972 mDocument
->GetDisplayDocument()->GetShell()->GetPresContext(),
973 "Why are we being initialized?");
974 mRefreshDriver
= mDocument
->GetDisplayDocument()->GetShell()->
975 GetPresContext()->RefreshDriver();
977 nsIDocument
* parent
= mDocument
->GetParentDocument();
978 // Unfortunately, sometimes |parent| here has no presshell because
979 // printing screws up things. Assert that in other cases it does,
980 // but whenever the shell is null just fall back on using our own
982 NS_ASSERTION(!parent
|| mDocument
->IsStaticDocument() || parent
->GetShell(),
983 "How did we end up with a presshell if our parent doesn't "
985 if (parent
&& parent
->GetShell()) {
986 NS_ASSERTION(parent
->GetShell()->GetPresContext(),
987 "How did we get a presshell?");
989 // We don't have our container set yet at this point
990 nsCOMPtr
<nsIDocShellTreeItem
> ourItem
= mDocument
->GetDocShell();
992 nsCOMPtr
<nsIDocShellTreeItem
> parentItem
;
993 ourItem
->GetSameTypeParent(getter_AddRefs(parentItem
));
995 Element
* containingElement
=
996 parent
->FindContentForSubDocument(mDocument
);
997 if (!containingElement
->IsXUL() ||
999 HasAttr(kNameSpaceID_None
,
1000 nsGkAtoms::forceOwnRefreshDriver
)) {
1001 mRefreshDriver
= parent
->GetShell()->GetPresContext()->RefreshDriver();
1007 if (!mRefreshDriver
) {
1008 mRefreshDriver
= new nsRefreshDriver(this);
1012 // Initialise refresh tick counters for OMTA
1013 mLastStyleUpdateForAllAnimations
= mRefreshDriver
->MostRecentRefresh();
1015 // Initialize restyle manager after initializing the refresh driver.
1016 // Since RestyleManager is also the name of a method of nsPresContext,
1017 // it is necessary to prefix the class with the mozilla namespace
1019 mRestyleManager
= new mozilla::RestyleManager(this);
1021 mLangService
= do_GetService(NS_LANGUAGEATOMSERVICE_CONTRACTID
);
1023 // Register callbacks so we're notified when the preferences change
1024 Preferences::RegisterCallback(nsPresContext::PrefChangedCallback
,
1027 Preferences::RegisterCallback(nsPresContext::PrefChangedCallback
,
1030 Preferences::RegisterCallback(nsPresContext::PrefChangedCallback
,
1031 "browser.underline_anchors",
1033 Preferences::RegisterCallback(nsPresContext::PrefChangedCallback
,
1034 "browser.anchor_color",
1036 Preferences::RegisterCallback(nsPresContext::PrefChangedCallback
,
1037 "browser.active_color",
1039 Preferences::RegisterCallback(nsPresContext::PrefChangedCallback
,
1040 "browser.visited_color",
1042 Preferences::RegisterCallback(nsPresContext::PrefChangedCallback
,
1043 "image.animation_mode",
1045 Preferences::RegisterCallback(nsPresContext::PrefChangedCallback
,
1048 Preferences::RegisterCallback(nsPresContext::PrefChangedCallback
,
1049 "dom.send_after_paint_to_content",
1051 Preferences::RegisterCallback(nsPresContext::PrefChangedCallback
,
1052 "gfx.font_rendering.",
1054 Preferences::RegisterCallback(nsPresContext::PrefChangedCallback
,
1057 Preferences::RegisterCallback(nsPresContext::PrefChangedCallback
,
1058 "layout.css.devPixelsPerPx",
1060 Preferences::RegisterCallback(nsPresContext::PrefChangedCallback
,
1061 "nglayout.debug.paint_flashing",
1063 Preferences::RegisterCallback(nsPresContext::PrefChangedCallback
,
1064 "nglayout.debug.paint_flashing_chrome",
1067 nsresult rv
= mEventManager
->Init();
1068 NS_ENSURE_SUCCESS(rv
, rv
);
1070 mEventManager
->SetPresContext(this);
1073 mInitialized
= true;
1076 mBorderWidthTable
[NS_STYLE_BORDER_WIDTH_THIN
] = CSSPixelsToAppUnits(1);
1077 mBorderWidthTable
[NS_STYLE_BORDER_WIDTH_MEDIUM
] = CSSPixelsToAppUnits(3);
1078 mBorderWidthTable
[NS_STYLE_BORDER_WIDTH_THICK
] = CSSPixelsToAppUnits(5);
1083 // Note: We don't hold a reference on the shell; it has a reference to
1086 nsPresContext::SetShell(nsIPresShell
* aShell
)
1089 // Clear out user font set if we have one
1090 mUserFontSet
->Destroy();
1091 NS_RELEASE(mUserFontSet
);
1093 if (mCounterStyleManager
) {
1094 mCounterStyleManager
->Disconnect();
1095 mCounterStyleManager
= nullptr;
1099 // Remove ourselves as the charset observer from the shell's doc, because
1100 // this shell may be going away for good.
1101 nsIDocument
*doc
= mShell
->GetDocument();
1103 doc
->RemoveCharSetObserver(this);
1110 // Since CounterStyleManager is also the name of a method of
1111 // nsPresContext, it is necessary to prefix the class with the mozilla
1113 mCounterStyleManager
= new mozilla::CounterStyleManager(this);
1115 nsIDocument
*doc
= mShell
->GetDocument();
1116 NS_ASSERTION(doc
, "expect document here");
1118 // Have to update PresContext's mDocument before calling any other methods.
1121 // Initialize our state from the user preferences, now that we
1122 // have a presshell, and hence a document.
1123 GetUserPreferences();
1126 nsIURI
*docURI
= doc
->GetDocumentURI();
1128 if (IsDynamic() && docURI
) {
1129 bool isChrome
= false;
1131 docURI
->SchemeIs("chrome", &isChrome
);
1132 docURI
->SchemeIs("resource", &isRes
);
1134 if (!isChrome
&& !isRes
)
1135 mImageAnimationMode
= mImageAnimationModePref
;
1137 mImageAnimationMode
= imgIContainer::kNormalAnimMode
;
1141 doc
->AddCharSetObserver(this);
1142 UpdateCharSet(doc
->GetDocumentCharacterSet());
1146 if (mTransitionManager
) {
1147 mTransitionManager
->Disconnect();
1148 mTransitionManager
= nullptr;
1150 if (mAnimationManager
) {
1151 mAnimationManager
->Disconnect();
1152 mAnimationManager
= nullptr;
1154 if (mRestyleManager
) {
1155 mRestyleManager
->Disconnect();
1156 mRestyleManager
= nullptr;
1160 // Have to cancel our plugin geometry timer, because the
1161 // callback for that depends on a non-null presshell.
1162 static_cast<nsRootPresContext
*>(this)->CancelApplyPluginGeometryTimer();
1168 nsPresContext::DoChangeCharSet(const nsCString
& aCharSet
)
1170 UpdateCharSet(aCharSet
);
1171 mDeviceContext
->FlushFontCache();
1172 RebuildAllStyleData(NS_STYLE_HINT_REFLOW
);
1176 nsPresContext::UpdateCharSet(const nsCString
& aCharSet
)
1179 mLanguage
= mLangService
->LookupCharSet(aCharSet
);
1180 // this will be a language group (or script) code rather than a true language code
1182 // bug 39570: moved from nsLanguageAtomService::LookupCharSet()
1183 if (mLanguage
== nsGkAtoms::Unicode
) {
1184 mLanguage
= mLangService
->GetLocaleLanguage();
1186 ResetCachedFontPrefs();
1189 switch (GET_BIDI_OPTION_TEXTTYPE(GetBidi())) {
1191 case IBMBIDI_TEXTTYPE_LOGICAL
:
1192 SetVisualMode(false);
1195 case IBMBIDI_TEXTTYPE_VISUAL
:
1196 SetVisualMode(true);
1199 case IBMBIDI_TEXTTYPE_CHARSET
:
1201 SetVisualMode(IsVisualCharset(aCharSet
));
1206 nsPresContext::Observe(nsISupports
* aSubject
,
1208 const char16_t
* aData
)
1210 if (!nsCRT::strcmp(aTopic
, "charset")) {
1211 nsRefPtr
<CharSetChangingRunnable
> runnable
=
1212 new CharSetChangingRunnable(this, NS_LossyConvertUTF16toASCII(aData
));
1213 return NS_DispatchToCurrentThread(runnable
);
1216 NS_WARNING("unrecognized topic in nsPresContext::Observe");
1217 return NS_ERROR_FAILURE
;
1221 nsPresContext::GetParentPresContext()
1223 nsIPresShell
* shell
= GetPresShell();
1225 nsViewManager
* viewManager
= shell
->GetViewManager();
1227 nsView
* view
= viewManager
->GetRootView();
1229 view
= view
->GetParent(); // anonymous inner view
1231 view
= view
->GetParent(); // subdocumentframe's view
1233 nsIFrame
* f
= view
->GetFrame();
1235 return f
->PresContext();
1246 nsPresContext::GetToplevelContentDocumentPresContext()
1250 nsPresContext
* pc
= this;
1252 nsPresContext
* parent
= pc
->GetParentPresContext();
1253 if (!parent
|| parent
->IsChrome())
1260 nsPresContext::GetNearestWidget(nsPoint
* aOffset
)
1262 NS_ENSURE_TRUE(mShell
, nullptr);
1263 nsIFrame
* frame
= mShell
->GetRootFrame();
1264 NS_ENSURE_TRUE(frame
, nullptr);
1265 return frame
->GetView()->GetNearestWidget(aOffset
);
1269 nsPresContext::GetRootWidget()
1271 NS_ENSURE_TRUE(mShell
, nullptr);
1272 nsViewManager
* vm
= mShell
->GetViewManager();
1276 nsCOMPtr
<nsIWidget
> widget
;
1277 vm
->GetRootWidget(getter_AddRefs(widget
));
1278 return widget
.get();
1281 // We may want to replace this with something faster, maybe caching the root prescontext
1283 nsPresContext::GetRootPresContext()
1285 nsPresContext
* pc
= this;
1287 nsPresContext
* parent
= pc
->GetParentPresContext();
1292 return pc
->IsRoot() ? static_cast<nsRootPresContext
*>(pc
) : nullptr;
1296 nsPresContext::GetDisplayRootPresContext()
1298 nsPresContext
* pc
= this;
1300 nsPresContext
* parent
= pc
->GetParentPresContext();
1302 // Not sure if this is always strictly the parent, but it works for GetRootPresContext
1303 // where the current pres context has no frames.
1304 nsIDocument
*doc
= pc
->Document();
1306 doc
= doc
->GetParentDocument();
1308 nsIPresShell
* shell
= doc
->GetShell();
1310 parent
= shell
->GetPresContext();
1315 if (!parent
|| parent
== pc
)
1319 return pc
->IsRoot() ? static_cast<nsRootPresContext
*>(pc
) : nullptr;
1323 nsPresContext::CompatibilityModeChanged()
1328 // enable/disable the QuirkSheet
1329 mShell
->StyleSet()->
1330 EnableQuirkStyleSheet(CompatibilityMode() == eCompatibility_NavQuirks
);
1333 // Helper function for setting Anim Mode on image
1334 static void SetImgAnimModeOnImgReq(imgIRequest
* aImgReq
, uint16_t aMode
)
1337 nsCOMPtr
<imgIContainer
> imgCon
;
1338 aImgReq
->GetImage(getter_AddRefs(imgCon
));
1340 imgCon
->SetAnimationMode(aMode
);
1345 // IMPORTANT: Assumption is that all images for a Presentation
1346 // have the same Animation Mode (pavlov said this was OK)
1348 // Walks content and set the animation mode
1349 // this is a way to turn on/off image animations
1350 void nsPresContext::SetImgAnimations(nsIContent
*aParent
, uint16_t aMode
)
1352 nsCOMPtr
<nsIImageLoadingContent
> imgContent(do_QueryInterface(aParent
));
1354 nsCOMPtr
<imgIRequest
> imgReq
;
1355 imgContent
->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST
,
1356 getter_AddRefs(imgReq
));
1357 SetImgAnimModeOnImgReq(imgReq
, aMode
);
1360 uint32_t count
= aParent
->GetChildCount();
1361 for (uint32_t i
= 0; i
< count
; ++i
) {
1362 SetImgAnimations(aParent
->GetChildAt(i
), aMode
);
1367 nsPresContext::SetSMILAnimations(nsIDocument
*aDoc
, uint16_t aNewMode
,
1370 if (aDoc
->HasAnimationController()) {
1371 nsSMILAnimationController
* controller
= aDoc
->GetAnimationController();
1374 case imgIContainer::kNormalAnimMode
:
1375 case imgIContainer::kLoopOnceAnimMode
:
1376 if (aOldMode
== imgIContainer::kDontAnimMode
)
1377 controller
->Resume(nsSMILTimeContainer::PAUSE_USERPREF
);
1380 case imgIContainer::kDontAnimMode
:
1381 if (aOldMode
!= imgIContainer::kDontAnimMode
)
1382 controller
->Pause(nsSMILTimeContainer::PAUSE_USERPREF
);
1389 nsPresContext::SetImageAnimationModeInternal(uint16_t aMode
)
1391 NS_ASSERTION(aMode
== imgIContainer::kNormalAnimMode
||
1392 aMode
== imgIContainer::kDontAnimMode
||
1393 aMode
== imgIContainer::kLoopOnceAnimMode
, "Wrong Animation Mode is being set!");
1395 // Image animation mode cannot be changed when rendering to a printer.
1399 // Now walk the content tree and set the animation mode
1400 // on all the images.
1401 if (mShell
!= nullptr) {
1402 nsIDocument
*doc
= mShell
->GetDocument();
1404 doc
->StyleImageLoader()->SetAnimationMode(aMode
);
1406 Element
*rootElement
= doc
->GetRootElement();
1408 SetImgAnimations(rootElement
, aMode
);
1410 SetSMILAnimations(doc
, aMode
, mImageAnimationMode
);
1414 mImageAnimationMode
= aMode
;
1418 nsPresContext::SetImageAnimationModeExternal(uint16_t aMode
)
1420 SetImageAnimationModeInternal(aMode
);
1424 nsPresContext::GetDefaultFont(uint8_t aFontID
, nsIAtom
*aLanguage
) const
1426 const LangGroupFontPrefs
*prefs
= GetFontPrefsForLang(aLanguage
);
1430 // Special (our default variable width font and fixed width font)
1431 case kPresContext_DefaultVariableFont_ID
:
1432 font
= &prefs
->mDefaultVariableFont
;
1434 case kPresContext_DefaultFixedFont_ID
:
1435 font
= &prefs
->mDefaultFixedFont
;
1438 case kGenericFont_serif
:
1439 font
= &prefs
->mDefaultSerifFont
;
1441 case kGenericFont_sans_serif
:
1442 font
= &prefs
->mDefaultSansSerifFont
;
1444 case kGenericFont_monospace
:
1445 font
= &prefs
->mDefaultMonospaceFont
;
1447 case kGenericFont_cursive
:
1448 font
= &prefs
->mDefaultCursiveFont
;
1450 case kGenericFont_fantasy
:
1451 font
= &prefs
->mDefaultFantasyFont
;
1455 NS_ERROR("invalid arg");
1462 nsPresContext::SetFullZoom(float aZoom
)
1464 if (!mShell
|| mFullZoom
== aZoom
) {
1468 // Re-fetch the view manager's window dimensions in case there's a deferred
1469 // resize which hasn't affected our mVisibleArea yet
1470 nscoord oldWidthAppUnits
, oldHeightAppUnits
;
1471 mShell
->GetViewManager()->GetWindowDimensions(&oldWidthAppUnits
, &oldHeightAppUnits
);
1472 float oldWidthDevPixels
= oldWidthAppUnits
/ float(mCurAppUnitsPerDevPixel
);
1473 float oldHeightDevPixels
= oldHeightAppUnits
/ float(mCurAppUnitsPerDevPixel
);
1474 mDeviceContext
->SetPixelScale(aZoom
);
1476 NS_ASSERTION(!mSupressResizeReflow
, "two zooms happening at the same time? impossible!");
1477 mSupressResizeReflow
= true;
1480 mShell
->GetViewManager()->
1481 SetWindowDimensions(NSToCoordRound(oldWidthDevPixels
* AppUnitsPerDevPixel()),
1482 NSToCoordRound(oldHeightDevPixels
* AppUnitsPerDevPixel()));
1484 AppUnitsPerDevPixelChanged();
1486 mSupressResizeReflow
= false;
1490 nsPresContext::ScreenWidthInchesForFontInflation(bool* aChanged
)
1496 nsDeviceContext
*dx
= DeviceContext();
1498 dx
->GetClientRect(clientRect
); // FIXME: GetClientRect looks expensive
1499 float deviceWidthInches
=
1500 float(clientRect
.width
) / float(dx
->AppUnitsPerPhysicalInch());
1502 if (mLastFontInflationScreenWidth
== -1.0) {
1503 mLastFontInflationScreenWidth
= deviceWidthInches
;
1506 if (deviceWidthInches
!= mLastFontInflationScreenWidth
&& aChanged
) {
1508 mLastFontInflationScreenWidth
= deviceWidthInches
;
1511 return deviceWidthInches
;
1515 nsPresContext::SetContainer(nsIDocShell
* aDocShell
)
1518 mContainer
= static_cast<nsDocShell
*>(aDocShell
);
1520 mContainer
= WeakPtr
<nsDocShell
>();
1524 GetDocumentColorPreferences();
1529 nsPresContext::GetContainerWeakInternal() const
1531 return static_cast<nsIDocShell
*>(mContainer
);
1535 nsPresContext::GetContainerWeakExternal() const
1537 return GetContainerWeakInternal();
1541 nsPresContext::GetDocShell() const
1547 nsPresContext::Detach()
1549 SetContainer(nullptr);
1550 SetLinkHandler(nullptr);
1552 mShell
->CancelInvalidatePresShellIfHidden();
1557 nsPresContext::StyleUpdateForAllAnimationsIsUpToDate()
1559 return mLastStyleUpdateForAllAnimations
== mRefreshDriver
->MostRecentRefresh();
1563 nsPresContext::TickLastStyleUpdateForAllAnimations()
1565 mLastStyleUpdateForAllAnimations
= mRefreshDriver
->MostRecentRefresh();
1569 nsPresContext::BidiEnabledExternal() const
1571 return BidiEnabledInternal();
1575 nsPresContext::BidiEnabledInternal() const
1577 return Document()->GetBidiEnabled();
1581 nsPresContext::SetBidiEnabled() const
1584 nsIDocument
*doc
= mShell
->GetDocument();
1586 doc
->SetBidiEnabled();
1592 nsPresContext::SetBidi(uint32_t aSource
, bool aForceRestyle
)
1594 // Don't do all this stuff unless the options have changed.
1595 if (aSource
== GetBidi()) {
1599 NS_ASSERTION(!(aForceRestyle
&& (GetBidi() == 0)),
1600 "ForceReflow on new prescontext");
1602 Document()->SetBidiOptions(aSource
);
1603 if (IBMBIDI_TEXTDIRECTION_RTL
== GET_BIDI_OPTION_DIRECTION(aSource
)
1604 || IBMBIDI_NUMERAL_HINDI
== GET_BIDI_OPTION_NUMERAL(aSource
)) {
1607 if (IBMBIDI_TEXTTYPE_VISUAL
== GET_BIDI_OPTION_TEXTTYPE(aSource
)) {
1608 SetVisualMode(true);
1610 else if (IBMBIDI_TEXTTYPE_LOGICAL
== GET_BIDI_OPTION_TEXTTYPE(aSource
)) {
1611 SetVisualMode(false);
1614 nsIDocument
* doc
= mShell
->GetDocument();
1616 SetVisualMode(IsVisualCharset(doc
->GetDocumentCharacterSet()));
1619 if (aForceRestyle
&& mShell
) {
1620 // Reconstruct the root document element's frame and its children,
1621 // because we need to trigger frame reconstruction for direction change.
1622 RebuildUserFontSet();
1623 mShell
->ReconstructFrames();
1628 nsPresContext::GetBidi() const
1630 return Document()->GetBidiOptions();
1634 nsPresContext::IsTopLevelWindowInactive()
1636 nsCOMPtr
<nsIDocShellTreeItem
> treeItem(mContainer
);
1640 nsCOMPtr
<nsIDocShellTreeItem
> rootItem
;
1641 treeItem
->GetRootTreeItem(getter_AddRefs(rootItem
));
1646 nsCOMPtr
<nsPIDOMWindow
> domWindow
= rootItem
->GetWindow();
1648 return domWindow
&& !domWindow
->IsActive();
1652 nsPresContext::GetTheme()
1654 if (!sNoTheme
&& !mTheme
) {
1655 mTheme
= do_GetService("@mozilla.org/chrome/chrome-native-theme;1");
1664 nsPresContext::ThemeChanged()
1666 if (!mPendingThemeChanged
) {
1667 sLookAndFeelChanged
= true;
1668 sThemeChanged
= true;
1670 nsCOMPtr
<nsIRunnable
> ev
=
1671 NS_NewRunnableMethod(this, &nsPresContext::ThemeChangedInternal
);
1672 if (NS_SUCCEEDED(NS_DispatchToCurrentThread(ev
))) {
1673 mPendingThemeChanged
= true;
1679 nsPresContext::ThemeChangedInternal()
1681 mPendingThemeChanged
= false;
1683 // Tell the theme that it changed, so it can flush any handles to stale theme
1685 if (mTheme
&& sThemeChanged
) {
1686 mTheme
->ThemeChanged();
1687 sThemeChanged
= false;
1690 if (sLookAndFeelChanged
) {
1691 // Clear all cached LookAndFeel colors.
1692 LookAndFeel::Refresh();
1693 sLookAndFeelChanged
= false;
1695 // Vector images (SVG) may be using theme colors so we discard all cached
1696 // surfaces. (We could add a vector image only version of DiscardAll, but
1697 // in bug 940625 we decided theme changes are rare enough not to bother.)
1698 mozilla::image::SurfaceCache::DiscardAll();
1701 // This will force the system metrics to be generated the next time they're used
1702 nsCSSRuleProcessor::FreeSystemMetrics();
1704 // Changes to system metrics can change media queries on them.
1705 // Changes in theme can change system colors (whose changes are
1706 // properly reflected in computed style data), system fonts (whose
1707 // changes are not), and -moz-appearance (whose changes likewise are
1708 // not), so we need to reflow.
1709 MediaFeatureValuesChanged(eAlwaysRebuildStyle
, NS_STYLE_HINT_REFLOW
);
1713 nsPresContext::SysColorChanged()
1715 if (!mPendingSysColorChanged
) {
1716 sLookAndFeelChanged
= true;
1717 nsCOMPtr
<nsIRunnable
> ev
=
1718 NS_NewRunnableMethod(this, &nsPresContext::SysColorChangedInternal
);
1719 if (NS_SUCCEEDED(NS_DispatchToCurrentThread(ev
))) {
1720 mPendingSysColorChanged
= true;
1726 nsPresContext::SysColorChangedInternal()
1728 mPendingSysColorChanged
= false;
1730 if (sLookAndFeelChanged
) {
1731 // Don't use the cached values for the system colors
1732 LookAndFeel::Refresh();
1733 sLookAndFeelChanged
= false;
1736 // Reset default background and foreground colors for the document since
1737 // they may be using system colors
1738 GetDocumentColorPreferences();
1740 // The system color values are computed to colors in the style data,
1741 // so normal style data comparison is sufficient here.
1742 RebuildAllStyleData(nsChangeHint(0));
1746 nsPresContext::UIResolutionChanged()
1748 if (!mPendingUIResolutionChanged
) {
1749 nsCOMPtr
<nsIRunnable
> ev
=
1750 NS_NewRunnableMethod(this, &nsPresContext::UIResolutionChangedInternal
);
1751 if (NS_SUCCEEDED(NS_DispatchToCurrentThread(ev
))) {
1752 mPendingUIResolutionChanged
= true;
1758 nsPresContext::UIResolutionChangedSubdocumentCallback(nsIDocument
* aDocument
,
1761 nsIPresShell
* shell
= aDocument
->GetShell();
1763 nsPresContext
* pc
= shell
->GetPresContext();
1765 pc
->UIResolutionChangedInternal();
1772 nsPresContext::UIResolutionChangedInternal()
1774 mPendingUIResolutionChanged
= false;
1776 mDeviceContext
->CheckDPIChange();
1777 if (mCurAppUnitsPerDevPixel
!= AppUnitsPerDevPixel()) {
1778 AppUnitsPerDevPixelChanged();
1781 nsCOMPtr
<nsIDOMChromeWindow
> chromeWindow(do_QueryInterface(mDocument
->GetWindow()));
1782 nsCOMPtr
<nsIMessageBroadcaster
> windowMM
;
1784 chromeWindow
->GetMessageManager(getter_AddRefs(windowMM
));
1787 NotifyUIResolutionChanged(windowMM
);
1790 mDocument
->EnumerateSubDocuments(UIResolutionChangedSubdocumentCallback
,
1795 nsPresContext::NotifyUIResolutionChanged(nsIMessageBroadcaster
* aManager
)
1797 uint32_t tabChildCount
= 0;
1798 aManager
->GetChildCount(&tabChildCount
);
1799 for (uint32_t j
= 0; j
< tabChildCount
; ++j
) {
1800 nsCOMPtr
<nsIMessageListenerManager
> childMM
;
1801 aManager
->GetChildAt(j
, getter_AddRefs(childMM
));
1806 nsCOMPtr
<nsIMessageBroadcaster
> nonLeafMM
= do_QueryInterface(childMM
);
1808 NotifyUIResolutionChanged(nonLeafMM
);
1812 nsCOMPtr
<nsIMessageSender
> tabMM
= do_QueryInterface(childMM
);
1814 mozilla::dom::ipc::MessageManagerCallback
* cb
=
1815 static_cast<nsFrameMessageManager
*>(tabMM
.get())->GetCallback();
1817 nsFrameLoader
* fl
= static_cast<nsFrameLoader
*>(cb
);
1818 PBrowserParent
* remoteBrowser
= fl
->GetRemoteBrowser();
1819 TabParent
* remote
= static_cast<TabParent
*>(remoteBrowser
);
1821 remote
->UIResolutionChanged();
1828 nsPresContext::EmulateMedium(const nsAString
& aMediaType
)
1830 nsIAtom
* previousMedium
= Medium();
1831 mIsEmulatingMedia
= true;
1833 nsAutoString mediaType
;
1834 nsContentUtils::ASCIIToLower(aMediaType
, mediaType
);
1836 mMediaEmulated
= do_GetAtom(mediaType
);
1837 if (mMediaEmulated
!= previousMedium
&& mShell
) {
1838 MediaFeatureValuesChanged(eRebuildStyleIfNeeded
, nsChangeHint(0));
1842 void nsPresContext::StopEmulatingMedium()
1844 nsIAtom
* previousMedium
= Medium();
1845 mIsEmulatingMedia
= false;
1846 if (Medium() != previousMedium
) {
1847 MediaFeatureValuesChanged(eRebuildStyleIfNeeded
, nsChangeHint(0));
1852 nsPresContext::RebuildAllStyleData(nsChangeHint aExtraHint
)
1855 // We must have been torn down. Nothing to do here.
1859 mUsesRootEMUnits
= false;
1860 mUsesViewportUnits
= false;
1861 RebuildUserFontSet();
1862 RebuildCounterStyles();
1864 RestyleManager()->RebuildAllStyleData(aExtraHint
);
1868 nsPresContext::PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint
)
1871 // We must have been torn down. Nothing to do here.
1874 RestyleManager()->PostRebuildAllStyleDataEvent(aExtraHint
);
1878 nsPresContext::MediaFeatureValuesChanged(StyleRebuildType aShouldRebuild
,
1879 nsChangeHint aChangeHint
)
1881 NS_ASSERTION(aShouldRebuild
== eAlwaysRebuildStyle
|| aChangeHint
== 0,
1882 "If you don't know if we need a rebuild, how can you provide a hint?");
1884 mPendingMediaFeatureValuesChanged
= false;
1886 // MediumFeaturesChanged updates the applied rules, so it always gets called.
1887 bool mediaFeaturesDidChange
= mShell
? mShell
->StyleSet()->MediumFeaturesChanged(this)
1890 if (aShouldRebuild
== eAlwaysRebuildStyle
||
1891 mediaFeaturesDidChange
||
1892 (mUsesViewportUnits
&& mPendingViewportChange
)) {
1893 RebuildAllStyleData(aChangeHint
);
1896 mPendingViewportChange
= false;
1898 if (mDocument
->IsBeingUsedAsImage()) {
1899 MOZ_ASSERT(PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists
));
1903 MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
1905 // Media query list listeners should be notified from a queued task
1906 // (in HTML5 terms), although we also want to notify them on certain
1907 // flushes. (We're already running off an event.)
1909 // Note that we do this after the new style from media queries in
1910 // style sheets has been computed.
1912 if (!PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists
)) {
1913 // We build a list of all the notifications we're going to send
1914 // before we send any of them. (The spec says the notifications
1915 // should be a queued task, so any removals that happen during the
1916 // notifications shouldn't affect what gets notified.) Furthermore,
1917 // we hold strong pointers to everything we're going to make
1918 // notification calls to, since each notification involves calling
1919 // arbitrary script that might otherwise destroy these objects, or,
1920 // for that matter, |this|.
1922 // Note that we intentionally send the notifications to media query
1923 // list in the order they were created and, for each list, to the
1924 // listeners in the order added.
1925 MediaQueryList::NotifyList notifyList
;
1926 for (PRCList
*l
= PR_LIST_HEAD(&mDOMMediaQueryLists
);
1927 l
!= &mDOMMediaQueryLists
; l
= PR_NEXT_LINK(l
)) {
1928 MediaQueryList
*mql
= static_cast<MediaQueryList
*>(l
);
1929 mql
->MediumFeaturesChanged(notifyList
);
1932 if (!notifyList
.IsEmpty()) {
1933 for (uint32_t i
= 0, i_end
= notifyList
.Length(); i
!= i_end
; ++i
) {
1935 MediaQueryList::HandleChangeData
&d
= notifyList
[i
];
1937 d
.callback
->Call(*d
.mql
, result
);
1941 // NOTE: When |notifyList| goes out of scope, our destructor could run.
1946 nsPresContext::PostMediaFeatureValuesChangedEvent()
1948 // FIXME: We should probably replace this event with use of
1949 // nsRefreshDriver::AddStyleFlushObserver (except the pres shell would
1950 // need to track whether it's been added).
1951 if (!mPendingMediaFeatureValuesChanged
) {
1952 nsCOMPtr
<nsIRunnable
> ev
=
1953 NS_NewRunnableMethod(this, &nsPresContext::HandleMediaFeatureValuesChangedEvent
);
1954 if (NS_SUCCEEDED(NS_DispatchToCurrentThread(ev
))) {
1955 mPendingMediaFeatureValuesChanged
= true;
1956 mDocument
->SetNeedStyleFlush();
1962 nsPresContext::HandleMediaFeatureValuesChangedEvent()
1964 // Null-check mShell in case the shell has been destroyed (and the
1965 // event is the only thing holding the pres context alive).
1966 if (mPendingMediaFeatureValuesChanged
&& mShell
) {
1967 MediaFeatureValuesChanged(eRebuildStyleIfNeeded
);
1971 already_AddRefed
<MediaQueryList
>
1972 nsPresContext::MatchMedia(const nsAString
& aMediaQueryList
)
1974 nsRefPtr
<MediaQueryList
> result
= new MediaQueryList(this, aMediaQueryList
);
1976 // Insert the new item at the end of the linked list.
1977 PR_INSERT_BEFORE(result
, &mDOMMediaQueryLists
);
1979 return result
.forget();
1983 nsPresContext::CompatibilityMode() const
1985 return Document()->GetCompatibilityMode();
1989 nsPresContext::SetPaginatedScrolling(bool aPaginated
)
1991 if (mType
== eContext_PrintPreview
|| mType
== eContext_PageLayout
)
1992 mCanPaginatedScroll
= aPaginated
;
1996 nsPresContext::SetPrintSettings(nsIPrintSettings
*aPrintSettings
)
1998 if (mMedium
== nsGkAtoms::print
)
1999 mPrintSettings
= aPrintSettings
;
2003 nsPresContext::EnsureVisible()
2005 nsCOMPtr
<nsIDocShell
> docShell(mContainer
);
2007 nsCOMPtr
<nsIContentViewer
> cv
;
2008 docShell
->GetContentViewer(getter_AddRefs(cv
));
2009 // Make sure this is the content viewer we belong with
2011 nsRefPtr
<nsPresContext
> currentPresContext
;
2012 cv
->GetPresContext(getter_AddRefs(currentPresContext
));
2013 if (currentPresContext
== this) {
2014 // OK, this is us. We want to call Show() on the content viewer.
2015 nsresult result
= cv
->Show();
2016 if (NS_SUCCEEDED(result
)) {
2025 #ifdef MOZ_REFLOW_PERF
2027 nsPresContext::CountReflows(const char * aName
, nsIFrame
* aFrame
)
2030 mShell
->CountReflows(aName
, aFrame
);
2036 nsPresContext::UpdateIsChrome()
2038 mIsChrome
= mContainer
&&
2039 nsIDocShellTreeItem::typeChrome
== mContainer
->ItemType();
2043 nsPresContext::HasAuthorSpecifiedRules(nsIFrame
*aFrame
, uint32_t ruleTypeMask
) const
2046 nsRuleNode::HasAuthorSpecifiedRules(aFrame
->StyleContext(),
2048 UseDocumentColors());
2052 nsPresContext::GetUserFontSetInternal()
2054 // We want to initialize the user font set lazily the first time the
2055 // user asks for it, rather than building it too early and forcing
2056 // rule cascade creation. Thus we try to enforce the invariant that
2057 // we *never* build the user font set until the first call to
2058 // GetUserFontSet. However, once it's been requested, we can't wait
2059 // for somebody to call GetUserFontSet in order to rebuild it (see
2060 // comments below in RebuildUserFontSet for why).
2062 bool userFontSetGottenBefore
= mGetUserFontSetCalled
;
2064 // Set mGetUserFontSetCalled up front, so that FlushUserFontSet will actually
2066 mGetUserFontSetCalled
= true;
2067 if (mUserFontSetDirty
) {
2068 // If this assertion fails, and there have actually been changes to
2069 // @font-face rules, then we will call StyleChangeReflow in
2070 // FlushUserFontSet. If we're in the middle of reflow,
2071 // that's a bad thing to do, and the caller was responsible for
2072 // flushing first. If we're not (e.g., in frame construction), it's
2074 NS_ASSERTION(!userFontSetGottenBefore
|| !mShell
->IsReflowLocked(),
2075 "FlushUserFontSet should have been called first");
2079 return mUserFontSet
;
2083 nsPresContext::GetUserFontSetExternal()
2085 return GetUserFontSetInternal();
2089 nsPresContext::FlushUserFontSet()
2092 return; // we've been torn down
2095 if (!mGetUserFontSetCalled
) {
2096 return; // No one cares about this font set yet, but we want to be careful
2097 // to not unset our mUserFontSetDirty bit, so when someone really
2098 // does we'll create it.
2101 if (mUserFontSetDirty
) {
2102 if (gfxPlatform::GetPlatform()->DownloadableFontsEnabled()) {
2103 nsTArray
<nsFontFaceRuleContainer
> rules
;
2104 if (!mShell
->StyleSet()->AppendFontFaceRules(this, rules
)) {
2106 mUserFontSet
->Destroy();
2107 NS_RELEASE(mUserFontSet
);
2112 bool changed
= false;
2114 if (rules
.Length() == 0) {
2116 mUserFontSet
->Destroy();
2117 NS_RELEASE(mUserFontSet
);
2121 if (!mUserFontSet
) {
2122 mUserFontSet
= new nsUserFontSet(this);
2123 NS_ADDREF(mUserFontSet
);
2125 changed
= mUserFontSet
->UpdateRules(rules
);
2128 // We need to enqueue a style change reflow (for later) to
2129 // reflect that we're modifying @font-face rules. (However,
2130 // without a reflow, nothing will happen to start any downloads
2131 // that are needed.)
2133 UserFontSetUpdated();
2137 mUserFontSetDirty
= false;
2142 nsPresContext::RebuildUserFontSet()
2144 if (!mGetUserFontSetCalled
) {
2145 // We want to lazily build the user font set the first time it's
2146 // requested (so we don't force creation of rule cascades too
2147 // early), so don't do anything now.
2151 mUserFontSetDirty
= true;
2152 mDocument
->SetNeedStyleFlush();
2154 // Somebody has already asked for the user font set, so we need to
2155 // post an event to rebuild it. Setting the user font set to be dirty
2156 // and lazily rebuilding it isn't sufficient, since it is only the act
2157 // of rebuilding it that will trigger the style change reflow that
2158 // calls GetUserFontSet. (This reflow causes rebuilding of text runs,
2159 // which starts font loads, whose completion causes another style
2161 if (!mPostedFlushUserFontSet
) {
2162 nsCOMPtr
<nsIRunnable
> ev
=
2163 NS_NewRunnableMethod(this, &nsPresContext::HandleRebuildUserFontSet
);
2164 if (NS_SUCCEEDED(NS_DispatchToCurrentThread(ev
))) {
2165 mPostedFlushUserFontSet
= true;
2171 nsPresContext::UserFontSetUpdated()
2176 // Changes to the set of available fonts can cause updates to layout by:
2178 // 1. Changing the font used for text, which changes anything that
2179 // depends on text measurement, including line breaking and
2180 // intrinsic widths, and any other parts of layout that depend on
2181 // font metrics. This requires a style change reflow to update.
2183 // 2. Changing the value of the 'ex' and 'ch' units in style data,
2184 // which also depend on font metrics. Updating this information
2185 // requires rebuilding the rule tree from the top, avoiding the
2186 // reuse of cached data even when no style rules have changed.
2188 PostRebuildAllStyleDataEvent(NS_STYLE_HINT_REFLOW
);
2192 nsPresContext::FlushCounterStyles()
2195 return; // we've been torn down
2197 if (mCounterStyleManager
->IsInitial()) {
2198 // Still in its initial state, no need to clean.
2202 if (mCounterStylesDirty
) {
2203 bool changed
= mCounterStyleManager
->NotifyRuleChanged();
2205 PresShell()->NotifyCounterStylesAreDirty();
2206 PostRebuildAllStyleDataEvent(NS_STYLE_HINT_REFLOW
);
2208 mCounterStylesDirty
= false;
2213 nsPresContext::RebuildCounterStyles()
2215 if (mCounterStyleManager
->IsInitial()) {
2216 // Still in its initial state, no need to reset.
2220 mCounterStylesDirty
= true;
2221 mDocument
->SetNeedStyleFlush();
2222 if (!mPostedFlushCounterStyles
) {
2223 nsCOMPtr
<nsIRunnable
> ev
=
2224 NS_NewRunnableMethod(this, &nsPresContext::HandleRebuildCounterStyles
);
2225 if (NS_SUCCEEDED(NS_DispatchToCurrentThread(ev
))) {
2226 mPostedFlushCounterStyles
= true;
2232 nsPresContext::EnsureSafeToHandOutCSSRules()
2234 CSSStyleSheet::EnsureUniqueInnerResult res
=
2235 mShell
->StyleSet()->EnsureUniqueInnerOnCSSSheets();
2236 if (res
== CSSStyleSheet::eUniqueInner_AlreadyUnique
) {
2241 MOZ_ASSERT(res
== CSSStyleSheet::eUniqueInner_ClonedInner
);
2242 RebuildAllStyleData(nsChangeHint(0));
2246 nsPresContext::FireDOMPaintEvent(nsInvalidateRequestList
* aList
)
2248 nsPIDOMWindow
* ourWindow
= mDocument
->GetWindow();
2252 nsCOMPtr
<EventTarget
> dispatchTarget
= do_QueryInterface(ourWindow
);
2253 nsCOMPtr
<EventTarget
> eventTarget
= dispatchTarget
;
2254 if (!IsChrome() && !mSendAfterPaintToContent
) {
2255 // Don't tell the window about this event, it should not know that
2256 // something happened in a subdocument. Tell only the chrome event handler.
2257 // (Events sent to the window get propagated to the chrome event handler
2259 dispatchTarget
= do_QueryInterface(ourWindow
->GetParentTarget());
2260 if (!dispatchTarget
) {
2264 // Events sent to the window get propagated to the chrome event handler
2266 nsCOMPtr
<nsIDOMEvent
> event
;
2267 // This will empty our list in case dispatching the event causes more damage
2268 // (hopefully it won't, or we're likely to get an infinite loop! At least
2269 // it won't be blocking app execution though).
2270 NS_NewDOMNotifyPaintEvent(getter_AddRefs(event
), eventTarget
, this, nullptr,
2271 NS_AFTERPAINT
, aList
);
2276 // Even if we're not telling the window about the event (so eventTarget is
2277 // the chrome event handler, not the window), the window is still
2278 // logically the event target.
2279 event
->SetTarget(eventTarget
);
2280 event
->SetTrusted(true);
2281 EventDispatcher::DispatchDOMEvent(dispatchTarget
, nullptr, event
, this,
2286 MayHavePaintEventListenerSubdocumentCallback(nsIDocument
* aDocument
, void* aData
)
2288 bool *result
= static_cast<bool*>(aData
);
2289 nsIPresShell
* shell
= aDocument
->GetShell();
2291 nsPresContext
* pc
= shell
->GetPresContext();
2293 *result
= pc
->MayHavePaintEventListenerInSubDocument();
2295 // If we found a paint event listener, then we can stop enumerating
2304 MayHavePaintEventListener(nsPIDOMWindow
* aInnerWindow
)
2308 if (aInnerWindow
->HasPaintEventListeners())
2311 EventTarget
* parentTarget
= aInnerWindow
->GetParentTarget();
2315 EventListenerManager
* manager
= nullptr;
2316 if ((manager
= parentTarget
->GetExistingListenerManager()) &&
2317 manager
->MayHavePaintEventListener()) {
2321 nsCOMPtr
<nsINode
> node
;
2322 if (parentTarget
!= aInnerWindow
->GetChromeEventHandler()) {
2323 nsCOMPtr
<nsIInProcessContentFrameMessageManager
> mm
=
2324 do_QueryInterface(parentTarget
);
2326 node
= mm
->GetOwnerContent();
2331 node
= do_QueryInterface(parentTarget
);
2334 return MayHavePaintEventListener(node
->OwnerDoc()->GetInnerWindow());
2336 nsCOMPtr
<nsPIDOMWindow
> window
= do_QueryInterface(parentTarget
);
2338 return MayHavePaintEventListener(window
);
2340 nsCOMPtr
<nsPIWindowRoot
> root
= do_QueryInterface(parentTarget
);
2341 EventTarget
* tabChildGlobal
;
2343 (tabChildGlobal
= root
->GetParentTarget()) &&
2344 (manager
= tabChildGlobal
->GetExistingListenerManager()) &&
2345 manager
->MayHavePaintEventListener();
2349 nsPresContext::MayHavePaintEventListener()
2351 return ::MayHavePaintEventListener(mDocument
->GetInnerWindow());
2355 nsPresContext::MayHavePaintEventListenerInSubDocument()
2357 if (MayHavePaintEventListener()) {
2361 bool result
= false;
2362 mDocument
->EnumerateSubDocuments(MayHavePaintEventListenerSubdocumentCallback
, &result
);
2367 nsPresContext::NotifyInvalidation(uint32_t aFlags
)
2369 nsIFrame
* rootFrame
= PresShell()->FrameManager()->GetRootFrame();
2370 NotifyInvalidation(rootFrame
->GetVisualOverflowRect(), aFlags
);
2371 mAllInvalidated
= true;
2375 nsPresContext::NotifyInvalidation(const nsIntRect
& aRect
, uint32_t aFlags
)
2377 nsRect
rect(DevPixelsToAppUnits(aRect
.x
),
2378 DevPixelsToAppUnits(aRect
.y
),
2379 DevPixelsToAppUnits(aRect
.width
),
2380 DevPixelsToAppUnits(aRect
.height
));
2381 NotifyInvalidation(rect
, aFlags
);
2385 nsPresContext::NotifyInvalidation(const nsRect
& aRect
, uint32_t aFlags
)
2387 MOZ_ASSERT(GetContainerWeak(), "Invalidation in detached pres context");
2389 // If there is no paint event listener, then we don't need to fire
2390 // the asynchronous event. We don't even need to record invalidation.
2391 // MayHavePaintEventListener is pretty cheap and we could make it
2392 // even cheaper by providing a more efficient
2393 // nsPIDOMWindow::GetListenerManager.
2395 if (mAllInvalidated
) {
2400 for (pc
= this; pc
; pc
= pc
->GetParentPresContext()) {
2401 if (pc
->mFireAfterPaintEvents
)
2403 pc
->mFireAfterPaintEvents
= true;
2406 nsRootPresContext
* rpc
= GetRootPresContext();
2408 rpc
->EnsureEventualDidPaintEvent();
2412 nsInvalidateRequestList::Request
* request
=
2413 mInvalidateRequestsSinceLastPaint
.mRequests
.AppendElement();
2417 request
->mRect
= aRect
;
2418 request
->mFlags
= aFlags
;
2422 nsPresContext::NotifySubDocInvalidation(ContainerLayer
* aContainer
,
2423 const nsIntRegion
& aRegion
)
2425 ContainerLayerPresContext
*data
=
2426 static_cast<ContainerLayerPresContext
*>(
2427 aContainer
->GetUserData(&gNotifySubDocInvalidationData
));
2432 nsIntPoint topLeft
= aContainer
->GetVisibleRegion().GetBounds().TopLeft();
2434 nsIntRegionRectIterator
iter(aRegion
);
2435 while (const nsIntRect
* r
= iter
.Next()) {
2436 nsIntRect rect
= *r
;
2437 //PresContext coordinate space is relative to the start of our visible
2438 // region. Is this really true? This feels like the wrong way to get the right
2440 rect
.MoveBy(-topLeft
);
2441 data
->mPresContext
->NotifyInvalidation(rect
, 0);
2446 nsPresContext::SetNotifySubDocInvalidationData(ContainerLayer
* aContainer
)
2448 ContainerLayerPresContext
* pres
= new ContainerLayerPresContext
;
2449 pres
->mPresContext
= this;
2450 aContainer
->SetUserData(&gNotifySubDocInvalidationData
, pres
);
2454 nsPresContext::ClearNotifySubDocInvalidationData(ContainerLayer
* aContainer
)
2456 aContainer
->SetUserData(&gNotifySubDocInvalidationData
, nullptr);
2459 struct NotifyDidPaintSubdocumentCallbackClosure
{
2461 bool mNeedsAnotherDidPaintNotification
;
2464 NotifyDidPaintSubdocumentCallback(nsIDocument
* aDocument
, void* aData
)
2466 NotifyDidPaintSubdocumentCallbackClosure
* closure
=
2467 static_cast<NotifyDidPaintSubdocumentCallbackClosure
*>(aData
);
2468 nsIPresShell
* shell
= aDocument
->GetShell();
2470 nsPresContext
* pc
= shell
->GetPresContext();
2472 pc
->NotifyDidPaintForSubtree(closure
->mFlags
);
2473 if (pc
->IsDOMPaintEventPending()) {
2474 closure
->mNeedsAnotherDidPaintNotification
= true;
2481 class DelayedFireDOMPaintEvent
: public nsRunnable
{
2483 DelayedFireDOMPaintEvent(nsPresContext
* aPresContext
,
2484 nsInvalidateRequestList
* aList
)
2485 : mPresContext(aPresContext
)
2487 MOZ_ASSERT(mPresContext
->GetContainerWeak(),
2488 "DOMPaintEvent requested for a detached pres context");
2489 mList
.TakeFrom(aList
);
2491 NS_IMETHOD
Run() MOZ_OVERRIDE
2493 // The pres context might have been detached during the delay -
2494 // that's fine, just don't fire the event.
2495 if (mPresContext
->GetContainerWeak()) {
2496 mPresContext
->FireDOMPaintEvent(&mList
);
2501 nsRefPtr
<nsPresContext
> mPresContext
;
2502 nsInvalidateRequestList mList
;
2506 nsPresContext::NotifyDidPaintForSubtree(uint32_t aFlags
)
2509 static_cast<nsRootPresContext
*>(this)->CancelDidPaintTimer();
2511 if (!mFireAfterPaintEvents
) {
2515 // Non-root prescontexts fire MozAfterPaint to all their descendants
2516 // unconditionally, even if no invalidations have been collected. This is
2517 // because we don't want to eat the cost of collecting invalidations for
2518 // every subdocument (which would require putting every subdocument in its
2521 if (aFlags
& nsIPresShell::PAINT_LAYERS
) {
2522 mUndeliveredInvalidateRequestsBeforeLastPaint
.TakeFrom(
2523 &mInvalidateRequestsSinceLastPaint
);
2524 mAllInvalidated
= false;
2526 if (aFlags
& nsIPresShell::PAINT_COMPOSITE
) {
2527 nsCOMPtr
<nsIRunnable
> ev
=
2528 new DelayedFireDOMPaintEvent(this, &mUndeliveredInvalidateRequestsBeforeLastPaint
);
2529 nsContentUtils::AddScriptRunner(ev
);
2532 NotifyDidPaintSubdocumentCallbackClosure closure
= { aFlags
, false };
2533 mDocument
->EnumerateSubDocuments(NotifyDidPaintSubdocumentCallback
, &closure
);
2535 if (!closure
.mNeedsAnotherDidPaintNotification
&&
2536 mInvalidateRequestsSinceLastPaint
.IsEmpty() &&
2537 mUndeliveredInvalidateRequestsBeforeLastPaint
.IsEmpty()) {
2538 // Nothing more to do for the moment.
2539 mFireAfterPaintEvents
= false;
2542 static_cast<nsRootPresContext
*>(this)->EnsureEventualDidPaintEvent();
2548 nsPresContext::HasCachedStyleData()
2550 return mShell
&& mShell
->StyleSet()->HasCachedStyleData();
2553 static bool sGotInterruptEnv
= false;
2554 enum InterruptMode
{
2559 // Controlled by the GECKO_REFLOW_INTERRUPT_MODE env var; allowed values are
2560 // "random" (except on Windows) or "counter". If neither is used, the mode is
2562 static InterruptMode sInterruptMode
= ModeEvent
;
2564 // Used for the "random" mode. Controlled by the GECKO_REFLOW_INTERRUPT_SEED
2566 static uint32_t sInterruptSeed
= 1;
2568 // Used for the "counter" mode. This is the number of unskipped interrupt
2569 // checks that have to happen before we interrupt. Controlled by the
2570 // GECKO_REFLOW_INTERRUPT_FREQUENCY env var.
2571 static uint32_t sInterruptMaxCounter
= 10;
2572 // Used for the "counter" mode. This counts up to sInterruptMaxCounter and is
2574 static uint32_t sInterruptCounter
;
2575 // Number of interrupt checks to skip before really trying to interrupt.
2576 // Controlled by the GECKO_REFLOW_INTERRUPT_CHECKS_TO_SKIP env var.
2577 static uint32_t sInterruptChecksToSkip
= 200;
2578 // Number of milliseconds that a reflow should be allowed to run for before we
2579 // actually allow interruption. Controlled by the
2580 // GECKO_REFLOW_MIN_NOINTERRUPT_DURATION env var. Can't be initialized here,
2581 // because TimeDuration/TimeStamp is not safe to use in static constructors..
2582 static TimeDuration sInterruptTimeout
;
2584 static void GetInterruptEnv()
2586 char *ev
= PR_GetEnv("GECKO_REFLOW_INTERRUPT_MODE");
2589 if (PL_strcasecmp(ev
, "random") == 0) {
2590 ev
= PR_GetEnv("GECKO_REFLOW_INTERRUPT_SEED");
2592 sInterruptSeed
= atoi(ev
);
2594 srandom(sInterruptSeed
);
2595 sInterruptMode
= ModeRandom
;
2598 if (PL_strcasecmp(ev
, "counter") == 0) {
2599 ev
= PR_GetEnv("GECKO_REFLOW_INTERRUPT_FREQUENCY");
2601 sInterruptMaxCounter
= atoi(ev
);
2603 sInterruptCounter
= 0;
2604 sInterruptMode
= ModeCounter
;
2607 ev
= PR_GetEnv("GECKO_REFLOW_INTERRUPT_CHECKS_TO_SKIP");
2609 sInterruptChecksToSkip
= atoi(ev
);
2612 ev
= PR_GetEnv("GECKO_REFLOW_MIN_NOINTERRUPT_DURATION");
2613 int duration_ms
= ev
? atoi(ev
) : 100;
2614 sInterruptTimeout
= TimeDuration::FromMilliseconds(duration_ms
);
2618 nsPresContext::HavePendingInputEvent()
2620 switch (sInterruptMode
) {
2623 return (random() & 1);
2626 if (sInterruptCounter
< sInterruptMaxCounter
) {
2627 ++sInterruptCounter
;
2630 sInterruptCounter
= 0;
2634 nsIFrame
* f
= PresShell()->GetRootFrame();
2636 nsIWidget
* w
= f
->GetNearestWidget();
2638 return w
->HasPendingInputEvent();
2647 nsPresContext::ReflowStarted(bool aInterruptible
)
2649 #ifdef NOISY_INTERRUPTIBLE_REFLOW
2650 if (!aInterruptible
) {
2651 printf("STARTING NONINTERRUPTIBLE REFLOW\n");
2654 // We don't support interrupting in paginated contexts, since page
2655 // sequences only handle initial reflow
2656 mInterruptsEnabled
= aInterruptible
&& !IsPaginated() &&
2657 nsLayoutUtils::InterruptibleReflowEnabled();
2659 // Don't set mHasPendingInterrupt based on HavePendingInputEvent() here. If
2660 // we ever change that, then we need to update the code in
2661 // PresShell::DoReflow to only add the just-reflown root to dirty roots if
2662 // it's actually dirty. Otherwise we can end up adding a root that has no
2663 // interruptible descendants, just because we detected an interrupt at reflow
2665 mHasPendingInterrupt
= false;
2667 mInterruptChecksToSkip
= sInterruptChecksToSkip
;
2669 if (mInterruptsEnabled
) {
2670 mReflowStartTime
= TimeStamp::Now();
2675 nsPresContext::CheckForInterrupt(nsIFrame
* aFrame
)
2677 if (mHasPendingInterrupt
) {
2678 mShell
->FrameNeedsToContinueReflow(aFrame
);
2682 if (!sGotInterruptEnv
) {
2683 sGotInterruptEnv
= true;
2687 if (!mInterruptsEnabled
) {
2691 if (mInterruptChecksToSkip
> 0) {
2692 --mInterruptChecksToSkip
;
2695 mInterruptChecksToSkip
= sInterruptChecksToSkip
;
2697 // Don't interrupt if it's been less than sInterruptTimeout since we started
2699 mHasPendingInterrupt
=
2700 TimeStamp::Now() - mReflowStartTime
> sInterruptTimeout
&&
2701 HavePendingInputEvent() &&
2703 if (mHasPendingInterrupt
) {
2704 #ifdef NOISY_INTERRUPTIBLE_REFLOW
2705 printf("*** DETECTED pending interrupt (time=%lld)\n", PR_Now());
2706 #endif /* NOISY_INTERRUPTIBLE_REFLOW */
2707 mShell
->FrameNeedsToContinueReflow(aFrame
);
2709 return mHasPendingInterrupt
;
2713 nsPresContext::GetPrimaryFrameFor(nsIContent
* aContent
)
2715 NS_PRECONDITION(aContent
, "Don't do that");
2716 if (GetPresShell() &&
2717 GetPresShell()->GetDocument() == aContent
->GetComposedDoc()) {
2718 return aContent
->GetPrimaryFrame();
2725 nsPresContext::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf
) const
2727 return mPropertyTable
.SizeOfExcludingThis(aMallocSizeOf
);
2728 mLangGroupFontPrefs
.SizeOfExcludingThis(aMallocSizeOf
);
2730 // Measurement of other members may be added later if DMD finds it is
2735 nsPresContext::IsRootContentDocument()
2737 // We are a root content document if: we are not a resource doc, we are
2738 // not chrome, and we either have no parent or our parent is chrome.
2739 if (mDocument
->IsResourceDoc()) {
2745 // We may not have a root frame, so use views.
2746 nsView
* view
= PresShell()->GetViewManager()->GetRootView();
2750 view
= view
->GetParent(); // anonymous inner view
2754 view
= view
->GetParent(); // subdocumentframe's view
2759 nsIFrame
* f
= view
->GetFrame();
2760 return (f
&& f
->PresContext()->IsChrome());
2764 nsPresContext::IsCrossProcessRootContentDocument()
2766 if (!IsRootContentDocument()) {
2770 if (XRE_GetProcessType() == GeckoProcessType_Default
) {
2774 TabChild
* tabChild
= TabChild::GetFrom(mShell
);
2775 return (tabChild
&& tabChild
->IsRootContentDocument());
2778 bool nsPresContext::GetPaintFlashing() const
2780 if (!mPaintFlashingInitialized
) {
2781 bool pref
= Preferences::GetBool("nglayout.debug.paint_flashing");
2782 if (!pref
&& IsChrome()) {
2783 pref
= Preferences::GetBool("nglayout.debug.paint_flashing_chrome");
2785 mPaintFlashing
= pref
;
2786 mPaintFlashingInitialized
= true;
2788 return mPaintFlashing
;
2792 nsPresContext::AppUnitsPerDevPixel() const
2794 return mDeviceContext
->AppUnitsPerDevPixel();
2798 nsPresContext::GfxUnitsToAppUnits(gfxFloat aGfxUnits
) const
2800 return mDeviceContext
->GfxUnitsToAppUnits(aGfxUnits
);
2804 nsPresContext::AppUnitsToGfxUnits(nscoord aAppUnits
) const
2806 return mDeviceContext
->AppUnitsToGfxUnits(aAppUnits
);
2810 nsPresContext::IsDeviceSizePageSize()
2812 bool isDeviceSizePageSize
= false;
2813 nsCOMPtr
<nsIDocShell
> docShell(mContainer
);
2815 isDeviceSizePageSize
= docShell
->GetDeviceSizeIsPageSize();
2817 return isDeviceSizePageSize
;
2820 nsRootPresContext::nsRootPresContext(nsIDocument
* aDocument
,
2821 nsPresContextType aType
)
2822 : nsPresContext(aDocument
, aType
),
2827 nsRootPresContext::~nsRootPresContext()
2829 NS_ASSERTION(mRegisteredPlugins
.Count() == 0,
2830 "All plugins should have been unregistered");
2831 CancelDidPaintTimer();
2832 CancelApplyPluginGeometryTimer();
2836 nsRootPresContext::Detach()
2838 CancelDidPaintTimer();
2839 // XXXmats maybe also CancelApplyPluginGeometryTimer(); ?
2840 nsPresContext::Detach();
2844 nsRootPresContext::RegisterPluginForGeometryUpdates(nsIContent
* aPlugin
)
2846 mRegisteredPlugins
.PutEntry(aPlugin
);
2850 nsRootPresContext::UnregisterPluginForGeometryUpdates(nsIContent
* aPlugin
)
2852 mRegisteredPlugins
.RemoveEntry(aPlugin
);
2855 static PLDHashOperator
2856 SetPluginHidden(nsRefPtrHashKey
<nsIContent
>* aEntry
, void* userArg
)
2858 nsIFrame
* root
= static_cast<nsIFrame
*>(userArg
);
2859 nsObjectFrame
* f
= static_cast<nsObjectFrame
*>(aEntry
->GetKey()->GetPrimaryFrame());
2861 NS_WARNING("Null frame in SetPluginHidden");
2862 return PL_DHASH_NEXT
;
2864 if (!nsLayoutUtils::IsAncestorFrameCrossDoc(root
, f
)) {
2865 // f is not managed by this frame so we should ignore it.
2866 return PL_DHASH_NEXT
;
2868 f
->SetEmptyWidgetConfiguration();
2869 return PL_DHASH_NEXT
;
2873 nsRootPresContext::ComputePluginGeometryUpdates(nsIFrame
* aFrame
,
2874 nsDisplayListBuilder
* aBuilder
,
2875 nsDisplayList
* aList
)
2877 if (mRegisteredPlugins
.Count() == 0) {
2881 // Initially make the next state for each plugin descendant of aFrame be
2882 // "hidden". Plugins that are visible will have their next state set to
2883 // unhidden by nsDisplayPlugin::ComputeVisibility.
2884 mRegisteredPlugins
.EnumerateEntries(SetPluginHidden
, aFrame
);
2886 nsIFrame
* rootFrame
= FrameManager()->GetRootFrame();
2888 if (rootFrame
&& aBuilder
->ContainsPluginItem()) {
2889 aBuilder
->SetForPluginGeometry();
2890 aBuilder
->SetAccurateVisibleRegions();
2891 // Merging and flattening has already been done and we should not do it
2892 // again. nsDisplayScroll(Info)Layer doesn't support trying to flatten
2894 aBuilder
->SetAllowMergingAndFlattening(false);
2895 nsRegion region
= rootFrame
->GetVisualOverflowRectRelativeToSelf();
2896 // nsDisplayPlugin::ComputeVisibility will automatically set a non-hidden
2897 // widget configuration for the plugin, if it's visible.
2898 aList
->ComputeVisibilityForRoot(aBuilder
, ®ion
);
2902 // We control painting of Mac plugins, so just apply geometry updates now.
2903 // This is not happening during a paint event.
2904 ApplyPluginGeometryUpdates();
2906 InitApplyPluginGeometryTimer();
2911 ApplyPluginGeometryUpdatesCallback(nsITimer
*aTimer
, void *aClosure
)
2913 static_cast<nsRootPresContext
*>(aClosure
)->ApplyPluginGeometryUpdates();
2917 nsRootPresContext::InitApplyPluginGeometryTimer()
2919 if (mApplyPluginGeometryTimer
) {
2923 // We'll apply the plugin geometry updates during the next compositing paint in this
2924 // presContext (either from nsPresShell::WillPaintWindow or from
2925 // nsPresShell::DidPaintWindow, depending on the platform). But paints might
2926 // get optimized away if the old plugin geometry covers the invalid region,
2927 // so set a backup timer to do this too. We want to make sure this
2928 // won't fire before our normal paint notifications, if those would
2929 // update the geometry, so set it for double the refresh driver interval.
2930 mApplyPluginGeometryTimer
= do_CreateInstance("@mozilla.org/timer;1");
2931 if (mApplyPluginGeometryTimer
) {
2932 mApplyPluginGeometryTimer
->
2933 InitWithFuncCallback(ApplyPluginGeometryUpdatesCallback
, this,
2934 nsRefreshDriver::DefaultInterval() * 2,
2935 nsITimer::TYPE_ONE_SHOT
);
2940 nsRootPresContext::CancelApplyPluginGeometryTimer()
2942 if (mApplyPluginGeometryTimer
) {
2943 mApplyPluginGeometryTimer
->Cancel();
2944 mApplyPluginGeometryTimer
= nullptr;
2949 HasOverlap(const nsIntPoint
& aOffset1
, const nsTArray
<nsIntRect
>& aClipRects1
,
2950 const nsIntPoint
& aOffset2
, const nsTArray
<nsIntRect
>& aClipRects2
)
2952 nsIntPoint offsetDelta
= aOffset1
- aOffset2
;
2953 for (uint32_t i
= 0; i
< aClipRects1
.Length(); ++i
) {
2954 for (uint32_t j
= 0; j
< aClipRects2
.Length(); ++j
) {
2955 if ((aClipRects1
[i
] + offsetDelta
).Intersects(aClipRects2
[j
]))
2963 * Given a list of plugin windows to move to new locations, sort the list
2964 * so that for each window move, the window moves to a location that
2965 * does not intersect other windows. This minimizes flicker and repainting.
2966 * It's not always possible to do this perfectly, since in general
2967 * we might have cycles. But we do our best.
2968 * We need to take into account that windows are clipped to particular
2969 * regions and the clip regions change as the windows are moved.
2972 SortConfigurations(nsTArray
<nsIWidget::Configuration
>* aConfigurations
)
2974 if (aConfigurations
->Length() > 10) {
2975 // Give up, we don't want to get bogged down here
2979 nsTArray
<nsIWidget::Configuration
> pluginsToMove
;
2980 pluginsToMove
.SwapElements(*aConfigurations
);
2982 // Our algorithm is quite naive. At each step we try to identify
2983 // a window that can be moved to its new location that won't overlap
2984 // any other windows at the new location. If there is no such
2985 // window, we just move the last window in the list anyway.
2986 while (!pluginsToMove
.IsEmpty()) {
2987 // Find a window whose destination does not overlap any other window
2989 for (i
= 0; i
+ 1 < pluginsToMove
.Length(); ++i
) {
2990 nsIWidget::Configuration
* config
= &pluginsToMove
[i
];
2991 bool foundOverlap
= false;
2992 for (uint32_t j
= 0; j
< pluginsToMove
.Length(); ++j
) {
2996 pluginsToMove
[j
].mChild
->GetBounds(bounds
);
2997 nsAutoTArray
<nsIntRect
,1> clipRects
;
2998 pluginsToMove
[j
].mChild
->GetWindowClipRegion(&clipRects
);
2999 if (HasOverlap(bounds
.TopLeft(), clipRects
,
3000 config
->mBounds
.TopLeft(),
3001 config
->mClipRegion
)) {
3002 foundOverlap
= true;
3009 // Note that we always move the last plugin in pluginsToMove, if we
3010 // can't find any other plugin to move
3011 aConfigurations
->AppendElement(pluginsToMove
[i
]);
3012 pluginsToMove
.RemoveElementAt(i
);
3016 static PLDHashOperator
3017 PluginDidSetGeometryEnumerator(nsRefPtrHashKey
<nsIContent
>* aEntry
, void* userArg
)
3019 nsObjectFrame
* f
= static_cast<nsObjectFrame
*>(aEntry
->GetKey()->GetPrimaryFrame());
3021 NS_WARNING("Null frame in PluginDidSetGeometryEnumerator");
3022 return PL_DHASH_NEXT
;
3024 f
->DidSetWidgetGeometry();
3025 return PL_DHASH_NEXT
;
3028 struct PluginGetGeometryUpdateClosure
{
3029 nsTArray
<nsIWidget::Configuration
> mConfigurations
;
3031 static PLDHashOperator
3032 PluginGetGeometryUpdate(nsRefPtrHashKey
<nsIContent
>* aEntry
, void* userArg
)
3034 PluginGetGeometryUpdateClosure
* closure
=
3035 static_cast<PluginGetGeometryUpdateClosure
*>(userArg
);
3036 nsObjectFrame
* f
= static_cast<nsObjectFrame
*>(aEntry
->GetKey()->GetPrimaryFrame());
3038 NS_WARNING("Null frame in GetPluginGeometryUpdate");
3039 return PL_DHASH_NEXT
;
3041 f
->GetWidgetConfiguration(&closure
->mConfigurations
);
3042 return PL_DHASH_NEXT
;
3046 nsRootPresContext::ApplyPluginGeometryUpdates()
3048 CancelApplyPluginGeometryTimer();
3050 PluginGetGeometryUpdateClosure closure
;
3051 mRegisteredPlugins
.EnumerateEntries(PluginGetGeometryUpdate
, &closure
);
3052 // Walk mRegisteredPlugins and ask each plugin for its configuration
3053 if (!closure
.mConfigurations
.IsEmpty()) {
3054 nsIWidget
* widget
= closure
.mConfigurations
[0].mChild
->GetParent();
3055 NS_ASSERTION(widget
, "Plugins must have a parent window");
3056 SortConfigurations(&closure
.mConfigurations
);
3057 widget
->ConfigureChildren(closure
.mConfigurations
);
3059 mRegisteredPlugins
.EnumerateEntries(PluginDidSetGeometryEnumerator
, nullptr);
3063 NotifyDidPaintForSubtreeCallback(nsITimer
*aTimer
, void *aClosure
)
3065 nsPresContext
* presContext
= (nsPresContext
*)aClosure
;
3066 nsAutoScriptBlocker blockScripts
;
3067 // This is a fallback if we don't get paint events for some reason
3068 // so we'll just pretend both layer painting and compositing happened.
3069 presContext
->NotifyDidPaintForSubtree(
3070 nsIPresShell::PAINT_LAYERS
| nsIPresShell::PAINT_COMPOSITE
);
3074 nsRootPresContext::EnsureEventualDidPaintEvent()
3076 if (mNotifyDidPaintTimer
)
3078 mNotifyDidPaintTimer
= do_CreateInstance("@mozilla.org/timer;1");
3079 if (!mNotifyDidPaintTimer
)
3081 mNotifyDidPaintTimer
->InitWithFuncCallback(NotifyDidPaintForSubtreeCallback
,
3082 (void*)this, 100, nsITimer::TYPE_ONE_SHOT
);
3086 nsRootPresContext::AddWillPaintObserver(nsIRunnable
* aRunnable
)
3088 if (!mWillPaintFallbackEvent
.IsPending()) {
3089 mWillPaintFallbackEvent
= new RunWillPaintObservers(this);
3090 NS_DispatchToMainThread(mWillPaintFallbackEvent
.get());
3092 mWillPaintObservers
.AppendElement(aRunnable
);
3096 * Run all runnables that need to get called before the next paint.
3099 nsRootPresContext::FlushWillPaintObservers()
3101 mWillPaintFallbackEvent
= nullptr;
3102 nsTArray
<nsCOMPtr
<nsIRunnable
> > observers
;
3103 observers
.SwapElements(mWillPaintObservers
);
3104 for (uint32_t i
= 0; i
< observers
.Length(); ++i
) {
3105 observers
[i
]->Run();
3110 nsRootPresContext::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf
) const
3112 return nsPresContext::SizeOfExcludingThis(aMallocSizeOf
);
3114 // Measurement of the following members may be added later if DMD finds it is
3116 // - mNotifyDidPaintTimer
3117 // - mRegisteredPlugins
3118 // - mWillPaintObservers
3119 // - mWillPaintFallbackEvent