1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
23 * L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
24 * Ehsan Akhgari <ehsan.akhgari@gmail.com>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 /* a presentation of a document, part 1 */
43 #include "nsPresContext.h"
44 #include "nsIPresShell.h"
45 #include "nsILinkHandler.h"
46 #include "nsIDocShellTreeItem.h"
47 #include "nsIDocShell.h"
48 #include "nsIContentViewer.h"
49 #include "nsIDocumentViewer.h"
50 #include "nsPIDOMWindow.h"
51 #include "nsStyleSet.h"
52 #include "nsImageLoader.h"
53 #include "nsIContent.h"
55 #include "nsIRenderingContext.h"
57 #include "nsIDocument.h"
58 #include "nsStyleContext.h"
59 #include "nsILookAndFeel.h"
60 #include "nsWidgetsCID.h"
61 #include "nsIComponentManager.h"
62 #include "nsIURIContentListener.h"
63 #include "nsIInterfaceRequestor.h"
64 #include "nsIInterfaceRequestorUtils.h"
65 #include "nsIServiceManager.h"
66 #include "nsIDOMElement.h"
67 #include "nsContentPolicyUtils.h"
68 #include "nsIDOMWindow.h"
69 #include "nsXPIDLString.h"
70 #include "nsIWeakReferenceUtils.h"
71 #include "nsCSSRendering.h"
73 #include "nsContentPolicyUtils.h"
74 #include "nsIDOMDocument.h"
75 #include "nsAutoPtr.h"
76 #include "nsEventStateManager.h"
77 #include "nsThreadUtils.h"
78 #include "nsFrameManager.h"
79 #include "nsLayoutUtils.h"
80 #include "nsIViewManager.h"
81 #include "nsCSSFrameConstructor.h"
82 #include "nsCSSRuleProcessor.h"
83 #include "nsStyleChangeList.h"
84 #include "nsRuleNode.h"
85 #include "nsEventDispatcher.h"
86 #include "gfxUserFontSet.h"
87 #include "gfxPlatform.h"
88 #include "nsCSSRules.h"
89 #include "nsFontFaceLoader.h"
90 #include "nsIEventListenerManager.h"
91 #include "nsStyleStructInlines.h"
92 #include "nsIAppShell.h"
94 #include "nsIPrivateDOMEvent.h"
95 #include "nsIDOMEventTarget.h"
96 #include "nsObjectFrame.h"
97 #include "nsTransitionManager.h"
98 #include "mozilla/dom/Element.h"
99 #include "nsIFrameMessageManager.h"
102 #include "nsSMILAnimationController.h"
106 #include "nsBidiPresUtils.h"
109 #include "nsContentUtils.h"
110 #include "nsPIWindowRoot.h"
112 // Needed for Start/Stop of Image Animation
113 #include "imgIContainer.h"
114 #include "nsIImageLoadingContent.h"
116 //needed for resetting of image service color
117 #include "nsLayoutCID.h"
119 using mozilla::TimeDuration
;
120 using mozilla::TimeStamp
;
121 using namespace mozilla::dom
;
124 MakeColorPref(const char *colstr
)
126 PRUint32 red
, green
, blue
;
129 // 4.x stored RGB color values as a string rather than as an int,
130 // thus we need to do this conversion
131 PR_sscanf(colstr
, "#%02x%02x%02x", &red
, &green
, &blue
);
132 colorref
= NS_RGB(red
, green
, blue
);
137 nsPresContext::PrefChangedCallback(const char* aPrefName
, void* instance_data
)
139 nsPresContext
* presContext
= (nsPresContext
*)instance_data
;
141 NS_ASSERTION(nsnull
!= presContext
, "bad instance data");
142 if (nsnull
!= presContext
) {
143 presContext
->PreferenceChanged(aPrefName
);
150 nsPresContext::PrefChangedUpdateTimerCallback(nsITimer
*aTimer
, void *aClosure
)
152 nsPresContext
* presContext
= (nsPresContext
*)aClosure
;
153 NS_ASSERTION(presContext
!= nsnull
, "bad instance data");
155 presContext
->UpdateAfterPreferencesChanged();
160 IsVisualCharset(const nsCString
& aCharset
)
162 if (aCharset
.LowerCaseEqualsLiteral("ibm864") // Arabic//ahmed
163 || aCharset
.LowerCaseEqualsLiteral("ibm862") // Hebrew
164 || aCharset
.LowerCaseEqualsLiteral("iso-8859-8") ) { // Hebrew
165 return PR_TRUE
; // visual text type
168 return PR_FALSE
; // logical text type
174 static PLDHashOperator
175 destroy_loads(const void * aKey
, nsRefPtr
<nsImageLoader
>& aData
, void* closure
)
178 return PL_DHASH_NEXT
;
181 static NS_DEFINE_CID(kLookAndFeelCID
, NS_LOOKANDFEEL_CID
);
182 #include "nsContentCID.h"
184 // NOTE! nsPresContext::operator new() zeroes out all members, so don't
185 // bother initializing members to 0.
187 nsPresContext::nsPresContext(nsIDocument
* aDocument
, nsPresContextType aType
)
188 : mType(aType
), mDocument(aDocument
), mTextZoom(1.0), mFullZoom(1.0),
189 mPageSize(-1, -1), mPPScale(1.0f
),
190 mViewportStyleOverflow(NS_STYLE_OVERFLOW_AUTO
, NS_STYLE_OVERFLOW_AUTO
),
191 mImageAnimationModePref(imgIContainer::kNormalAnimMode
),
192 // Font sizes default to zero; they will be set in GetFontPreferences
193 mDefaultVariableFont("serif", NS_FONT_STYLE_NORMAL
, NS_FONT_VARIANT_NORMAL
,
194 NS_FONT_WEIGHT_NORMAL
, NS_FONT_STRETCH_NORMAL
, 0, 0),
195 mDefaultFixedFont("monospace", NS_FONT_STYLE_NORMAL
,
196 NS_FONT_VARIANT_NORMAL
, NS_FONT_WEIGHT_NORMAL
,
197 NS_FONT_STRETCH_NORMAL
, 0, 0),
198 mDefaultSerifFont("serif", NS_FONT_STYLE_NORMAL
, NS_FONT_VARIANT_NORMAL
,
199 NS_FONT_WEIGHT_NORMAL
, NS_FONT_STRETCH_NORMAL
, 0, 0),
200 mDefaultSansSerifFont("sans-serif", NS_FONT_STYLE_NORMAL
,
201 NS_FONT_VARIANT_NORMAL
, NS_FONT_WEIGHT_NORMAL
,
202 NS_FONT_STRETCH_NORMAL
, 0, 0),
203 mDefaultMonospaceFont("monospace", NS_FONT_STYLE_NORMAL
,
204 NS_FONT_VARIANT_NORMAL
, NS_FONT_WEIGHT_NORMAL
,
205 NS_FONT_STRETCH_NORMAL
, 0, 0),
206 mDefaultCursiveFont("cursive", NS_FONT_STYLE_NORMAL
,
207 NS_FONT_VARIANT_NORMAL
, NS_FONT_WEIGHT_NORMAL
,
208 NS_FONT_STRETCH_NORMAL
, 0, 0),
209 mDefaultFantasyFont("fantasy", NS_FONT_STYLE_NORMAL
,
210 NS_FONT_VARIANT_NORMAL
, NS_FONT_WEIGHT_NORMAL
,
211 NS_FONT_STRETCH_NORMAL
, 0, 0)
213 // NOTE! nsPresContext::operator new() zeroes out all members, so don't
214 // bother initializing members to 0.
216 mDoScaledTwips
= PR_TRUE
;
218 SetBackgroundImageDraw(PR_TRUE
); // always draw the background
219 SetBackgroundColorDraw(PR_TRUE
);
221 mBackgroundColor
= NS_RGB(0xFF, 0xFF, 0xFF);
223 mUseDocumentColors
= PR_TRUE
;
224 mUseDocumentFonts
= PR_TRUE
;
226 // the minimum font-size is unconstrained by default
228 mLinkColor
= NS_RGB(0x00, 0x00, 0xEE);
229 mActiveLinkColor
= NS_RGB(0xEE, 0x00, 0x00);
230 mVisitedLinkColor
= NS_RGB(0x55, 0x1A, 0x8B);
231 mUnderlineLinks
= PR_TRUE
;
232 mSendAfterPaintToContent
= PR_FALSE
;
234 mFocusTextColor
= mDefaultColor
;
235 mFocusBackgroundColor
= mBackgroundColor
;
238 if (aType
== eContext_Galley
) {
239 mMedium
= nsGkAtoms::screen
;
241 mMedium
= nsGkAtoms::print
;
242 mPaginated
= PR_TRUE
;
246 mImageAnimationMode
= imgIContainer::kDontAnimMode
;
247 mNeverAnimate
= PR_TRUE
;
249 mImageAnimationMode
= imgIContainer::kNormalAnimMode
;
250 mNeverAnimate
= PR_FALSE
;
252 NS_ASSERTION(mDocument
, "Null document");
253 mUserFontSet
= nsnull
;
254 mUserFontSetDirty
= PR_TRUE
;
257 nsPresContext::~nsPresContext()
259 NS_PRECONDITION(!mShell
, "Presshell forgot to clear our mShell pointer");
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(nsnull
);
273 NS_RELEASE(mEventManager
);
276 if (mPrefChangedTimer
)
278 mPrefChangedTimer
->Cancel();
279 mPrefChangedTimer
= nsnull
;
282 // Unregister preference callbacks
283 nsContentUtils::UnregisterPrefCallback("font.",
284 nsPresContext::PrefChangedCallback
,
286 nsContentUtils::UnregisterPrefCallback("browser.display.",
287 nsPresContext::PrefChangedCallback
,
289 nsContentUtils::UnregisterPrefCallback("browser.underline_anchors",
290 nsPresContext::PrefChangedCallback
,
292 nsContentUtils::UnregisterPrefCallback("browser.anchor_color",
293 nsPresContext::PrefChangedCallback
,
295 nsContentUtils::UnregisterPrefCallback("browser.active_color",
296 nsPresContext::PrefChangedCallback
,
298 nsContentUtils::UnregisterPrefCallback("browser.visited_color",
299 nsPresContext::PrefChangedCallback
,
301 nsContentUtils::UnregisterPrefCallback("image.animation_mode",
302 nsPresContext::PrefChangedCallback
,
305 nsContentUtils::UnregisterPrefCallback("bidi.", PrefChangedCallback
, this);
307 nsContentUtils::UnregisterPrefCallback("dom.send_after_paint_to_content",
308 nsPresContext::PrefChangedCallback
,
310 nsContentUtils::UnregisterPrefCallback("gfx.font_rendering.",
311 nsPresContext::PrefChangedCallback
,
313 nsContentUtils::UnregisterPrefCallback("layout.css.dpi",
314 nsPresContext::PrefChangedCallback
,
316 nsContentUtils::UnregisterPrefCallback("layout.css.devPixelsPerPx",
317 nsPresContext::PrefChangedCallback
,
320 NS_IF_RELEASE(mDeviceContext
);
321 NS_IF_RELEASE(mLookAndFeel
);
322 NS_IF_RELEASE(mLanguage
);
325 NS_IMPL_CYCLE_COLLECTION_CLASS(nsPresContext
)
327 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPresContext
)
328 NS_INTERFACE_MAP_ENTRY(nsISupports
)
329 NS_INTERFACE_MAP_ENTRY(nsIObserver
)
332 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPresContext
)
333 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPresContext
)
335 static PLDHashOperator
336 TraverseImageLoader(const void * aKey
, nsRefPtr
<nsImageLoader
>& aData
,
339 nsCycleCollectionTraversalCallback
*cb
=
340 static_cast<nsCycleCollectionTraversalCallback
*>(aClosure
);
342 cb
->NoteXPCOMChild(aData
);
344 return PL_DHASH_NEXT
;
347 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsPresContext
)
348 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocument
);
349 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mDeviceContext
); // worth bothering?
350 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mEventManager
);
351 // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mLookAndFeel); // a service
352 // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mLanguage); // an atom
354 for (PRUint32 i
= 0; i
< IMAGE_LOAD_TYPE_COUNT
; ++i
)
355 tmp
->mImageLoaders
[i
].Enumerate(TraverseImageLoader
, &cb
);
357 // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTheme); // a service
358 // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLangService); // a service
359 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrintSettings
);
360 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrefChangedTimer
);
362 tmp
->mBidiUtils
->Traverse(cb
);
363 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
365 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsPresContext
)
366 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocument
);
367 NS_RELEASE(tmp
->mDeviceContext
); // worth bothering?
368 if (tmp
->mEventManager
) {
369 // unclear if these are needed, but can't hurt
370 tmp
->mEventManager
->NotifyDestroyPresContext(tmp
);
371 tmp
->mEventManager
->SetPresContext(nsnull
);
373 NS_RELEASE(tmp
->mEventManager
);
376 // NS_RELEASE(tmp->mLookAndFeel); // a service
377 // NS_RELEASE(tmp->mLanguage); // an atom
379 // NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTheme); // a service
380 // NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLangService); // a service
381 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mPrintSettings
);
382 if (tmp
->mPrefChangedTimer
)
384 tmp
->mPrefChangedTimer
->Cancel();
385 tmp
->mPrefChangedTimer
= nsnull
;
388 tmp
->mBidiUtils
->Unlink();
389 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
392 #define MAKE_FONT_PREF_KEY(_pref, _s0, _s1) \
396 static const char* const kGenericFont
[] = {
406 // whether no native theme service exists;
407 // if this gets set to true, we'll stop asking for it.
408 static PRBool sNoTheme
= PR_FALSE
;
410 // Set to true when LookAndFeelChanged needs to be called. This is used
411 // because the look and feel is a service, so there's no need to notify it from
412 // more than one prescontext.
413 static PRBool sLookAndFeelChanged
;
415 // Set to true when ThemeChanged needs to be called on mTheme. This is used
416 // because mTheme is a service, so there's no need to notify it from more than
418 static PRBool sThemeChanged
;
421 nsPresContext::GetFontPreferences()
423 /* Fetch the font prefs to be used -- see bug 61883 for details.
424 Not all prefs are needed upfront. Some are fallback prefs intended
425 for the GFX font sub-system...
427 1) unit : assumed to be the same for all language groups -------------
428 font.size.unit = px | pt XXX could be folded in the size... bug 90440
430 2) attributes for generic fonts --------------------------------------
431 font.default = serif | sans-serif - fallback generic font
432 font.name.[generic].[langGroup] = current user' selected font on the pref dialog
433 font.name-list.[generic].[langGroup] = fontname1, fontname2, ... [factory pre-built list]
434 font.size.[generic].[langGroup] = integer - settable by the user
435 font.size-adjust.[generic].[langGroup] = "float" - settable by the user
436 font.minimum-size.[langGroup] = integer - settable by the user
439 mDefaultVariableFont
.size
= CSSPixelsToAppUnits(16);
440 mDefaultFixedFont
.size
= CSSPixelsToAppUnits(13);
442 // the font prefs are based on langGroup, not actual language
443 nsCAutoString langGroup
;
444 if (mLanguage
&& mLangService
) {
446 nsIAtom
*group
= mLangService
->GetLanguageGroup(mLanguage
, &rv
);
447 if (NS_SUCCEEDED(rv
) && group
) {
448 group
->ToUTF8String(langGroup
);
451 langGroup
.AssignLiteral("x-western"); // Assume x-western is safe...
455 langGroup
.AssignLiteral("x-western"); // Assume x-western is safe...
460 // get the current applicable font-size unit
461 enum {eUnit_unknown
= -1, eUnit_px
, eUnit_pt
};
462 PRInt32 unit
= eUnit_px
;
464 nsAdoptingCString cvalue
=
465 nsContentUtils::GetCharPref("font.size.unit");
467 if (!cvalue
.IsEmpty()) {
468 if (cvalue
.Equals("px")) {
471 else if (cvalue
.Equals("pt")) {
475 NS_WARNING("unexpected font-size unit -- expected: 'px' or 'pt'");
476 unit
= eUnit_unknown
;
480 // get font.minimum-size.[langGroup]
482 pref
.Assign("font.minimum-size.");
483 pref
.Append(langGroup
);
485 PRInt32 size
= nsContentUtils::GetIntPref(pref
.get());
486 if (unit
== eUnit_px
) {
487 mMinimumFontSize
= CSSPixelsToAppUnits(size
);
489 else if (unit
== eUnit_pt
) {
490 mMinimumFontSize
= CSSPointsToAppUnits(size
);
493 // get attributes specific to each generic font
494 nsCAutoString generic_dot_langGroup
;
495 for (PRInt32 eType
= eDefaultFont_Variable
; eType
< eDefaultFont_COUNT
; ++eType
) {
496 generic_dot_langGroup
.Assign(kGenericFont
[eType
]);
497 generic_dot_langGroup
.Append(langGroup
);
501 case eDefaultFont_Variable
: font
= &mDefaultVariableFont
; break;
502 case eDefaultFont_Fixed
: font
= &mDefaultFixedFont
; break;
503 case eDefaultFont_Serif
: font
= &mDefaultSerifFont
; break;
504 case eDefaultFont_SansSerif
: font
= &mDefaultSansSerifFont
; break;
505 case eDefaultFont_Monospace
: font
= &mDefaultMonospaceFont
; break;
506 case eDefaultFont_Cursive
: font
= &mDefaultCursiveFont
; break;
507 case eDefaultFont_Fantasy
: font
= &mDefaultFantasyFont
; break;
510 // set the default variable font (the other fonts are seen as 'generic' fonts
511 // in GFX and will be queried there when hunting for alternative fonts)
512 if (eType
== eDefaultFont_Variable
) {
513 MAKE_FONT_PREF_KEY(pref
, "font.name", generic_dot_langGroup
);
515 nsAdoptingString value
=
516 nsContentUtils::GetStringPref(pref
.get());
517 if (!value
.IsEmpty()) {
518 font
->name
.Assign(value
);
521 MAKE_FONT_PREF_KEY(pref
, "font.default.", langGroup
);
522 value
= nsContentUtils::GetStringPref(pref
.get());
523 if (!value
.IsEmpty()) {
524 mDefaultVariableFont
.name
.Assign(value
);
529 if (eType
== eDefaultFont_Monospace
) {
530 // This takes care of the confusion whereby people often expect "monospace"
531 // to have the same default font-size as "-moz-fixed" (this tentative
532 // size may be overwritten with the specific value for "monospace" when
533 // "font.size.monospace.[langGroup]" is read -- see below)
534 font
->size
= mDefaultFixedFont
.size
;
536 else if (eType
!= eDefaultFont_Fixed
) {
537 // all the other generic fonts are initialized with the size of the
538 // variable font, but their specific size can supersede later -- see below
539 font
->size
= mDefaultVariableFont
.size
;
543 // Bug 84398: for spec purists, a different font-size only applies to the
544 // .variable. and .fixed. fonts and the other fonts should get |font-size-adjust|.
545 // The problem is that only GfxWin has the support for |font-size-adjust|. So for
546 // parity, we enable the ability to set a different font-size on all platforms.
548 // get font.size.[generic].[langGroup]
549 // size=0 means 'Auto', i.e., generic fonts retain the size of the variable font
550 MAKE_FONT_PREF_KEY(pref
, "font.size", generic_dot_langGroup
);
551 size
= nsContentUtils::GetIntPref(pref
.get());
553 if (unit
== eUnit_px
) {
554 font
->size
= CSSPixelsToAppUnits(size
);
556 else if (unit
== eUnit_pt
) {
557 font
->size
= CSSPointsToAppUnits(size
);
561 // get font.size-adjust.[generic].[langGroup]
562 // XXX only applicable on GFX ports that handle |font-size-adjust|
563 MAKE_FONT_PREF_KEY(pref
, "font.size-adjust", generic_dot_langGroup
);
564 cvalue
= nsContentUtils::GetCharPref(pref
.get());
565 if (!cvalue
.IsEmpty()) {
566 font
->sizeAdjust
= (float)atof(cvalue
.get());
570 printf("%s Family-list:%s size:%d sizeAdjust:%.2f\n",
571 generic_dot_langGroup
.get(),
572 NS_ConvertUTF16toUTF8(font
->name
).get(), font
->size
,
579 nsPresContext::GetDocumentColorPreferences()
581 PRInt32 useAccessibilityTheme
= 0;
582 PRBool usePrefColors
= PR_TRUE
;
583 nsCOMPtr
<nsIDocShellTreeItem
> docShell(do_QueryReferent(mContainer
));
585 PRInt32 docShellType
;
586 docShell
->GetItemType(&docShellType
);
587 if (nsIDocShellTreeItem::typeChrome
== docShellType
) {
588 usePrefColors
= PR_FALSE
;
591 mLookAndFeel
->GetMetric(nsILookAndFeel::eMetric_UseAccessibilityTheme
, useAccessibilityTheme
);
592 usePrefColors
= !useAccessibilityTheme
;
598 !nsContentUtils::GetBoolPref("browser.display.use_system_colors",
603 nsAdoptingCString colorStr
=
604 nsContentUtils::GetCharPref("browser.display.foreground_color");
606 if (!colorStr
.IsEmpty()) {
607 mDefaultColor
= MakeColorPref(colorStr
);
611 nsContentUtils::GetCharPref("browser.display.background_color");
613 if (!colorStr
.IsEmpty()) {
614 mBackgroundColor
= MakeColorPref(colorStr
);
618 mDefaultColor
= NS_RGB(0x00, 0x00, 0x00);
619 mBackgroundColor
= NS_RGB(0xFF, 0xFF, 0xFF);
620 mLookAndFeel
->GetColor(nsILookAndFeel::eColor_WindowForeground
,
622 mLookAndFeel
->GetColor(nsILookAndFeel::eColor_WindowBackground
,
626 // Wherever we got the default background color from, ensure it is
628 mBackgroundColor
= NS_ComposeColors(NS_RGB(0xFF, 0xFF, 0xFF),
631 mUseDocumentColors
= !useAccessibilityTheme
&&
632 nsContentUtils::GetBoolPref("browser.display.use_document_colors",
637 nsPresContext::GetUserPreferences()
639 if (!GetPresShell()) {
640 // No presshell means nothing to do here. We'll do this when we
646 nsContentUtils::GetIntPref("browser.display.base_font_scaler",
650 mAutoQualityMinFontSizePixelsPref
=
651 nsContentUtils::GetIntPref("browser.display.auto_quality_min_font_size");
654 GetDocumentColorPreferences();
656 mSendAfterPaintToContent
=
657 nsContentUtils::GetBoolPref("dom.send_after_paint_to_content",
658 mSendAfterPaintToContent
);
662 nsContentUtils::GetBoolPref("browser.underline_anchors", mUnderlineLinks
);
664 nsAdoptingCString colorStr
=
665 nsContentUtils::GetCharPref("browser.anchor_color");
667 if (!colorStr
.IsEmpty()) {
668 mLinkColor
= MakeColorPref(colorStr
);
672 nsContentUtils::GetCharPref("browser.active_color");
674 if (!colorStr
.IsEmpty()) {
675 mActiveLinkColor
= MakeColorPref(colorStr
);
678 colorStr
= nsContentUtils::GetCharPref("browser.visited_color");
680 if (!colorStr
.IsEmpty()) {
681 mVisitedLinkColor
= MakeColorPref(colorStr
);
685 nsContentUtils::GetBoolPref("browser.display.use_focus_colors",
688 mFocusTextColor
= mDefaultColor
;
689 mFocusBackgroundColor
= mBackgroundColor
;
691 colorStr
= nsContentUtils::GetCharPref("browser.display.focus_text_color");
693 if (!colorStr
.IsEmpty()) {
694 mFocusTextColor
= MakeColorPref(colorStr
);
698 nsContentUtils::GetCharPref("browser.display.focus_background_color");
700 if (!colorStr
.IsEmpty()) {
701 mFocusBackgroundColor
= MakeColorPref(colorStr
);
705 nsContentUtils::GetIntPref("browser.display.focus_ring_width",
708 mFocusRingOnAnything
=
709 nsContentUtils::GetBoolPref("browser.display.focus_ring_on_anything",
710 mFocusRingOnAnything
);
713 nsContentUtils::GetIntPref("browser.display.focus_ring_style",
717 nsContentUtils::GetIntPref("browser.display.use_document_fonts") != 0;
719 // * replace backslashes with Yen signs? (bug 245770)
720 mEnableJapaneseTransform
=
721 nsContentUtils::GetBoolPref("layout.enable_japanese_specific_transform");
724 nsContentUtils::GetIntPref("layout.scrollbar.side");
726 GetFontPreferences();
729 const nsAdoptingCString
& animatePref
=
730 nsContentUtils::GetCharPref("image.animation_mode");
731 if (animatePref
.Equals("normal"))
732 mImageAnimationModePref
= imgIContainer::kNormalAnimMode
;
733 else if (animatePref
.Equals("none"))
734 mImageAnimationModePref
= imgIContainer::kDontAnimMode
;
735 else if (animatePref
.Equals("once"))
736 mImageAnimationModePref
= imgIContainer::kLoopOnceAnimMode
;
737 else // dynamic change to invalid value should act like it does initially
738 mImageAnimationModePref
= imgIContainer::kNormalAnimMode
;
740 PRUint32 bidiOptions
= GetBidi();
743 nsContentUtils::GetIntPref(IBMBIDI_TEXTDIRECTION_STR
,
744 GET_BIDI_OPTION_DIRECTION(bidiOptions
));
745 SET_BIDI_OPTION_DIRECTION(bidiOptions
, prefInt
);
746 mPrefBidiDirection
= prefInt
;
749 nsContentUtils::GetIntPref(IBMBIDI_TEXTTYPE_STR
,
750 GET_BIDI_OPTION_TEXTTYPE(bidiOptions
));
751 SET_BIDI_OPTION_TEXTTYPE(bidiOptions
, prefInt
);
754 nsContentUtils::GetIntPref(IBMBIDI_NUMERAL_STR
,
755 GET_BIDI_OPTION_NUMERAL(bidiOptions
));
756 SET_BIDI_OPTION_NUMERAL(bidiOptions
, prefInt
);
759 nsContentUtils::GetIntPref(IBMBIDI_SUPPORTMODE_STR
,
760 GET_BIDI_OPTION_SUPPORT(bidiOptions
));
761 SET_BIDI_OPTION_SUPPORT(bidiOptions
, prefInt
);
764 nsContentUtils::GetIntPref(IBMBIDI_CHARSET_STR
,
765 GET_BIDI_OPTION_CHARACTERSET(bidiOptions
));
766 SET_BIDI_OPTION_CHARACTERSET(bidiOptions
, prefInt
);
768 // We don't need to force reflow: either we are initializing a new
769 // prescontext or we are being called from UpdateAfterPreferencesChanged()
770 // which triggers a reflow anyway.
771 SetBidi(bidiOptions
, PR_FALSE
);
775 nsPresContext::PreferenceChanged(const char* aPrefName
)
777 nsDependentCString
prefName(aPrefName
);
778 if (prefName
.EqualsLiteral("layout.css.dpi") ||
779 prefName
.EqualsLiteral("layout.css.devPixelsPerPx")) {
780 PRInt32 oldAppUnitsPerDevPixel
= AppUnitsPerDevPixel();
781 if (mDeviceContext
->CheckDPIChange() && mShell
) {
782 mDeviceContext
->FlushFontCache();
784 // Re-fetch the view manager's window dimensions in case there's a deferred
785 // resize which hasn't affected our mVisibleArea yet
786 nscoord oldWidthAppUnits
, oldHeightAppUnits
;
787 nsIViewManager
* vm
= mShell
->GetViewManager();
788 vm
->GetWindowDimensions(&oldWidthAppUnits
, &oldHeightAppUnits
);
789 float oldWidthDevPixels
= oldWidthAppUnits
/oldAppUnitsPerDevPixel
;
790 float oldHeightDevPixels
= oldHeightAppUnits
/oldAppUnitsPerDevPixel
;
792 nscoord width
= NSToCoordRound(oldWidthDevPixels
*AppUnitsPerDevPixel());
793 nscoord height
= NSToCoordRound(oldHeightDevPixels
*AppUnitsPerDevPixel());
794 vm
->SetWindowDimensions(width
, height
);
796 MediaFeatureValuesChanged(PR_TRUE
);
797 RebuildAllStyleData(NS_STYLE_HINT_REFLOW
);
801 if (StringBeginsWith(prefName
, NS_LITERAL_CSTRING("font."))) {
802 // Changes to font family preferences don't change anything in the
803 // computed style data, so the style system won't generate a reflow
804 // hint for us. We need to do that manually.
806 // FIXME We could probably also handle changes to
807 // browser.display.auto_quality_min_font_size here, but that
808 // probably also requires clearing the text run cache, so don't
809 // bother (yet, anyway).
810 mPrefChangePendingNeedsReflow
= PR_TRUE
;
812 if (StringBeginsWith(prefName
, NS_LITERAL_CSTRING("bidi."))) {
813 // Changes to bidi prefs need to trigger a reflow (see bug 443629)
814 mPrefChangePendingNeedsReflow
= PR_TRUE
;
816 // Changes to bidi.numeral also needs to empty the text run cache.
817 // This is handled in gfxTextRunWordCache.cpp.
819 if (StringBeginsWith(prefName
, NS_LITERAL_CSTRING("gfx.font_rendering."))) {
820 // Changes to font_rendering prefs need to trigger a reflow
821 mPrefChangePendingNeedsReflow
= PR_TRUE
;
823 // we use a zero-delay timer to coalesce multiple pref updates
824 if (!mPrefChangedTimer
)
826 mPrefChangedTimer
= do_CreateInstance("@mozilla.org/timer;1");
827 if (!mPrefChangedTimer
)
829 mPrefChangedTimer
->InitWithFuncCallback(nsPresContext::PrefChangedUpdateTimerCallback
, (void*)this, 0, nsITimer::TYPE_ONE_SHOT
);
834 nsPresContext::UpdateAfterPreferencesChanged()
836 mPrefChangedTimer
= nsnull
;
838 nsCOMPtr
<nsIDocShellTreeItem
> docShell(do_QueryReferent(mContainer
));
840 PRInt32 docShellType
;
841 docShell
->GetItemType(&docShellType
);
842 if (nsIDocShellTreeItem::typeChrome
== docShellType
)
846 // Initialize our state from the user preferences
847 GetUserPreferences();
849 // update the presShell: tell it to set the preference style rules up
851 mShell
->SetPreferenceStyleRules(PR_TRUE
);
854 mDeviceContext
->FlushFontCache();
856 nsChangeHint hint
= nsChangeHint(0);
858 if (mPrefChangePendingNeedsReflow
) {
859 NS_UpdateHint(hint
, NS_STYLE_HINT_REFLOW
);
862 RebuildAllStyleData(hint
);
866 nsPresContext::Init(nsIDeviceContext
* aDeviceContext
)
868 NS_ASSERTION(!mInitialized
, "attempt to reinit pres context");
869 NS_ENSURE_ARG(aDeviceContext
);
871 mDeviceContext
= aDeviceContext
;
872 NS_ADDREF(mDeviceContext
);
874 if (mDeviceContext
->SetPixelScale(mFullZoom
))
875 mDeviceContext
->FlushFontCache();
876 mCurAppUnitsPerDevPixel
= AppUnitsPerDevPixel();
878 for (PRUint32 i
= 0; i
< IMAGE_LOAD_TYPE_COUNT
; ++i
)
879 if (!mImageLoaders
[i
].Init())
880 return NS_ERROR_OUT_OF_MEMORY
;
882 // Get the look and feel service here; default colors will be initialized
883 // from calling GetUserPreferences() when we get a presshell.
884 nsresult rv
= CallGetService(kLookAndFeelCID
, &mLookAndFeel
);
886 NS_ERROR("LookAndFeel service must be implemented for this toolkit");
890 mEventManager
= new nsEventStateManager();
892 return NS_ERROR_OUT_OF_MEMORY
;
894 NS_ADDREF(mEventManager
);
896 mTransitionManager
= new nsTransitionManager(this);
897 if (!mTransitionManager
)
898 return NS_ERROR_OUT_OF_MEMORY
;
900 if (mDocument
->GetDisplayDocument()) {
901 NS_ASSERTION(mDocument
->GetDisplayDocument()->GetShell() &&
902 mDocument
->GetDisplayDocument()->GetShell()->GetPresContext(),
903 "Why are we being initialized?");
904 mRefreshDriver
= mDocument
->GetDisplayDocument()->GetShell()->
905 GetPresContext()->RefreshDriver();
907 nsIDocument
* parent
= mDocument
->GetParentDocument();
908 // Unfortunately, sometimes |parent| here has no presshell because
909 // printing screws up things. Assert that in other cases it does,
910 // but whenever the shell is null just fall back on using our own
912 NS_ASSERTION(!parent
|| mDocument
->IsStaticDocument() || parent
->GetShell(),
913 "How did we end up with a presshell if our parent doesn't "
915 if (parent
&& parent
->GetShell()) {
916 NS_ASSERTION(parent
->GetShell()->GetPresContext(),
917 "How did we get a presshell?");
919 // We don't have our container set yet at this point
920 nsCOMPtr
<nsISupports
> ourContainer
= mDocument
->GetContainer();
922 nsCOMPtr
<nsIDocShellTreeItem
> ourItem
= do_QueryInterface(ourContainer
);
924 nsCOMPtr
<nsIDocShellTreeItem
> parentItem
;
925 ourItem
->GetSameTypeParent(getter_AddRefs(parentItem
));
927 mRefreshDriver
= parent
->GetShell()->GetPresContext()->RefreshDriver();
932 if (!mRefreshDriver
) {
933 mRefreshDriver
= new nsRefreshDriver(this);
935 return NS_ERROR_OUT_OF_MEMORY
;
939 mLangService
= do_GetService(NS_LANGUAGEATOMSERVICE_CONTRACTID
);
941 // Register callbacks so we're notified when the preferences change
942 nsContentUtils::RegisterPrefCallback("font.",
943 nsPresContext::PrefChangedCallback
,
945 nsContentUtils::RegisterPrefCallback("browser.display.",
946 nsPresContext::PrefChangedCallback
,
948 nsContentUtils::RegisterPrefCallback("browser.underline_anchors",
949 nsPresContext::PrefChangedCallback
,
951 nsContentUtils::RegisterPrefCallback("browser.anchor_color",
952 nsPresContext::PrefChangedCallback
,
954 nsContentUtils::RegisterPrefCallback("browser.active_color",
955 nsPresContext::PrefChangedCallback
,
957 nsContentUtils::RegisterPrefCallback("browser.visited_color",
958 nsPresContext::PrefChangedCallback
,
960 nsContentUtils::RegisterPrefCallback("image.animation_mode",
961 nsPresContext::PrefChangedCallback
,
964 nsContentUtils::RegisterPrefCallback("bidi.", PrefChangedCallback
,
967 nsContentUtils::RegisterPrefCallback("dom.send_after_paint_to_content",
968 nsPresContext::PrefChangedCallback
,
970 nsContentUtils::RegisterPrefCallback("gfx.font_rendering.", PrefChangedCallback
,
972 nsContentUtils::RegisterPrefCallback("layout.css.dpi",
973 nsPresContext::PrefChangedCallback
,
975 nsContentUtils::RegisterPrefCallback("layout.css.devPixelsPerPx",
976 nsPresContext::PrefChangedCallback
,
979 rv
= mEventManager
->Init();
980 NS_ENSURE_SUCCESS(rv
, rv
);
982 mEventManager
->SetPresContext(this);
985 mInitialized
= PR_TRUE
;
988 mBorderWidthTable
[NS_STYLE_BORDER_WIDTH_THIN
] = CSSPixelsToAppUnits(1);
989 mBorderWidthTable
[NS_STYLE_BORDER_WIDTH_MEDIUM
] = CSSPixelsToAppUnits(3);
990 mBorderWidthTable
[NS_STYLE_BORDER_WIDTH_THICK
] = CSSPixelsToAppUnits(5);
995 // Note: We don't hold a reference on the shell; it has a reference to
998 nsPresContext::SetShell(nsIPresShell
* aShell
)
1001 // Clear out user font set if we have one
1002 mUserFontSet
->Destroy();
1003 NS_RELEASE(mUserFontSet
);
1007 // Remove ourselves as the charset observer from the shell's doc, because
1008 // this shell may be going away for good.
1009 nsIDocument
*doc
= mShell
->GetDocument();
1011 doc
->RemoveCharSetObserver(this);
1018 nsIDocument
*doc
= mShell
->GetDocument();
1019 NS_ASSERTION(doc
, "expect document here");
1021 // Have to update PresContext's mDocument before calling any other methods.
1024 // Initialize our state from the user preferences, now that we
1025 // have a presshell, and hence a document.
1026 GetUserPreferences();
1029 nsIURI
*docURI
= doc
->GetDocumentURI();
1031 if (IsDynamic() && docURI
) {
1032 PRBool isChrome
= PR_FALSE
;
1033 PRBool isRes
= PR_FALSE
;
1034 docURI
->SchemeIs("chrome", &isChrome
);
1035 docURI
->SchemeIs("resource", &isRes
);
1037 if (!isChrome
&& !isRes
)
1038 mImageAnimationMode
= mImageAnimationModePref
;
1040 mImageAnimationMode
= imgIContainer::kNormalAnimMode
;
1044 doc
->AddCharSetObserver(this);
1045 UpdateCharSet(doc
->GetDocumentCharacterSet());
1049 // Destroy image loaders now that the presshell is going away.
1050 // This is important since imageloaders can have pointers to frames and
1051 // we don't want those pointers to outlive the destruction of the frame
1053 for (PRUint32 i
= 0; i
< IMAGE_LOAD_TYPE_COUNT
; ++i
) {
1054 mImageLoaders
[i
].Enumerate(destroy_loads
, nsnull
);
1055 mImageLoaders
[i
].Clear();
1058 if (mTransitionManager
) {
1059 mTransitionManager
->Disconnect();
1060 mTransitionManager
= nsnull
;
1066 nsPresContext::UpdateCharSet(const nsAFlatCString
& aCharSet
)
1069 NS_IF_RELEASE(mLanguage
);
1070 mLanguage
= mLangService
->LookupCharSet(aCharSet
.get()).get(); // addrefs
1071 // this will be a language group (or script) code rather than a true language code
1073 // bug 39570: moved from nsLanguageAtomService::LookupCharSet()
1074 #if !defined(XP_BEOS)
1075 if (mLanguage
== nsGkAtoms::Unicode
) {
1076 NS_RELEASE(mLanguage
);
1077 NS_IF_ADDREF(mLanguage
= mLangService
->GetLocaleLanguage());
1080 GetFontPreferences();
1085 switch (GET_BIDI_OPTION_TEXTTYPE(GetBidi())) {
1087 case IBMBIDI_TEXTTYPE_LOGICAL
:
1088 SetVisualMode(PR_FALSE
);
1091 case IBMBIDI_TEXTTYPE_VISUAL
:
1092 SetVisualMode(PR_TRUE
);
1095 case IBMBIDI_TEXTTYPE_CHARSET
:
1097 SetVisualMode(IsVisualCharset(aCharSet
));
1103 nsPresContext::Observe(nsISupports
* aSubject
,
1105 const PRUnichar
* aData
)
1107 if (!nsCRT::strcmp(aTopic
, "charset")) {
1108 UpdateCharSet(NS_LossyConvertUTF16toASCII(aData
));
1109 mDeviceContext
->FlushFontCache();
1110 RebuildAllStyleData(NS_STYLE_HINT_REFLOW
);
1114 NS_WARNING("unrecognized topic in nsPresContext::Observe");
1115 return NS_ERROR_FAILURE
;
1118 static nsPresContext
*
1119 GetParentPresContext(nsPresContext
* aPresContext
)
1121 nsIPresShell
* shell
= aPresContext
->GetPresShell();
1123 nsIFrame
* rootFrame
= shell
->FrameManager()->GetRootFrame();
1125 nsIFrame
* f
= nsLayoutUtils::GetCrossDocParentFrame(rootFrame
);
1127 return f
->PresContext();
1133 // We may want to replace this with something faster, maybe caching the root prescontext
1135 nsPresContext::GetRootPresContext()
1137 nsPresContext
* pc
= this;
1139 nsPresContext
* parent
= GetParentPresContext(pc
);
1144 return pc
->IsRoot() ? static_cast<nsRootPresContext
*>(pc
) : nsnull
;
1148 nsPresContext::CompatibilityModeChanged()
1153 // enable/disable the QuirkSheet
1154 mShell
->StyleSet()->
1155 EnableQuirkStyleSheet(CompatibilityMode() == eCompatibility_NavQuirks
);
1158 // Helper function for setting Anim Mode on image
1159 static void SetImgAnimModeOnImgReq(imgIRequest
* aImgReq
, PRUint16 aMode
)
1162 nsCOMPtr
<imgIContainer
> imgCon
;
1163 aImgReq
->GetImage(getter_AddRefs(imgCon
));
1165 imgCon
->SetAnimationMode(aMode
);
1170 // Enumeration call back for HashTable
1171 static PLDHashOperator
1172 set_animation_mode(const void * aKey
, nsRefPtr
<nsImageLoader
>& aData
, void* closure
)
1174 for (nsImageLoader
*loader
= aData
; loader
;
1175 loader
= loader
->GetNextLoader()) {
1176 imgIRequest
* imgReq
= loader
->GetRequest();
1177 SetImgAnimModeOnImgReq(imgReq
, (PRUint16
)NS_PTR_TO_INT32(closure
));
1179 return PL_DHASH_NEXT
;
1182 // IMPORTANT: Assumption is that all images for a Presentation
1183 // have the same Animation Mode (pavlov said this was OK)
1185 // Walks content and set the animation mode
1186 // this is a way to turn on/off image animations
1187 void nsPresContext::SetImgAnimations(nsIContent
*aParent
, PRUint16 aMode
)
1189 nsCOMPtr
<nsIImageLoadingContent
> imgContent(do_QueryInterface(aParent
));
1191 nsCOMPtr
<imgIRequest
> imgReq
;
1192 imgContent
->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST
,
1193 getter_AddRefs(imgReq
));
1194 SetImgAnimModeOnImgReq(imgReq
, aMode
);
1197 PRUint32 count
= aParent
->GetChildCount();
1198 for (PRUint32 i
= 0; i
< count
; ++i
) {
1199 SetImgAnimations(aParent
->GetChildAt(i
), aMode
);
1205 nsPresContext::SetSMILAnimations(nsIDocument
*aDoc
, PRUint16 aNewMode
,
1208 if (aDoc
->HasAnimationController()) {
1209 nsSMILAnimationController
* controller
= aDoc
->GetAnimationController();
1212 case imgIContainer::kNormalAnimMode
:
1213 case imgIContainer::kLoopOnceAnimMode
:
1214 if (aOldMode
== imgIContainer::kDontAnimMode
)
1215 controller
->Resume(nsSMILTimeContainer::PAUSE_USERPREF
);
1218 case imgIContainer::kDontAnimMode
:
1219 if (aOldMode
!= imgIContainer::kDontAnimMode
)
1220 controller
->Pause(nsSMILTimeContainer::PAUSE_USERPREF
);
1228 nsPresContext::SetImageAnimationModeInternal(PRUint16 aMode
)
1230 NS_ASSERTION(aMode
== imgIContainer::kNormalAnimMode
||
1231 aMode
== imgIContainer::kDontAnimMode
||
1232 aMode
== imgIContainer::kLoopOnceAnimMode
, "Wrong Animation Mode is being set!");
1234 // Image animation mode cannot be changed when rendering to a printer.
1238 // Set the mode on the image loaders.
1239 for (PRUint32 i
= 0; i
< IMAGE_LOAD_TYPE_COUNT
; ++i
)
1240 mImageLoaders
[i
].Enumerate(set_animation_mode
, NS_INT32_TO_PTR(aMode
));
1242 // Now walk the content tree and set the animation mode
1243 // on all the images.
1244 if (mShell
!= nsnull
) {
1245 nsIDocument
*doc
= mShell
->GetDocument();
1247 Element
*rootElement
= doc
->GetRootElement();
1249 SetImgAnimations(rootElement
, aMode
);
1253 SetSMILAnimations(doc
, aMode
, mImageAnimationMode
);
1258 mImageAnimationMode
= aMode
;
1262 nsPresContext::SetImageAnimationModeExternal(PRUint16 aMode
)
1264 SetImageAnimationModeInternal(aMode
);
1267 already_AddRefed
<nsIFontMetrics
>
1268 nsPresContext::GetMetricsFor(const nsFont
& aFont
, PRBool aUseUserFontSet
)
1270 nsIFontMetrics
* metrics
= nsnull
;
1271 mDeviceContext
->GetMetricsFor(aFont
, mLanguage
,
1272 aUseUserFontSet
? GetUserFontSet() : nsnull
,
1278 nsPresContext::GetDefaultFont(PRUint8 aFontID
) const
1282 // Special (our default variable width font and fixed width font)
1283 case kPresContext_DefaultVariableFont_ID
:
1284 font
= &mDefaultVariableFont
;
1286 case kPresContext_DefaultFixedFont_ID
:
1287 font
= &mDefaultFixedFont
;
1290 case kGenericFont_serif
:
1291 font
= &mDefaultSerifFont
;
1293 case kGenericFont_sans_serif
:
1294 font
= &mDefaultSansSerifFont
;
1296 case kGenericFont_monospace
:
1297 font
= &mDefaultMonospaceFont
;
1299 case kGenericFont_cursive
:
1300 font
= &mDefaultCursiveFont
;
1302 case kGenericFont_fantasy
:
1303 font
= &mDefaultFantasyFont
;
1307 NS_ERROR("invalid arg");
1314 nsPresContext::SetFullZoom(float aZoom
)
1316 if (!mShell
|| mFullZoom
== aZoom
) {
1319 // Re-fetch the view manager's window dimensions in case there's a deferred
1320 // resize which hasn't affected our mVisibleArea yet
1321 nscoord oldWidthAppUnits
, oldHeightAppUnits
;
1322 mShell
->GetViewManager()->GetWindowDimensions(&oldWidthAppUnits
, &oldHeightAppUnits
);
1323 float oldWidthDevPixels
= oldWidthAppUnits
/ float(mCurAppUnitsPerDevPixel
);
1324 float oldHeightDevPixels
= oldHeightAppUnits
/ float(mCurAppUnitsPerDevPixel
);
1325 if (mDeviceContext
->SetPixelScale(aZoom
)) {
1326 mDeviceContext
->FlushFontCache();
1329 NS_ASSERTION(!mSupressResizeReflow
, "two zooms happening at the same time? impossible!");
1330 mSupressResizeReflow
= PR_TRUE
;
1333 mShell
->GetViewManager()->
1334 SetWindowDimensions(NSToCoordRound(oldWidthDevPixels
* AppUnitsPerDevPixel()),
1335 NSToCoordRound(oldHeightDevPixels
* AppUnitsPerDevPixel()));
1336 if (HasCachedStyleData()) {
1337 MediaFeatureValuesChanged(PR_TRUE
);
1338 RebuildAllStyleData(NS_STYLE_HINT_REFLOW
);
1341 mSupressResizeReflow
= PR_FALSE
;
1343 mCurAppUnitsPerDevPixel
= AppUnitsPerDevPixel();
1347 nsPresContext::SetImageLoaders(nsIFrame
* aTargetFrame
,
1348 ImageLoadType aType
,
1349 nsImageLoader
* aImageLoaders
)
1351 NS_ASSERTION(mShell
|| !aImageLoaders
,
1352 "Shouldn't add new image loader after the shell is gone");
1354 nsRefPtr
<nsImageLoader
> oldLoaders
;
1355 mImageLoaders
[aType
].Get(aTargetFrame
, getter_AddRefs(oldLoaders
));
1357 if (aImageLoaders
) {
1358 mImageLoaders
[aType
].Put(aTargetFrame
, aImageLoaders
);
1359 } else if (oldLoaders
) {
1360 mImageLoaders
[aType
].Remove(aTargetFrame
);
1364 oldLoaders
->Destroy();
1368 nsPresContext::SetupBackgroundImageLoaders(nsIFrame
* aFrame
,
1369 const nsStyleBackground
* aStyleBackground
)
1371 nsRefPtr
<nsImageLoader
> loaders
;
1372 NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i
, aStyleBackground
) {
1373 if (aStyleBackground
->mLayers
[i
].mImage
.GetType() == eStyleImageType_Image
) {
1374 PRUint32 actions
= nsImageLoader::ACTION_REDRAW_ON_DECODE
;
1375 imgIRequest
*image
= aStyleBackground
->mLayers
[i
].mImage
.GetImageData();
1376 loaders
= nsImageLoader::Create(aFrame
, image
, actions
, loaders
);
1379 SetImageLoaders(aFrame
, BACKGROUND_IMAGE
, loaders
);
1383 nsPresContext::SetupBorderImageLoaders(nsIFrame
* aFrame
,
1384 const nsStyleBorder
* aStyleBorder
)
1386 PRUint32 actions
= nsImageLoader::ACTION_REDRAW_ON_LOAD
;
1387 if (aStyleBorder
->ImageBorderDiffers())
1388 actions
|= nsImageLoader::ACTION_REFLOW_ON_LOAD
;
1389 nsRefPtr
<nsImageLoader
> loader
=
1390 nsImageLoader::Create(aFrame
, aStyleBorder
->GetBorderImage(),
1392 SetImageLoaders(aFrame
, BORDER_IMAGE
, loader
);
1396 nsPresContext::StopImagesFor(nsIFrame
* aTargetFrame
)
1398 for (PRUint32 i
= 0; i
< IMAGE_LOAD_TYPE_COUNT
; ++i
)
1399 SetImageLoaders(aTargetFrame
, ImageLoadType(i
), nsnull
);
1403 nsPresContext::SetContainer(nsISupports
* aHandler
)
1405 mContainer
= do_GetWeakReference(aHandler
);
1406 InvalidateIsChromeCache();
1408 GetDocumentColorPreferences();
1412 already_AddRefed
<nsISupports
>
1413 nsPresContext::GetContainerInternal() const
1415 nsISupports
*result
= nsnull
;
1417 CallQueryReferent(mContainer
.get(), &result
);
1422 already_AddRefed
<nsISupports
>
1423 nsPresContext::GetContainerExternal() const
1425 return GetContainerInternal();
1430 nsPresContext::SetBidiEnabled() const
1433 nsIDocument
*doc
= mShell
->GetDocument();
1435 doc
->SetBidiEnabled();
1441 nsPresContext::GetBidiUtils()
1444 mBidiUtils
= new nsBidiPresUtils
;
1450 nsPresContext::SetBidi(PRUint32 aSource
, PRBool aForceRestyle
)
1452 // Don't do all this stuff unless the options have changed.
1453 if (aSource
== GetBidi()) {
1457 NS_ASSERTION(!(aForceRestyle
&& (GetBidi() == 0)),
1458 "ForceReflow on new prescontext");
1460 Document()->SetBidiOptions(aSource
);
1461 if (IBMBIDI_TEXTDIRECTION_RTL
== GET_BIDI_OPTION_DIRECTION(aSource
)
1462 || IBMBIDI_NUMERAL_HINDI
== GET_BIDI_OPTION_NUMERAL(aSource
)) {
1465 if (IBMBIDI_TEXTTYPE_VISUAL
== GET_BIDI_OPTION_TEXTTYPE(aSource
)) {
1466 SetVisualMode(PR_TRUE
);
1468 else if (IBMBIDI_TEXTTYPE_LOGICAL
== GET_BIDI_OPTION_TEXTTYPE(aSource
)) {
1469 SetVisualMode(PR_FALSE
);
1472 nsIDocument
* doc
= mShell
->GetDocument();
1474 SetVisualMode(IsVisualCharset(doc
->GetDocumentCharacterSet()));
1477 if (aForceRestyle
&& mShell
) {
1478 // Reconstruct the root document element's frame and its children,
1479 // because we need to trigger frame reconstruction for direction change.
1480 RebuildUserFontSet();
1481 mShell
->ReconstructFrames();
1486 nsPresContext::GetBidi() const
1488 return Document()->GetBidiOptions();
1492 nsPresContext::GetBidiMemoryUsed()
1497 return mBidiUtils
->EstimateMemoryUsed();
1503 nsPresContext::IsTopLevelWindowInactive()
1505 nsCOMPtr
<nsIDocShellTreeItem
> treeItem(do_QueryReferent(mContainer
));
1509 nsCOMPtr
<nsIDocShellTreeItem
> rootItem
;
1510 treeItem
->GetRootTreeItem(getter_AddRefs(rootItem
));
1511 nsCOMPtr
<nsPIDOMWindow
> domWindow(do_GetInterface(rootItem
));
1513 return domWindow
&& !domWindow
->IsActive();
1517 nsPresContext::GetTheme()
1519 if (!sNoTheme
&& !mTheme
) {
1520 mTheme
= do_GetService("@mozilla.org/chrome/chrome-native-theme;1");
1529 nsPresContext::ThemeChanged()
1531 if (!mPendingThemeChanged
) {
1532 sLookAndFeelChanged
= PR_TRUE
;
1533 sThemeChanged
= PR_TRUE
;
1535 nsCOMPtr
<nsIRunnable
> ev
=
1536 NS_NewRunnableMethod(this, &nsPresContext::ThemeChangedInternal
);
1537 if (NS_SUCCEEDED(NS_DispatchToCurrentThread(ev
))) {
1538 mPendingThemeChanged
= PR_TRUE
;
1544 nsPresContext::ThemeChangedInternal()
1546 mPendingThemeChanged
= PR_FALSE
;
1548 // Tell the theme that it changed, so it can flush any handles to stale theme
1550 if (mTheme
&& sThemeChanged
) {
1551 mTheme
->ThemeChanged();
1552 sThemeChanged
= PR_FALSE
;
1555 // Clear all cached nsILookAndFeel colors.
1556 if (mLookAndFeel
&& sLookAndFeelChanged
) {
1557 mLookAndFeel
->LookAndFeelChanged();
1558 sLookAndFeelChanged
= PR_FALSE
;
1561 // This will force the system metrics to be generated the next time they're used
1562 nsCSSRuleProcessor::FreeSystemMetrics();
1564 // Changes to system metrics can change media queries on them.
1565 MediaFeatureValuesChanged(PR_TRUE
);
1567 // Changes in theme can change system colors (whose changes are
1568 // properly reflected in computed style data), system fonts (whose
1569 // changes are not), and -moz-appearance (whose changes likewise are
1570 // not), so we need to reflow.
1571 RebuildAllStyleData(NS_STYLE_HINT_REFLOW
);
1575 nsPresContext::SysColorChanged()
1577 if (!mPendingSysColorChanged
) {
1578 sLookAndFeelChanged
= PR_TRUE
;
1579 nsCOMPtr
<nsIRunnable
> ev
=
1580 NS_NewRunnableMethod(this, &nsPresContext::SysColorChangedInternal
);
1581 if (NS_SUCCEEDED(NS_DispatchToCurrentThread(ev
))) {
1582 mPendingSysColorChanged
= PR_TRUE
;
1588 nsPresContext::SysColorChangedInternal()
1590 mPendingSysColorChanged
= PR_FALSE
;
1592 if (mLookAndFeel
&& sLookAndFeelChanged
) {
1593 // Don't use the cached values for the system colors
1594 mLookAndFeel
->LookAndFeelChanged();
1595 sLookAndFeelChanged
= PR_FALSE
;
1598 // Reset default background and foreground colors for the document since
1599 // they may be using system colors
1600 GetDocumentColorPreferences();
1602 // The system color values are computed to colors in the style data,
1603 // so normal style data comparison is sufficient here.
1604 RebuildAllStyleData(nsChangeHint(0));
1608 nsPresContext::RebuildAllStyleData(nsChangeHint aExtraHint
)
1611 // We must have been torn down. Nothing to do here.
1615 RebuildUserFontSet();
1617 mShell
->FrameConstructor()->RebuildAllStyleData(aExtraHint
);
1621 nsPresContext::PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint
)
1624 // We must have been torn down. Nothing to do here.
1627 mShell
->FrameConstructor()->PostRebuildAllStyleDataEvent(aExtraHint
);
1631 nsPresContext::MediaFeatureValuesChanged(PRBool aCallerWillRebuildStyleData
)
1633 mPendingMediaFeatureValuesChanged
= PR_FALSE
;
1635 mShell
->StyleSet()->MediumFeaturesChanged(this) &&
1636 !aCallerWillRebuildStyleData
) {
1637 RebuildAllStyleData(nsChangeHint(0));
1642 nsPresContext::PostMediaFeatureValuesChangedEvent()
1644 if (!mPendingMediaFeatureValuesChanged
) {
1645 nsCOMPtr
<nsIRunnable
> ev
=
1646 NS_NewRunnableMethod(this, &nsPresContext::HandleMediaFeatureValuesChangedEvent
);
1647 if (NS_SUCCEEDED(NS_DispatchToCurrentThread(ev
))) {
1648 mPendingMediaFeatureValuesChanged
= PR_TRUE
;
1654 nsPresContext::HandleMediaFeatureValuesChangedEvent()
1656 // Null-check mShell in case the shell has been destroyed (and the
1657 // event is the only thing holding the pres context alive).
1658 if (mPendingMediaFeatureValuesChanged
&& mShell
) {
1659 MediaFeatureValuesChanged(PR_FALSE
);
1664 nsPresContext::SetPaginatedScrolling(PRBool aPaginated
)
1666 if (mType
== eContext_PrintPreview
|| mType
== eContext_PageLayout
)
1667 mCanPaginatedScroll
= aPaginated
;
1671 nsPresContext::SetPrintSettings(nsIPrintSettings
*aPrintSettings
)
1673 if (mMedium
== nsGkAtoms::print
)
1674 mPrintSettings
= aPrintSettings
;
1678 nsPresContext::EnsureVisible()
1680 nsCOMPtr
<nsIDocShell
> docShell(do_QueryReferent(mContainer
));
1682 nsCOMPtr
<nsIContentViewer
> cv
;
1683 docShell
->GetContentViewer(getter_AddRefs(cv
));
1684 // Make sure this is the content viewer we belong with
1685 nsCOMPtr
<nsIDocumentViewer
> docV(do_QueryInterface(cv
));
1687 nsRefPtr
<nsPresContext
> currentPresContext
;
1688 docV
->GetPresContext(getter_AddRefs(currentPresContext
));
1689 if (currentPresContext
== this) {
1690 // OK, this is us. We want to call Show() on the content viewer.
1699 #ifdef MOZ_REFLOW_PERF
1701 nsPresContext::CountReflows(const char * aName
, nsIFrame
* aFrame
)
1704 mShell
->CountReflows(aName
, aFrame
);
1710 nsPresContext::IsChromeSlow() const
1712 PRBool isChrome
= PR_FALSE
;
1713 nsCOMPtr
<nsISupports
> container
= GetContainer();
1716 nsCOMPtr
<nsIDocShellTreeItem
> docShell(do_QueryInterface(container
, &result
));
1717 if (NS_SUCCEEDED(result
) && docShell
) {
1718 PRInt32 docShellType
;
1719 result
= docShell
->GetItemType(&docShellType
);
1720 if (NS_SUCCEEDED(result
)) {
1721 isChrome
= nsIDocShellTreeItem::typeChrome
== docShellType
;
1725 mIsChrome
= isChrome
;
1726 mIsChromeIsCached
= PR_TRUE
;
1731 nsPresContext::InvalidateIsChromeCacheExternal()
1733 InvalidateIsChromeCacheInternal();
1736 /* virtual */ PRBool
1737 nsPresContext::HasAuthorSpecifiedRules(nsIFrame
*aFrame
, PRUint32 ruleTypeMask
) const
1740 nsRuleNode::HasAuthorSpecifiedRules(aFrame
->GetStyleContext(),
1742 UseDocumentColors());
1746 InsertFontFaceRule(nsCSSFontFaceRule
*aRule
, gfxUserFontSet
* aFontSet
,
1749 NS_ABORT_IF_FALSE(aRule
->GetType() == nsICSSRule::FONT_FACE_RULE
,
1750 "InsertFontFaceRule passed a non-fontface CSS rule");
1754 nsAutoString fontfamily
;
1758 PRUint32 weight
= NS_STYLE_FONT_WEIGHT_NORMAL
;
1759 PRUint32 stretch
= NS_STYLE_FONT_STRETCH_NORMAL
;
1760 PRUint32 italicStyle
= FONT_STYLE_NORMAL
;
1761 nsString featureSettings
, languageOverride
;
1763 // set up family name
1764 aRule
->GetDesc(eCSSFontDesc_Family
, val
);
1765 unit
= val
.GetUnit();
1766 if (unit
== eCSSUnit_String
) {
1767 val
.GetStringValue(fontfamily
);
1769 NS_ASSERTION(unit
== eCSSUnit_Null
,
1770 "@font-face family name has unexpected unit");
1771 // If there is no family name, this rule cannot contribute a
1772 // usable font, so there is no point in processing it further.
1777 aRule
->GetDesc(eCSSFontDesc_Weight
, val
);
1778 unit
= val
.GetUnit();
1779 if (unit
== eCSSUnit_Integer
|| unit
== eCSSUnit_Enumerated
) {
1780 weight
= val
.GetIntValue();
1781 } else if (unit
== eCSSUnit_Normal
) {
1782 weight
= NS_STYLE_FONT_WEIGHT_NORMAL
;
1784 NS_ASSERTION(unit
== eCSSUnit_Null
,
1785 "@font-face weight has unexpected unit");
1789 aRule
->GetDesc(eCSSFontDesc_Stretch
, val
);
1790 unit
= val
.GetUnit();
1791 if (unit
== eCSSUnit_Enumerated
) {
1792 stretch
= val
.GetIntValue();
1793 } else if (unit
== eCSSUnit_Normal
) {
1794 stretch
= NS_STYLE_FONT_STRETCH_NORMAL
;
1796 NS_ASSERTION(unit
== eCSSUnit_Null
,
1797 "@font-face stretch has unexpected unit");
1800 // set up font style
1801 aRule
->GetDesc(eCSSFontDesc_Style
, val
);
1802 unit
= val
.GetUnit();
1803 if (unit
== eCSSUnit_Enumerated
) {
1804 italicStyle
= val
.GetIntValue();
1805 } else if (unit
== eCSSUnit_Normal
) {
1806 italicStyle
= FONT_STYLE_NORMAL
;
1808 NS_ASSERTION(unit
== eCSSUnit_Null
,
1809 "@font-face style has unexpected unit");
1812 // set up font features
1813 aRule
->GetDesc(eCSSFontDesc_FontFeatureSettings
, val
);
1814 unit
= val
.GetUnit();
1815 if (unit
== eCSSUnit_Normal
) {
1816 // empty feature string
1817 } else if (unit
== eCSSUnit_String
) {
1818 val
.GetStringValue(featureSettings
);
1820 NS_ASSERTION(unit
== eCSSUnit_Null
,
1821 "@font-face font-feature-settings has unexpected unit");
1824 // set up font language override
1825 aRule
->GetDesc(eCSSFontDesc_FontLanguageOverride
, val
);
1826 unit
= val
.GetUnit();
1827 if (unit
== eCSSUnit_Normal
) {
1828 // empty feature string
1829 } else if (unit
== eCSSUnit_String
) {
1830 val
.GetStringValue(languageOverride
);
1832 NS_ASSERTION(unit
== eCSSUnit_Null
,
1833 "@font-face font-language-override has unexpected unit");
1837 nsTArray
<gfxFontFaceSrc
> srcArray
;
1839 aRule
->GetDesc(eCSSFontDesc_Src
, val
);
1840 unit
= val
.GetUnit();
1841 if (unit
== eCSSUnit_Array
) {
1842 nsCSSValue::Array
*srcArr
= val
.GetArrayValue();
1843 size_t numSrc
= srcArr
->Count();
1845 for (size_t i
= 0; i
< numSrc
; i
++) {
1846 val
= srcArr
->Item(i
);
1847 unit
= val
.GetUnit();
1848 gfxFontFaceSrc
*face
= srcArray
.AppendElements(1);
1854 case eCSSUnit_Local_Font
:
1855 val
.GetStringValue(face
->mLocalName
);
1856 face
->mIsLocal
= PR_TRUE
;
1857 face
->mURI
= nsnull
;
1858 face
->mFormatFlags
= 0;
1861 face
->mIsLocal
= PR_FALSE
;
1862 face
->mURI
= val
.GetURLValue();
1863 NS_ASSERTION(face
->mURI
, "null url in @font-face rule");
1864 face
->mReferrer
= val
.GetURLStructValue()->mReferrer
;
1865 face
->mOriginPrincipal
= val
.GetURLStructValue()->mOriginPrincipal
;
1866 NS_ASSERTION(face
->mOriginPrincipal
, "null origin principal in @font-face rule");
1868 // agent and user stylesheets are treated slightly differently,
1869 // the same-site origin check and access control headers are
1870 // enforced against the sheet principal rather than the document
1871 // principal to allow user stylesheets to include @font-face rules
1872 face
->mUseOriginPrincipal
= (aSheetType
== nsStyleSet::eUserSheet
||
1873 aSheetType
== nsStyleSet::eAgentSheet
);
1875 face
->mLocalName
.Truncate();
1876 face
->mFormatFlags
= 0;
1877 while (i
+ 1 < numSrc
&& (val
= srcArr
->Item(i
+1),
1878 val
.GetUnit() == eCSSUnit_Font_Format
)) {
1879 nsDependentString
valueString(val
.GetStringBufferValue());
1880 if (valueString
.LowerCaseEqualsASCII("woff")) {
1881 face
->mFormatFlags
|= gfxUserFontSet::FLAG_FORMAT_WOFF
;
1882 } else if (valueString
.LowerCaseEqualsASCII("opentype")) {
1883 face
->mFormatFlags
|= gfxUserFontSet::FLAG_FORMAT_OPENTYPE
;
1884 } else if (valueString
.LowerCaseEqualsASCII("truetype")) {
1885 face
->mFormatFlags
|= gfxUserFontSet::FLAG_FORMAT_TRUETYPE
;
1886 } else if (valueString
.LowerCaseEqualsASCII("truetype-aat")) {
1887 face
->mFormatFlags
|= gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT
;
1888 } else if (valueString
.LowerCaseEqualsASCII("embedded-opentype")) {
1889 face
->mFormatFlags
|= gfxUserFontSet::FLAG_FORMAT_EOT
;
1890 } else if (valueString
.LowerCaseEqualsASCII("svg")) {
1891 face
->mFormatFlags
|= gfxUserFontSet::FLAG_FORMAT_SVG
;
1893 // unknown format specified, mark to distinguish from the
1894 // case where no format hints are specified
1895 face
->mFormatFlags
|= gfxUserFontSet::FLAG_FORMAT_UNKNOWN
;
1901 NS_ASSERTION(unit
== eCSSUnit_Local_Font
|| unit
== eCSSUnit_URL
,
1902 "strange unit type in font-face src array");
1907 NS_ASSERTION(unit
== eCSSUnit_Null
, "@font-face src has unexpected unit");
1910 if (!fontfamily
.IsEmpty() && srcArray
.Length() > 0) {
1911 aFontSet
->AddFontFace(fontfamily
, srcArray
, weight
, stretch
, italicStyle
,
1912 featureSettings
, languageOverride
);
1917 nsPresContext::GetUserFontSetInternal()
1919 // We want to initialize the user font set lazily the first time the
1920 // user asks for it, rather than building it too early and forcing
1921 // rule cascade creation. Thus we try to enforce the invariant that
1922 // we *never* build the user font set until the first call to
1923 // GetUserFontSet. However, once it's been requested, we can't wait
1924 // for somebody to call GetUserFontSet in order to rebuild it (see
1925 // comments below in RebuildUserFontSet for why).
1927 PRBool userFontSetGottenBefore
= mGetUserFontSetCalled
;
1929 // Set mGetUserFontSetCalled up front, so that FlushUserFontSet will actually
1931 mGetUserFontSetCalled
= PR_TRUE
;
1932 if (mUserFontSetDirty
) {
1933 // If this assertion fails, and there have actually been changes to
1934 // @font-face rules, then we will call StyleChangeReflow in
1935 // FlushUserFontSet. If we're in the middle of reflow,
1936 // that's a bad thing to do, and the caller was responsible for
1937 // flushing first. If we're not (e.g., in frame construction), it's
1939 NS_ASSERTION(!userFontSetGottenBefore
|| !mShell
->IsReflowLocked(),
1940 "FlushUserFontSet should have been called first");
1944 return mUserFontSet
;
1948 nsPresContext::GetUserFontSetExternal()
1950 return GetUserFontSetInternal();
1954 nsPresContext::FlushUserFontSet()
1957 return; // we've been torn down
1959 if (!mGetUserFontSetCalled
) {
1960 return; // No one cares about this font set yet, but we want to be careful
1961 // to not unset our mUserFontSetDirty bit, so when someone really
1962 // does we'll create it.
1965 if (mUserFontSetDirty
) {
1966 if (gfxPlatform::GetPlatform()->DownloadableFontsEnabled()) {
1967 nsRefPtr
<gfxUserFontSet
> oldUserFontSet
= mUserFontSet
;
1969 nsTArray
<nsFontFaceRuleContainer
> rules
;
1970 if (!mShell
->StyleSet()->AppendFontFaceRules(this, rules
))
1974 if (rules
.Length() == mFontFaceRules
.Length()) {
1976 for (PRUint32 i
= 0, i_end
= rules
.Length(); i
< i_end
; ++i
) {
1977 if (rules
[i
].mRule
!= mFontFaceRules
[i
].mRule
||
1978 rules
[i
].mSheetType
!= mFontFaceRules
[i
].mSheetType
) {
1987 // Only rebuild things if the set of @font-face rules is different.
1990 mUserFontSet
->Destroy();
1991 NS_RELEASE(mUserFontSet
);
1994 if (rules
.Length() > 0) {
1995 nsUserFontSet
*fs
= new nsUserFontSet(this);
1999 NS_ADDREF(mUserFontSet
);
2001 for (PRUint32 i
= 0, i_end
= rules
.Length(); i
< i_end
; ++i
) {
2002 InsertFontFaceRule(rules
[i
].mRule
, fs
, rules
[i
].mSheetType
);
2010 rules
.SwapElements(mFontFaceRules
);
2011 NS_ASSERTION(success
, "should never fail given both are heap arrays");
2013 if (mGetUserFontSetCalled
&& oldUserFontSet
!= mUserFontSet
) {
2014 // If we've changed, created, or destroyed a user font set, we
2015 // need to trigger a style change reflow.
2016 // We need to enqueue a style change reflow (for later) to
2017 // reflect that we're dropping @font-face rules. (However,
2018 // without a reflow, nothing will happen to start any downloads
2019 // that are needed.)
2020 UserFontSetUpdated();
2024 mUserFontSetDirty
= PR_FALSE
;
2029 nsPresContext::RebuildUserFontSet()
2031 if (!mGetUserFontSetCalled
) {
2032 // We want to lazily build the user font set the first time it's
2033 // requested (so we don't force creation of rule cascades too
2034 // early), so don't do anything now.
2038 mUserFontSetDirty
= PR_TRUE
;
2040 // Somebody has already asked for the user font set, so we need to
2041 // post an event to rebuild it. Setting the user font set to be dirty
2042 // and lazily rebuilding it isn't sufficient, since it is only the act
2043 // of rebuilding it that will trigger the style change reflow that
2044 // calls GetUserFontSet. (This reflow causes rebuilding of text runs,
2045 // which starts font loads, whose completion causes another style
2047 if (!mPostedFlushUserFontSet
) {
2048 nsCOMPtr
<nsIRunnable
> ev
=
2049 NS_NewRunnableMethod(this, &nsPresContext::HandleRebuildUserFontSet
);
2050 if (NS_SUCCEEDED(NS_DispatchToCurrentThread(ev
))) {
2051 mPostedFlushUserFontSet
= PR_TRUE
;
2057 nsPresContext::UserFontSetUpdated()
2062 // Changes to the set of available fonts can cause updates to layout by:
2064 // 1. Changing the font used for text, which changes anything that
2065 // depends on text measurement, including line breaking and
2066 // intrinsic widths, and any other parts of layout that depend on
2067 // font metrics. This requires a style change reflow to update.
2069 // 2. Changing the value of the 'ex' and 'ch' units in style data,
2070 // which also depend on font metrics. Updating this information
2071 // requires rebuilding the rule tree from the top, avoiding the
2072 // reuse of cached data even when no style rules have changed.
2074 PostRebuildAllStyleDataEvent(NS_STYLE_HINT_REFLOW
);
2078 nsPresContext::EnsureSafeToHandOutCSSRules()
2080 nsCSSStyleSheet::EnsureUniqueInnerResult res
=
2081 mShell
->StyleSet()->EnsureUniqueInnerOnCSSSheets();
2082 if (res
== nsCSSStyleSheet::eUniqueInner_AlreadyUnique
) {
2086 if (res
== nsCSSStyleSheet::eUniqueInner_CloneFailed
) {
2090 NS_ABORT_IF_FALSE(res
== nsCSSStyleSheet::eUniqueInner_ClonedInner
,
2091 "unexpected result");
2092 RebuildAllStyleData(nsChangeHint(0));
2097 nsPresContext::FireDOMPaintEvent()
2099 nsPIDOMWindow
* ourWindow
= mDocument
->GetWindow();
2103 nsCOMPtr
<nsIDOMEventTarget
> dispatchTarget
= do_QueryInterface(ourWindow
);
2104 nsCOMPtr
<nsIDOMEventTarget
> eventTarget
= dispatchTarget
;
2106 PRBool notifyContent
= mSendAfterPaintToContent
;
2108 if (notifyContent
) {
2109 // If the pref is set, we still don't post events when they're
2110 // entirely cross-doc.
2111 notifyContent
= PR_FALSE
;
2112 for (PRUint32 i
= 0; i
< mInvalidateRequests
.mRequests
.Length(); ++i
) {
2113 if (!(mInvalidateRequests
.mRequests
[i
].mFlags
&
2114 nsIFrame::INVALIDATE_CROSS_DOC
)) {
2115 notifyContent
= PR_TRUE
;
2119 if (!notifyContent
) {
2120 // Don't tell the window about this event, it should not know that
2121 // something happened in a subdocument. Tell only the chrome event handler.
2122 // (Events sent to the window get propagated to the chrome event handler
2124 dispatchTarget
= do_QueryInterface(ourWindow
->GetParentTarget());
2125 if (!dispatchTarget
) {
2130 // Events sent to the window get propagated to the chrome event handler
2132 nsCOMPtr
<nsIDOMEvent
> event
;
2133 // This will empty our list in case dispatching the event causes more damage
2134 // (hopefully it won't, or we're likely to get an infinite loop! At least
2135 // it won't be blocking app execution though).
2136 NS_NewDOMNotifyPaintEvent(getter_AddRefs(event
), this, nsnull
,
2138 &mInvalidateRequests
);
2139 nsCOMPtr
<nsIPrivateDOMEvent
> pEvent
= do_QueryInterface(event
);
2140 if (!pEvent
) return;
2142 // Even if we're not telling the window about the event (so eventTarget is
2143 // the chrome event handler, not the window), the window is still
2144 // logically the event target.
2145 pEvent
->SetTarget(eventTarget
);
2146 pEvent
->SetTrusted(PR_TRUE
);
2147 nsEventDispatcher::DispatchDOMEvent(dispatchTarget
, nsnull
, event
, this, nsnull
);
2151 MayHavePaintEventListener(nsPIDOMWindow
* aInnerWindow
)
2155 if (aInnerWindow
->HasPaintEventListeners())
2158 nsPIDOMEventTarget
* parentTarget
= aInnerWindow
->GetParentTarget();
2162 nsIEventListenerManager
* manager
= nsnull
;
2163 if ((manager
= parentTarget
->GetListenerManager(PR_FALSE
)) &&
2164 manager
->MayHavePaintEventListener()) {
2168 nsCOMPtr
<nsINode
> node
;
2169 if (parentTarget
!= aInnerWindow
->GetChromeEventHandler()) {
2170 nsCOMPtr
<nsIInProcessContentFrameMessageManager
> mm
=
2171 do_QueryInterface(parentTarget
);
2173 node
= mm
->GetOwnerContent();
2178 node
= do_QueryInterface(parentTarget
);
2181 return MayHavePaintEventListener(node
->GetOwnerDoc()->GetInnerWindow());
2183 nsCOMPtr
<nsPIDOMWindow
> window
= do_QueryInterface(parentTarget
);
2185 return MayHavePaintEventListener(window
);
2187 nsCOMPtr
<nsPIWindowRoot
> root
= do_QueryInterface(parentTarget
);
2188 nsPIDOMEventTarget
* tabChildGlobal
;
2190 (tabChildGlobal
= root
->GetParentTarget()) &&
2191 (manager
= tabChildGlobal
->GetListenerManager(PR_FALSE
)) &&
2192 manager
->MayHavePaintEventListener();
2196 nsPresContext::MayHavePaintEventListener()
2198 return ::MayHavePaintEventListener(mDocument
->GetInnerWindow());
2202 nsPresContext::NotifyInvalidation(const nsRect
& aRect
, PRUint32 aFlags
)
2204 // If there is no paint event listener, then we don't need to fire
2205 // the asynchronous event. We don't even need to record invalidation.
2206 // MayHavePaintEventListener is pretty cheap and we could make it
2207 // even cheaper by providing a more efficient
2208 // nsPIDOMWindow::GetListenerManager.
2209 if (aRect
.IsEmpty() || !MayHavePaintEventListener())
2213 for (pc
= this; pc
; pc
= GetParentPresContext(pc
)) {
2214 if (pc
->mFireAfterPaintEvents
)
2216 pc
->mFireAfterPaintEvents
= PR_TRUE
;
2219 nsRootPresContext
* rpc
= GetRootPresContext();
2221 rpc
->EnsureEventualDidPaintEvent();
2225 nsInvalidateRequestList::Request
* request
=
2226 mInvalidateRequests
.mRequests
.AppendElement();
2230 request
->mRect
= aRect
;
2231 request
->mFlags
= aFlags
;
2235 NotifyDidPaintSubdocumentCallback(nsIDocument
* aDocument
, void* aData
)
2237 nsIPresShell
* shell
= aDocument
->GetShell();
2239 nsPresContext
* pc
= shell
->GetPresContext();
2241 pc
->NotifyDidPaintForSubtree();
2248 nsPresContext::NotifyDidPaintForSubtree()
2250 if (!mFireAfterPaintEvents
)
2252 mFireAfterPaintEvents
= PR_FALSE
;
2255 static_cast<nsRootPresContext
*>(this)->CancelDidPaintTimer();
2258 if (!mInvalidateRequests
.mRequests
.IsEmpty()) {
2259 nsCOMPtr
<nsIRunnable
> ev
=
2260 NS_NewRunnableMethod(this, &nsPresContext::FireDOMPaintEvent
);
2261 nsContentUtils::AddScriptRunner(ev
);
2264 mDocument
->EnumerateSubDocuments(NotifyDidPaintSubdocumentCallback
, nsnull
);
2268 nsPresContext::HasCachedStyleData()
2270 return mShell
&& mShell
->StyleSet()->HasCachedStyleData();
2273 static PRBool sGotInterruptEnv
= PR_FALSE
;
2274 enum InterruptMode
{
2279 // Controlled by the GECKO_REFLOW_INTERRUPT_MODE env var; allowed values are
2280 // "random" (except on Windows) or "counter". If neither is used, the mode is
2282 static InterruptMode sInterruptMode
= ModeEvent
;
2283 // Used for the "random" mode. Controlled by the GECKO_REFLOW_INTERRUPT_SEED
2285 static PRUint32 sInterruptSeed
= 1;
2286 // Used for the "counter" mode. This is the number of unskipped interrupt
2287 // checks that have to happen before we interrupt. Controlled by the
2288 // GECKO_REFLOW_INTERRUPT_FREQUENCY env var.
2289 static PRUint32 sInterruptMaxCounter
= 10;
2290 // Used for the "counter" mode. This counts up to sInterruptMaxCounter and is
2292 static PRUint32 sInterruptCounter
;
2293 // Number of interrupt checks to skip before really trying to interrupt.
2294 // Controlled by the GECKO_REFLOW_INTERRUPT_CHECKS_TO_SKIP env var.
2295 static PRUint32 sInterruptChecksToSkip
= 200;
2296 // Number of milliseconds that a reflow should be allowed to run for before we
2297 // actually allow interruption. Controlled by the
2298 // GECKO_REFLOW_MIN_NOINTERRUPT_DURATION env var.
2299 static TimeDuration sInterruptTimeout
= TimeDuration::FromMilliseconds(100);
2301 static void GetInterruptEnv()
2303 char *ev
= PR_GetEnv("GECKO_REFLOW_INTERRUPT_MODE");
2306 if (PL_strcasecmp(ev
, "random") == 0) {
2307 ev
= PR_GetEnv("GECKO_REFLOW_INTERRUPT_SEED");
2309 sInterruptSeed
= atoi(ev
);
2311 srandom(sInterruptSeed
);
2312 sInterruptMode
= ModeRandom
;
2315 if (PL_strcasecmp(ev
, "counter") == 0) {
2316 ev
= PR_GetEnv("GECKO_REFLOW_INTERRUPT_FREQUENCY");
2318 sInterruptMaxCounter
= atoi(ev
);
2320 sInterruptCounter
= 0;
2321 sInterruptMode
= ModeCounter
;
2324 ev
= PR_GetEnv("GECKO_REFLOW_INTERRUPT_CHECKS_TO_SKIP");
2326 sInterruptChecksToSkip
= atoi(ev
);
2329 ev
= PR_GetEnv("GECKO_REFLOW_MIN_NOINTERRUPT_DURATION");
2331 sInterruptTimeout
= TimeDuration::FromMilliseconds(atoi(ev
));
2336 nsPresContext::HavePendingInputEvent()
2338 switch (sInterruptMode
) {
2341 return (random() & 1);
2344 if (sInterruptCounter
< sInterruptMaxCounter
) {
2345 ++sInterruptCounter
;
2348 sInterruptCounter
= 0;
2352 nsIFrame
* f
= PresShell()->GetRootFrame();
2354 nsIWidget
* w
= f
->GetNearestWidget();
2356 return w
->HasPendingInputEvent();
2365 nsPresContext::ReflowStarted(PRBool aInterruptible
)
2367 #ifdef NOISY_INTERRUPTIBLE_REFLOW
2368 if (!aInterruptible
) {
2369 printf("STARTING NONINTERRUPTIBLE REFLOW\n");
2372 // We don't support interrupting in paginated contexts, since page
2373 // sequences only handle initial reflow
2374 mInterruptsEnabled
= aInterruptible
&& !IsPaginated();
2376 // Don't set mHasPendingInterrupt based on HavePendingInputEvent() here. If
2377 // we ever change that, then we need to update the code in
2378 // PresShell::DoReflow to only add the just-reflown root to dirty roots if
2379 // it's actually dirty. Otherwise we can end up adding a root that has no
2380 // interruptible descendants, just because we detected an interrupt at reflow
2382 mHasPendingInterrupt
= PR_FALSE
;
2384 mInterruptChecksToSkip
= sInterruptChecksToSkip
;
2386 if (mInterruptsEnabled
) {
2387 mReflowStartTime
= TimeStamp::Now();
2392 nsPresContext::CheckForInterrupt(nsIFrame
* aFrame
)
2394 if (mHasPendingInterrupt
) {
2395 mShell
->FrameNeedsToContinueReflow(aFrame
);
2399 if (!sGotInterruptEnv
) {
2400 sGotInterruptEnv
= PR_TRUE
;
2404 if (!mInterruptsEnabled
) {
2408 if (mInterruptChecksToSkip
> 0) {
2409 --mInterruptChecksToSkip
;
2412 mInterruptChecksToSkip
= sInterruptChecksToSkip
;
2414 // Don't interrupt if it's been less than sInterruptTimeout since we started
2416 mHasPendingInterrupt
=
2417 TimeStamp::Now() - mReflowStartTime
> sInterruptTimeout
&&
2418 HavePendingInputEvent() &&
2420 if (mHasPendingInterrupt
) {
2421 #ifdef NOISY_INTERRUPTIBLE_REFLOW
2422 printf("*** DETECTED pending interrupt (time=%lld)\n", PR_Now());
2423 #endif /* NOISY_INTERRUPTIBLE_REFLOW */
2424 mShell
->FrameNeedsToContinueReflow(aFrame
);
2426 return mHasPendingInterrupt
;
2430 nsPresContext::IsRootContentDocument()
2432 // We are a root content document if: we are not a resource doc, we are
2433 // not chrome, and we either have no parent or our parent is chrome.
2434 if (mDocument
->IsResourceDoc()) {
2440 // We may not have a root frame, so use views.
2441 nsIViewManager
* vm
= PresShell()->GetViewManager();
2442 nsIView
* view
= nsnull
;
2443 if (NS_FAILED(vm
->GetRootView(view
)) || !view
) {
2446 view
= view
->GetParent(); // anonymous inner view
2450 view
= view
->GetParent(); // subdocumentframe's view
2455 nsIFrame
* f
= static_cast<nsIFrame
*>(view
->GetClientData());
2456 return (f
&& f
->PresContext()->IsChrome());
2459 nsRootPresContext::nsRootPresContext(nsIDocument
* aDocument
,
2460 nsPresContextType aType
)
2461 : nsPresContext(aDocument
, aType
),
2462 mUpdatePluginGeometryForFrame(nsnull
),
2464 mNeedsToUpdatePluginGeometry(PR_FALSE
)
2466 mRegisteredPlugins
.Init();
2469 nsRootPresContext::~nsRootPresContext()
2471 NS_ASSERTION(mRegisteredPlugins
.Count() == 0,
2472 "All plugins should have been unregistered");
2473 CancelDidPaintTimer();
2477 nsRootPresContext::RegisterPluginForGeometryUpdates(nsObjectFrame
* aPlugin
)
2479 mRegisteredPlugins
.PutEntry(aPlugin
);
2483 nsRootPresContext::UnregisterPluginForGeometryUpdates(nsObjectFrame
* aPlugin
)
2485 mRegisteredPlugins
.RemoveEntry(aPlugin
);
2488 struct PluginGeometryClosure
{
2489 nsIFrame
* mRootFrame
;
2491 nsIFrame
* mChangedSubtree
;
2492 nsRect mChangedRect
;
2493 nsTHashtable
<nsPtrHashKey
<nsObjectFrame
> > mAffectedPlugins
;
2494 nsRect mAffectedPluginBounds
;
2495 nsTArray
<nsIWidget::Configuration
>* mOutputConfigurations
;
2497 static PLDHashOperator
2498 PluginBoundsEnumerator(nsPtrHashKey
<nsObjectFrame
>* aEntry
, void* userArg
)
2500 PluginGeometryClosure
* closure
= static_cast<PluginGeometryClosure
*>(userArg
);
2501 nsObjectFrame
* f
= aEntry
->GetKey();
2502 nsRect fBounds
= f
->GetContentRect() +
2503 f
->GetParent()->GetOffsetToCrossDoc(closure
->mRootFrame
);
2504 PRInt32 APD
= f
->PresContext()->AppUnitsPerDevPixel();
2505 fBounds
= fBounds
.ConvertAppUnitsRoundOut(APD
, closure
->mRootAPD
);
2506 // We're identifying the plugins that may have been affected by changes
2507 // to the frame subtree rooted at aChangedRoot. Any plugin that overlaps
2508 // the overflow area of aChangedRoot could have its clip region affected
2509 // because it might be covered (or uncovered) by changes to the subtree.
2510 // Plugins in the subtree might have changed position and/or size, and
2511 // they might not be in aChangedRoot's overflow area (because they're
2512 // being clipped by an ancestor in the subtree).
2513 if (fBounds
.Intersects(closure
->mChangedRect
) ||
2514 nsLayoutUtils::IsAncestorFrameCrossDoc(closure
->mChangedSubtree
, f
)) {
2515 closure
->mAffectedPluginBounds
.UnionRect(
2516 closure
->mAffectedPluginBounds
, fBounds
);
2517 closure
->mAffectedPlugins
.PutEntry(f
);
2519 return PL_DHASH_NEXT
;
2522 static PLDHashOperator
2523 PluginHideEnumerator(nsPtrHashKey
<nsObjectFrame
>* aEntry
, void* userArg
)
2525 PluginGeometryClosure
* closure
= static_cast<PluginGeometryClosure
*>(userArg
);
2526 nsObjectFrame
* f
= aEntry
->GetKey();
2527 f
->GetEmptyClipConfiguration(closure
->mOutputConfigurations
);
2528 return PL_DHASH_NEXT
;
2532 RecoverPluginGeometry(nsDisplayListBuilder
* aBuilder
,
2533 nsDisplayList
* aList
, PluginGeometryClosure
* aClosure
)
2535 for (nsDisplayItem
* i
= aList
->GetBottom(); i
; i
= i
->GetAbove()) {
2536 switch (i
->GetType()) {
2537 case nsDisplayItem::TYPE_PLUGIN
: {
2538 nsDisplayPlugin
* displayPlugin
= static_cast<nsDisplayPlugin
*>(i
);
2539 nsObjectFrame
* f
= static_cast<nsObjectFrame
*>(
2540 displayPlugin
->GetUnderlyingFrame());
2541 // Ignore plugins which aren't supposed to be affected by this
2542 // operation --- their bounds will not have been included in the
2543 // display list computations so the visible region computed for them
2544 // would be incorrect
2545 nsPtrHashKey
<nsObjectFrame
>* entry
=
2546 aClosure
->mAffectedPlugins
.GetEntry(f
);
2548 displayPlugin
->GetWidgetConfiguration(aBuilder
,
2549 aClosure
->mOutputConfigurations
);
2550 // we've dealt with this plugin now
2551 aClosure
->mAffectedPlugins
.RawRemoveEntry(entry
);
2556 nsDisplayList
* sublist
= i
->GetList();
2558 RecoverPluginGeometry(aBuilder
, sublist
, aClosure
);
2569 static PRBool gDumpPluginList
= PR_FALSE
;
2573 nsRootPresContext::GetPluginGeometryUpdates(nsIFrame
* aChangedSubtree
,
2574 nsTArray
<nsIWidget::Configuration
>* aConfigurations
)
2576 if (mRegisteredPlugins
.Count() == 0)
2579 PluginGeometryClosure closure
;
2580 closure
.mRootFrame
= mShell
->FrameManager()->GetRootFrame();
2581 closure
.mRootAPD
= closure
.mRootFrame
->PresContext()->AppUnitsPerDevPixel();
2582 closure
.mChangedSubtree
= aChangedSubtree
;
2583 closure
.mChangedRect
= aChangedSubtree
->GetVisualOverflowRect() +
2584 aChangedSubtree
->GetOffsetToCrossDoc(closure
.mRootFrame
);
2585 PRInt32 subtreeAPD
= aChangedSubtree
->PresContext()->AppUnitsPerDevPixel();
2586 closure
.mChangedRect
=
2587 closure
.mChangedRect
.ConvertAppUnitsRoundOut(subtreeAPD
, closure
.mRootAPD
);
2588 closure
.mAffectedPlugins
.Init();
2589 closure
.mOutputConfigurations
= aConfigurations
;
2590 // Fill in closure.mAffectedPlugins and closure.mAffectedPluginBounds
2591 mRegisteredPlugins
.EnumerateEntries(PluginBoundsEnumerator
, &closure
);
2594 if (bounds
.IntersectRect(closure
.mAffectedPluginBounds
,
2595 closure
.mRootFrame
->GetRect())) {
2596 nsDisplayListBuilder
builder(closure
.mRootFrame
,
2597 nsDisplayListBuilder::PLUGIN_GEOMETRY
, PR_FALSE
);
2598 builder
.SetAccurateVisibleRegions();
2601 builder
.EnterPresShell(closure
.mRootFrame
, bounds
);
2602 closure
.mRootFrame
->BuildDisplayListForStackingContext(
2603 &builder
, bounds
, &list
);
2604 builder
.LeavePresShell(closure
.mRootFrame
, bounds
);
2607 if (gDumpPluginList
) {
2608 fprintf(stderr
, "Plugins --- before optimization (bounds %d,%d,%d,%d):\n",
2609 bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
);
2610 nsFrame::PrintDisplayList(&builder
, list
);
2614 nsRegion
visibleRegion(bounds
);
2615 list
.ComputeVisibilityForRoot(&builder
, &visibleRegion
);
2618 if (gDumpPluginList
) {
2619 fprintf(stderr
, "Plugins --- after optimization:\n");
2620 nsFrame::PrintDisplayList(&builder
, list
);
2624 RecoverPluginGeometry(&builder
, &list
, &closure
);
2628 // Plugins that we didn't find in the display list are not visible
2629 closure
.mAffectedPlugins
.EnumerateEntries(PluginHideEnumerator
, &closure
);
2633 HasOverlap(const nsIntPoint
& aOffset1
, const nsTArray
<nsIntRect
>& aClipRects1
,
2634 const nsIntPoint
& aOffset2
, const nsTArray
<nsIntRect
>& aClipRects2
)
2636 nsIntPoint offsetDelta
= aOffset1
- aOffset2
;
2637 for (PRUint32 i
= 0; i
< aClipRects1
.Length(); ++i
) {
2638 for (PRUint32 j
= 0; j
< aClipRects2
.Length(); ++j
) {
2639 if ((aClipRects1
[i
] + offsetDelta
).Intersects(aClipRects2
[j
]))
2647 * Given a list of plugin windows to move to new locations, sort the list
2648 * so that for each window move, the window moves to a location that
2649 * does not intersect other windows. This minimizes flicker and repainting.
2650 * It's not always possible to do this perfectly, since in general
2651 * we might have cycles. But we do our best.
2652 * We need to take into account that windows are clipped to particular
2653 * regions and the clip regions change as the windows are moved.
2656 SortConfigurations(nsTArray
<nsIWidget::Configuration
>* aConfigurations
)
2658 if (aConfigurations
->Length() > 10) {
2659 // Give up, we don't want to get bogged down here
2663 nsTArray
<nsIWidget::Configuration
> pluginsToMove
;
2664 pluginsToMove
.SwapElements(*aConfigurations
);
2666 // Our algorithm is quite naive. At each step we try to identify
2667 // a window that can be moved to its new location that won't overlap
2668 // any other windows at the new location. If there is no such
2669 // window, we just move the last window in the list anyway.
2670 while (!pluginsToMove
.IsEmpty()) {
2671 // Find a window whose destination does not overlap any other window
2673 for (i
= 0; i
+ 1 < pluginsToMove
.Length(); ++i
) {
2674 nsIWidget::Configuration
* config
= &pluginsToMove
[i
];
2675 PRBool foundOverlap
= PR_FALSE
;
2676 for (PRUint32 j
= 0; j
< pluginsToMove
.Length(); ++j
) {
2680 pluginsToMove
[j
].mChild
->GetBounds(bounds
);
2681 nsAutoTArray
<nsIntRect
,1> clipRects
;
2682 pluginsToMove
[j
].mChild
->GetWindowClipRegion(&clipRects
);
2683 if (HasOverlap(bounds
.TopLeft(), clipRects
,
2684 config
->mBounds
.TopLeft(),
2685 config
->mClipRegion
)) {
2686 foundOverlap
= PR_TRUE
;
2693 // Note that we always move the last plugin in pluginsToMove, if we
2694 // can't find any other plugin to move
2695 aConfigurations
->AppendElement(pluginsToMove
[i
]);
2696 pluginsToMove
.RemoveElementAt(i
);
2701 nsRootPresContext::UpdatePluginGeometry()
2703 if (!mNeedsToUpdatePluginGeometry
)
2705 mNeedsToUpdatePluginGeometry
= PR_FALSE
;
2707 nsIFrame
* f
= mUpdatePluginGeometryForFrame
;
2709 mUpdatePluginGeometryForFrame
->PresContext()->
2710 SetContainsUpdatePluginGeometryFrame(PR_FALSE
);
2711 mUpdatePluginGeometryForFrame
= nsnull
;
2713 f
= FrameManager()->GetRootFrame();
2716 nsTArray
<nsIWidget::Configuration
> configurations
;
2717 GetPluginGeometryUpdates(f
, &configurations
);
2718 if (configurations
.IsEmpty())
2720 SortConfigurations(&configurations
);
2721 nsIWidget
* widget
= FrameManager()->GetRootFrame()->GetNearestWidget();
2722 NS_ASSERTION(widget
, "Plugins must have a parent window");
2723 widget
->ConfigureChildren(configurations
);
2724 DidApplyPluginGeometryUpdates();
2728 nsRootPresContext::SynchronousPluginGeometryUpdate()
2730 if (!mNeedsToUpdatePluginGeometry
) {
2735 // Force synchronous paint
2736 nsIPresShell
* shell
= GetPresShell();
2739 nsIFrame
* rootFrame
= shell
->GetRootFrame();
2742 nsCOMPtr
<nsIWidget
> widget
= rootFrame
->GetNearestWidget();
2745 // Force synchronous paint of a single pixel, just to force plugin
2746 // updates to be flushed. Doing plugin updates during paint is the best
2747 // way to ensure that plugin updates are in sync with our content.
2748 widget
->Invalidate(nsIntRect(0,0,1,1), PR_TRUE
);
2750 // Update plugin geometry just in case that invalidate didn't work
2751 // (e.g. if none of the widget is visible, it might not have processed
2752 // a paint event). Normally this won't need to do anything.
2753 UpdatePluginGeometry();
2757 nsRootPresContext::RequestUpdatePluginGeometry(nsIFrame
* aFrame
)
2759 if (mRegisteredPlugins
.Count() == 0)
2762 if (!mNeedsToUpdatePluginGeometry
) {
2763 mNeedsToUpdatePluginGeometry
= PR_TRUE
;
2765 // Dispatch a Gecko event to ensure plugin geometry gets updated
2766 // XXX this really should be done through the refresh driver, once
2767 // all painting happens in the refresh driver
2768 nsCOMPtr
<nsIRunnable
> event
=
2769 NS_NewRunnableMethod(this, &nsRootPresContext::SynchronousPluginGeometryUpdate
);
2770 NS_DispatchToMainThread(event
);
2772 mUpdatePluginGeometryForFrame
= aFrame
;
2773 mUpdatePluginGeometryForFrame
->PresContext()->
2774 SetContainsUpdatePluginGeometryFrame(PR_TRUE
);
2776 if (!mUpdatePluginGeometryForFrame
||
2777 aFrame
== mUpdatePluginGeometryForFrame
)
2779 mUpdatePluginGeometryForFrame
->PresContext()->
2780 SetContainsUpdatePluginGeometryFrame(PR_FALSE
);
2781 mUpdatePluginGeometryForFrame
= nsnull
;
2785 static PLDHashOperator
2786 PluginDidSetGeometryEnumerator(nsPtrHashKey
<nsObjectFrame
>* aEntry
, void* userArg
)
2788 nsObjectFrame
* f
= aEntry
->GetKey();
2789 f
->DidSetWidgetGeometry();
2790 return PL_DHASH_NEXT
;
2794 nsRootPresContext::DidApplyPluginGeometryUpdates()
2796 mRegisteredPlugins
.EnumerateEntries(PluginDidSetGeometryEnumerator
, nsnull
);
2800 nsRootPresContext::RootForgetUpdatePluginGeometryFrame(nsIFrame
* aFrame
)
2802 if (aFrame
== mUpdatePluginGeometryForFrame
) {
2803 mUpdatePluginGeometryForFrame
->PresContext()->
2804 SetContainsUpdatePluginGeometryFrame(PR_FALSE
);
2805 mUpdatePluginGeometryForFrame
= nsnull
;
2810 NotifyDidPaintForSubtreeCallback(nsITimer
*aTimer
, void *aClosure
)
2812 nsPresContext
* presContext
= (nsPresContext
*)aClosure
;
2813 nsAutoScriptBlocker blockScripts
;
2814 presContext
->NotifyDidPaintForSubtree();
2818 nsRootPresContext::EnsureEventualDidPaintEvent()
2820 if (mNotifyDidPaintTimer
)
2822 mNotifyDidPaintTimer
= do_CreateInstance("@mozilla.org/timer;1");
2823 if (!mNotifyDidPaintTimer
)
2825 mNotifyDidPaintTimer
->InitWithFuncCallback(NotifyDidPaintForSubtreeCallback
,
2826 (void*)this, 100, nsITimer::TYPE_ONE_SHOT
);