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 "nsIFocusController.h"
52 #include "nsStyleSet.h"
53 #include "nsImageLoader.h"
54 #include "nsIContent.h"
56 #include "nsIRenderingContext.h"
58 #include "nsIDocument.h"
59 #include "nsStyleContext.h"
60 #include "nsILookAndFeel.h"
61 #include "nsWidgetsCID.h"
62 #include "nsIComponentManager.h"
63 #include "nsIURIContentListener.h"
64 #include "nsIInterfaceRequestor.h"
65 #include "nsIInterfaceRequestorUtils.h"
66 #include "nsIServiceManager.h"
67 #include "nsIDOMElement.h"
68 #include "nsContentPolicyUtils.h"
69 #include "nsIDOMWindow.h"
70 #include "nsXPIDLString.h"
71 #include "nsIWeakReferenceUtils.h"
72 #include "nsCSSRendering.h"
74 #include "nsContentPolicyUtils.h"
75 #include "nsIDOMDocument.h"
76 #include "nsAutoPtr.h"
77 #include "nsEventStateManager.h"
78 #include "nsThreadUtils.h"
79 #include "nsFrameManager.h"
80 #include "nsLayoutUtils.h"
81 #include "nsIViewManager.h"
82 #include "nsCSSFrameConstructor.h"
83 #include "nsCSSRuleProcessor.h"
84 #include "nsStyleChangeList.h"
85 #include "nsRuleNode.h"
86 #include "nsEventDispatcher.h"
87 #include "gfxUserFontSet.h"
88 #include "gfxPlatform.h"
89 #include "nsCSSRules.h"
90 #include "nsFontFaceLoader.h"
91 #include "nsIEventListenerManager.h"
94 #include "nsBidiPresUtils.h"
97 #include "nsContentUtils.h"
99 // Needed for Start/Stop of Image Animation
100 #include "imgIContainer.h"
101 #include "nsIImageLoadingContent.h"
103 //needed for resetting of image service color
104 #include "nsLayoutCID.h"
107 MakeColorPref(const char *colstr
)
109 PRUint32 red
, green
, blue
;
112 // 4.x stored RGB color values as a string rather than as an int,
113 // thus we need to do this conversion
114 PR_sscanf(colstr
, "#%02x%02x%02x", &red
, &green
, &blue
);
115 colorref
= NS_RGB(red
, green
, blue
);
120 nsPresContext::PrefChangedCallback(const char* aPrefName
, void* instance_data
)
122 nsPresContext
* presContext
= (nsPresContext
*)instance_data
;
124 NS_ASSERTION(nsnull
!= presContext
, "bad instance data");
125 if (nsnull
!= presContext
) {
126 presContext
->PreferenceChanged(aPrefName
);
133 nsPresContext::PrefChangedUpdateTimerCallback(nsITimer
*aTimer
, void *aClosure
)
135 nsPresContext
* presContext
= (nsPresContext
*)aClosure
;
136 NS_ASSERTION(presContext
!= nsnull
, "bad instance data");
138 presContext
->UpdateAfterPreferencesChanged();
143 IsVisualCharset(const nsCString
& aCharset
)
145 if (aCharset
.LowerCaseEqualsLiteral("ibm864") // Arabic//ahmed
146 || aCharset
.LowerCaseEqualsLiteral("ibm862") // Hebrew
147 || aCharset
.LowerCaseEqualsLiteral("iso-8859-8") ) { // Hebrew
148 return PR_TRUE
; // visual text type
151 return PR_FALSE
; // logical text type
157 static PLDHashOperator
158 destroy_loads(const void * aKey
, nsCOMPtr
<nsImageLoader
>& aData
, void* closure
)
161 return PL_DHASH_NEXT
;
164 static NS_DEFINE_CID(kLookAndFeelCID
, NS_LOOKANDFEEL_CID
);
165 #include "nsContentCID.h"
167 // NOTE! nsPresContext::operator new() zeroes out all members, so don't
168 // bother initializing members to 0.
170 nsPresContext::nsPresContext(nsIDocument
* aDocument
, nsPresContextType aType
)
171 : mType(aType
), mDocument(aDocument
), mTextZoom(1.0), mFullZoom(1.0),
172 mPageSize(-1, -1), mPPScale(1.0f
),
173 mViewportStyleOverflow(NS_STYLE_OVERFLOW_AUTO
, NS_STYLE_OVERFLOW_AUTO
),
174 mImageAnimationModePref(imgIContainer::kNormalAnimMode
),
175 // Font sizes default to zero; they will be set in GetFontPreferences
176 mDefaultVariableFont("serif", NS_FONT_STYLE_NORMAL
, NS_FONT_VARIANT_NORMAL
,
177 NS_FONT_WEIGHT_NORMAL
, 0, 0),
178 mDefaultFixedFont("monospace", NS_FONT_STYLE_NORMAL
,
179 NS_FONT_VARIANT_NORMAL
, NS_FONT_WEIGHT_NORMAL
, 0, 0),
180 mDefaultSerifFont("serif", NS_FONT_STYLE_NORMAL
, NS_FONT_VARIANT_NORMAL
,
181 NS_FONT_WEIGHT_NORMAL
, 0, 0),
182 mDefaultSansSerifFont("sans-serif", NS_FONT_STYLE_NORMAL
,
183 NS_FONT_VARIANT_NORMAL
, NS_FONT_WEIGHT_NORMAL
, 0, 0),
184 mDefaultMonospaceFont("monospace", NS_FONT_STYLE_NORMAL
,
185 NS_FONT_VARIANT_NORMAL
, NS_FONT_WEIGHT_NORMAL
, 0, 0),
186 mDefaultCursiveFont("cursive", NS_FONT_STYLE_NORMAL
,
187 NS_FONT_VARIANT_NORMAL
, NS_FONT_WEIGHT_NORMAL
, 0, 0),
188 mDefaultFantasyFont("fantasy", NS_FONT_STYLE_NORMAL
,
189 NS_FONT_VARIANT_NORMAL
, NS_FONT_WEIGHT_NORMAL
, 0, 0),
190 mCanPaginatedScroll(PR_FALSE
),
191 mIsRootPaginatedDocument(PR_FALSE
), mSupressResizeReflow(PR_FALSE
)
193 // NOTE! nsPresContext::operator new() zeroes out all members, so don't
194 // bother initializing members to 0.
196 mDoScaledTwips
= PR_TRUE
;
198 SetBackgroundImageDraw(PR_TRUE
); // always draw the background
199 SetBackgroundColorDraw(PR_TRUE
);
201 mBackgroundColor
= NS_RGB(0xFF, 0xFF, 0xFF);
203 mUseDocumentColors
= PR_TRUE
;
204 mUseDocumentFonts
= PR_TRUE
;
206 // the minimum font-size is unconstrained by default
208 mLinkColor
= NS_RGB(0x00, 0x00, 0xEE);
209 mActiveLinkColor
= NS_RGB(0xEE, 0x00, 0x00);
210 mVisitedLinkColor
= NS_RGB(0x55, 0x1A, 0x8B);
211 mUnderlineLinks
= PR_TRUE
;
213 mFocusTextColor
= mDefaultColor
;
214 mFocusBackgroundColor
= mBackgroundColor
;
217 if (aType
== eContext_Galley
) {
218 mMedium
= nsGkAtoms::screen
;
220 SetBackgroundImageDraw(PR_FALSE
);
221 SetBackgroundColorDraw(PR_FALSE
);
222 mMedium
= nsGkAtoms::print
;
223 mPaginated
= PR_TRUE
;
227 mImageAnimationMode
= imgIContainer::kDontAnimMode
;
228 mNeverAnimate
= PR_TRUE
;
230 mImageAnimationMode
= imgIContainer::kNormalAnimMode
;
231 mNeverAnimate
= PR_FALSE
;
233 NS_ASSERTION(mDocument
, "Null document");
234 mUserFontSet
= nsnull
;
235 mUserFontSetDirty
= PR_TRUE
;
238 nsPresContext::~nsPresContext()
240 mImageLoaders
.Enumerate(destroy_loads
, nsnull
);
241 mBorderImageLoaders
.Enumerate(destroy_loads
, nsnull
);
243 NS_PRECONDITION(!mShell
, "Presshell forgot to clear our mShell pointer");
247 // unclear if these are needed, but can't hurt
248 mEventManager
->NotifyDestroyPresContext(this);
249 mEventManager
->SetPresContext(nsnull
);
251 NS_RELEASE(mEventManager
);
254 if (mPrefChangedTimer
)
256 mPrefChangedTimer
->Cancel();
257 mPrefChangedTimer
= nsnull
;
260 // Unregister preference callbacks
261 nsContentUtils::UnregisterPrefCallback("font.",
262 nsPresContext::PrefChangedCallback
,
264 nsContentUtils::UnregisterPrefCallback("browser.display.",
265 nsPresContext::PrefChangedCallback
,
267 nsContentUtils::UnregisterPrefCallback("browser.underline_anchors",
268 nsPresContext::PrefChangedCallback
,
270 nsContentUtils::UnregisterPrefCallback("browser.anchor_color",
271 nsPresContext::PrefChangedCallback
,
273 nsContentUtils::UnregisterPrefCallback("browser.active_color",
274 nsPresContext::PrefChangedCallback
,
276 nsContentUtils::UnregisterPrefCallback("browser.visited_color",
277 nsPresContext::PrefChangedCallback
,
279 nsContentUtils::UnregisterPrefCallback("image.animation_mode",
280 nsPresContext::PrefChangedCallback
,
283 nsContentUtils::UnregisterPrefCallback("bidi.", PrefChangedCallback
, this);
287 nsContentUtils::UnregisterPrefCallback("layout.css.dpi",
288 nsPresContext::PrefChangedCallback
,
291 NS_IF_RELEASE(mDeviceContext
);
292 NS_IF_RELEASE(mLookAndFeel
);
293 NS_IF_RELEASE(mLangGroup
);
294 NS_IF_RELEASE(mUserFontSet
);
297 NS_IMPL_CYCLE_COLLECTION_CLASS(nsPresContext
)
299 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPresContext
)
300 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIObserver
)
301 NS_INTERFACE_MAP_ENTRY(nsIObserver
)
304 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPresContext
)
305 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPresContext
)
307 static PLDHashOperator
308 TraverseImageLoader(const void * aKey
, nsCOMPtr
<nsImageLoader
>& aData
,
311 nsCycleCollectionTraversalCallback
*cb
=
312 static_cast<nsCycleCollectionTraversalCallback
*>(aClosure
);
314 cb
->NoteXPCOMChild(aData
);
316 return PL_DHASH_NEXT
;
319 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsPresContext
)
320 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocument
);
321 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mDeviceContext
); // worth bothering?
322 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mEventManager
);
323 // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mLookAndFeel); // a service
324 // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mLangGroup); // an atom
326 tmp
->mImageLoaders
.Enumerate(TraverseImageLoader
, &cb
);
327 tmp
->mBorderImageLoaders
.Enumerate(TraverseImageLoader
, &cb
);
329 // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTheme); // a service
330 // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLangService); // a service
331 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrintSettings
);
332 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrefChangedTimer
);
333 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
335 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsPresContext
)
336 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocument
);
337 NS_RELEASE(tmp
->mDeviceContext
); // worth bothering?
338 if (tmp
->mEventManager
) {
339 // unclear if these are needed, but can't hurt
340 tmp
->mEventManager
->NotifyDestroyPresContext(tmp
);
341 tmp
->mEventManager
->SetPresContext(nsnull
);
343 NS_RELEASE(tmp
->mEventManager
);
346 // NS_RELEASE(tmp->mLookAndFeel); // a service
347 // NS_RELEASE(tmp->mLangGroup); // an atom
349 tmp
->mImageLoaders
.Enumerate(destroy_loads
, nsnull
);
350 tmp
->mImageLoaders
.Clear();
351 tmp
->mBorderImageLoaders
.Enumerate(destroy_loads
, nsnull
);
352 tmp
->mBorderImageLoaders
.Clear();
354 // NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTheme); // a service
355 // NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLangService); // a service
356 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mPrintSettings
);
357 if (tmp
->mPrefChangedTimer
)
359 tmp
->mPrefChangedTimer
->Cancel();
360 tmp
->mPrefChangedTimer
= nsnull
;
362 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
365 #define MAKE_FONT_PREF_KEY(_pref, _s0, _s1) \
369 static const char* const kGenericFont
[] = {
379 // Set to true when LookAndFeelChanged needs to be called. This is used
380 // because the look and feel is a service, so there's no need to notify it from
381 // more than one prescontext.
382 static PRBool sLookAndFeelChanged
;
384 // Set to true when ThemeChanged needs to be called on mTheme. This is used
385 // because mTheme is a service, so there's no need to notify it from more than
387 static PRBool sThemeChanged
;
390 nsPresContext::GetFontPreferences()
392 /* Fetch the font prefs to be used -- see bug 61883 for details.
393 Not all prefs are needed upfront. Some are fallback prefs intended
394 for the GFX font sub-system...
396 1) unit : assumed to be the same for all language groups -------------
397 font.size.unit = px | pt XXX could be folded in the size... bug 90440
399 2) attributes for generic fonts --------------------------------------
400 font.default = serif | sans-serif - fallback generic font
401 font.name.[generic].[langGroup] = current user' selected font on the pref dialog
402 font.name-list.[generic].[langGroup] = fontname1, fontname2, ... [factory pre-built list]
403 font.size.[generic].[langGroup] = integer - settable by the user
404 font.size-adjust.[generic].[langGroup] = "float" - settable by the user
405 font.minimum-size.[langGroup] = integer - settable by the user
408 mDefaultVariableFont
.size
= CSSPixelsToAppUnits(16);
409 mDefaultFixedFont
.size
= CSSPixelsToAppUnits(13);
411 const char *langGroup
= "x-western"; // Assume x-western is safe...
413 mLangGroup
->GetUTF8String(&langGroup
);
418 // get the current applicable font-size unit
419 enum {eUnit_unknown
= -1, eUnit_px
, eUnit_pt
};
420 PRInt32 unit
= eUnit_px
;
422 nsAdoptingCString cvalue
=
423 nsContentUtils::GetCharPref("font.size.unit");
425 if (!cvalue
.IsEmpty()) {
426 if (cvalue
.Equals("px")) {
429 else if (cvalue
.Equals("pt")) {
433 NS_WARNING("unexpected font-size unit -- expected: 'px' or 'pt'");
434 unit
= eUnit_unknown
;
438 // get font.minimum-size.[langGroup]
440 pref
.Assign("font.minimum-size.");
441 pref
.Append(langGroup
);
443 PRInt32 size
= nsContentUtils::GetIntPref(pref
.get());
444 if (unit
== eUnit_px
) {
445 mMinimumFontSize
= CSSPixelsToAppUnits(size
);
447 else if (unit
== eUnit_pt
) {
448 mMinimumFontSize
= this->PointsToAppUnits(size
);
451 // get attributes specific to each generic font
452 nsCAutoString generic_dot_langGroup
;
453 for (PRInt32 eType
= eDefaultFont_Variable
; eType
< eDefaultFont_COUNT
; ++eType
) {
454 generic_dot_langGroup
.Assign(kGenericFont
[eType
]);
455 generic_dot_langGroup
.Append(langGroup
);
459 case eDefaultFont_Variable
: font
= &mDefaultVariableFont
; break;
460 case eDefaultFont_Fixed
: font
= &mDefaultFixedFont
; break;
461 case eDefaultFont_Serif
: font
= &mDefaultSerifFont
; break;
462 case eDefaultFont_SansSerif
: font
= &mDefaultSansSerifFont
; break;
463 case eDefaultFont_Monospace
: font
= &mDefaultMonospaceFont
; break;
464 case eDefaultFont_Cursive
: font
= &mDefaultCursiveFont
; break;
465 case eDefaultFont_Fantasy
: font
= &mDefaultFantasyFont
; break;
468 // set the default variable font (the other fonts are seen as 'generic' fonts
469 // in GFX and will be queried there when hunting for alternative fonts)
470 if (eType
== eDefaultFont_Variable
) {
471 MAKE_FONT_PREF_KEY(pref
, "font.name", generic_dot_langGroup
);
473 nsAdoptingString value
=
474 nsContentUtils::GetStringPref(pref
.get());
475 if (!value
.IsEmpty()) {
476 font
->name
.Assign(value
);
479 MAKE_FONT_PREF_KEY(pref
, "font.default.", langGroup
);
480 value
= nsContentUtils::GetStringPref(pref
.get());
481 if (!value
.IsEmpty()) {
482 mDefaultVariableFont
.name
.Assign(value
);
487 if (eType
== eDefaultFont_Monospace
) {
488 // This takes care of the confusion whereby people often expect "monospace"
489 // to have the same default font-size as "-moz-fixed" (this tentative
490 // size may be overwritten with the specific value for "monospace" when
491 // "font.size.monospace.[langGroup]" is read -- see below)
492 font
->size
= mDefaultFixedFont
.size
;
494 else if (eType
!= eDefaultFont_Fixed
) {
495 // all the other generic fonts are initialized with the size of the
496 // variable font, but their specific size can supersede later -- see below
497 font
->size
= mDefaultVariableFont
.size
;
501 // Bug 84398: for spec purists, a different font-size only applies to the
502 // .variable. and .fixed. fonts and the other fonts should get |font-size-adjust|.
503 // The problem is that only GfxWin has the support for |font-size-adjust|. So for
504 // parity, we enable the ability to set a different font-size on all platforms.
506 // get font.size.[generic].[langGroup]
507 // size=0 means 'Auto', i.e., generic fonts retain the size of the variable font
508 MAKE_FONT_PREF_KEY(pref
, "font.size", generic_dot_langGroup
);
509 size
= nsContentUtils::GetIntPref(pref
.get());
511 if (unit
== eUnit_px
) {
512 font
->size
= nsPresContext::CSSPixelsToAppUnits(size
);
514 else if (unit
== eUnit_pt
) {
515 font
->size
= this->PointsToAppUnits(size
);
519 // get font.size-adjust.[generic].[langGroup]
520 // XXX only applicable on GFX ports that handle |font-size-adjust|
521 MAKE_FONT_PREF_KEY(pref
, "font.size-adjust", generic_dot_langGroup
);
522 cvalue
= nsContentUtils::GetCharPref(pref
.get());
523 if (!cvalue
.IsEmpty()) {
524 font
->sizeAdjust
= (float)atof(cvalue
.get());
528 printf("%s Family-list:%s size:%d sizeAdjust:%.2f\n",
529 generic_dot_langGroup
.get(),
530 NS_ConvertUTF16toUTF8(font
->name
).get(), font
->size
,
537 nsPresContext::GetDocumentColorPreferences()
539 PRInt32 useAccessibilityTheme
= 0;
540 PRBool usePrefColors
= PR_TRUE
;
541 nsCOMPtr
<nsIDocShellTreeItem
> docShell(do_QueryReferent(mContainer
));
543 PRInt32 docShellType
;
544 docShell
->GetItemType(&docShellType
);
545 if (nsIDocShellTreeItem::typeChrome
== docShellType
) {
546 usePrefColors
= PR_FALSE
;
549 mLookAndFeel
->GetMetric(nsILookAndFeel::eMetric_UseAccessibilityTheme
, useAccessibilityTheme
);
550 usePrefColors
= !useAccessibilityTheme
;
556 !nsContentUtils::GetBoolPref("browser.display.use_system_colors",
561 nsAdoptingCString colorStr
=
562 nsContentUtils::GetCharPref("browser.display.foreground_color");
564 if (!colorStr
.IsEmpty()) {
565 mDefaultColor
= MakeColorPref(colorStr
);
569 nsContentUtils::GetCharPref("browser.display.background_color");
571 if (!colorStr
.IsEmpty()) {
572 mBackgroundColor
= MakeColorPref(colorStr
);
576 mDefaultColor
= NS_RGB(0x00, 0x00, 0x00);
577 mBackgroundColor
= NS_RGB(0xFF, 0xFF, 0xFF);
578 mLookAndFeel
->GetColor(nsILookAndFeel::eColor_WindowForeground
,
580 mLookAndFeel
->GetColor(nsILookAndFeel::eColor_WindowBackground
,
584 // Wherever we got the default background color from, ensure it is
586 mBackgroundColor
= NS_ComposeColors(NS_RGB(0xFF, 0xFF, 0xFF),
589 mUseDocumentColors
= !useAccessibilityTheme
&&
590 nsContentUtils::GetBoolPref("browser.display.use_document_colors",
595 nsPresContext::GetUserPreferences()
597 if (!GetPresShell()) {
598 // No presshell means nothing to do here. We'll do this when we
604 nsContentUtils::GetIntPref("browser.display.base_font_scaler",
608 mAutoQualityMinFontSizePixelsPref
=
609 nsContentUtils::GetIntPref("browser.display.auto_quality_min_font_size");
612 GetDocumentColorPreferences();
616 nsContentUtils::GetBoolPref("browser.underline_anchors", mUnderlineLinks
);
618 nsAdoptingCString colorStr
=
619 nsContentUtils::GetCharPref("browser.anchor_color");
621 if (!colorStr
.IsEmpty()) {
622 mLinkColor
= MakeColorPref(colorStr
);
626 nsContentUtils::GetCharPref("browser.active_color");
628 if (!colorStr
.IsEmpty()) {
629 mActiveLinkColor
= MakeColorPref(colorStr
);
632 colorStr
= nsContentUtils::GetCharPref("browser.visited_color");
634 if (!colorStr
.IsEmpty()) {
635 mVisitedLinkColor
= MakeColorPref(colorStr
);
639 nsContentUtils::GetBoolPref("browser.display.use_focus_colors",
642 mFocusTextColor
= mDefaultColor
;
643 mFocusBackgroundColor
= mBackgroundColor
;
645 colorStr
= nsContentUtils::GetCharPref("browser.display.focus_text_color");
647 if (!colorStr
.IsEmpty()) {
648 mFocusTextColor
= MakeColorPref(colorStr
);
652 nsContentUtils::GetCharPref("browser.display.focus_background_color");
654 if (!colorStr
.IsEmpty()) {
655 mFocusBackgroundColor
= MakeColorPref(colorStr
);
659 nsContentUtils::GetIntPref("browser.display.focus_ring_width",
662 mFocusRingOnAnything
=
663 nsContentUtils::GetBoolPref("browser.display.focus_ring_on_anything",
664 mFocusRingOnAnything
);
667 nsContentUtils::GetIntPref("browser.display.focus_ring_style",
671 nsContentUtils::GetIntPref("browser.display.use_document_fonts") != 0;
673 // * replace backslashes with Yen signs? (bug 245770)
674 mEnableJapaneseTransform
=
675 nsContentUtils::GetBoolPref("layout.enable_japanese_specific_transform");
678 nsContentUtils::GetIntPref("layout.scrollbar.side");
680 GetFontPreferences();
683 const nsAdoptingCString
& animatePref
=
684 nsContentUtils::GetCharPref("image.animation_mode");
685 if (animatePref
.Equals("normal"))
686 mImageAnimationModePref
= imgIContainer::kNormalAnimMode
;
687 else if (animatePref
.Equals("none"))
688 mImageAnimationModePref
= imgIContainer::kDontAnimMode
;
689 else if (animatePref
.Equals("once"))
690 mImageAnimationModePref
= imgIContainer::kLoopOnceAnimMode
;
691 else // dynamic change to invalid value should act like it does initially
692 mImageAnimationModePref
= imgIContainer::kNormalAnimMode
;
694 PRUint32 bidiOptions
= GetBidi();
697 nsContentUtils::GetIntPref(IBMBIDI_TEXTDIRECTION_STR
,
698 GET_BIDI_OPTION_DIRECTION(bidiOptions
));
699 SET_BIDI_OPTION_DIRECTION(bidiOptions
, prefInt
);
700 mPrefBidiDirection
= prefInt
;
703 nsContentUtils::GetIntPref(IBMBIDI_TEXTTYPE_STR
,
704 GET_BIDI_OPTION_TEXTTYPE(bidiOptions
));
705 SET_BIDI_OPTION_TEXTTYPE(bidiOptions
, prefInt
);
708 nsContentUtils::GetIntPref(IBMBIDI_CONTROLSTEXTMODE_STR
,
709 GET_BIDI_OPTION_CONTROLSTEXTMODE(bidiOptions
));
710 SET_BIDI_OPTION_CONTROLSTEXTMODE(bidiOptions
, prefInt
);
713 nsContentUtils::GetIntPref(IBMBIDI_NUMERAL_STR
,
714 GET_BIDI_OPTION_NUMERAL(bidiOptions
));
715 SET_BIDI_OPTION_NUMERAL(bidiOptions
, prefInt
);
718 nsContentUtils::GetIntPref(IBMBIDI_SUPPORTMODE_STR
,
719 GET_BIDI_OPTION_SUPPORT(bidiOptions
));
720 SET_BIDI_OPTION_SUPPORT(bidiOptions
, prefInt
);
723 nsContentUtils::GetIntPref(IBMBIDI_CHARSET_STR
,
724 GET_BIDI_OPTION_CHARACTERSET(bidiOptions
));
725 SET_BIDI_OPTION_CHARACTERSET(bidiOptions
, prefInt
);
727 // We don't need to force reflow: either we are initializing a new
728 // prescontext or we are being called from UpdateAfterPreferencesChanged()
729 // which triggers a reflow anyway.
730 SetBidi(bidiOptions
, PR_FALSE
);
734 nsPresContext::PreferenceChanged(const char* aPrefName
)
736 nsDependentCString
prefName(aPrefName
);
737 if (prefName
.EqualsLiteral("layout.css.dpi")) {
738 PRInt32 oldAppUnitsPerDevPixel
= AppUnitsPerDevPixel();
739 if (mDeviceContext
->CheckDPIChange() && mShell
) {
740 mDeviceContext
->FlushFontCache();
742 // Re-fetch the view manager's window dimensions in case there's a deferred
743 // resize which hasn't affected our mVisibleArea yet
744 nscoord oldWidthAppUnits
, oldHeightAppUnits
;
745 nsIViewManager
* vm
= GetViewManager();
746 vm
->GetWindowDimensions(&oldWidthAppUnits
, &oldHeightAppUnits
);
747 float oldWidthDevPixels
= oldWidthAppUnits
/oldAppUnitsPerDevPixel
;
748 float oldHeightDevPixels
= oldHeightAppUnits
/oldAppUnitsPerDevPixel
;
750 nscoord width
= NSToCoordRound(oldWidthDevPixels
*AppUnitsPerDevPixel());
751 nscoord height
= NSToCoordRound(oldHeightDevPixels
*AppUnitsPerDevPixel());
752 vm
->SetWindowDimensions(width
, height
);
754 MediaFeatureValuesChanged(PR_TRUE
);
755 RebuildAllStyleData(NS_STYLE_HINT_REFLOW
);
759 if (StringBeginsWith(prefName
, NS_LITERAL_CSTRING("font."))) {
760 // Changes to font family preferences don't change anything in the
761 // computed style data, so the style system won't generate a reflow
762 // hint for us. We need to do that manually.
764 // FIXME We could probably also handle changes to
765 // browser.display.auto_quality_min_font_size here, but that
766 // probably also requires clearing the text run cache, so don't
767 // bother (yet, anyway).
768 mPrefChangePendingNeedsReflow
= PR_TRUE
;
770 if (StringBeginsWith(prefName
, NS_LITERAL_CSTRING("bidi."))) {
771 // Changes to bidi prefs need to trigger a reflow (see bug 443629)
772 mPrefChangePendingNeedsReflow
= PR_TRUE
;
774 // Changes to bidi.numeral also needs to empty the text run cache.
775 // This is handled in gfxTextRunWordCache.cpp.
777 // we use a zero-delay timer to coalesce multiple pref updates
778 if (!mPrefChangedTimer
)
780 mPrefChangedTimer
= do_CreateInstance("@mozilla.org/timer;1");
781 if (!mPrefChangedTimer
)
783 mPrefChangedTimer
->InitWithFuncCallback(nsPresContext::PrefChangedUpdateTimerCallback
, (void*)this, 0, nsITimer::TYPE_ONE_SHOT
);
788 nsPresContext::UpdateAfterPreferencesChanged()
790 mPrefChangedTimer
= nsnull
;
792 nsCOMPtr
<nsIDocShellTreeItem
> docShell(do_QueryReferent(mContainer
));
794 PRInt32 docShellType
;
795 docShell
->GetItemType(&docShellType
);
796 if (nsIDocShellTreeItem::typeChrome
== docShellType
)
800 // Initialize our state from the user preferences
801 GetUserPreferences();
803 // update the presShell: tell it to set the preference style rules up
805 mShell
->SetPreferenceStyleRules(PR_TRUE
);
808 mDeviceContext
->FlushFontCache();
810 nsChangeHint hint
= nsChangeHint(0);
812 if (mPrefChangePendingNeedsReflow
) {
813 NS_UpdateHint(hint
, NS_STYLE_HINT_REFLOW
);
816 RebuildAllStyleData(hint
);
820 nsPresContext::Init(nsIDeviceContext
* aDeviceContext
)
822 NS_ASSERTION(!(mInitialized
== PR_TRUE
), "attempt to reinit pres context");
823 NS_ENSURE_ARG(aDeviceContext
);
825 mDeviceContext
= aDeviceContext
;
826 NS_ADDREF(mDeviceContext
);
828 if (mDeviceContext
->SetPixelScale(mFullZoom
))
829 mDeviceContext
->FlushFontCache();
830 mCurAppUnitsPerDevPixel
= AppUnitsPerDevPixel();
832 if (!mImageLoaders
.Init())
833 return NS_ERROR_OUT_OF_MEMORY
;
835 if (!mBorderImageLoaders
.Init())
836 return NS_ERROR_OUT_OF_MEMORY
;
838 // Get the look and feel service here; default colors will be initialized
839 // from calling GetUserPreferences() when we get a presshell.
840 nsresult rv
= CallGetService(kLookAndFeelCID
, &mLookAndFeel
);
842 NS_ERROR("LookAndFeel service must be implemented for this toolkit");
846 mEventManager
= new nsEventStateManager();
848 return NS_ERROR_OUT_OF_MEMORY
;
850 NS_ADDREF(mEventManager
);
852 mLangService
= do_GetService(NS_LANGUAGEATOMSERVICE_CONTRACTID
);
854 // Register callbacks so we're notified when the preferences change
855 nsContentUtils::RegisterPrefCallback("font.",
856 nsPresContext::PrefChangedCallback
,
858 nsContentUtils::RegisterPrefCallback("browser.display.",
859 nsPresContext::PrefChangedCallback
,
861 nsContentUtils::RegisterPrefCallback("browser.underline_anchors",
862 nsPresContext::PrefChangedCallback
,
864 nsContentUtils::RegisterPrefCallback("browser.anchor_color",
865 nsPresContext::PrefChangedCallback
,
867 nsContentUtils::RegisterPrefCallback("browser.active_color",
868 nsPresContext::PrefChangedCallback
,
870 nsContentUtils::RegisterPrefCallback("browser.visited_color",
871 nsPresContext::PrefChangedCallback
,
873 nsContentUtils::RegisterPrefCallback("image.animation_mode",
874 nsPresContext::PrefChangedCallback
,
877 nsContentUtils::RegisterPrefCallback("bidi.", PrefChangedCallback
,
880 nsContentUtils::RegisterPrefCallback("layout.css.dpi",
881 nsPresContext::PrefChangedCallback
,
884 rv
= mEventManager
->Init();
885 NS_ENSURE_SUCCESS(rv
, rv
);
887 mEventManager
->SetPresContext(this);
890 mInitialized
= PR_TRUE
;
893 mBorderWidthTable
[NS_STYLE_BORDER_WIDTH_THIN
] = CSSPixelsToAppUnits(1);
894 mBorderWidthTable
[NS_STYLE_BORDER_WIDTH_MEDIUM
] = CSSPixelsToAppUnits(3);
895 mBorderWidthTable
[NS_STYLE_BORDER_WIDTH_THICK
] = CSSPixelsToAppUnits(5);
900 // Note: We don't hold a reference on the shell; it has a reference to
903 nsPresContext::SetShell(nsIPresShell
* aShell
)
906 // Remove ourselves as the charset observer from the shell's doc, because
907 // this shell may be going away for good.
908 nsIDocument
*doc
= mShell
->GetDocument();
910 doc
->RemoveCharSetObserver(this);
917 nsIDocument
*doc
= mShell
->GetDocument();
918 NS_ASSERTION(doc
, "expect document here");
920 // Have to update PresContext's mDocument before calling any other methods.
923 // Initialize our state from the user preferences, now that we
924 // have a presshell, and hence a document.
925 GetUserPreferences();
928 nsIURI
*docURI
= doc
->GetDocumentURI();
930 if (IsDynamic() && docURI
) {
931 PRBool isChrome
= PR_FALSE
;
932 PRBool isRes
= PR_FALSE
;
933 docURI
->SchemeIs("chrome", &isChrome
);
934 docURI
->SchemeIs("resource", &isRes
);
936 if (!isChrome
&& !isRes
)
937 mImageAnimationMode
= mImageAnimationModePref
;
939 mImageAnimationMode
= imgIContainer::kNormalAnimMode
;
943 doc
->AddCharSetObserver(this);
944 UpdateCharSet(doc
->GetDocumentCharacterSet());
951 nsPresContext::UpdateCharSet(const nsAFlatCString
& aCharSet
)
954 NS_IF_RELEASE(mLangGroup
);
955 mLangGroup
= mLangService
->LookupCharSet(aCharSet
.get()).get(); // addrefs
957 // bug 39570: moved from nsLanguageAtomService::LookupCharSet()
958 #if !defined(XP_BEOS)
959 if (mLangGroup
== nsGkAtoms::Unicode
) {
960 NS_RELEASE(mLangGroup
);
961 NS_IF_ADDREF(mLangGroup
= mLangService
->GetLocaleLanguageGroup());
964 GetFontPreferences();
969 switch (GET_BIDI_OPTION_TEXTTYPE(GetBidi())) {
971 case IBMBIDI_TEXTTYPE_LOGICAL
:
972 SetVisualMode(PR_FALSE
);
975 case IBMBIDI_TEXTTYPE_VISUAL
:
976 SetVisualMode(PR_TRUE
);
979 case IBMBIDI_TEXTTYPE_CHARSET
:
981 SetVisualMode(IsVisualCharset(aCharSet
));
987 nsPresContext::Observe(nsISupports
* aSubject
,
989 const PRUnichar
* aData
)
991 if (!nsCRT::strcmp(aTopic
, "charset")) {
992 UpdateCharSet(NS_LossyConvertUTF16toASCII(aData
));
993 mDeviceContext
->FlushFontCache();
994 RebuildAllStyleData(NS_STYLE_HINT_REFLOW
);
998 NS_WARNING("unrecognized topic in nsPresContext::Observe");
999 return NS_ERROR_FAILURE
;
1002 // We may want to replace this with something faster, maybe caching the root prescontext
1004 nsPresContext::RootPresContext()
1006 nsPresContext
* pc
= this;
1009 nsIFrame
* rootFrame
= pc
->mShell
->FrameManager()->GetRootFrame();
1011 nsIFrame
* f
= nsLayoutUtils::GetCrossDocParentFrame(rootFrame
);
1013 pc
= f
->PresContext();
1023 nsPresContext::CompatibilityModeChanged()
1028 // enable/disable the QuirkSheet
1029 mShell
->StyleSet()->
1030 EnableQuirkStyleSheet(CompatibilityMode() == eCompatibility_NavQuirks
);
1033 // Helper function for setting Anim Mode on image
1034 static void SetImgAnimModeOnImgReq(imgIRequest
* aImgReq
, PRUint16 aMode
)
1037 nsCOMPtr
<imgIContainer
> imgCon
;
1038 aImgReq
->GetImage(getter_AddRefs(imgCon
));
1040 imgCon
->SetAnimationMode(aMode
);
1045 // Enumeration call back for HashTable
1046 static PLDHashOperator
1047 set_animation_mode(const void * aKey
, nsCOMPtr
<nsImageLoader
>& aData
, void* closure
)
1049 imgIRequest
* imgReq
= aData
->GetRequest();
1050 SetImgAnimModeOnImgReq(imgReq
, (PRUint16
)NS_PTR_TO_INT32(closure
));
1051 return PL_DHASH_NEXT
;
1054 // IMPORTANT: Assumption is that all images for a Presentation
1055 // have the same Animation Mode (pavlov said this was OK)
1057 // Walks content and set the animation mode
1058 // this is a way to turn on/off image animations
1059 void nsPresContext::SetImgAnimations(nsIContent
*aParent
, PRUint16 aMode
)
1061 nsCOMPtr
<nsIImageLoadingContent
> imgContent(do_QueryInterface(aParent
));
1063 nsCOMPtr
<imgIRequest
> imgReq
;
1064 imgContent
->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST
,
1065 getter_AddRefs(imgReq
));
1066 SetImgAnimModeOnImgReq(imgReq
, aMode
);
1069 PRUint32 count
= aParent
->GetChildCount();
1070 for (PRUint32 i
= 0; i
< count
; ++i
) {
1071 SetImgAnimations(aParent
->GetChildAt(i
), aMode
);
1076 nsPresContext::SetImageAnimationModeInternal(PRUint16 aMode
)
1078 NS_ASSERTION(aMode
== imgIContainer::kNormalAnimMode
||
1079 aMode
== imgIContainer::kDontAnimMode
||
1080 aMode
== imgIContainer::kLoopOnceAnimMode
, "Wrong Animation Mode is being set!");
1082 // Image animation mode cannot be changed when rendering to a printer.
1086 // Set the mode on the image loaders.
1087 mImageLoaders
.Enumerate(set_animation_mode
, NS_INT32_TO_PTR(aMode
));
1088 mBorderImageLoaders
.Enumerate(set_animation_mode
, NS_INT32_TO_PTR(aMode
));
1090 // Now walk the content tree and set the animation mode
1091 // on all the images.
1092 if (mShell
!= nsnull
) {
1093 nsIDocument
*doc
= mShell
->GetDocument();
1095 nsIContent
*rootContent
= doc
->GetRootContent();
1097 SetImgAnimations(rootContent
, aMode
);
1102 mImageAnimationMode
= aMode
;
1106 nsPresContext::SetImageAnimationModeExternal(PRUint16 aMode
)
1108 SetImageAnimationModeInternal(aMode
);
1111 already_AddRefed
<nsIFontMetrics
>
1112 nsPresContext::GetMetricsFor(const nsFont
& aFont
)
1114 nsIFontMetrics
* metrics
= nsnull
;
1115 mDeviceContext
->GetMetricsFor(aFont
, mLangGroup
, GetUserFontSet(), metrics
);
1120 nsPresContext::GetDefaultFont(PRUint8 aFontID
) const
1124 // Special (our default variable width font and fixed width font)
1125 case kPresContext_DefaultVariableFont_ID
:
1126 font
= &mDefaultVariableFont
;
1128 case kPresContext_DefaultFixedFont_ID
:
1129 font
= &mDefaultFixedFont
;
1132 case kGenericFont_serif
:
1133 font
= &mDefaultSerifFont
;
1135 case kGenericFont_sans_serif
:
1136 font
= &mDefaultSansSerifFont
;
1138 case kGenericFont_monospace
:
1139 font
= &mDefaultMonospaceFont
;
1141 case kGenericFont_cursive
:
1142 font
= &mDefaultCursiveFont
;
1144 case kGenericFont_fantasy
:
1145 font
= &mDefaultFantasyFont
;
1149 NS_ERROR("invalid arg");
1156 nsPresContext::SetFullZoom(float aZoom
)
1158 if (!mShell
|| mFullZoom
== aZoom
) {
1161 // Re-fetch the view manager's window dimensions in case there's a deferred
1162 // resize which hasn't affected our mVisibleArea yet
1163 nscoord oldWidthAppUnits
, oldHeightAppUnits
;
1164 GetViewManager()->GetWindowDimensions(&oldWidthAppUnits
, &oldHeightAppUnits
);
1165 float oldWidthDevPixels
= oldWidthAppUnits
/ float(mCurAppUnitsPerDevPixel
);
1166 float oldHeightDevPixels
= oldHeightAppUnits
/ float(mCurAppUnitsPerDevPixel
);
1167 if (mDeviceContext
->SetPixelScale(aZoom
)) {
1168 mDeviceContext
->FlushFontCache();
1171 NS_ASSERTION(mSupressResizeReflow
== PR_FALSE
, "two zooms happening at the same time? impossible!");
1172 mSupressResizeReflow
= PR_TRUE
;
1175 GetViewManager()->SetWindowDimensions(NSToCoordRound(oldWidthDevPixels
* AppUnitsPerDevPixel()),
1176 NSToCoordRound(oldHeightDevPixels
* AppUnitsPerDevPixel()));
1177 MediaFeatureValuesChanged(PR_TRUE
);
1178 RebuildAllStyleData(NS_STYLE_HINT_REFLOW
);
1180 mSupressResizeReflow
= PR_FALSE
;
1182 mCurAppUnitsPerDevPixel
= AppUnitsPerDevPixel();
1186 nsPresContext::DoLoadImage(nsPresContext::ImageLoaderTable
& aTable
,
1187 imgIRequest
* aImage
,
1188 nsIFrame
* aTargetFrame
,
1189 PRBool aReflowOnLoad
)
1191 // look and see if we have a loader for the target frame.
1192 nsCOMPtr
<nsImageLoader
> loader
;
1193 aTable
.Get(aTargetFrame
, getter_AddRefs(loader
));
1196 loader
= new nsImageLoader();
1200 loader
->Init(aTargetFrame
, this, aReflowOnLoad
);
1201 aTable
.Put(aTargetFrame
, loader
);
1204 loader
->Load(aImage
);
1206 imgIRequest
*request
= loader
->GetRequest();
1212 nsPresContext::LoadImage(imgIRequest
* aImage
, nsIFrame
* aTargetFrame
)
1214 return DoLoadImage(mImageLoaders
, aImage
, aTargetFrame
, PR_FALSE
);
1218 nsPresContext::LoadBorderImage(imgIRequest
* aImage
, nsIFrame
* aTargetFrame
)
1220 return DoLoadImage(mBorderImageLoaders
, aImage
, aTargetFrame
,
1221 aTargetFrame
->GetStyleBorder()->ImageBorderDiffers());
1225 nsPresContext::StopImagesFor(nsIFrame
* aTargetFrame
)
1227 StopBackgroundImageFor(aTargetFrame
);
1228 StopBorderImageFor(aTargetFrame
);
1232 nsPresContext::DoStopImageFor(nsPresContext::ImageLoaderTable
& aTable
,
1233 nsIFrame
* aTargetFrame
)
1235 nsCOMPtr
<nsImageLoader
> loader
;
1236 aTable
.Get(aTargetFrame
, getter_AddRefs(loader
));
1241 aTable
.Remove(aTargetFrame
);
1246 nsPresContext::SetContainer(nsISupports
* aHandler
)
1248 mContainer
= do_GetWeakReference(aHandler
);
1250 GetDocumentColorPreferences();
1254 already_AddRefed
<nsISupports
>
1255 nsPresContext::GetContainerInternal() const
1257 nsISupports
*result
= nsnull
;
1259 CallQueryReferent(mContainer
.get(), &result
);
1264 already_AddRefed
<nsISupports
>
1265 nsPresContext::GetContainerExternal() const
1267 return GetContainerInternal();
1272 nsPresContext::BidiEnabledInternal() const
1274 PRBool bidiEnabled
= PR_FALSE
;
1275 NS_ASSERTION(mShell
, "PresShell must be set on PresContext before calling nsPresContext::GetBidiEnabled");
1277 nsIDocument
*doc
= mShell
->GetDocument();
1278 NS_ASSERTION(doc
, "PresShell has no document in nsPresContext::GetBidiEnabled");
1280 bidiEnabled
= doc
->GetBidiEnabled();
1287 nsPresContext::BidiEnabledExternal() const
1289 return BidiEnabledInternal();
1293 nsPresContext::SetBidiEnabled() const
1296 nsIDocument
*doc
= mShell
->GetDocument();
1298 doc
->SetBidiEnabled();
1304 nsPresContext::GetBidiUtils()
1307 mBidiUtils
= new nsBidiPresUtils
;
1313 nsPresContext::SetBidi(PRUint32 aSource
, PRBool aForceRestyle
)
1315 // Don't do all this stuff unless the options have changed.
1316 if (aSource
== GetBidi()) {
1320 NS_ASSERTION(!(aForceRestyle
&& (GetBidi() == 0)),
1321 "ForceReflow on new prescontext");
1323 Document()->SetBidiOptions(aSource
);
1324 if (IBMBIDI_TEXTDIRECTION_RTL
== GET_BIDI_OPTION_DIRECTION(aSource
)
1325 || IBMBIDI_NUMERAL_HINDI
== GET_BIDI_OPTION_NUMERAL(aSource
)) {
1328 if (IBMBIDI_TEXTTYPE_VISUAL
== GET_BIDI_OPTION_TEXTTYPE(aSource
)) {
1329 SetVisualMode(PR_TRUE
);
1331 else if (IBMBIDI_TEXTTYPE_LOGICAL
== GET_BIDI_OPTION_TEXTTYPE(aSource
)) {
1332 SetVisualMode(PR_FALSE
);
1335 nsIDocument
* doc
= mShell
->GetDocument();
1337 SetVisualMode(IsVisualCharset(doc
->GetDocumentCharacterSet()));
1340 if (aForceRestyle
) {
1341 RebuildAllStyleData(NS_STYLE_HINT_REFLOW
);
1346 nsPresContext::GetBidi() const
1348 return Document()->GetBidiOptions();
1353 nsPresContext::GetTheme()
1355 if (!mNoTheme
&& !mTheme
) {
1356 mTheme
= do_GetService("@mozilla.org/chrome/chrome-native-theme;1");
1365 nsPresContext::ThemeChanged()
1367 if (!mPendingThemeChanged
) {
1368 sLookAndFeelChanged
= PR_TRUE
;
1369 sThemeChanged
= PR_TRUE
;
1371 nsCOMPtr
<nsIRunnable
> ev
=
1372 new nsRunnableMethod
<nsPresContext
>(this,
1373 &nsPresContext::ThemeChangedInternal
);
1374 if (NS_SUCCEEDED(NS_DispatchToCurrentThread(ev
))) {
1375 mPendingThemeChanged
= PR_TRUE
;
1381 nsPresContext::ThemeChangedInternal()
1383 mPendingThemeChanged
= PR_FALSE
;
1385 // Tell the theme that it changed, so it can flush any handles to stale theme
1387 if (mTheme
&& sThemeChanged
) {
1388 mTheme
->ThemeChanged();
1389 sThemeChanged
= PR_FALSE
;
1392 // Clear all cached nsILookAndFeel colors.
1393 if (mLookAndFeel
&& sLookAndFeelChanged
) {
1394 mLookAndFeel
->LookAndFeelChanged();
1395 sLookAndFeelChanged
= PR_FALSE
;
1398 // This will force the system metrics to be generated the next time they're used
1399 nsCSSRuleProcessor::FreeSystemMetrics();
1401 // Changes in theme can change system colors (whose changes are
1402 // properly reflected in computed style data), system fonts (whose
1403 // changes are not), and -moz-appearance (whose changes likewise are
1404 // not), so we need to reflow.
1405 RebuildAllStyleData(NS_STYLE_HINT_REFLOW
);
1409 nsPresContext::SysColorChanged()
1411 if (!mPendingSysColorChanged
) {
1412 sLookAndFeelChanged
= PR_TRUE
;
1413 nsCOMPtr
<nsIRunnable
> ev
=
1414 new nsRunnableMethod
<nsPresContext
>(this,
1415 &nsPresContext::SysColorChangedInternal
);
1416 if (NS_SUCCEEDED(NS_DispatchToCurrentThread(ev
))) {
1417 mPendingSysColorChanged
= PR_TRUE
;
1423 nsPresContext::SysColorChangedInternal()
1425 mPendingSysColorChanged
= PR_FALSE
;
1427 if (mLookAndFeel
&& sLookAndFeelChanged
) {
1428 // Don't use the cached values for the system colors
1429 mLookAndFeel
->LookAndFeelChanged();
1430 sLookAndFeelChanged
= PR_FALSE
;
1433 // Reset default background and foreground colors for the document since
1434 // they may be using system colors
1435 GetDocumentColorPreferences();
1437 // The system color values are computed to colors in the style data,
1438 // so normal style data comparison is sufficient here.
1439 RebuildAllStyleData(nsChangeHint(0));
1443 nsPresContext::RebuildAllStyleData(nsChangeHint aExtraHint
)
1446 // We must have been torn down. Nothing to do here.
1450 RebuildUserFontSet();
1452 mShell
->FrameConstructor()->RebuildAllStyleData(aExtraHint
);
1456 nsPresContext::PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint
)
1459 // We must have been torn down. Nothing to do here.
1462 mShell
->FrameConstructor()->PostRebuildAllStyleDataEvent(aExtraHint
);
1466 nsPresContext::MediaFeatureValuesChanged(PRBool aCallerWillRebuildStyleData
)
1468 mPendingMediaFeatureValuesChanged
= PR_FALSE
;
1469 if (mShell
->StyleSet()->MediumFeaturesChanged(this) &&
1470 !aCallerWillRebuildStyleData
) {
1471 RebuildAllStyleData(nsChangeHint(0));
1476 nsPresContext::PostMediaFeatureValuesChangedEvent()
1478 if (!mPendingMediaFeatureValuesChanged
) {
1479 nsCOMPtr
<nsIRunnable
> ev
=
1480 new nsRunnableMethod
<nsPresContext
>(this,
1481 &nsPresContext::HandleMediaFeatureValuesChangedEvent
);
1482 if (NS_SUCCEEDED(NS_DispatchToCurrentThread(ev
))) {
1483 mPendingMediaFeatureValuesChanged
= PR_TRUE
;
1489 nsPresContext::HandleMediaFeatureValuesChangedEvent()
1491 // Null-check mShell in case the shell has been destroyed (and the
1492 // event is the only thing holding the pres context alive).
1493 if (mPendingMediaFeatureValuesChanged
&& mShell
) {
1494 MediaFeatureValuesChanged(PR_FALSE
);
1499 nsPresContext::SetPaginatedScrolling(PRBool aPaginated
)
1501 if (mType
== eContext_PrintPreview
|| mType
== eContext_PageLayout
)
1502 mCanPaginatedScroll
= aPaginated
;
1506 nsPresContext::SetPrintSettings(nsIPrintSettings
*aPrintSettings
)
1508 if (mMedium
== nsGkAtoms::print
)
1509 mPrintSettings
= aPrintSettings
;
1513 nsPresContext::EnsureVisible(PRBool aUnsuppressFocus
)
1515 nsCOMPtr
<nsIDocShell
> docShell(do_QueryReferent(mContainer
));
1517 nsCOMPtr
<nsIContentViewer
> cv
;
1518 docShell
->GetContentViewer(getter_AddRefs(cv
));
1519 // Make sure this is the content viewer we belong with
1520 nsCOMPtr
<nsIDocumentViewer
> docV(do_QueryInterface(cv
));
1522 nsCOMPtr
<nsPresContext
> currentPresContext
;
1523 docV
->GetPresContext(getter_AddRefs(currentPresContext
));
1524 if (currentPresContext
== this) {
1525 // OK, this is us. We want to call Show() on the content viewer. But
1526 // first, we need to suppress focus changes; otherwise the focus will
1527 // get sent to the wrong place (toplevel window).
1528 nsCOMPtr
<nsPIDOMWindow
> privWindow
= do_GetInterface(docShell
);
1529 // XXXbz privWindow should never really be null!
1530 nsIFocusController
* fc
=
1531 privWindow
? privWindow
->GetRootFocusController() : nsnull
;
1533 fc
->SetSuppressFocus(PR_TRUE
,
1534 "nsPresContext::EnsureVisible Suppression");
1537 if (fc
&& aUnsuppressFocus
) {
1538 fc
->SetSuppressFocus(PR_FALSE
,
1539 "nsPresContext::EnsureVisible Suppression");
1548 #ifdef MOZ_REFLOW_PERF
1550 nsPresContext::CountReflows(const char * aName
, nsIFrame
* aFrame
)
1553 mShell
->CountReflows(aName
, aFrame
);
1559 nsPresContext::IsChrome() const
1561 PRBool isChrome
= PR_FALSE
;
1562 nsCOMPtr
<nsISupports
> container
= GetContainer();
1565 nsCOMPtr
<nsIDocShellTreeItem
> docShell(do_QueryInterface(container
, &result
));
1566 if (NS_SUCCEEDED(result
) && docShell
) {
1567 PRInt32 docShellType
;
1568 result
= docShell
->GetItemType(&docShellType
);
1569 if (NS_SUCCEEDED(result
)) {
1570 isChrome
= nsIDocShellTreeItem::typeChrome
== docShellType
;
1577 /* virtual */ PRBool
1578 nsPresContext::HasAuthorSpecifiedRules(nsIFrame
*aFrame
, PRUint32 ruleTypeMask
) const
1581 HasAuthorSpecifiedRules(aFrame
->GetStyleContext(), ruleTypeMask
);
1585 InsertFontFaceRule(nsCSSFontFaceRule
*aRule
, gfxUserFontSet
* aFontSet
,
1589 NS_ABORT_IF_FALSE(NS_SUCCEEDED(aRule
->GetType(type
))
1590 && type
== nsICSSRule::FONT_FACE_RULE
,
1591 "InsertFontFaceRule passed a non-fontface CSS rule");
1595 nsAutoString fontfamily
;
1599 PRUint32 weight
= NS_STYLE_FONT_WEIGHT_NORMAL
;
1600 PRUint32 stretch
= NS_STYLE_FONT_STRETCH_NORMAL
;
1601 PRUint32 italicStyle
= FONT_STYLE_NORMAL
;
1603 // set up family name
1604 aRule
->GetDesc(eCSSFontDesc_Family
, val
);
1605 unit
= val
.GetUnit();
1606 if (unit
== eCSSUnit_String
) {
1607 val
.GetStringValue(fontfamily
);
1608 fontfamily
.Trim("\"");
1610 NS_ASSERTION(unit
== eCSSUnit_Null
,
1611 "@font-face family name has unexpected unit");
1612 // If there is no family name, this rule cannot contribute a
1613 // usable font, so there is no point in processing it further.
1618 aRule
->GetDesc(eCSSFontDesc_Weight
, val
);
1619 unit
= val
.GetUnit();
1620 if (unit
== eCSSUnit_Integer
|| unit
== eCSSUnit_Enumerated
) {
1621 weight
= val
.GetIntValue();
1622 } else if (unit
== eCSSUnit_Normal
) {
1623 weight
= NS_STYLE_FONT_WEIGHT_NORMAL
;
1625 NS_ASSERTION(unit
== eCSSUnit_Null
,
1626 "@font-face weight has unexpected unit");
1630 aRule
->GetDesc(eCSSFontDesc_Stretch
, val
);
1631 unit
= val
.GetUnit();
1632 if (unit
== eCSSUnit_Enumerated
) {
1633 stretch
= val
.GetIntValue();
1634 } else if (unit
== eCSSUnit_Normal
) {
1635 stretch
= NS_STYLE_FONT_STRETCH_NORMAL
;
1637 NS_ASSERTION(unit
== eCSSUnit_Null
,
1638 "@font-face stretch has unexpected unit");
1641 // set up font style
1642 aRule
->GetDesc(eCSSFontDesc_Style
, val
);
1643 unit
= val
.GetUnit();
1644 if (unit
== eCSSUnit_Enumerated
) {
1645 italicStyle
= val
.GetIntValue();
1646 } else if (unit
== eCSSUnit_Normal
) {
1647 italicStyle
= FONT_STYLE_NORMAL
;
1649 NS_ASSERTION(unit
== eCSSUnit_Null
,
1650 "@font-face style has unexpected unit");
1654 nsTArray
<gfxFontFaceSrc
> srcArray
;
1656 aRule
->GetDesc(eCSSFontDesc_Src
, val
);
1657 unit
= val
.GetUnit();
1658 if (unit
== eCSSUnit_Array
) {
1659 nsCSSValue::Array
*srcArr
= val
.GetArrayValue();
1660 PRUint32 i
, numSrc
= srcArr
->Count();
1662 for (i
= 0; i
< numSrc
; i
++) {
1663 val
= srcArr
->Item(i
);
1664 unit
= val
.GetUnit();
1665 gfxFontFaceSrc
*face
= srcArray
.AppendElements(1);
1671 case eCSSUnit_Local_Font
:
1672 val
.GetStringValue(face
->mLocalName
);
1673 face
->mIsLocal
= PR_TRUE
;
1674 face
->mURI
= nsnull
;
1675 face
->mFormatFlags
= 0;
1678 face
->mIsLocal
= PR_FALSE
;
1679 face
->mURI
= val
.GetURLValue();
1680 NS_ASSERTION(face
->mURI
, "null url in @font-face rule");
1681 face
->mReferrer
= val
.GetURLStructValue()->mReferrer
;
1682 face
->mOriginPrincipal
= val
.GetURLStructValue()->mOriginPrincipal
;
1683 NS_ASSERTION(face
->mOriginPrincipal
, "null origin principal in @font-face rule");
1685 // agent and user stylesheets are treated slightly differently,
1686 // the same-site origin check and access control headers are
1687 // enforced against the sheet principal rather than the document
1688 // principal to allow user stylesheets to include @font-face rules
1689 face
->mUseOriginPrincipal
= (aSheetType
== nsStyleSet::eUserSheet
||
1690 aSheetType
== nsStyleSet::eAgentSheet
);
1692 face
->mLocalName
.Truncate();
1693 face
->mFormatFlags
= 0;
1694 while (i
+ 1 < numSrc
&& (val
= srcArr
->Item(i
+1),
1695 val
.GetUnit() == eCSSUnit_Font_Format
)) {
1696 nsDependentString
valueString(val
.GetStringBufferValue());
1697 if (valueString
.LowerCaseEqualsASCII("opentype")) {
1698 face
->mFormatFlags
|= gfxUserFontSet::FLAG_FORMAT_OPENTYPE
;
1699 } else if (valueString
.LowerCaseEqualsASCII("truetype")) {
1700 face
->mFormatFlags
|= gfxUserFontSet::FLAG_FORMAT_TRUETYPE
;
1701 } else if (valueString
.LowerCaseEqualsASCII("truetype-aat")) {
1702 face
->mFormatFlags
|= gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT
;
1703 } else if (valueString
.LowerCaseEqualsASCII("embedded-opentype")) {
1704 face
->mFormatFlags
|= gfxUserFontSet::FLAG_FORMAT_EOT
;
1705 } else if (valueString
.LowerCaseEqualsASCII("svg")) {
1706 face
->mFormatFlags
|= gfxUserFontSet::FLAG_FORMAT_SVG
;
1712 NS_ASSERTION(unit
== eCSSUnit_Local_Font
|| unit
== eCSSUnit_URL
,
1713 "strange unit type in font-face src array");
1718 NS_ASSERTION(unit
== eCSSUnit_Null
, "@font-face src has unexpected unit");
1721 if (!fontfamily
.IsEmpty() && srcArray
.Length() > 0) {
1722 aFontSet
->AddFontFace(fontfamily
, srcArray
, weight
, stretch
, italicStyle
);
1727 nsPresContext::GetUserFontSetInternal()
1729 // We want to initialize the user font set lazily the first time the
1730 // user asks for it, rather than building it too early and forcing
1731 // rule cascade creation. Thus we try to enforce the invariant that
1732 // we *never* build the user font set until the first call to
1733 // GetUserFontSet. However, once it's been requested, we can't wait
1734 // for somebody to call GetUserFontSet in order to rebuild it (see
1735 // comments below in RebuildUserFontSet for why).
1736 if (mUserFontSetDirty
) {
1737 // If this assertion fails, and there have actually been changes to
1738 // @font-face rules, then we will call StyleChangeReflow in
1739 // FlushUserFontSet. If we're in the middle of reflow,
1740 // that's a bad thing to do, and the caller was responsible for
1741 // flushing first. If we're not (e.g., in frame construction), it's
1746 NS_ASSERTION(!mGetUserFontSetCalled
||
1747 (NS_SUCCEEDED(mShell
->IsReflowLocked(&inReflow
)) &&
1749 "FlushUserFontSet should have been called first");
1755 mGetUserFontSetCalled
= PR_TRUE
;
1756 return mUserFontSet
;
1760 nsPresContext::GetUserFontSetExternal()
1762 return GetUserFontSetInternal();
1766 nsPresContext::FlushUserFontSet()
1769 return; // we've been torn down
1771 if (mUserFontSetDirty
) {
1772 if (gfxPlatform::GetPlatform()->DownloadableFontsEnabled()) {
1773 nsRefPtr
<gfxUserFontSet
> oldUserFontSet
= mUserFontSet
;
1775 nsTArray
<nsFontFaceRuleContainer
> rules
;
1776 if (!mShell
->StyleSet()->AppendFontFaceRules(this, rules
))
1780 if (rules
.Length() == mFontFaceRules
.Length()) {
1782 for (PRUint32 i
= 0, i_end
= rules
.Length(); i
< i_end
; ++i
) {
1783 if (rules
[i
].mRule
!= mFontFaceRules
[i
].mRule
||
1784 rules
[i
].mSheetType
!= mFontFaceRules
[i
].mSheetType
) {
1793 // Only rebuild things if the set of @font-face rules is different.
1795 NS_IF_RELEASE(mUserFontSet
);
1797 if (rules
.Length() > 0) {
1798 gfxUserFontSet
*fs
= new nsUserFontSet(this);
1802 NS_ADDREF(mUserFontSet
);
1804 for (PRUint32 i
= 0, i_end
= rules
.Length(); i
< i_end
; ++i
) {
1805 InsertFontFaceRule(rules
[i
].mRule
, fs
, rules
[i
].mSheetType
);
1813 rules
.SwapElements(mFontFaceRules
);
1814 NS_ASSERTION(success
, "should never fail given both are heap arrays");
1816 if (mGetUserFontSetCalled
&& oldUserFontSet
!= mUserFontSet
) {
1817 // If we've changed, created, or destroyed a user font set, we
1818 // need to trigger a style change reflow.
1819 // We need to enqueue a style change reflow (for later) to
1820 // reflect that we're dropping @font-face rules. (However,
1821 // without a reflow, nothing will happen to start any downloads
1822 // that are needed.)
1823 UserFontSetUpdated();
1827 mUserFontSetDirty
= PR_FALSE
;
1832 nsPresContext::RebuildUserFontSet()
1834 if (!mGetUserFontSetCalled
) {
1835 // We want to lazily build the user font set the first time it's
1836 // requested (so we don't force creation of rule cascades too
1837 // early), so don't do anything now.
1841 mUserFontSetDirty
= PR_TRUE
;
1843 // Somebody has already asked for the user font set, so we need to
1844 // post an event to rebuild it. Setting the user font set to be dirty
1845 // and lazily rebuilding it isn't sufficient, since it is only the act
1846 // of rebuilding it that will trigger the style change reflow that
1847 // calls GetUserFontSet. (This reflow causes rebuilding of text runs,
1848 // which starts font loads, whose completion causes another style
1850 if (!mPostedFlushUserFontSet
) {
1851 nsCOMPtr
<nsIRunnable
> ev
=
1852 new nsRunnableMethod
<nsPresContext
>(this,
1853 &nsPresContext::HandleRebuildUserFontSet
);
1854 if (NS_SUCCEEDED(NS_DispatchToCurrentThread(ev
))) {
1855 mPostedFlushUserFontSet
= PR_TRUE
;
1861 nsPresContext::UserFontSetUpdated()
1866 // Changes to the set of available fonts can cause updates to layout by:
1868 // 1. Changing the font used for text, which changes anything that
1869 // depends on text measurement, including line breaking and
1870 // intrinsic widths, and any other parts of layout that depend on
1871 // font metrics. This requires a style change reflow to update.
1873 // 2. Changing the value of the 'ex' and 'ch' units in style data,
1874 // which also depend on font metrics. Updating this information
1875 // requires rebuilding the rule tree from the top, avoiding the
1876 // reuse of cached data even when no style rules have changed.
1878 PostRebuildAllStyleDataEvent(NS_STYLE_HINT_REFLOW
);
1882 nsPresContext::FireDOMPaintEvent()
1884 nsCOMPtr
<nsPIDOMWindow
> ourWindow
= mDocument
->GetWindow();
1888 nsISupports
* eventTarget
= ourWindow
;
1889 if (mSameDocDirtyRegion
.IsEmpty() && !IsChrome()) {
1890 // Don't tell the window about this event, it should not know that
1891 // something happened in a subdocument. Tell only the chrome event handler.
1892 // (Events sent to the window get propagated to the chrome event handler
1894 eventTarget
= ourWindow
->GetChromeEventHandler();
1899 // Events sent to the window get propagated to the chrome event handler
1902 nsNotifyPaintEvent
event(PR_TRUE
, NS_AFTERPAINT
, mSameDocDirtyRegion
,
1903 mCrossDocDirtyRegion
);
1904 // Empty our regions now in case dispatching the event causes more damage
1905 // (hopefully it won't, or we're likely to get an infinite loop! At least
1906 // it won't be blocking app execution though).
1907 mSameDocDirtyRegion
.SetEmpty();
1908 mCrossDocDirtyRegion
.SetEmpty();
1909 // Even if we're not telling the window about the event (so eventTarget is
1910 // the chrome event handler, not the window), the window is still
1911 // logically the event target.
1912 event
.target
= do_QueryInterface(ourWindow
);
1913 nsEventDispatcher::Dispatch(eventTarget
, this, &event
);
1916 static PRBool
MayHavePaintEventListener(nsPIDOMWindow
* aInnerWindow
)
1920 if (aInnerWindow
->HasPaintEventListeners())
1923 nsPIDOMEventTarget
* chromeEventHandler
= aInnerWindow
->GetChromeEventHandler();
1924 if (!chromeEventHandler
)
1927 nsCOMPtr
<nsIEventListenerManager
> manager
;
1928 chromeEventHandler
->GetListenerManager(PR_FALSE
, getter_AddRefs(manager
));
1929 if (manager
&& manager
->MayHavePaintEventListener())
1932 nsCOMPtr
<nsINode
> node
= do_QueryInterface(chromeEventHandler
);
1934 return MayHavePaintEventListener(node
->GetOwnerDoc()->GetInnerWindow());
1936 nsCOMPtr
<nsPIDOMWindow
> window
= do_QueryInterface(chromeEventHandler
);
1938 return MayHavePaintEventListener(window
);
1944 nsPresContext::NotifyInvalidation(const nsRect
& aRect
, PRBool aIsCrossDoc
)
1946 // If there is no paint event listener, then we don't need to fire
1947 // the asynchronous event. We don't even need to record invalidation.
1948 // MayHavePaintEventListener is pretty cheap and we could make it
1949 // even cheaper by providing a more efficient
1950 // nsPIDOMWindow::GetListenerManager.
1951 if (aRect
.IsEmpty() ||
1952 !MayHavePaintEventListener(mDocument
->GetInnerWindow()))
1955 if (mSameDocDirtyRegion
.IsEmpty() && mCrossDocDirtyRegion
.IsEmpty()) {
1956 // No event is pending. Dispatch one now.
1957 nsCOMPtr
<nsIRunnable
> ev
=
1958 new nsRunnableMethod
<nsPresContext
>(this,
1959 &nsPresContext::FireDOMPaintEvent
);
1960 NS_DispatchToCurrentThread(ev
);
1963 nsRegion
* r
= aIsCrossDoc
? &mCrossDocDirtyRegion
: &mSameDocDirtyRegion
;
1965 r
->SimplifyOutward(10);