Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / layout / base / nsPresContext.cpp
blob64a2fbd4f1a0d86d9d9be38613ef8fa05113e797
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
13 * License.
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.
22 * Contributor(s):
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 */
42 #include "nsCOMPtr.h"
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"
55 #include "nsIFrame.h"
56 #include "nsIRenderingContext.h"
57 #include "nsIURL.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"
73 #include "prprf.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"
93 #ifdef IBMBIDI
94 #include "nsBidiPresUtils.h"
95 #endif // IBMBIDI
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"
106 static nscolor
107 MakeColorPref(const char *colstr)
109 PRUint32 red, green, blue;
110 nscolor colorref;
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);
116 return colorref;
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);
128 return 0; // PREF_OK
132 void
133 nsPresContext::PrefChangedUpdateTimerCallback(nsITimer *aTimer, void *aClosure)
135 nsPresContext* presContext = (nsPresContext*)aClosure;
136 NS_ASSERTION(presContext != nsnull, "bad instance data");
137 if (presContext)
138 presContext->UpdateAfterPreferencesChanged();
141 #ifdef IBMBIDI
142 static PRBool
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
150 else {
151 return PR_FALSE; // logical text type
154 #endif // IBMBIDI
157 static PLDHashOperator
158 destroy_loads(const void * aKey, nsCOMPtr<nsImageLoader>& aData, void* closure)
160 aData->Destroy();
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;
215 mFocusRingWidth = 1;
217 if (aType == eContext_Galley) {
218 mMedium = nsGkAtoms::screen;
219 } else {
220 SetBackgroundImageDraw(PR_FALSE);
221 SetBackgroundColorDraw(PR_FALSE);
222 mMedium = nsGkAtoms::print;
223 mPaginated = PR_TRUE;
226 if (!IsDynamic()) {
227 mImageAnimationMode = imgIContainer::kDontAnimMode;
228 mNeverAnimate = PR_TRUE;
229 } else {
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");
244 SetShell(nsnull);
246 if (mEventManager) {
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,
263 this);
264 nsContentUtils::UnregisterPrefCallback("browser.display.",
265 nsPresContext::PrefChangedCallback,
266 this);
267 nsContentUtils::UnregisterPrefCallback("browser.underline_anchors",
268 nsPresContext::PrefChangedCallback,
269 this);
270 nsContentUtils::UnregisterPrefCallback("browser.anchor_color",
271 nsPresContext::PrefChangedCallback,
272 this);
273 nsContentUtils::UnregisterPrefCallback("browser.active_color",
274 nsPresContext::PrefChangedCallback,
275 this);
276 nsContentUtils::UnregisterPrefCallback("browser.visited_color",
277 nsPresContext::PrefChangedCallback,
278 this);
279 nsContentUtils::UnregisterPrefCallback("image.animation_mode",
280 nsPresContext::PrefChangedCallback,
281 this);
282 #ifdef IBMBIDI
283 nsContentUtils::UnregisterPrefCallback("bidi.", PrefChangedCallback, this);
285 delete mBidiUtils;
286 #endif // IBMBIDI
287 nsContentUtils::UnregisterPrefCallback("layout.css.dpi",
288 nsPresContext::PrefChangedCallback,
289 this);
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)
302 NS_INTERFACE_MAP_END
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,
309 void* aClosure)
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) \
366 _pref.Assign(_s0); \
367 _pref.Append(_s1);
369 static const char* const kGenericFont[] = {
370 ".variable.",
371 ".fixed.",
372 ".serif.",
373 ".sans-serif.",
374 ".monospace.",
375 ".cursive.",
376 ".fantasy."
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
386 // one prescontext.
387 static PRBool sThemeChanged;
389 void
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...
412 if (mLangGroup) {
413 mLangGroup->GetUTF8String(&langGroup);
416 nsCAutoString pref;
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")) {
427 unit = eUnit_px;
429 else if (cvalue.Equals("pt")) {
430 unit = eUnit_pt;
432 else {
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);
457 nsFont* font;
458 switch (eType) {
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);
478 else {
479 MAKE_FONT_PREF_KEY(pref, "font.default.", langGroup);
480 value = nsContentUtils::GetStringPref(pref.get());
481 if (!value.IsEmpty()) {
482 mDefaultVariableFont.name.Assign(value);
486 else {
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());
510 if (size > 0) {
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());
527 #ifdef DEBUG_rbs
528 printf("%s Family-list:%s size:%d sizeAdjust:%.2f\n",
529 generic_dot_langGroup.get(),
530 NS_ConvertUTF16toUTF8(font->name).get(), font->size,
531 font->sizeAdjust);
532 #endif
536 void
537 nsPresContext::GetDocumentColorPreferences()
539 PRInt32 useAccessibilityTheme = 0;
540 PRBool usePrefColors = PR_TRUE;
541 nsCOMPtr<nsIDocShellTreeItem> docShell(do_QueryReferent(mContainer));
542 if (docShell) {
543 PRInt32 docShellType;
544 docShell->GetItemType(&docShellType);
545 if (nsIDocShellTreeItem::typeChrome == docShellType) {
546 usePrefColors = PR_FALSE;
548 else {
549 mLookAndFeel->GetMetric(nsILookAndFeel::eMetric_UseAccessibilityTheme, useAccessibilityTheme);
550 usePrefColors = !useAccessibilityTheme;
554 if (usePrefColors) {
555 usePrefColors =
556 !nsContentUtils::GetBoolPref("browser.display.use_system_colors",
557 PR_FALSE);
560 if (usePrefColors) {
561 nsAdoptingCString colorStr =
562 nsContentUtils::GetCharPref("browser.display.foreground_color");
564 if (!colorStr.IsEmpty()) {
565 mDefaultColor = MakeColorPref(colorStr);
568 colorStr =
569 nsContentUtils::GetCharPref("browser.display.background_color");
571 if (!colorStr.IsEmpty()) {
572 mBackgroundColor = MakeColorPref(colorStr);
575 else {
576 mDefaultColor = NS_RGB(0x00, 0x00, 0x00);
577 mBackgroundColor = NS_RGB(0xFF, 0xFF, 0xFF);
578 mLookAndFeel->GetColor(nsILookAndFeel::eColor_WindowForeground,
579 mDefaultColor);
580 mLookAndFeel->GetColor(nsILookAndFeel::eColor_WindowBackground,
581 mBackgroundColor);
584 // Wherever we got the default background color from, ensure it is
585 // opaque.
586 mBackgroundColor = NS_ComposeColors(NS_RGB(0xFF, 0xFF, 0xFF),
587 mBackgroundColor);
589 mUseDocumentColors = !useAccessibilityTheme &&
590 nsContentUtils::GetBoolPref("browser.display.use_document_colors",
591 mUseDocumentColors);
594 void
595 nsPresContext::GetUserPreferences()
597 if (!GetPresShell()) {
598 // No presshell means nothing to do here. We'll do this when we
599 // get a presshell.
600 return;
603 mFontScaler =
604 nsContentUtils::GetIntPref("browser.display.base_font_scaler",
605 mFontScaler);
608 mAutoQualityMinFontSizePixelsPref =
609 nsContentUtils::GetIntPref("browser.display.auto_quality_min_font_size");
611 // * document colors
612 GetDocumentColorPreferences();
614 // * link colors
615 mUnderlineLinks =
616 nsContentUtils::GetBoolPref("browser.underline_anchors", mUnderlineLinks);
618 nsAdoptingCString colorStr =
619 nsContentUtils::GetCharPref("browser.anchor_color");
621 if (!colorStr.IsEmpty()) {
622 mLinkColor = MakeColorPref(colorStr);
625 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);
638 mUseFocusColors =
639 nsContentUtils::GetBoolPref("browser.display.use_focus_colors",
640 mUseFocusColors);
642 mFocusTextColor = mDefaultColor;
643 mFocusBackgroundColor = mBackgroundColor;
645 colorStr = nsContentUtils::GetCharPref("browser.display.focus_text_color");
647 if (!colorStr.IsEmpty()) {
648 mFocusTextColor = MakeColorPref(colorStr);
651 colorStr =
652 nsContentUtils::GetCharPref("browser.display.focus_background_color");
654 if (!colorStr.IsEmpty()) {
655 mFocusBackgroundColor = MakeColorPref(colorStr);
658 mFocusRingWidth =
659 nsContentUtils::GetIntPref("browser.display.focus_ring_width",
660 mFocusRingWidth);
662 mFocusRingOnAnything =
663 nsContentUtils::GetBoolPref("browser.display.focus_ring_on_anything",
664 mFocusRingOnAnything);
666 mFocusRingStyle =
667 nsContentUtils::GetIntPref("browser.display.focus_ring_style",
668 mFocusRingStyle);
669 // * use fonts?
670 mUseDocumentFonts =
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");
677 mPrefScrollbarSide =
678 nsContentUtils::GetIntPref("layout.scrollbar.side");
680 GetFontPreferences();
682 // * image animation
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();
696 PRInt32 prefInt =
697 nsContentUtils::GetIntPref(IBMBIDI_TEXTDIRECTION_STR,
698 GET_BIDI_OPTION_DIRECTION(bidiOptions));
699 SET_BIDI_OPTION_DIRECTION(bidiOptions, prefInt);
700 mPrefBidiDirection = prefInt;
702 prefInt =
703 nsContentUtils::GetIntPref(IBMBIDI_TEXTTYPE_STR,
704 GET_BIDI_OPTION_TEXTTYPE(bidiOptions));
705 SET_BIDI_OPTION_TEXTTYPE(bidiOptions, prefInt);
707 prefInt =
708 nsContentUtils::GetIntPref(IBMBIDI_CONTROLSTEXTMODE_STR,
709 GET_BIDI_OPTION_CONTROLSTEXTMODE(bidiOptions));
710 SET_BIDI_OPTION_CONTROLSTEXTMODE(bidiOptions, prefInt);
712 prefInt =
713 nsContentUtils::GetIntPref(IBMBIDI_NUMERAL_STR,
714 GET_BIDI_OPTION_NUMERAL(bidiOptions));
715 SET_BIDI_OPTION_NUMERAL(bidiOptions, prefInt);
717 prefInt =
718 nsContentUtils::GetIntPref(IBMBIDI_SUPPORTMODE_STR,
719 GET_BIDI_OPTION_SUPPORT(bidiOptions));
720 SET_BIDI_OPTION_SUPPORT(bidiOptions, prefInt);
722 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);
733 void
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);
757 return;
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)
782 return;
783 mPrefChangedTimer->InitWithFuncCallback(nsPresContext::PrefChangedUpdateTimerCallback, (void*)this, 0, nsITimer::TYPE_ONE_SHOT);
787 void
788 nsPresContext::UpdateAfterPreferencesChanged()
790 mPrefChangedTimer = nsnull;
792 nsCOMPtr<nsIDocShellTreeItem> docShell(do_QueryReferent(mContainer));
793 if (docShell) {
794 PRInt32 docShellType;
795 docShell->GetItemType(&docShellType);
796 if (nsIDocShellTreeItem::typeChrome == docShellType)
797 return;
800 // Initialize our state from the user preferences
801 GetUserPreferences();
803 // update the presShell: tell it to set the preference style rules up
804 if (mShell) {
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);
819 nsresult
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);
841 if (NS_FAILED(rv)) {
842 NS_ERROR("LookAndFeel service must be implemented for this toolkit");
843 return rv;
846 mEventManager = new nsEventStateManager();
847 if (!mEventManager)
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,
857 this);
858 nsContentUtils::RegisterPrefCallback("browser.display.",
859 nsPresContext::PrefChangedCallback,
860 this);
861 nsContentUtils::RegisterPrefCallback("browser.underline_anchors",
862 nsPresContext::PrefChangedCallback,
863 this);
864 nsContentUtils::RegisterPrefCallback("browser.anchor_color",
865 nsPresContext::PrefChangedCallback,
866 this);
867 nsContentUtils::RegisterPrefCallback("browser.active_color",
868 nsPresContext::PrefChangedCallback,
869 this);
870 nsContentUtils::RegisterPrefCallback("browser.visited_color",
871 nsPresContext::PrefChangedCallback,
872 this);
873 nsContentUtils::RegisterPrefCallback("image.animation_mode",
874 nsPresContext::PrefChangedCallback,
875 this);
876 #ifdef IBMBIDI
877 nsContentUtils::RegisterPrefCallback("bidi.", PrefChangedCallback,
878 this);
879 #endif
880 nsContentUtils::RegisterPrefCallback("layout.css.dpi",
881 nsPresContext::PrefChangedCallback,
882 this);
884 rv = mEventManager->Init();
885 NS_ENSURE_SUCCESS(rv, rv);
887 mEventManager->SetPresContext(this);
889 #ifdef DEBUG
890 mInitialized = PR_TRUE;
891 #endif
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);
897 return NS_OK;
900 // Note: We don't hold a reference on the shell; it has a reference to
901 // us
902 void
903 nsPresContext::SetShell(nsIPresShell* aShell)
905 if (mShell) {
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();
909 if (doc) {
910 doc->RemoveCharSetObserver(this);
914 mShell = aShell;
916 if (mShell) {
917 nsIDocument *doc = mShell->GetDocument();
918 NS_ASSERTION(doc, "expect document here");
919 if (doc) {
920 // Have to update PresContext's mDocument before calling any other methods.
921 mDocument = doc;
923 // Initialize our state from the user preferences, now that we
924 // have a presshell, and hence a document.
925 GetUserPreferences();
927 if (doc) {
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;
938 else
939 mImageAnimationMode = imgIContainer::kNormalAnimMode;
942 if (mLangService) {
943 doc->AddCharSetObserver(this);
944 UpdateCharSet(doc->GetDocumentCharacterSet());
950 void
951 nsPresContext::UpdateCharSet(const nsAFlatCString& aCharSet)
953 if (mLangService) {
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());
963 #endif
964 GetFontPreferences();
966 #ifdef IBMBIDI
967 //ahmed
969 switch (GET_BIDI_OPTION_TEXTTYPE(GetBidi())) {
971 case IBMBIDI_TEXTTYPE_LOGICAL:
972 SetVisualMode(PR_FALSE);
973 break;
975 case IBMBIDI_TEXTTYPE_VISUAL:
976 SetVisualMode(PR_TRUE);
977 break;
979 case IBMBIDI_TEXTTYPE_CHARSET:
980 default:
981 SetVisualMode(IsVisualCharset(aCharSet));
983 #endif // IBMBIDI
986 NS_IMETHODIMP
987 nsPresContext::Observe(nsISupports* aSubject,
988 const char* aTopic,
989 const PRUnichar* aData)
991 if (!nsCRT::strcmp(aTopic, "charset")) {
992 UpdateCharSet(NS_LossyConvertUTF16toASCII(aData));
993 mDeviceContext->FlushFontCache();
994 RebuildAllStyleData(NS_STYLE_HINT_REFLOW);
995 return NS_OK;
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
1003 nsPresContext*
1004 nsPresContext::RootPresContext()
1006 nsPresContext* pc = this;
1007 for (;;) {
1008 if (pc->mShell) {
1009 nsIFrame* rootFrame = pc->mShell->FrameManager()->GetRootFrame();
1010 if (rootFrame) {
1011 nsIFrame* f = nsLayoutUtils::GetCrossDocParentFrame(rootFrame);
1012 if (f) {
1013 pc = f->PresContext();
1014 continue;
1018 return pc;
1022 void
1023 nsPresContext::CompatibilityModeChanged()
1025 if (!mShell)
1026 return;
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)
1036 if (aImgReq) {
1037 nsCOMPtr<imgIContainer> imgCon;
1038 aImgReq->GetImage(getter_AddRefs(imgCon));
1039 if (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));
1062 if (imgContent) {
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);
1075 void
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.
1083 if (!IsDynamic())
1084 return;
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();
1094 if (doc) {
1095 nsIContent *rootContent = doc->GetRootContent();
1096 if (rootContent) {
1097 SetImgAnimations(rootContent, aMode);
1102 mImageAnimationMode = aMode;
1105 void
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);
1116 return metrics;
1119 const nsFont*
1120 nsPresContext::GetDefaultFont(PRUint8 aFontID) const
1122 const nsFont *font;
1123 switch (aFontID) {
1124 // Special (our default variable width font and fixed width font)
1125 case kPresContext_DefaultVariableFont_ID:
1126 font = &mDefaultVariableFont;
1127 break;
1128 case kPresContext_DefaultFixedFont_ID:
1129 font = &mDefaultFixedFont;
1130 break;
1131 // CSS
1132 case kGenericFont_serif:
1133 font = &mDefaultSerifFont;
1134 break;
1135 case kGenericFont_sans_serif:
1136 font = &mDefaultSansSerifFont;
1137 break;
1138 case kGenericFont_monospace:
1139 font = &mDefaultMonospaceFont;
1140 break;
1141 case kGenericFont_cursive:
1142 font = &mDefaultCursiveFont;
1143 break;
1144 case kGenericFont_fantasy:
1145 font = &mDefaultFantasyFont;
1146 break;
1147 default:
1148 font = nsnull;
1149 NS_ERROR("invalid arg");
1150 break;
1152 return font;
1155 void
1156 nsPresContext::SetFullZoom(float aZoom)
1158 if (!mShell || mFullZoom == aZoom) {
1159 return;
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;
1174 mFullZoom = aZoom;
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();
1185 imgIRequest*
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));
1195 if (!loader) {
1196 loader = new nsImageLoader();
1197 if (!loader)
1198 return nsnull;
1200 loader->Init(aTargetFrame, this, aReflowOnLoad);
1201 aTable.Put(aTargetFrame, loader);
1204 loader->Load(aImage);
1206 imgIRequest *request = loader->GetRequest();
1208 return request;
1211 imgIRequest*
1212 nsPresContext::LoadImage(imgIRequest* aImage, nsIFrame* aTargetFrame)
1214 return DoLoadImage(mImageLoaders, aImage, aTargetFrame, PR_FALSE);
1217 imgIRequest*
1218 nsPresContext::LoadBorderImage(imgIRequest* aImage, nsIFrame* aTargetFrame)
1220 return DoLoadImage(mBorderImageLoaders, aImage, aTargetFrame,
1221 aTargetFrame->GetStyleBorder()->ImageBorderDiffers());
1224 void
1225 nsPresContext::StopImagesFor(nsIFrame* aTargetFrame)
1227 StopBackgroundImageFor(aTargetFrame);
1228 StopBorderImageFor(aTargetFrame);
1231 void
1232 nsPresContext::DoStopImageFor(nsPresContext::ImageLoaderTable& aTable,
1233 nsIFrame* aTargetFrame)
1235 nsCOMPtr<nsImageLoader> loader;
1236 aTable.Get(aTargetFrame, getter_AddRefs(loader));
1238 if (loader) {
1239 loader->Destroy();
1241 aTable.Remove(aTargetFrame);
1245 void
1246 nsPresContext::SetContainer(nsISupports* aHandler)
1248 mContainer = do_GetWeakReference(aHandler);
1249 if (mContainer) {
1250 GetDocumentColorPreferences();
1254 already_AddRefed<nsISupports>
1255 nsPresContext::GetContainerInternal() const
1257 nsISupports *result = nsnull;
1258 if (mContainer)
1259 CallQueryReferent(mContainer.get(), &result);
1261 return result;
1264 already_AddRefed<nsISupports>
1265 nsPresContext::GetContainerExternal() const
1267 return GetContainerInternal();
1270 #ifdef IBMBIDI
1271 PRBool
1272 nsPresContext::BidiEnabledInternal() const
1274 PRBool bidiEnabled = PR_FALSE;
1275 NS_ASSERTION(mShell, "PresShell must be set on PresContext before calling nsPresContext::GetBidiEnabled");
1276 if (mShell) {
1277 nsIDocument *doc = mShell->GetDocument();
1278 NS_ASSERTION(doc, "PresShell has no document in nsPresContext::GetBidiEnabled");
1279 if (doc) {
1280 bidiEnabled = doc->GetBidiEnabled();
1283 return bidiEnabled;
1286 PRBool
1287 nsPresContext::BidiEnabledExternal() const
1289 return BidiEnabledInternal();
1292 void
1293 nsPresContext::SetBidiEnabled() const
1295 if (mShell) {
1296 nsIDocument *doc = mShell->GetDocument();
1297 if (doc) {
1298 doc->SetBidiEnabled();
1303 nsBidiPresUtils*
1304 nsPresContext::GetBidiUtils()
1306 if (!mBidiUtils)
1307 mBidiUtils = new nsBidiPresUtils;
1309 return mBidiUtils;
1312 void
1313 nsPresContext::SetBidi(PRUint32 aSource, PRBool aForceRestyle)
1315 // Don't do all this stuff unless the options have changed.
1316 if (aSource == GetBidi()) {
1317 return;
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)) {
1326 SetBidiEnabled();
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);
1334 else {
1335 nsIDocument* doc = mShell->GetDocument();
1336 if (doc) {
1337 SetVisualMode(IsVisualCharset(doc->GetDocumentCharacterSet()));
1340 if (aForceRestyle) {
1341 RebuildAllStyleData(NS_STYLE_HINT_REFLOW);
1345 PRUint32
1346 nsPresContext::GetBidi() const
1348 return Document()->GetBidiOptions();
1350 #endif //IBMBIDI
1352 nsITheme*
1353 nsPresContext::GetTheme()
1355 if (!mNoTheme && !mTheme) {
1356 mTheme = do_GetService("@mozilla.org/chrome/chrome-native-theme;1");
1357 if (!mTheme)
1358 mNoTheme = PR_TRUE;
1361 return mTheme;
1364 void
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;
1380 void
1381 nsPresContext::ThemeChangedInternal()
1383 mPendingThemeChanged = PR_FALSE;
1385 // Tell the theme that it changed, so it can flush any handles to stale theme
1386 // data.
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);
1408 void
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;
1422 void
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));
1442 void
1443 nsPresContext::RebuildAllStyleData(nsChangeHint aExtraHint)
1445 if (!mShell) {
1446 // We must have been torn down. Nothing to do here.
1447 return;
1450 RebuildUserFontSet();
1452 mShell->FrameConstructor()->RebuildAllStyleData(aExtraHint);
1455 void
1456 nsPresContext::PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint)
1458 if (!mShell) {
1459 // We must have been torn down. Nothing to do here.
1460 return;
1462 mShell->FrameConstructor()->PostRebuildAllStyleDataEvent(aExtraHint);
1465 void
1466 nsPresContext::MediaFeatureValuesChanged(PRBool aCallerWillRebuildStyleData)
1468 mPendingMediaFeatureValuesChanged = PR_FALSE;
1469 if (mShell->StyleSet()->MediumFeaturesChanged(this) &&
1470 !aCallerWillRebuildStyleData) {
1471 RebuildAllStyleData(nsChangeHint(0));
1475 void
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;
1488 void
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);
1498 void
1499 nsPresContext::SetPaginatedScrolling(PRBool aPaginated)
1501 if (mType == eContext_PrintPreview || mType == eContext_PageLayout)
1502 mCanPaginatedScroll = aPaginated;
1505 void
1506 nsPresContext::SetPrintSettings(nsIPrintSettings *aPrintSettings)
1508 if (mMedium == nsGkAtoms::print)
1509 mPrintSettings = aPrintSettings;
1512 PRBool
1513 nsPresContext::EnsureVisible(PRBool aUnsuppressFocus)
1515 nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer));
1516 if (docShell) {
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));
1521 if (docV) {
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;
1532 if (fc) {
1533 fc->SetSuppressFocus(PR_TRUE,
1534 "nsPresContext::EnsureVisible Suppression");
1536 cv->Show();
1537 if (fc && aUnsuppressFocus) {
1538 fc->SetSuppressFocus(PR_FALSE,
1539 "nsPresContext::EnsureVisible Suppression");
1541 return PR_TRUE;
1545 return PR_FALSE;
1548 #ifdef MOZ_REFLOW_PERF
1549 void
1550 nsPresContext::CountReflows(const char * aName, nsIFrame * aFrame)
1552 if (mShell) {
1553 mShell->CountReflows(aName, aFrame);
1556 #endif
1558 PRBool
1559 nsPresContext::IsChrome() const
1561 PRBool isChrome = PR_FALSE;
1562 nsCOMPtr<nsISupports> container = GetContainer();
1563 if (container) {
1564 nsresult result;
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;
1574 return isChrome;
1577 /* virtual */ PRBool
1578 nsPresContext::HasAuthorSpecifiedRules(nsIFrame *aFrame, PRUint32 ruleTypeMask) const
1580 return nsRuleNode::
1581 HasAuthorSpecifiedRules(aFrame->GetStyleContext(), ruleTypeMask);
1584 static void
1585 InsertFontFaceRule(nsCSSFontFaceRule *aRule, gfxUserFontSet* aFontSet,
1586 PRUint8 aSheetType)
1588 PRInt32 type;
1589 NS_ABORT_IF_FALSE(NS_SUCCEEDED(aRule->GetType(type))
1590 && type == nsICSSRule::FONT_FACE_RULE,
1591 "InsertFontFaceRule passed a non-fontface CSS rule");
1593 // aRule->List();
1595 nsAutoString fontfamily;
1596 nsCSSValue val;
1598 PRUint32 unit;
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("\"");
1609 } else {
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.
1614 return;
1617 // set up weight
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;
1624 } else {
1625 NS_ASSERTION(unit == eCSSUnit_Null,
1626 "@font-face weight has unexpected unit");
1629 // set up stretch
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;
1636 } else {
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;
1648 } else {
1649 NS_ASSERTION(unit == eCSSUnit_Null,
1650 "@font-face style has unexpected unit");
1653 // set up src array
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);
1666 if (!face)
1667 return;
1669 switch (unit) {
1671 case eCSSUnit_Local_Font:
1672 val.GetStringValue(face->mLocalName);
1673 face->mIsLocal = PR_TRUE;
1674 face->mURI = nsnull;
1675 face->mFormatFlags = 0;
1676 break;
1677 case eCSSUnit_URL:
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;
1708 i++;
1710 break;
1711 default:
1712 NS_ASSERTION(unit == eCSSUnit_Local_Font || unit == eCSSUnit_URL,
1713 "strange unit type in font-face src array");
1714 break;
1717 } else {
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);
1726 gfxUserFontSet*
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
1742 // ok.
1743 #ifdef DEBUG
1745 PRBool inReflow;
1746 NS_ASSERTION(!mGetUserFontSetCalled ||
1747 (NS_SUCCEEDED(mShell->IsReflowLocked(&inReflow)) &&
1748 !inReflow),
1749 "FlushUserFontSet should have been called first");
1751 #endif
1752 FlushUserFontSet();
1755 mGetUserFontSetCalled = PR_TRUE;
1756 return mUserFontSet;
1759 gfxUserFontSet*
1760 nsPresContext::GetUserFontSetExternal()
1762 return GetUserFontSetInternal();
1765 void
1766 nsPresContext::FlushUserFontSet()
1768 if (!mShell)
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))
1777 return;
1779 PRBool differ;
1780 if (rules.Length() == mFontFaceRules.Length()) {
1781 differ = PR_FALSE;
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) {
1785 differ = PR_TRUE;
1786 break;
1789 } else {
1790 differ = PR_TRUE;
1793 // Only rebuild things if the set of @font-face rules is different.
1794 if (differ) {
1795 NS_IF_RELEASE(mUserFontSet);
1797 if (rules.Length() > 0) {
1798 gfxUserFontSet *fs = new nsUserFontSet(this);
1799 if (!fs)
1800 return;
1801 mUserFontSet = fs;
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);
1810 #ifdef DEBUG
1811 PRBool success =
1812 #endif
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;
1831 void
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.
1838 return;
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
1849 // change reflow).
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;
1860 void
1861 nsPresContext::UserFontSetUpdated()
1863 if (!mShell)
1864 return;
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);
1881 void
1882 nsPresContext::FireDOMPaintEvent()
1884 nsCOMPtr<nsPIDOMWindow> ourWindow = mDocument->GetWindow();
1885 if (!ourWindow)
1886 return;
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
1893 // automatically.)
1894 eventTarget = ourWindow->GetChromeEventHandler();
1895 if (!eventTarget) {
1896 return;
1899 // Events sent to the window get propagated to the chrome event handler
1900 // automatically.
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)
1918 if (!aInnerWindow)
1919 return PR_FALSE;
1920 if (aInnerWindow->HasPaintEventListeners())
1921 return PR_TRUE;
1923 nsPIDOMEventTarget* chromeEventHandler = aInnerWindow->GetChromeEventHandler();
1924 if (!chromeEventHandler)
1925 return PR_FALSE;
1927 nsCOMPtr<nsIEventListenerManager> manager;
1928 chromeEventHandler->GetListenerManager(PR_FALSE, getter_AddRefs(manager));
1929 if (manager && manager->MayHavePaintEventListener())
1930 return PR_TRUE;
1932 nsCOMPtr<nsINode> node = do_QueryInterface(chromeEventHandler);
1933 if (node)
1934 return MayHavePaintEventListener(node->GetOwnerDoc()->GetInnerWindow());
1936 nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(chromeEventHandler);
1937 if (window)
1938 return MayHavePaintEventListener(window);
1940 return PR_FALSE;
1943 void
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()))
1953 return;
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;
1964 r->Or(*r, aRect);
1965 r->SimplifyOutward(10);