1998-04-14 00:24:54 +04:00
|
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
2006-04-18 03:16:46 +04:00
|
|
|
|
* vim: set ts=2 sw=2 et tw=78:
|
2004-04-18 18:30:37 +04:00
|
|
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
1998-04-14 00:24:54 +04:00
|
|
|
|
*
|
2004-04-18 18:30:37 +04:00
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
|
*
|
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
|
* License.
|
1998-04-14 00:24:54 +04:00
|
|
|
|
*
|
1999-11-06 06:40:37 +03:00
|
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
|
*
|
2004-04-18 18:30:37 +04:00
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
|
* Netscape Communications Corporation.
|
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
1999-11-06 06:40:37 +03:00
|
|
|
|
*
|
2004-04-18 18:30:37 +04:00
|
|
|
|
* Contributor(s):
|
2001-04-18 10:06:31 +04:00
|
|
|
|
* Steve Clark <buster@netscape.com>
|
|
|
|
|
* H<EFBFBD>kan Waara <hwaara@chello.se>
|
|
|
|
|
* Dan Rosen <dr@netscape.com>
|
2001-08-02 18:34:55 +04:00
|
|
|
|
* Daniel Glazman <glazman@netscape.com>
|
2005-03-27 15:36:08 +04:00
|
|
|
|
* Mats Palmgren <mats.palmgren@bredband.net>
|
2000-05-15 07:37:21 +04:00
|
|
|
|
*
|
2004-04-18 18:30:37 +04:00
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
|
|
|
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
|
*
|
|
|
|
|
* ***** END LICENSE BLOCK *****
|
2000-05-15 07:37:21 +04:00
|
|
|
|
*
|
|
|
|
|
* This Original Code has been modified by IBM Corporation.
|
|
|
|
|
* Modifications made by IBM described herein are
|
|
|
|
|
* Copyright (c) International Business Machines
|
|
|
|
|
* Corporation, 2000
|
|
|
|
|
*
|
|
|
|
|
* Modifications to Mozilla code or documentation
|
|
|
|
|
* identified per MPL Section 3.3
|
|
|
|
|
*
|
|
|
|
|
* Date Modified by Description of modification
|
|
|
|
|
* 05/03/2000 IBM Corp. Observer events for reflow states
|
1999-09-10 22:29:37 +04:00
|
|
|
|
*/
|
2001-04-18 10:06:31 +04:00
|
|
|
|
|
2006-03-30 09:56:38 +04:00
|
|
|
|
/* a presentation of a document, part 2 */
|
|
|
|
|
|
1999-12-07 07:36:08 +03:00
|
|
|
|
#define PL_ARENA_CONST_ALIGN_MASK 3
|
2005-04-13 08:35:13 +04:00
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
|
#include "nsIPresShell.h"
|
2004-08-01 03:15:21 +04:00
|
|
|
|
#include "nsPresContext.h"
|
1998-04-14 00:24:54 +04:00
|
|
|
|
#include "nsIContent.h"
|
|
|
|
|
#include "nsIDocument.h"
|
2003-03-07 02:07:00 +03:00
|
|
|
|
#include "nsIDOMXULDocument.h"
|
2004-01-29 04:45:34 +03:00
|
|
|
|
#include "nsStubDocumentObserver.h"
|
2004-01-08 01:30:53 +03:00
|
|
|
|
#include "nsStyleSet.h"
|
1998-11-26 04:34:53 +03:00
|
|
|
|
#include "nsICSSStyleSheet.h" // XXX for UA sheet loading hack, can this go away please?
|
2000-10-11 12:33:01 +04:00
|
|
|
|
#include "nsIDOMCSSStyleSheet.h" // for Pref-related rule management (bugs 22963,20760,31816)
|
|
|
|
|
#include "nsINameSpaceManager.h" // for Pref-related rule management (bugs 22963,20760,31816)
|
1999-08-06 00:17:44 +04:00
|
|
|
|
#include "nsIServiceManager.h"
|
1998-05-20 20:24:54 +04:00
|
|
|
|
#include "nsFrame.h"
|
2001-12-18 01:39:59 +03:00
|
|
|
|
#include "nsHTMLReflowCommand.h"
|
1998-04-14 00:24:54 +04:00
|
|
|
|
#include "nsIViewManager.h"
|
|
|
|
|
#include "nsCRT.h"
|
1998-06-03 19:46:54 +04:00
|
|
|
|
#include "prlog.h"
|
2000-04-01 12:35:40 +04:00
|
|
|
|
#include "prmem.h"
|
2004-01-18 17:44:43 +03:00
|
|
|
|
#include "prprf.h"
|
1998-12-12 22:21:05 +03:00
|
|
|
|
#include "prinrval.h"
|
1998-06-09 08:51:44 +04:00
|
|
|
|
#include "nsVoidArray.h"
|
2004-09-13 07:22:46 +04:00
|
|
|
|
#include "nsCOMArray.h"
|
2000-10-09 07:08:41 +04:00
|
|
|
|
#include "nsHashtable.h"
|
1998-08-28 06:54:06 +04:00
|
|
|
|
#include "nsIViewObserver.h"
|
1998-09-19 07:24:26 +04:00
|
|
|
|
#include "nsContainerFrame.h"
|
1998-10-02 05:12:39 +04:00
|
|
|
|
#include "nsIDeviceContext.h"
|
2004-09-04 23:28:46 +04:00
|
|
|
|
#include "nsEventStateManager.h"
|
|
|
|
|
#include "nsDOMEvent.h"
|
2001-07-16 06:40:48 +04:00
|
|
|
|
#include "nsGUIEvent.h"
|
1998-11-17 05:14:38 +03:00
|
|
|
|
#include "nsHTMLParts.h"
|
2004-04-30 03:34:19 +04:00
|
|
|
|
#include "nsContentUtils.h"
|
2000-09-14 15:45:01 +04:00
|
|
|
|
#include "nsISelection.h"
|
1999-12-03 00:45:21 +03:00
|
|
|
|
#include "nsISelectionController.h"
|
2002-05-10 22:22:41 +04:00
|
|
|
|
#include "nsReflowPath.h"
|
1998-12-08 21:26:06 +03:00
|
|
|
|
#include "nsLayoutCID.h"
|
2000-03-23 02:19:10 +03:00
|
|
|
|
#include "nsLayoutAtoms.h"
|
1998-12-14 21:34:14 +03:00
|
|
|
|
#include "nsIDOMRange.h"
|
|
|
|
|
#include "nsIDOMDocument.h"
|
|
|
|
|
#include "nsIDOMNode.h"
|
2003-06-16 15:17:18 +04:00
|
|
|
|
#include "nsIDOM3Node.h"
|
2000-09-14 15:45:01 +04:00
|
|
|
|
#include "nsIDOMNodeList.h"
|
1998-12-14 21:34:14 +03:00
|
|
|
|
#include "nsIDOMElement.h"
|
1999-01-07 07:47:43 +03:00
|
|
|
|
#include "nsHTMLAtoms.h"
|
2002-11-17 18:37:56 +03:00
|
|
|
|
#include "nsCSSPseudoElements.h"
|
1999-01-22 21:58:14 +03:00
|
|
|
|
#include "nsCOMPtr.h"
|
2003-02-22 03:32:13 +03:00
|
|
|
|
#include "nsAutoPtr.h"
|
2001-09-29 12:28:41 +04:00
|
|
|
|
#include "nsReadableUtils.h"
|
2001-12-17 10:14:49 +03:00
|
|
|
|
#include "nsUnicharUtils.h"
|
1999-08-25 14:51:55 +04:00
|
|
|
|
#include "nsWeakReference.h"
|
2000-01-04 23:24:09 +03:00
|
|
|
|
#include "nsIPageSequenceFrame.h"
|
1999-02-12 03:02:56 +03:00
|
|
|
|
#include "nsICaret.h"
|
1999-02-12 08:39:33 +03:00
|
|
|
|
#include "nsIDOMHTMLDocument.h"
|
2003-03-20 02:45:42 +03:00
|
|
|
|
#include "nsIXPointer.h"
|
2001-12-20 08:15:52 +03:00
|
|
|
|
#include "nsIDOMXMLDocument.h"
|
1999-02-12 08:39:33 +03:00
|
|
|
|
#include "nsIScrollableView.h"
|
1999-03-01 22:21:01 +03:00
|
|
|
|
#include "nsIParser.h"
|
|
|
|
|
#include "nsParserCIID.h"
|
2006-04-26 06:01:07 +04:00
|
|
|
|
#include "nsFrameSelection.h"
|
2000-06-14 06:57:26 +04:00
|
|
|
|
#include "nsIDOMNSHTMLInputElement.h" //optimization for ::DoXXX commands
|
2000-06-30 02:33:36 +04:00
|
|
|
|
#include "nsIDOMNSHTMLTextAreaElement.h"
|
1999-04-03 22:58:04 +04:00
|
|
|
|
#include "nsViewsCID.h"
|
2004-02-24 00:29:06 +03:00
|
|
|
|
#include "nsFrameManager.h"
|
2002-09-04 03:36:13 +04:00
|
|
|
|
#include "nsXPCOM.h"
|
1999-08-25 12:35:06 +04:00
|
|
|
|
#include "nsISupportsPrimitives.h"
|
1999-08-31 02:38:58 +04:00
|
|
|
|
#include "nsILayoutHistoryState.h"
|
1999-10-15 08:29:30 +04:00
|
|
|
|
#include "nsIScrollPositionListener.h"
|
|
|
|
|
#include "nsICompositeListener.h"
|
2001-01-10 05:43:00 +03:00
|
|
|
|
#include "nsILineIterator.h" // for ScrollFrameIntoView
|
1999-11-10 06:41:09 +03:00
|
|
|
|
#include "nsTimer.h"
|
1999-11-09 06:23:26 +03:00
|
|
|
|
#include "nsWeakPtr.h"
|
1999-12-07 07:36:08 +03:00
|
|
|
|
#include "plarena.h"
|
2004-05-02 22:07:12 +04:00
|
|
|
|
#include "pldhash.h"
|
2004-07-18 05:16:27 +04:00
|
|
|
|
#include "nsIObserverService.h"
|
|
|
|
|
#include "nsIObserver.h"
|
2000-08-30 04:35:43 +04:00
|
|
|
|
#include "nsIDocShell.h" // for reflow observation
|
2004-10-15 01:51:00 +04:00
|
|
|
|
#include "nsIBaseWindow.h"
|
2002-11-25 14:21:22 +03:00
|
|
|
|
#include "nsLayoutErrors.h"
|
2003-01-05 08:05:17 +03:00
|
|
|
|
#include "nsLayoutUtils.h"
|
2003-01-17 12:33:52 +03:00
|
|
|
|
#include "nsCSSRendering.h"
|
1999-11-02 01:12:45 +03:00
|
|
|
|
#ifdef NS_DEBUG
|
|
|
|
|
#include "nsIFrameDebug.h"
|
|
|
|
|
#endif
|
2001-10-26 09:12:25 +04:00
|
|
|
|
// for |#ifdef DEBUG| code
|
|
|
|
|
#include "nsSpaceManager.h"
|
2001-06-27 08:04:04 +04:00
|
|
|
|
#include "prenv.h"
|
2005-02-20 12:55:02 +03:00
|
|
|
|
#include "nsIAttribute.h"
|
2005-08-24 02:26:10 +04:00
|
|
|
|
#include "nsIGlobalHistory2.h"
|
2006-01-26 05:29:17 +03:00
|
|
|
|
#include "nsDisplayList.h"
|
|
|
|
|
#include "nsRegion.h"
|
1999-02-20 02:47:36 +03:00
|
|
|
|
|
2001-03-13 04:47:22 +03:00
|
|
|
|
#ifdef MOZ_REFLOW_PERF_DSP
|
|
|
|
|
#include "nsIRenderingContext.h"
|
|
|
|
|
#include "nsIFontMetrics.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
2000-07-14 03:00:59 +04:00
|
|
|
|
#include "nsIReflowCallback.h"
|
|
|
|
|
|
2000-02-13 09:07:38 +03:00
|
|
|
|
#include "nsPIDOMWindow.h"
|
2000-11-04 11:21:20 +03:00
|
|
|
|
#include "nsIFocusController.h"
|
2005-05-05 00:22:32 +04:00
|
|
|
|
#include "nsIPluginInstance.h"
|
|
|
|
|
#include "nsIObjectFrame.h"
|
2005-12-03 14:27:42 +03:00
|
|
|
|
#include "nsIObjectLoadingContent.h"
|
2005-11-01 14:37:25 +03:00
|
|
|
|
#include "nsNetUtil.h"
|
2006-03-07 20:08:51 +03:00
|
|
|
|
#include "nsEventDispatcher.h"
|
2006-05-10 21:30:15 +04:00
|
|
|
|
#include "nsThreadUtils.h"
|
2006-06-08 18:32:20 +04:00
|
|
|
|
#include "nsStyleSheetService.h"
|
2000-02-13 09:07:38 +03:00
|
|
|
|
|
1999-03-24 00:32:48 +03:00
|
|
|
|
// Drag & Drop, Clipboard
|
|
|
|
|
#include "nsWidgetsCID.h"
|
|
|
|
|
#include "nsIClipboard.h"
|
2001-05-10 06:35:00 +04:00
|
|
|
|
#include "nsIClipboardHelper.h"
|
1999-12-18 05:09:29 +03:00
|
|
|
|
#include "nsIDocShellTreeItem.h"
|
1999-11-09 06:23:26 +03:00
|
|
|
|
#include "nsIURI.h"
|
1999-12-07 08:28:32 +03:00
|
|
|
|
#include "nsIScrollableFrame.h"
|
1999-12-23 05:02:33 +03:00
|
|
|
|
#include "prtime.h"
|
|
|
|
|
#include "prlong.h"
|
2000-06-15 03:18:54 +04:00
|
|
|
|
#include "nsIDragService.h"
|
2001-02-15 16:22:26 +03:00
|
|
|
|
#include "nsCopySupport.h"
|
2001-04-18 10:06:31 +04:00
|
|
|
|
#include "nsIDOMHTMLAnchorElement.h"
|
2001-09-13 03:31:37 +04:00
|
|
|
|
#include "nsIDOMHTMLAreaElement.h"
|
|
|
|
|
#include "nsIDOMHTMLLinkElement.h"
|
2001-04-18 03:25:21 +04:00
|
|
|
|
#include "nsITimer.h"
|
2003-04-15 12:45:55 +04:00
|
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
|
#include "nsIAccessibilityService.h"
|
|
|
|
|
#include "nsIAccessible.h"
|
2005-06-10 17:57:27 +04:00
|
|
|
|
#include "nsIAccessibleEvent.h"
|
2003-04-15 12:45:55 +04:00
|
|
|
|
#endif
|
2000-06-15 03:18:54 +04:00
|
|
|
|
|
2001-12-18 01:51:39 +03:00
|
|
|
|
// For style data reconstruction
|
|
|
|
|
#include "nsStyleChangeList.h"
|
2004-01-08 01:30:53 +03:00
|
|
|
|
#include "nsCSSFrameConstructor.h"
|
2001-12-18 01:51:39 +03:00
|
|
|
|
#include "nsIBindingManager.h"
|
2003-04-11 04:56:27 +04:00
|
|
|
|
#ifdef MOZ_XUL
|
2001-12-18 01:51:39 +03:00
|
|
|
|
#include "nsIMenuFrame.h"
|
2002-03-29 05:46:01 +03:00
|
|
|
|
#include "nsITreeBoxObject.h"
|
2003-04-11 04:56:27 +04:00
|
|
|
|
#endif
|
2001-12-18 01:51:39 +03:00
|
|
|
|
#include "nsPlaceholderFrame.h"
|
|
|
|
|
|
2001-05-02 02:54:11 +04:00
|
|
|
|
// Content viewer interfaces
|
|
|
|
|
#include "nsIContentViewer.h"
|
|
|
|
|
|
2001-03-09 06:29:00 +03:00
|
|
|
|
#ifdef IBMBIDI
|
|
|
|
|
#include "nsIBidiKeyboard.h"
|
|
|
|
|
#endif // IBMBIDI
|
|
|
|
|
|
2001-02-20 00:50:04 +03:00
|
|
|
|
#include "nsContentCID.h"
|
|
|
|
|
static NS_DEFINE_CID(kCSSStyleSheetCID, NS_CSS_STYLESHEET_CID);
|
2001-03-28 03:59:56 +04:00
|
|
|
|
static NS_DEFINE_IID(kRangeCID, NS_RANGE_CID);
|
2001-02-20 00:50:04 +03:00
|
|
|
|
|
2000-10-11 12:33:01 +04:00
|
|
|
|
// convert a color value to a string, in the CSS format #RRGGBB
|
|
|
|
|
// * - initially created for bugs 31816, 20760, 22963
|
|
|
|
|
static void ColorToString(nscolor aColor, nsAutoString &aString);
|
|
|
|
|
|
2000-01-04 23:24:09 +03:00
|
|
|
|
// Class ID's
|
|
|
|
|
static NS_DEFINE_CID(kFrameSelectionCID, NS_FRAMESELECTION_CID);
|
1999-03-24 00:32:48 +03:00
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
|
#undef NOISY
|
|
|
|
|
|
2002-05-10 22:22:41 +04:00
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
#ifdef NS_DEBUG
|
|
|
|
|
// Set the environment variable GECKO_VERIFY_REFLOW_FLAGS to one or
|
|
|
|
|
// more of the following flags (comma separated) for handy debug
|
|
|
|
|
// output.
|
|
|
|
|
static PRUint32 gVerifyReflowFlags;
|
|
|
|
|
|
|
|
|
|
struct VerifyReflowFlags {
|
2004-01-21 07:15:00 +03:00
|
|
|
|
const char* name;
|
2002-05-10 22:22:41 +04:00
|
|
|
|
PRUint32 bit;
|
|
|
|
|
};
|
|
|
|
|
|
2004-01-21 07:15:00 +03:00
|
|
|
|
static const VerifyReflowFlags gFlags[] = {
|
2002-05-10 22:22:41 +04:00
|
|
|
|
{ "verify", VERIFY_REFLOW_ON },
|
|
|
|
|
{ "reflow", VERIFY_REFLOW_NOISY },
|
|
|
|
|
{ "all", VERIFY_REFLOW_ALL },
|
|
|
|
|
{ "list-commands", VERIFY_REFLOW_DUMP_COMMANDS },
|
|
|
|
|
{ "noisy-commands", VERIFY_REFLOW_NOISY_RC },
|
|
|
|
|
{ "really-noisy-commands", VERIFY_REFLOW_REALLY_NOISY_RC },
|
|
|
|
|
{ "space-manager", VERIFY_REFLOW_INCLUDE_SPACE_MANAGER },
|
|
|
|
|
{ "resize", VERIFY_REFLOW_DURING_RESIZE_REFLOW },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define NUM_VERIFY_REFLOW_FLAGS (sizeof(gFlags) / sizeof(gFlags[0]))
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ShowVerifyReflowFlags()
|
|
|
|
|
{
|
|
|
|
|
printf("Here are the available GECKO_VERIFY_REFLOW_FLAGS:\n");
|
2004-01-21 07:15:00 +03:00
|
|
|
|
const VerifyReflowFlags* flag = gFlags;
|
|
|
|
|
const VerifyReflowFlags* limit = gFlags + NUM_VERIFY_REFLOW_FLAGS;
|
2002-05-10 22:22:41 +04:00
|
|
|
|
while (flag < limit) {
|
|
|
|
|
printf(" %s\n", flag->name);
|
|
|
|
|
++flag;
|
|
|
|
|
}
|
|
|
|
|
printf("Note: GECKO_VERIFY_REFLOW_FLAGS is a comma separated list of flag\n");
|
|
|
|
|
printf("names (no whitespace)\n");
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-03-13 04:47:22 +03:00
|
|
|
|
//========================================================================
|
|
|
|
|
//========================================================================
|
2000-04-27 01:01:57 +04:00
|
|
|
|
//========================================================================
|
|
|
|
|
#ifdef MOZ_REFLOW_PERF
|
|
|
|
|
class ReflowCountMgr;
|
|
|
|
|
|
2003-05-27 07:52:33 +04:00
|
|
|
|
static const char kGrandTotalsStr[] = "Grand Totals";
|
2000-04-27 01:01:57 +04:00
|
|
|
|
#define NUM_REFLOW_TYPES 5
|
|
|
|
|
|
|
|
|
|
// Counting Class
|
|
|
|
|
class ReflowCounter {
|
|
|
|
|
public:
|
2001-02-22 16:58:17 +03:00
|
|
|
|
ReflowCounter(ReflowCountMgr * aMgr = nsnull);
|
2000-04-27 01:01:57 +04:00
|
|
|
|
~ReflowCounter();
|
|
|
|
|
|
|
|
|
|
void ClearTotals();
|
|
|
|
|
void DisplayTotals(const char * aStr);
|
2000-04-29 03:32:04 +04:00
|
|
|
|
void DisplayDiffTotals(const char * aStr);
|
2000-04-27 01:01:57 +04:00
|
|
|
|
void DisplayHTMLTotals(const char * aStr);
|
|
|
|
|
|
2000-04-29 03:32:04 +04:00
|
|
|
|
void Add(nsReflowReason aType) { mTotals[aType]++; }
|
|
|
|
|
void Add(nsReflowReason aType, PRUint32 aTotal) { mTotals[aType] += aTotal; }
|
|
|
|
|
|
|
|
|
|
void CalcDiffInTotals();
|
|
|
|
|
void SetTotalsCache();
|
|
|
|
|
|
|
|
|
|
void SetMgr(ReflowCountMgr * aMgr) { mMgr = aMgr; }
|
2000-04-27 01:01:57 +04:00
|
|
|
|
|
2001-02-22 16:58:17 +03:00
|
|
|
|
PRUint32 GetTotalByType(nsReflowReason aType) { if (aType >= eReflowReason_Initial && aType <= eReflowReason_Dirty) return mTotals[aType]; else return 0; }
|
|
|
|
|
|
2000-04-27 01:01:57 +04:00
|
|
|
|
protected:
|
|
|
|
|
void DisplayTotals(PRUint32 * aArray, const char * aTitle);
|
|
|
|
|
void DisplayHTMLTotals(PRUint32 * aArray, const char * aTitle);
|
|
|
|
|
|
|
|
|
|
PRUint32 mTotals[NUM_REFLOW_TYPES];
|
2000-04-29 03:32:04 +04:00
|
|
|
|
PRUint32 mCacheTotals[NUM_REFLOW_TYPES];
|
|
|
|
|
|
2001-03-13 04:47:22 +03:00
|
|
|
|
ReflowCountMgr * mMgr; // weak reference (don't delete)
|
2000-04-27 01:01:57 +04:00
|
|
|
|
};
|
|
|
|
|
|
2001-02-22 16:58:17 +03:00
|
|
|
|
// Counting Class
|
|
|
|
|
class IndiReflowCounter {
|
|
|
|
|
public:
|
2001-10-25 07:21:53 +04:00
|
|
|
|
IndiReflowCounter(ReflowCountMgr * aMgr = nsnull)
|
|
|
|
|
: mFrame(nsnull),
|
|
|
|
|
mCount(0),
|
|
|
|
|
mMgr(aMgr),
|
|
|
|
|
mCounter(aMgr),
|
|
|
|
|
mHasBeenOutput(PR_FALSE)
|
|
|
|
|
{}
|
2001-02-22 16:58:17 +03:00
|
|
|
|
virtual ~IndiReflowCounter() {}
|
|
|
|
|
|
|
|
|
|
nsAutoString mName;
|
2001-03-13 04:47:22 +03:00
|
|
|
|
nsIFrame * mFrame; // weak reference (don't delete)
|
2001-02-22 16:58:17 +03:00
|
|
|
|
PRInt32 mCount;
|
|
|
|
|
|
2001-03-13 04:47:22 +03:00
|
|
|
|
ReflowCountMgr * mMgr; // weak reference (don't delete)
|
2001-02-22 16:58:17 +03:00
|
|
|
|
|
|
|
|
|
ReflowCounter mCounter;
|
|
|
|
|
PRBool mHasBeenOutput;
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
2001-03-13 04:47:22 +03:00
|
|
|
|
//--------------------
|
2000-04-27 01:01:57 +04:00
|
|
|
|
// Manager Class
|
2001-03-13 04:47:22 +03:00
|
|
|
|
//--------------------
|
2000-04-27 01:01:57 +04:00
|
|
|
|
class ReflowCountMgr {
|
|
|
|
|
public:
|
|
|
|
|
ReflowCountMgr();
|
2001-03-13 04:47:22 +03:00
|
|
|
|
virtual ~ReflowCountMgr();
|
2000-04-27 01:01:57 +04:00
|
|
|
|
|
|
|
|
|
void ClearTotals();
|
2000-04-29 03:32:04 +04:00
|
|
|
|
void ClearGrandTotals();
|
2000-04-27 01:01:57 +04:00
|
|
|
|
void DisplayTotals(const char * aStr);
|
|
|
|
|
void DisplayHTMLTotals(const char * aStr);
|
2000-04-29 03:32:04 +04:00
|
|
|
|
void DisplayDiffsInTotals(const char * aStr);
|
2000-04-27 01:01:57 +04:00
|
|
|
|
|
2001-02-22 16:58:17 +03:00
|
|
|
|
void Add(const char * aName, nsReflowReason aType, nsIFrame * aFrame);
|
2000-04-27 01:01:57 +04:00
|
|
|
|
ReflowCounter * LookUp(const char * aName);
|
|
|
|
|
|
2004-08-01 03:15:21 +04:00
|
|
|
|
void PaintCount(const char * aName, nsIRenderingContext* aRenderingContext, nsPresContext* aPresContext, nsIFrame * aFrame, PRUint32 aColor);
|
2001-03-13 04:47:22 +03:00
|
|
|
|
|
2000-04-27 01:01:57 +04:00
|
|
|
|
FILE * GetOutFile() { return mFD; }
|
|
|
|
|
|
2001-02-22 16:58:17 +03:00
|
|
|
|
PLHashTable * GetIndiFrameHT() { return mIndiFrameCounts; }
|
|
|
|
|
|
2004-08-01 03:15:21 +04:00
|
|
|
|
void SetPresContext(nsPresContext * aPresContext) { mPresContext = aPresContext; } // weak reference
|
2001-03-13 04:47:22 +03:00
|
|
|
|
void SetPresShell(nsIPresShell* aPresShell) { mPresShell= aPresShell; } // weak reference
|
|
|
|
|
|
|
|
|
|
void SetDumpFrameCounts(PRBool aVal) { mDumpFrameCounts = aVal; }
|
|
|
|
|
void SetDumpFrameByFrameCounts(PRBool aVal) { mDumpFrameByFrameCounts = aVal; }
|
|
|
|
|
void SetPaintFrameCounts(PRBool aVal) { mPaintFrameByFrameCounts = aVal; }
|
2001-02-22 16:58:17 +03:00
|
|
|
|
|
2000-04-27 01:01:57 +04:00
|
|
|
|
protected:
|
|
|
|
|
void DisplayTotals(PRUint32 * aArray, PRUint32 * aDupArray, char * aTitle);
|
|
|
|
|
void DisplayHTMLTotals(PRUint32 * aArray, PRUint32 * aDupArray, char * aTitle);
|
|
|
|
|
|
2001-03-15 02:57:37 +03:00
|
|
|
|
PR_STATIC_CALLBACK(PRIntn) RemoveItems(PLHashEntry *he, PRIntn i, void *arg);
|
|
|
|
|
PR_STATIC_CALLBACK(PRIntn) RemoveIndiItems(PLHashEntry *he, PRIntn i, void *arg);
|
2000-04-27 01:01:57 +04:00
|
|
|
|
void CleanUp();
|
|
|
|
|
|
|
|
|
|
// stdout Output Methods
|
2001-03-15 02:57:37 +03:00
|
|
|
|
PR_STATIC_CALLBACK(PRIntn) DoSingleTotal(PLHashEntry *he, PRIntn i, void *arg);
|
|
|
|
|
PR_STATIC_CALLBACK(PRIntn) DoSingleIndi(PLHashEntry *he, PRIntn i, void *arg);
|
2001-02-22 16:58:17 +03:00
|
|
|
|
|
2000-04-27 01:01:57 +04:00
|
|
|
|
void DoGrandTotals();
|
2001-02-22 16:58:17 +03:00
|
|
|
|
void DoIndiTotalsTree();
|
2000-04-27 01:01:57 +04:00
|
|
|
|
|
|
|
|
|
// HTML Output Methods
|
2001-03-15 02:57:37 +03:00
|
|
|
|
PR_STATIC_CALLBACK(PRIntn) DoSingleHTMLTotal(PLHashEntry *he, PRIntn i, void *arg);
|
2000-04-27 01:01:57 +04:00
|
|
|
|
void DoGrandHTMLTotals();
|
|
|
|
|
|
2000-04-29 03:32:04 +04:00
|
|
|
|
// Zero Out the Totals
|
2001-03-15 02:57:37 +03:00
|
|
|
|
PR_STATIC_CALLBACK(PRIntn) DoClearTotals(PLHashEntry *he, PRIntn i, void *arg);
|
2000-04-29 03:32:04 +04:00
|
|
|
|
|
|
|
|
|
// Displays the Diff Totals
|
2001-03-15 02:57:37 +03:00
|
|
|
|
PR_STATIC_CALLBACK(PRIntn) DoDisplayDiffTotals(PLHashEntry *he, PRIntn i, void *arg);
|
2000-04-29 03:32:04 +04:00
|
|
|
|
|
2000-04-27 01:01:57 +04:00
|
|
|
|
PLHashTable * mCounts;
|
2001-02-22 16:58:17 +03:00
|
|
|
|
PLHashTable * mIndiFrameCounts;
|
2000-04-27 01:01:57 +04:00
|
|
|
|
FILE * mFD;
|
2001-02-22 16:58:17 +03:00
|
|
|
|
|
2001-03-13 04:47:22 +03:00
|
|
|
|
PRBool mDumpFrameCounts;
|
|
|
|
|
PRBool mDumpFrameByFrameCounts;
|
|
|
|
|
PRBool mPaintFrameByFrameCounts;
|
|
|
|
|
|
2000-04-29 03:32:04 +04:00
|
|
|
|
PRBool mCycledOnce;
|
|
|
|
|
|
2001-02-22 16:58:17 +03:00
|
|
|
|
// Root Frame for Individual Tracking
|
2004-08-01 03:15:21 +04:00
|
|
|
|
nsPresContext * mPresContext;
|
2001-02-22 16:58:17 +03:00
|
|
|
|
nsIPresShell* mPresShell;
|
|
|
|
|
|
2000-04-27 01:01:57 +04:00
|
|
|
|
// ReflowCountMgr gReflowCountMgr;
|
|
|
|
|
};
|
|
|
|
|
#endif
|
|
|
|
|
//========================================================================
|
|
|
|
|
|
1999-02-12 03:02:56 +03:00
|
|
|
|
// comment out to hide caret
|
1999-03-02 07:26:49 +03:00
|
|
|
|
#define SHOW_CARET
|
1999-02-12 03:02:56 +03:00
|
|
|
|
|
2002-05-10 22:22:41 +04:00
|
|
|
|
// The upper bound on the amount of time to spend reflowing, in
|
|
|
|
|
// microseconds. When this bound is exceeded and reflow commands are
|
|
|
|
|
// still queued up, a reflow event is posted. The idea is for reflow
|
|
|
|
|
// to not hog the processor beyond the time specifed in
|
|
|
|
|
// gMaxRCProcessingTime. This data member is initialized from the
|
|
|
|
|
// layout.reflow.timeslice pref.
|
1999-12-23 05:02:33 +03:00
|
|
|
|
#define NS_MAX_REFLOW_TIME 1000000
|
1999-12-23 06:47:02 +03:00
|
|
|
|
static PRInt32 gMaxRCProcessingTime = -1;
|
1999-12-23 05:02:33 +03:00
|
|
|
|
|
1999-12-07 07:36:08 +03:00
|
|
|
|
// Largest chunk size we recycle
|
2000-03-31 11:02:06 +04:00
|
|
|
|
static const size_t gMaxRecycledSize = 400;
|
1999-12-07 07:36:08 +03:00
|
|
|
|
|
2000-03-31 11:02:06 +04:00
|
|
|
|
#define MARK_INCREMENT 50
|
2002-08-06 17:51:07 +04:00
|
|
|
|
#define BLOCK_INCREMENT 4044 /* a bit under 4096, for malloc overhead */
|
2000-03-31 11:02:06 +04:00
|
|
|
|
|
|
|
|
|
/**A block of memory that the stack will
|
|
|
|
|
* chop up and hand out
|
|
|
|
|
*/
|
|
|
|
|
struct StackBlock {
|
|
|
|
|
|
2002-08-06 17:51:07 +04:00
|
|
|
|
// a block of memory. Note that this must be first so that it will
|
|
|
|
|
// be aligned.
|
|
|
|
|
char mBlock[BLOCK_INCREMENT];
|
2000-03-31 11:02:06 +04:00
|
|
|
|
|
|
|
|
|
// another block of memory that would only be created
|
|
|
|
|
// if our stack overflowed. Yes we have the ability
|
|
|
|
|
// to grow on a stack overflow
|
|
|
|
|
StackBlock* mNext;
|
2002-08-06 17:51:07 +04:00
|
|
|
|
|
|
|
|
|
StackBlock() : mNext(nsnull) { }
|
|
|
|
|
~StackBlock() { }
|
2000-03-31 11:02:06 +04:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* we hold an array of marks. A push pushes a mark on the stack
|
|
|
|
|
* a pop pops it off.
|
|
|
|
|
*/
|
|
|
|
|
struct StackMark {
|
|
|
|
|
// the block of memory we are currently handing out chunks of
|
|
|
|
|
StackBlock* mBlock;
|
|
|
|
|
|
|
|
|
|
// our current position in the memory
|
|
|
|
|
size_t mPos;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* A stack arena allows a stack based interface to a block of memory.
|
|
|
|
|
* It should be used when you need to allocate some temporary memory that
|
|
|
|
|
* you will immediately return.
|
|
|
|
|
*/
|
|
|
|
|
class StackArena {
|
|
|
|
|
public:
|
|
|
|
|
StackArena();
|
|
|
|
|
~StackArena();
|
|
|
|
|
|
|
|
|
|
// Memory management functions
|
|
|
|
|
nsresult Allocate(size_t aSize, void** aResult);
|
|
|
|
|
nsresult Push();
|
|
|
|
|
nsresult Pop();
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
// our current position in memory
|
|
|
|
|
size_t mPos;
|
|
|
|
|
|
|
|
|
|
// a list of memory block. Usually there is only one
|
|
|
|
|
// but if we overrun our stack size we can get more memory.
|
|
|
|
|
StackBlock* mBlocks;
|
|
|
|
|
|
|
|
|
|
// the current block of memory we are passing our chucks of
|
|
|
|
|
StackBlock* mCurBlock;
|
|
|
|
|
|
|
|
|
|
// our stack of mark where push has been called
|
|
|
|
|
StackMark* mMarks;
|
|
|
|
|
|
2005-11-21 01:05:24 +03:00
|
|
|
|
// the current top of the mark list
|
2000-03-31 11:02:06 +04:00
|
|
|
|
PRUint32 mStackTop;
|
|
|
|
|
|
|
|
|
|
// the size of the mark array
|
|
|
|
|
PRUint32 mMarkLength;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
StackArena::StackArena()
|
|
|
|
|
{
|
|
|
|
|
// allocate the marks array
|
|
|
|
|
mMarkLength = MARK_INCREMENT;
|
|
|
|
|
mMarks = new StackMark[mMarkLength];
|
|
|
|
|
|
|
|
|
|
// allocate our stack memory
|
|
|
|
|
mBlocks = new StackBlock();
|
|
|
|
|
mCurBlock = mBlocks;
|
|
|
|
|
|
|
|
|
|
mStackTop = 0;
|
|
|
|
|
mPos = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
StackArena::~StackArena()
|
|
|
|
|
{
|
|
|
|
|
// free up our data
|
|
|
|
|
delete[] mMarks;
|
|
|
|
|
while(mBlocks)
|
|
|
|
|
{
|
|
|
|
|
StackBlock* toDelete = mBlocks;
|
|
|
|
|
mBlocks = mBlocks->mNext;
|
|
|
|
|
delete toDelete;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
|
StackArena::Push()
|
|
|
|
|
{
|
|
|
|
|
// if the we overrun our mark array. Resize it.
|
|
|
|
|
if (mStackTop + 1 >= mMarkLength)
|
|
|
|
|
{
|
|
|
|
|
StackMark* oldMarks = mMarks;
|
|
|
|
|
PRUint32 oldLength = mMarkLength;
|
|
|
|
|
mMarkLength += MARK_INCREMENT;
|
|
|
|
|
mMarks = new StackMark[mMarkLength];
|
2002-01-12 06:18:55 +03:00
|
|
|
|
memcpy(mMarks, oldMarks, sizeof(StackMark)*oldLength);
|
2000-03-31 11:02:06 +04:00
|
|
|
|
|
|
|
|
|
delete[] oldMarks;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// set a mark at the top
|
|
|
|
|
mMarks[mStackTop].mBlock = mCurBlock;
|
|
|
|
|
mMarks[mStackTop].mPos = mPos;
|
|
|
|
|
|
|
|
|
|
mStackTop++;
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
|
StackArena::Allocate(size_t aSize, void** aResult)
|
|
|
|
|
{
|
|
|
|
|
NS_ASSERTION(mStackTop > 0, "Error allocate called before push!!!");
|
|
|
|
|
|
|
|
|
|
// make sure we are aligned. Beard said 8 was safer then 4.
|
|
|
|
|
// Round size to multiple of 8
|
|
|
|
|
aSize = PR_ROUNDUP(aSize, 8);
|
|
|
|
|
|
|
|
|
|
// if the size makes the stack overflow. Grab another block for the stack
|
|
|
|
|
if (mPos + aSize >= BLOCK_INCREMENT)
|
|
|
|
|
{
|
|
|
|
|
NS_ASSERTION(aSize <= BLOCK_INCREMENT,"Requested memory is greater that our block size!!");
|
|
|
|
|
if (mCurBlock->mNext == nsnull)
|
|
|
|
|
mCurBlock->mNext = new StackBlock();
|
|
|
|
|
|
|
|
|
|
mCurBlock = mCurBlock->mNext;
|
|
|
|
|
mPos = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// return the chunk they need.
|
2002-08-06 17:51:07 +04:00
|
|
|
|
*aResult = mCurBlock->mBlock + mPos;
|
2000-03-31 11:02:06 +04:00
|
|
|
|
mPos += aSize;
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
|
StackArena::Pop()
|
|
|
|
|
{
|
|
|
|
|
// pop off the mark
|
|
|
|
|
NS_ASSERTION(mStackTop > 0, "Error Pop called 1 too many times");
|
|
|
|
|
mStackTop--;
|
2002-08-14 16:49:24 +04:00
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
// Mark the "freed" memory with 0xdd to help with debugging of memory
|
|
|
|
|
// allocation problems.
|
|
|
|
|
{
|
|
|
|
|
StackBlock *block = mMarks[mStackTop].mBlock, *block_end = mCurBlock;
|
|
|
|
|
size_t pos = mMarks[mStackTop].mPos;
|
|
|
|
|
for (; block != block_end; block = block->mNext, pos = 0) {
|
|
|
|
|
memset(block->mBlock + pos, 0xdd, sizeof(block->mBlock) - pos);
|
|
|
|
|
}
|
|
|
|
|
memset(block->mBlock + pos, 0xdd, mPos - pos);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2000-03-31 11:02:06 +04:00
|
|
|
|
mCurBlock = mMarks[mStackTop].mBlock;
|
|
|
|
|
mPos = mMarks[mStackTop].mPos;
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-21 03:16:26 +03:00
|
|
|
|
// Uncomment this to disable the frame arena.
|
|
|
|
|
//#define DEBUG_TRACEMALLOC_FRAMEARENA 1
|
2000-03-31 11:02:06 +04:00
|
|
|
|
|
1999-12-07 07:36:08 +03:00
|
|
|
|
// Memory is allocated 4-byte aligned. We have recyclers for chunks up to
|
|
|
|
|
// 200 bytes
|
|
|
|
|
class FrameArena {
|
|
|
|
|
public:
|
2000-03-31 08:11:28 +04:00
|
|
|
|
FrameArena(PRUint32 aArenaSize = 4096);
|
1999-12-07 07:36:08 +03:00
|
|
|
|
~FrameArena();
|
|
|
|
|
|
|
|
|
|
// Memory management functions
|
2004-04-13 04:28:44 +04:00
|
|
|
|
NS_HIDDEN_(void*) AllocateFrame(size_t aSize);
|
|
|
|
|
NS_HIDDEN_(void) FreeFrame(size_t aSize, void* aPtr);
|
1999-12-07 07:36:08 +03:00
|
|
|
|
|
|
|
|
|
private:
|
2001-12-21 03:16:26 +03:00
|
|
|
|
#if !defined(DEBUG_TRACEMALLOC_FRAMEARENA)
|
1999-12-07 07:36:08 +03:00
|
|
|
|
// Underlying arena pool
|
|
|
|
|
PLArenaPool mPool;
|
|
|
|
|
|
|
|
|
|
// The recycler array is sparse with the indices being multiples of 4,
|
|
|
|
|
// i.e., 0, 4, 8, 12, 16, 20, ...
|
|
|
|
|
void* mRecyclers[gMaxRecycledSize >> 2];
|
2001-12-21 03:16:26 +03:00
|
|
|
|
#endif
|
1999-12-07 07:36:08 +03:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
FrameArena::FrameArena(PRUint32 aArenaSize)
|
|
|
|
|
{
|
2001-12-21 03:16:26 +03:00
|
|
|
|
#if !defined(DEBUG_TRACEMALLOC_FRAMEARENA)
|
1999-12-07 07:36:08 +03:00
|
|
|
|
// Initialize the arena pool
|
|
|
|
|
PL_INIT_ARENA_POOL(&mPool, "FrameArena", aArenaSize);
|
|
|
|
|
|
|
|
|
|
// Zero out the recyclers array
|
2002-02-05 04:41:13 +03:00
|
|
|
|
memset(mRecyclers, 0, sizeof(mRecyclers));
|
2001-12-21 03:16:26 +03:00
|
|
|
|
#endif
|
1999-12-07 07:36:08 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FrameArena::~FrameArena()
|
|
|
|
|
{
|
2001-12-21 03:16:26 +03:00
|
|
|
|
#if !defined(DEBUG_TRACEMALLOC_FRAMEARENA)
|
1999-12-07 07:36:08 +03:00
|
|
|
|
// Free the arena in the pool and finish using it
|
|
|
|
|
PL_FinishArenaPool(&mPool);
|
2001-12-21 03:16:26 +03:00
|
|
|
|
#endif
|
2000-03-31 11:02:06 +04:00
|
|
|
|
}
|
1999-12-07 07:36:08 +03:00
|
|
|
|
|
2004-04-13 04:28:44 +04:00
|
|
|
|
void*
|
|
|
|
|
FrameArena::AllocateFrame(size_t aSize)
|
1999-12-07 07:36:08 +03:00
|
|
|
|
{
|
2001-12-21 03:16:26 +03:00
|
|
|
|
#if defined(DEBUG_TRACEMALLOC_FRAMEARENA)
|
2004-04-13 04:28:44 +04:00
|
|
|
|
return PR_Malloc(aSize);
|
2001-12-21 03:16:26 +03:00
|
|
|
|
#else
|
1999-12-07 07:36:08 +03:00
|
|
|
|
void* result = nsnull;
|
|
|
|
|
|
2001-06-26 05:19:05 +04:00
|
|
|
|
// Ensure we have correct alignment for pointers. Important for Tru64
|
|
|
|
|
aSize = PR_ROUNDUP(aSize, sizeof(void*));
|
1999-12-07 07:36:08 +03:00
|
|
|
|
|
|
|
|
|
// Check recyclers first
|
|
|
|
|
if (aSize < gMaxRecycledSize) {
|
|
|
|
|
const int index = aSize >> 2;
|
|
|
|
|
|
|
|
|
|
result = mRecyclers[index];
|
|
|
|
|
if (result) {
|
|
|
|
|
// Need to move to the next object
|
|
|
|
|
void* next = *((void**)result);
|
|
|
|
|
mRecyclers[index] = next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!result) {
|
|
|
|
|
// Allocate a new chunk from the arena
|
|
|
|
|
PL_ARENA_ALLOCATE(result, &mPool, aSize);
|
|
|
|
|
}
|
|
|
|
|
|
2004-04-13 04:28:44 +04:00
|
|
|
|
return result;
|
2001-12-21 03:16:26 +03:00
|
|
|
|
#endif
|
1999-12-07 07:36:08 +03:00
|
|
|
|
}
|
|
|
|
|
|
2004-04-13 04:28:44 +04:00
|
|
|
|
void
|
1999-12-07 07:36:08 +03:00
|
|
|
|
FrameArena::FreeFrame(size_t aSize, void* aPtr)
|
|
|
|
|
{
|
2002-08-06 17:57:16 +04:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
// Mark the memory with 0xdd in DEBUG builds so that there will be
|
|
|
|
|
// problems if someone tries to access memory that they've freed.
|
|
|
|
|
memset(aPtr, 0xdd, aSize);
|
|
|
|
|
#endif
|
2001-12-21 03:16:26 +03:00
|
|
|
|
#if defined(DEBUG_TRACEMALLOC_FRAMEARENA)
|
|
|
|
|
PR_Free(aPtr);
|
|
|
|
|
#else
|
2001-06-26 05:19:05 +04:00
|
|
|
|
// Ensure we have correct alignment for pointers. Important for Tru64
|
|
|
|
|
aSize = PR_ROUNDUP(aSize, sizeof(void*));
|
1999-12-07 07:36:08 +03:00
|
|
|
|
|
|
|
|
|
// See if it's a size that we recycle
|
|
|
|
|
if (aSize < gMaxRecycledSize) {
|
|
|
|
|
const int index = aSize >> 2;
|
|
|
|
|
void* currentTop = mRecyclers[index];
|
|
|
|
|
mRecyclers[index] = aPtr;
|
|
|
|
|
*((void**)aPtr) = currentTop;
|
|
|
|
|
}
|
2003-02-22 22:26:30 +03:00
|
|
|
|
#ifdef DEBUG_dbaron
|
|
|
|
|
else {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"WARNING: FrameArena::FreeFrame leaking chunk of %d bytes.\n",
|
|
|
|
|
aSize);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2001-12-21 03:16:26 +03:00
|
|
|
|
#endif
|
1999-12-07 07:36:08 +03:00
|
|
|
|
}
|
|
|
|
|
|
1999-10-15 08:29:30 +04:00
|
|
|
|
class PresShellViewEventListener : public nsIScrollPositionListener,
|
|
|
|
|
public nsICompositeListener
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
PresShellViewEventListener();
|
|
|
|
|
virtual ~PresShellViewEventListener();
|
|
|
|
|
|
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
|
|
|
|
|
|
// nsIScrollPositionListener methods
|
|
|
|
|
NS_IMETHOD ScrollPositionWillChange(nsIScrollableView *aView, nscoord aX, nscoord aY);
|
|
|
|
|
NS_IMETHOD ScrollPositionDidChange(nsIScrollableView *aView, nscoord aX, nscoord aY);
|
|
|
|
|
|
|
|
|
|
// nsICompositeListener methods
|
2003-03-12 06:22:11 +03:00
|
|
|
|
NS_IMETHOD WillRefreshRegion(nsIViewManager *aViewManager,
|
1999-10-15 08:29:30 +04:00
|
|
|
|
nsIView *aView,
|
|
|
|
|
nsIRenderingContext *aContext,
|
|
|
|
|
nsIRegion *aRegion,
|
|
|
|
|
PRUint32 aUpdateFlags);
|
|
|
|
|
|
2003-03-12 06:22:11 +03:00
|
|
|
|
NS_IMETHOD DidRefreshRegion(nsIViewManager *aViewManager,
|
1999-10-15 08:29:30 +04:00
|
|
|
|
nsIView *aView,
|
|
|
|
|
nsIRenderingContext *aContext,
|
|
|
|
|
nsIRegion *aRegion,
|
|
|
|
|
PRUint32 aUpdateFlags);
|
|
|
|
|
|
2003-03-12 06:22:11 +03:00
|
|
|
|
NS_IMETHOD WillRefreshRect(nsIViewManager *aViewManager,
|
1999-10-15 08:29:30 +04:00
|
|
|
|
nsIView *aView,
|
|
|
|
|
nsIRenderingContext *aContext,
|
|
|
|
|
const nsRect *aRect,
|
|
|
|
|
PRUint32 aUpdateFlags);
|
|
|
|
|
|
2003-03-12 06:22:11 +03:00
|
|
|
|
NS_IMETHOD DidRefreshRect(nsIViewManager *aViewManager,
|
1999-10-15 08:29:30 +04:00
|
|
|
|
nsIView *aView,
|
|
|
|
|
nsIRenderingContext *aContext,
|
|
|
|
|
const nsRect *aRect,
|
|
|
|
|
PRUint32 aUpdateFlags);
|
|
|
|
|
|
|
|
|
|
nsresult SetPresShell(nsIPresShell *aPresShell);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
nsresult HideCaret();
|
|
|
|
|
nsresult RestoreCaretVisibility();
|
|
|
|
|
|
|
|
|
|
nsIPresShell *mPresShell;
|
|
|
|
|
PRBool mWasVisible;
|
|
|
|
|
PRInt32 mCallCount;
|
|
|
|
|
};
|
|
|
|
|
|
2000-06-23 09:15:04 +04:00
|
|
|
|
struct nsDOMEventRequest
|
|
|
|
|
{
|
|
|
|
|
nsIContent* content;
|
|
|
|
|
nsEvent* event;
|
|
|
|
|
nsDOMEventRequest* next;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct nsAttributeChangeRequest
|
|
|
|
|
{
|
|
|
|
|
nsIContent* content;
|
|
|
|
|
PRInt32 nameSpaceID;
|
|
|
|
|
nsIAtom* name;
|
|
|
|
|
nsAutoString value;
|
|
|
|
|
PRBool notify;
|
|
|
|
|
nsAttributeChangeType type;
|
|
|
|
|
nsAttributeChangeRequest* next;
|
|
|
|
|
};
|
|
|
|
|
|
2000-07-14 03:00:59 +04:00
|
|
|
|
struct nsCallbackEventRequest
|
|
|
|
|
{
|
|
|
|
|
nsIReflowCallback* callback;
|
|
|
|
|
nsCallbackEventRequest* next;
|
|
|
|
|
};
|
|
|
|
|
|
2000-09-12 04:35:11 +04:00
|
|
|
|
|
2001-10-23 02:43:52 +04:00
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
2002-05-10 22:22:41 +04:00
|
|
|
|
/**
|
|
|
|
|
* Used to build and maintain the incremental reflow tree, and
|
|
|
|
|
* dispatch incremental reflows to individual reflow roots.
|
|
|
|
|
*/
|
|
|
|
|
class IncrementalReflow
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
~IncrementalReflow();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add a reflow command to the set of commands that are to be
|
2004-01-10 22:12:23 +03:00
|
|
|
|
* dispatched in the incremental reflow.
|
2002-05-10 22:22:41 +04:00
|
|
|
|
*/
|
2004-01-10 22:12:23 +03:00
|
|
|
|
enum AddCommandResult {
|
|
|
|
|
eEnqueued, // the command was successfully added
|
|
|
|
|
eTryLater, // the command could not be added; try again
|
|
|
|
|
eCancel, // the command was not added; delete it
|
|
|
|
|
eOOM // Out of memory.
|
|
|
|
|
};
|
|
|
|
|
AddCommandResult
|
2004-08-01 03:15:21 +04:00
|
|
|
|
AddCommand(nsPresContext *aPresContext,
|
2002-05-10 22:22:41 +04:00
|
|
|
|
nsHTMLReflowCommand *aCommand);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Dispatch the incremental reflow.
|
|
|
|
|
*/
|
|
|
|
|
void
|
2004-08-01 03:15:21 +04:00
|
|
|
|
Dispatch(nsPresContext *aPresContext,
|
2002-05-10 22:22:41 +04:00
|
|
|
|
nsHTMLReflowMetrics &aDesiredSize,
|
|
|
|
|
const nsSize &aMaxSize,
|
|
|
|
|
nsIRenderingContext &aRendContext);
|
|
|
|
|
|
|
|
|
|
#ifdef NS_DEBUG
|
|
|
|
|
/**
|
|
|
|
|
* Dump the incremental reflow state.
|
|
|
|
|
*/
|
|
|
|
|
void
|
2004-08-01 03:15:21 +04:00
|
|
|
|
Dump(nsPresContext *aPresContext) const;
|
2002-05-10 22:22:41 +04:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
/**
|
|
|
|
|
* The set of incremental reflow roots.
|
|
|
|
|
*/
|
|
|
|
|
nsAutoVoidArray mRoots;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
IncrementalReflow::~IncrementalReflow()
|
|
|
|
|
{
|
|
|
|
|
for (PRInt32 i = mRoots.Count() - 1; i >= 0; --i)
|
|
|
|
|
delete NS_STATIC_CAST(nsReflowPath *, mRoots[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2004-08-01 03:15:21 +04:00
|
|
|
|
IncrementalReflow::Dispatch(nsPresContext *aPresContext,
|
2002-05-10 22:22:41 +04:00
|
|
|
|
nsHTMLReflowMetrics &aDesiredSize,
|
|
|
|
|
const nsSize &aMaxSize,
|
|
|
|
|
nsIRenderingContext &aRendContext)
|
|
|
|
|
{
|
|
|
|
|
for (PRInt32 i = mRoots.Count() - 1; i >= 0; --i) {
|
|
|
|
|
// Send an incremental reflow notification to the first frame in the
|
|
|
|
|
// path.
|
|
|
|
|
nsReflowPath *path = NS_STATIC_CAST(nsReflowPath *, mRoots[i]);
|
|
|
|
|
nsIFrame *first = path->mFrame;
|
|
|
|
|
|
2004-09-02 07:08:51 +04:00
|
|
|
|
nsIFrame* root = aPresContext->PresShell()->FrameManager()->GetRootFrame();
|
2002-05-10 22:22:41 +04:00
|
|
|
|
|
|
|
|
|
first->WillReflow(aPresContext);
|
2004-12-27 18:05:18 +03:00
|
|
|
|
nsContainerFrame::PositionFrameView(first);
|
2002-05-10 22:22:41 +04:00
|
|
|
|
|
|
|
|
|
// If the first frame in the path is the root of the frame
|
|
|
|
|
// hierarchy, then use all the available space. If it's simply a
|
|
|
|
|
// `reflow root', then use the first frame's size as the available
|
|
|
|
|
// space.
|
|
|
|
|
nsSize size;
|
|
|
|
|
if (first == root)
|
|
|
|
|
size = aMaxSize;
|
|
|
|
|
else
|
2003-06-30 14:46:59 +04:00
|
|
|
|
size = first->GetSize();
|
2002-05-10 22:22:41 +04:00
|
|
|
|
|
|
|
|
|
nsHTMLReflowState reflowState(aPresContext, first, path,
|
|
|
|
|
&aRendContext, size);
|
|
|
|
|
|
|
|
|
|
nsReflowStatus status;
|
|
|
|
|
first->Reflow(aPresContext, aDesiredSize, reflowState, status);
|
|
|
|
|
|
|
|
|
|
// If an incremental reflow is initiated at a frame other than the
|
|
|
|
|
// root frame, then its desired size had better not change!
|
|
|
|
|
NS_ASSERTION(first == root ||
|
|
|
|
|
(aDesiredSize.width == size.width && aDesiredSize.height == size.height),
|
|
|
|
|
"non-root frame's desired size changed during an incremental reflow");
|
|
|
|
|
|
2003-06-30 14:46:59 +04:00
|
|
|
|
first->SetSize(nsSize(aDesiredSize.width, aDesiredSize.height));
|
2002-05-10 22:22:41 +04:00
|
|
|
|
|
2004-07-16 20:56:21 +04:00
|
|
|
|
nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, first, first->GetView(),
|
|
|
|
|
&aDesiredSize.mOverflowArea);
|
2002-05-10 22:22:41 +04:00
|
|
|
|
|
|
|
|
|
first->DidReflow(aPresContext, nsnull, NS_FRAME_REFLOW_FINISHED);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-10 22:12:23 +03:00
|
|
|
|
IncrementalReflow::AddCommandResult
|
2004-08-01 03:15:21 +04:00
|
|
|
|
IncrementalReflow::AddCommand(nsPresContext *aPresContext,
|
2002-05-10 22:22:41 +04:00
|
|
|
|
nsHTMLReflowCommand *aCommand)
|
|
|
|
|
{
|
|
|
|
|
nsIFrame *frame;
|
|
|
|
|
aCommand->GetTarget(frame);
|
|
|
|
|
NS_ASSERTION(frame != nsnull, "reflow command with no target");
|
|
|
|
|
|
|
|
|
|
// Construct the reflow path by walking up the through the frames'
|
|
|
|
|
// parent chain until we reach either a `reflow root' or the root
|
|
|
|
|
// frame in the frame hierarchy.
|
|
|
|
|
nsAutoVoidArray path;
|
|
|
|
|
do {
|
|
|
|
|
path.AppendElement(frame);
|
2003-06-30 14:46:59 +04:00
|
|
|
|
} while (!(frame->GetStateBits() & NS_FRAME_REFLOW_ROOT) &&
|
|
|
|
|
(frame = frame->GetParent()) != nsnull);
|
2002-05-10 22:22:41 +04:00
|
|
|
|
|
|
|
|
|
// Pop off the root, add it to the set if it's not there already.
|
|
|
|
|
PRInt32 lastIndex = path.Count() - 1;
|
|
|
|
|
nsIFrame *rootFrame = NS_STATIC_CAST(nsIFrame *, path[lastIndex]);
|
|
|
|
|
path.RemoveElementAt(lastIndex);
|
|
|
|
|
|
2004-01-10 22:12:23 +03:00
|
|
|
|
// Prevent an incremental reflow from being posted inside a reflow
|
|
|
|
|
// root if the reflow root's container has not yet been reflowed.
|
|
|
|
|
// This can cause problems like bug 228156.
|
|
|
|
|
if (rootFrame->GetParent() &&
|
|
|
|
|
(rootFrame->GetParent()->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
|
|
|
|
|
return eCancel;
|
|
|
|
|
}
|
|
|
|
|
|
2002-05-10 22:22:41 +04:00
|
|
|
|
nsReflowPath *root = nsnull;
|
|
|
|
|
|
|
|
|
|
PRInt32 i;
|
|
|
|
|
for (i = mRoots.Count() - 1; i >= 0; --i) {
|
2004-01-10 22:12:23 +03:00
|
|
|
|
nsReflowPath *r = NS_STATIC_CAST(nsReflowPath *, mRoots[i]);
|
|
|
|
|
if (r->mFrame == rootFrame) {
|
|
|
|
|
root = r;
|
2002-05-10 22:22:41 +04:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! root) {
|
|
|
|
|
root = new nsReflowPath(rootFrame);
|
|
|
|
|
if (! root)
|
2004-01-10 22:12:23 +03:00
|
|
|
|
return eOOM;
|
2002-05-10 22:22:41 +04:00
|
|
|
|
|
|
|
|
|
root->mReflowCommand = nsnull;
|
|
|
|
|
mRoots.AppendElement(root);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now walk the path from the root to the leaf, adding to the reflow
|
|
|
|
|
// tree as necessary.
|
|
|
|
|
nsReflowPath *target = root;
|
|
|
|
|
for (i = path.Count() - 1; i >= 0; --i) {
|
2004-01-10 22:12:23 +03:00
|
|
|
|
nsIFrame *f = NS_STATIC_CAST(nsIFrame *, path[i]);
|
|
|
|
|
target = target->EnsureSubtreeFor(f);
|
2002-05-10 22:22:41 +04:00
|
|
|
|
|
|
|
|
|
// Out of memory. Ugh.
|
|
|
|
|
if (! target)
|
2004-01-10 22:12:23 +03:00
|
|
|
|
return eOOM;
|
2002-05-10 22:22:41 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Place the reflow command in the leaf, if one isn't there already.
|
|
|
|
|
if (target->mReflowCommand) {
|
|
|
|
|
// XXXwaterson it's probably possible to have some notion of
|
|
|
|
|
// `promotion' here that would avoid any re-queuing; for example,
|
|
|
|
|
// promote a dirty reflow to a style changed. For now, let's punt
|
|
|
|
|
// and not worry about it.
|
|
|
|
|
#ifdef NS_DEBUG
|
|
|
|
|
if (gVerifyReflowFlags & VERIFY_REFLOW_NOISY_RC)
|
|
|
|
|
printf("requeuing command %p because %p was already scheduled "
|
|
|
|
|
"for the same frame",
|
2002-08-24 18:41:28 +04:00
|
|
|
|
(void*)aCommand, (void*)target->mReflowCommand);
|
2002-05-10 22:22:41 +04:00
|
|
|
|
#endif
|
|
|
|
|
|
2004-01-10 22:12:23 +03:00
|
|
|
|
return eTryLater;
|
2002-05-10 22:22:41 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
target->mReflowCommand = aCommand;
|
2004-01-10 22:12:23 +03:00
|
|
|
|
return eEnqueued;
|
2002-05-10 22:22:41 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef NS_DEBUG
|
|
|
|
|
void
|
2004-08-01 03:15:21 +04:00
|
|
|
|
IncrementalReflow::Dump(nsPresContext *aPresContext) const
|
2002-05-10 22:22:41 +04:00
|
|
|
|
{
|
|
|
|
|
for (PRInt32 i = mRoots.Count() - 1; i >= 0; --i)
|
|
|
|
|
NS_STATIC_CAST(nsReflowPath *, mRoots[i])->Dump(aPresContext, stdout, 0);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
2004-05-02 22:07:12 +04:00
|
|
|
|
struct ReflowCommandEntry : public PLDHashEntryHdr
|
|
|
|
|
{
|
|
|
|
|
nsHTMLReflowCommand* mCommand;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
PR_STATIC_CALLBACK(const void *)
|
|
|
|
|
ReflowCommandHashGetKey(PLDHashTable *table, PLDHashEntryHdr *entry)
|
|
|
|
|
{
|
|
|
|
|
ReflowCommandEntry *e = NS_STATIC_CAST(ReflowCommandEntry *, entry);
|
|
|
|
|
|
|
|
|
|
return e->mCommand;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PR_STATIC_CALLBACK(PLDHashNumber)
|
|
|
|
|
ReflowCommandHashHashKey(PLDHashTable *table, const void *key)
|
|
|
|
|
{
|
|
|
|
|
const nsHTMLReflowCommand* command =
|
|
|
|
|
NS_STATIC_CAST(const nsHTMLReflowCommand*, key);
|
|
|
|
|
|
2004-05-02 23:56:06 +04:00
|
|
|
|
// The target is going to be reasonably unique, if we shift out the
|
|
|
|
|
// always-zero low-order bits, the type comes from an enum and we just don't
|
|
|
|
|
// have that many types, and the child list name is either null or has the
|
|
|
|
|
// same high-order bits as all the other child list names.
|
2004-05-02 22:07:12 +04:00
|
|
|
|
return
|
2004-05-02 23:56:06 +04:00
|
|
|
|
(NS_PTR_TO_INT32(command->GetTarget()) >> 2) ^
|
2005-02-08 03:59:52 +03:00
|
|
|
|
(command->Type() << 17) ^
|
2004-05-02 22:07:12 +04:00
|
|
|
|
(NS_PTR_TO_INT32(command->GetChildListName()) << 20);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PR_STATIC_CALLBACK(PRBool)
|
|
|
|
|
ReflowCommandHashMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *entry,
|
|
|
|
|
const void *key)
|
|
|
|
|
{
|
|
|
|
|
const ReflowCommandEntry *e =
|
|
|
|
|
NS_STATIC_CAST(const ReflowCommandEntry *, entry);
|
|
|
|
|
const nsHTMLReflowCommand *command = e->mCommand;
|
|
|
|
|
const nsHTMLReflowCommand *command2 =
|
|
|
|
|
NS_STATIC_CAST(const nsHTMLReflowCommand *, key);
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
command->GetTarget() == command2->GetTarget() &&
|
2005-02-08 03:59:52 +03:00
|
|
|
|
command->Type() == command2->Type() &&
|
2004-05-02 22:07:12 +04:00
|
|
|
|
command->GetChildListName() == command2->GetChildListName();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2006-03-07 20:08:51 +03:00
|
|
|
|
class nsPresShellEventCB;
|
2004-05-02 22:07:12 +04:00
|
|
|
|
|
1998-08-28 06:54:06 +04:00
|
|
|
|
class PresShell : public nsIPresShell, public nsIViewObserver,
|
2004-09-01 09:16:00 +04:00
|
|
|
|
public nsStubDocumentObserver,
|
2004-07-18 05:16:27 +04:00
|
|
|
|
public nsISelectionController, public nsIObserver,
|
1999-10-22 04:19:18 +04:00
|
|
|
|
public nsSupportsWeakReference
|
1998-08-28 06:54:06 +04:00
|
|
|
|
{
|
1998-04-14 00:24:54 +04:00
|
|
|
|
public:
|
|
|
|
|
PresShell();
|
|
|
|
|
|
1999-02-26 23:02:06 +03:00
|
|
|
|
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
|
1999-02-26 20:08:48 +03:00
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
|
// nsISupports
|
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
|
|
|
|
|
|
// nsIPresShell
|
1998-06-03 19:46:54 +04:00
|
|
|
|
NS_IMETHOD Init(nsIDocument* aDocument,
|
2004-08-01 03:15:21 +04:00
|
|
|
|
nsPresContext* aPresContext,
|
1998-06-03 19:46:54 +04:00
|
|
|
|
nsIViewManager* aViewManager,
|
2004-01-08 01:30:53 +03:00
|
|
|
|
nsStyleSet* aStyleSet,
|
2002-06-26 01:16:17 +04:00
|
|
|
|
nsCompatibility aCompatMode);
|
2001-08-01 07:15:50 +04:00
|
|
|
|
NS_IMETHOD Destroy();
|
1999-12-05 02:49:50 +03:00
|
|
|
|
|
2004-04-13 04:28:44 +04:00
|
|
|
|
virtual NS_HIDDEN_(void*) AllocateFrame(size_t aSize);
|
|
|
|
|
virtual NS_HIDDEN_(void) FreeFrame(size_t aSize, void* aFreeChunk);
|
2000-03-31 11:02:06 +04:00
|
|
|
|
|
|
|
|
|
// Dynamic stack memory allocation
|
|
|
|
|
NS_IMETHOD PushStackMemory();
|
|
|
|
|
NS_IMETHOD PopStackMemory();
|
|
|
|
|
NS_IMETHOD AllocateStackMemory(size_t aSize, void** aResult);
|
|
|
|
|
|
1999-01-23 10:03:46 +03:00
|
|
|
|
NS_IMETHOD GetActiveAlternateStyleSheet(nsString& aSheetTitle);
|
|
|
|
|
NS_IMETHOD SelectAlternateStyleSheet(const nsString& aSheetTitle);
|
|
|
|
|
NS_IMETHOD ListAlternateStyleSheets(nsStringArray& aTitleList);
|
2000-12-16 02:48:55 +03:00
|
|
|
|
NS_IMETHOD SetPreferenceStyleRules(PRBool aForceReflow);
|
2006-04-26 06:01:07 +04:00
|
|
|
|
|
2002-08-27 00:55:30 +04:00
|
|
|
|
NS_IMETHOD GetSelection(SelectionType aType, nsISelection** aSelection);
|
2006-04-26 06:01:07 +04:00
|
|
|
|
virtual nsISelection* GetCurrentSelection(SelectionType aType);
|
2002-08-27 00:55:30 +04:00
|
|
|
|
|
2000-04-28 10:21:31 +04:00
|
|
|
|
NS_IMETHOD SetDisplaySelection(PRInt16 aToggle);
|
|
|
|
|
NS_IMETHOD GetDisplaySelection(PRInt16 *aToggle);
|
2002-06-14 00:35:12 +04:00
|
|
|
|
NS_IMETHOD ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion, PRBool aIsSynchronous);
|
1999-08-31 01:54:40 +04:00
|
|
|
|
NS_IMETHOD RepaintSelection(SelectionType aType);
|
1999-11-09 06:23:26 +03:00
|
|
|
|
|
1998-12-29 07:56:31 +03:00
|
|
|
|
NS_IMETHOD BeginObservingDocument();
|
|
|
|
|
NS_IMETHOD EndObservingDocument();
|
2002-09-06 09:44:31 +04:00
|
|
|
|
NS_IMETHOD GetDidInitialReflow(PRBool *aDidInitialReflow);
|
1998-09-10 23:32:14 +04:00
|
|
|
|
NS_IMETHOD InitialReflow(nscoord aWidth, nscoord aHeight);
|
1998-08-28 06:54:06 +04:00
|
|
|
|
NS_IMETHOD ResizeReflow(nscoord aWidth, nscoord aHeight);
|
1998-11-06 19:16:01 +03:00
|
|
|
|
NS_IMETHOD StyleChangeReflow();
|
1999-02-12 20:45:58 +03:00
|
|
|
|
NS_IMETHOD GetPageSequenceFrame(nsIPageSequenceFrame** aResult) const;
|
2005-08-23 02:24:29 +04:00
|
|
|
|
virtual NS_HIDDEN_(nsIFrame*) GetPrimaryFrameFor(nsIContent* aContent) const;
|
2002-08-27 00:55:30 +04:00
|
|
|
|
|
1999-02-11 02:21:22 +03:00
|
|
|
|
NS_IMETHOD GetLayoutObjectFor(nsIContent* aContent,
|
|
|
|
|
nsISupports** aResult) const;
|
1998-12-29 06:38:16 +03:00
|
|
|
|
NS_IMETHOD GetPlaceholderFrameFor(nsIFrame* aFrame,
|
1999-02-12 20:45:58 +03:00
|
|
|
|
nsIFrame** aPlaceholderFrame) const;
|
2005-02-08 03:59:52 +03:00
|
|
|
|
NS_IMETHOD AppendReflowCommand(nsIFrame* aTargetFrame,
|
|
|
|
|
nsReflowType aReflowType,
|
|
|
|
|
nsIAtom* aChildListName);
|
|
|
|
|
NS_IMETHOD CancelReflowCommand(nsIFrame* aTargetFrame,
|
2001-12-18 01:39:59 +03:00
|
|
|
|
nsReflowType* aCmdType);
|
2005-08-23 05:29:02 +04:00
|
|
|
|
void CancelReflowCommandInternal(nsIFrame* aTargetFrame,
|
|
|
|
|
nsReflowType* aCmdType);
|
2000-09-20 11:20:23 +04:00
|
|
|
|
NS_IMETHOD CancelAllReflowCommands();
|
2000-10-17 09:07:39 +04:00
|
|
|
|
NS_IMETHOD IsSafeToFlush(PRBool& aIsSafeToFlush);
|
2004-05-28 02:08:42 +04:00
|
|
|
|
NS_IMETHOD FlushPendingNotifications(mozFlushType aType);
|
2000-04-17 11:13:57 +04:00
|
|
|
|
|
2002-10-22 10:07:52 +04:00
|
|
|
|
/**
|
|
|
|
|
* Recreates the frames for a node
|
|
|
|
|
*/
|
|
|
|
|
NS_IMETHOD RecreateFramesFor(nsIContent* aContent);
|
|
|
|
|
|
2000-06-23 09:15:04 +04:00
|
|
|
|
/**
|
|
|
|
|
* Post a request to handle a DOM event after Reflow has finished.
|
|
|
|
|
*/
|
|
|
|
|
NS_IMETHOD PostDOMEvent(nsIContent* aContent, nsEvent* aEvent);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Post a request to set and attribute after reflow has finished.
|
|
|
|
|
*/
|
|
|
|
|
NS_IMETHOD PostAttributeChange(nsIContent* aContent,
|
|
|
|
|
PRInt32 aNameSpaceID,
|
|
|
|
|
nsIAtom* aName,
|
|
|
|
|
const nsString& aValue,
|
|
|
|
|
PRBool aNotify,
|
|
|
|
|
nsAttributeChangeType aType);
|
2000-07-14 03:00:59 +04:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Post a callback that should be handled after reflow has finished.
|
|
|
|
|
*/
|
|
|
|
|
NS_IMETHOD PostReflowCallback(nsIReflowCallback* aCallback);
|
2000-10-07 04:49:08 +04:00
|
|
|
|
NS_IMETHOD CancelReflowCallback(nsIReflowCallback* aCallback);
|
2000-07-14 03:00:59 +04:00
|
|
|
|
|
2000-04-17 11:13:57 +04:00
|
|
|
|
/**
|
|
|
|
|
* Reflow batching
|
|
|
|
|
*/
|
|
|
|
|
NS_IMETHOD BeginReflowBatching();
|
|
|
|
|
NS_IMETHOD EndReflowBatching(PRBool aFlushPendingReflows);
|
|
|
|
|
NS_IMETHOD GetReflowBatchingStatus(PRBool* aBatch);
|
|
|
|
|
|
1999-02-12 20:45:58 +03:00
|
|
|
|
NS_IMETHOD ClearFrameRefs(nsIFrame* aFrame);
|
|
|
|
|
NS_IMETHOD CreateRenderingContext(nsIFrame *aFrame,
|
|
|
|
|
nsIRenderingContext** aContext);
|
2003-01-14 02:10:53 +03:00
|
|
|
|
NS_IMETHOD GoToAnchor(const nsAString& aAnchorName, PRBool aScroll);
|
1998-08-28 06:54:06 +04:00
|
|
|
|
|
1999-02-19 01:52:21 +03:00
|
|
|
|
NS_IMETHOD ScrollFrameIntoView(nsIFrame *aFrame,
|
1999-07-19 22:38:33 +04:00
|
|
|
|
PRIntn aVPercent,
|
|
|
|
|
PRIntn aHPercent) const;
|
1999-04-07 07:56:07 +04:00
|
|
|
|
|
2001-12-01 03:22:00 +03:00
|
|
|
|
NS_IMETHOD SetIgnoreFrameDestruction(PRBool aIgnore);
|
1999-07-17 03:27:46 +04:00
|
|
|
|
NS_IMETHOD NotifyDestroyingFrame(nsIFrame* aFrame);
|
1999-08-04 08:02:40 +04:00
|
|
|
|
|
1999-04-07 07:56:07 +04:00
|
|
|
|
NS_IMETHOD DoCopy();
|
2005-08-29 19:19:13 +04:00
|
|
|
|
NS_IMETHOD GetSelectionForCopy(nsISelection** outSelection);
|
|
|
|
|
|
2002-08-02 01:36:02 +04:00
|
|
|
|
NS_IMETHOD GetLinkLocation(nsIDOMNode* aNode, nsAString& aLocationString);
|
2003-04-22 22:11:12 +04:00
|
|
|
|
NS_IMETHOD DoGetContents(const nsACString& aMimeType, PRUint32 aFlags, PRBool aSelectionOnly, nsAString& outValue);
|
1999-08-31 18:35:50 +04:00
|
|
|
|
|
2000-06-15 04:35:46 +04:00
|
|
|
|
NS_IMETHOD CaptureHistoryState(nsILayoutHistoryState** aLayoutHistoryState, PRBool aLeavingPage);
|
1999-08-31 02:38:58 +04:00
|
|
|
|
|
2000-03-23 03:34:54 +03:00
|
|
|
|
NS_IMETHOD GetGeneratedContentIterator(nsIContent* aContent,
|
|
|
|
|
GeneratedContentType aType,
|
|
|
|
|
nsIContentIterator** aIterator) const;
|
2000-04-24 08:41:27 +04:00
|
|
|
|
|
2000-10-09 07:08:41 +04:00
|
|
|
|
NS_IMETHOD SetAnonymousContentFor(nsIContent* aContent, nsISupportsArray* aAnonymousElements);
|
|
|
|
|
NS_IMETHOD GetAnonymousContentFor(nsIContent* aContent, nsISupportsArray** aAnonymousElements);
|
|
|
|
|
NS_IMETHOD ReleaseAnonymousContent();
|
|
|
|
|
|
2001-04-25 23:52:49 +04:00
|
|
|
|
NS_IMETHOD IsPaintingSuppressed(PRBool* aResult);
|
2001-05-02 02:54:11 +04:00
|
|
|
|
NS_IMETHOD UnsuppressPainting();
|
|
|
|
|
|
2002-09-21 05:03:38 +04:00
|
|
|
|
NS_IMETHOD DisableThemeSupport();
|
|
|
|
|
virtual PRBool IsThemeSupportEnabled();
|
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
|
virtual nsresult GetAgentStyleSheets(nsCOMArray<nsIStyleSheet>& aSheets);
|
|
|
|
|
virtual nsresult SetAgentStyleSheets(const nsCOMArray<nsIStyleSheet>& aSheets);
|
|
|
|
|
|
|
|
|
|
virtual nsresult AddOverrideStyleSheet(nsIStyleSheet *aSheet);
|
|
|
|
|
virtual nsresult RemoveOverrideStyleSheet(nsIStyleSheet *aSheet);
|
|
|
|
|
|
2006-03-07 20:08:51 +03:00
|
|
|
|
NS_IMETHOD HandleEventWithTarget(nsEvent* aEvent, nsIFrame* aFrame,
|
|
|
|
|
nsIContent* aContent,
|
|
|
|
|
nsEventStatus* aStatus);
|
2000-06-24 07:58:13 +04:00
|
|
|
|
NS_IMETHOD GetEventTargetFrame(nsIFrame** aFrame);
|
2003-02-15 00:43:06 +03:00
|
|
|
|
NS_IMETHOD GetEventTargetContent(nsEvent* aEvent, nsIContent** aContent);
|
2000-03-23 03:34:54 +03:00
|
|
|
|
|
2000-02-09 18:48:01 +03:00
|
|
|
|
NS_IMETHOD IsReflowLocked(PRBool* aIsLocked);
|
2004-01-22 02:05:10 +03:00
|
|
|
|
|
|
|
|
|
virtual nsresult ReconstructFrames(void);
|
2005-05-05 00:22:32 +04:00
|
|
|
|
virtual void Freeze();
|
2005-07-19 21:07:40 +04:00
|
|
|
|
virtual void Thaw();
|
2006-01-26 05:29:17 +03:00
|
|
|
|
|
|
|
|
|
NS_IMETHOD RenderOffscreen(nsRect aRect, PRBool aUntrusted,
|
|
|
|
|
PRBool aIgnoreViewportScrolling,
|
|
|
|
|
nscolor aBackgroundColor,
|
|
|
|
|
nsIRenderingContext** aRenderedContext);
|
2004-01-22 02:05:10 +03:00
|
|
|
|
|
2001-03-09 06:29:00 +03:00
|
|
|
|
#ifdef IBMBIDI
|
2001-10-01 00:35:55 +04:00
|
|
|
|
NS_IMETHOD SetCaretBidiLevel(PRUint8 aLevel);
|
|
|
|
|
NS_IMETHOD GetCaretBidiLevel(PRUint8 *aOutLevel);
|
|
|
|
|
NS_IMETHOD UndefineCaretBidiLevel();
|
2001-03-09 06:29:00 +03:00
|
|
|
|
NS_IMETHOD BidiStyleChangeReflow();
|
|
|
|
|
#endif
|
2000-01-28 03:48:02 +03:00
|
|
|
|
|
1998-08-28 06:54:06 +04:00
|
|
|
|
//nsIViewObserver interface
|
|
|
|
|
|
|
|
|
|
NS_IMETHOD Paint(nsIView *aView,
|
2006-01-26 05:29:17 +03:00
|
|
|
|
nsIRenderingContext* aRenderingContext,
|
|
|
|
|
const nsRegion& aDirtyRegion);
|
|
|
|
|
NS_IMETHOD ComputeRepaintRegionForCopy(nsIView* aRootView,
|
|
|
|
|
nsIView* aMovingView,
|
|
|
|
|
nsPoint aDelta,
|
|
|
|
|
const nsRect& aCopyRect,
|
|
|
|
|
nsRegion* aRepaintRegion);
|
1998-08-28 06:54:06 +04:00
|
|
|
|
NS_IMETHOD HandleEvent(nsIView* aView,
|
|
|
|
|
nsGUIEvent* aEvent,
|
2006-01-26 05:29:17 +03:00
|
|
|
|
nsEventStatus* aEventStatus);
|
2000-06-29 06:02:43 +04:00
|
|
|
|
NS_IMETHOD HandleDOMEventWithTarget(nsIContent* aTargetContent,
|
2006-03-07 20:08:51 +03:00
|
|
|
|
nsEvent* aEvent,
|
|
|
|
|
nsEventStatus* aStatus);
|
1998-08-28 06:54:06 +04:00
|
|
|
|
NS_IMETHOD ResizeReflow(nsIView *aView, nscoord aWidth, nscoord aHeight);
|
2004-10-15 01:51:00 +04:00
|
|
|
|
NS_IMETHOD_(PRBool) IsVisible();
|
2005-01-20 06:39:09 +03:00
|
|
|
|
NS_IMETHOD_(void) WillPaint();
|
1998-08-28 06:54:06 +04:00
|
|
|
|
|
1999-02-13 07:45:44 +03:00
|
|
|
|
// caret handling
|
1999-08-05 00:46:16 +04:00
|
|
|
|
NS_IMETHOD GetCaret(nsICaret **aOutCaret);
|
2000-05-11 08:25:43 +04:00
|
|
|
|
NS_IMETHOD SetCaretEnabled(PRBool aInEnable);
|
|
|
|
|
NS_IMETHOD SetCaretReadOnly(PRBool aReadOnly);
|
1999-08-05 00:46:16 +04:00
|
|
|
|
NS_IMETHOD GetCaretEnabled(PRBool *aOutEnabled);
|
2003-06-25 05:14:25 +04:00
|
|
|
|
NS_IMETHOD SetCaretVisibilityDuringSelection(PRBool aVisibility);
|
2006-04-18 03:16:46 +04:00
|
|
|
|
virtual already_AddRefed<nsICaret> SetCaret(nsICaret *aNewCaret);
|
1999-02-13 07:45:44 +03:00
|
|
|
|
|
2001-12-18 04:29:49 +03:00
|
|
|
|
NS_IMETHOD SetSelectionFlags(PRInt16 aInEnable);
|
|
|
|
|
NS_IMETHOD GetSelectionFlags(PRInt16 *aOutEnable);
|
1999-05-17 04:21:18 +04:00
|
|
|
|
|
1999-12-03 00:45:21 +03:00
|
|
|
|
// nsISelectionController
|
1999-10-22 04:19:18 +04:00
|
|
|
|
|
|
|
|
|
NS_IMETHOD CharacterMove(PRBool aForward, PRBool aExtend);
|
|
|
|
|
NS_IMETHOD WordMove(PRBool aForward, PRBool aExtend);
|
2006-07-18 11:28:38 +04:00
|
|
|
|
NS_IMETHOD WordExtendForDelete(PRBool aForward);
|
1999-10-22 04:19:18 +04:00
|
|
|
|
NS_IMETHOD LineMove(PRBool aForward, PRBool aExtend);
|
|
|
|
|
NS_IMETHOD IntraLineMove(PRBool aForward, PRBool aExtend);
|
|
|
|
|
NS_IMETHOD PageMove(PRBool aForward, PRBool aExtend);
|
|
|
|
|
NS_IMETHOD ScrollPage(PRBool aForward);
|
1999-12-15 06:54:52 +03:00
|
|
|
|
NS_IMETHOD ScrollLine(PRBool aForward);
|
|
|
|
|
NS_IMETHOD ScrollHorizontal(PRBool aLeft);
|
1999-12-11 03:02:08 +03:00
|
|
|
|
NS_IMETHOD CompleteScroll(PRBool aForward);
|
|
|
|
|
NS_IMETHOD CompleteMove(PRBool aForward, PRBool aExtend);
|
1999-10-22 04:19:18 +04:00
|
|
|
|
NS_IMETHOD SelectAll();
|
2000-07-26 15:31:12 +04:00
|
|
|
|
NS_IMETHOD CheckVisibility(nsIDOMNode *node, PRInt16 startOffset, PRInt16 EndOffset, PRBool *_retval);
|
1999-02-13 07:45:44 +03:00
|
|
|
|
|
1999-07-14 21:30:07 +04:00
|
|
|
|
// nsIDocumentObserver
|
2004-01-29 04:45:34 +03:00
|
|
|
|
virtual void BeginUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType);
|
|
|
|
|
virtual void EndUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType);
|
|
|
|
|
virtual void BeginLoad(nsIDocument* aDocument);
|
|
|
|
|
virtual void EndLoad(nsIDocument* aDocument);
|
2004-02-21 00:38:31 +03:00
|
|
|
|
virtual void CharacterDataChanged(nsIDocument* aDocument,
|
|
|
|
|
nsIContent* aContent,
|
|
|
|
|
PRBool aAppend);
|
2004-01-29 04:45:34 +03:00
|
|
|
|
virtual void ContentStatesChanged(nsIDocument* aDocument,
|
|
|
|
|
nsIContent* aContent1,
|
|
|
|
|
nsIContent* aContent2,
|
|
|
|
|
PRInt32 aStateMask);
|
2005-11-02 03:41:51 +03:00
|
|
|
|
virtual void AttributeChanged(nsIDocument* aDocument, nsIContent* aContent,
|
2004-01-29 04:45:34 +03:00
|
|
|
|
PRInt32 aNameSpaceID, nsIAtom* aAttribute,
|
|
|
|
|
PRInt32 aModType);
|
|
|
|
|
virtual void ContentAppended(nsIDocument* aDocument, nsIContent* aContainer,
|
|
|
|
|
PRInt32 aNewIndexInContainer);
|
|
|
|
|
virtual void ContentInserted(nsIDocument* aDocument, nsIContent* aContainer,
|
|
|
|
|
nsIContent* aChild, PRInt32 aIndexInContainer);
|
|
|
|
|
virtual void ContentRemoved(nsIDocument* aDocument, nsIContent* aContainer,
|
|
|
|
|
nsIContent* aChild, PRInt32 aIndexInContainer);
|
|
|
|
|
virtual void StyleSheetAdded(nsIDocument* aDocument,
|
2004-07-28 11:08:41 +04:00
|
|
|
|
nsIStyleSheet* aStyleSheet,
|
|
|
|
|
PRBool aDocumentSheet);
|
2004-01-29 04:45:34 +03:00
|
|
|
|
virtual void StyleSheetRemoved(nsIDocument* aDocument,
|
2004-07-28 11:08:41 +04:00
|
|
|
|
nsIStyleSheet* aStyleSheet,
|
|
|
|
|
PRBool aDocumentSheet);
|
2004-01-29 04:45:34 +03:00
|
|
|
|
virtual void StyleSheetApplicableStateChanged(nsIDocument* aDocument,
|
|
|
|
|
nsIStyleSheet* aStyleSheet,
|
|
|
|
|
PRBool aApplicable);
|
|
|
|
|
virtual void StyleRuleChanged(nsIDocument* aDocument,
|
|
|
|
|
nsIStyleSheet* aStyleSheet,
|
|
|
|
|
nsIStyleRule* aOldStyleRule,
|
|
|
|
|
nsIStyleRule* aNewStyleRule);
|
|
|
|
|
virtual void StyleRuleAdded(nsIDocument* aDocument,
|
|
|
|
|
nsIStyleSheet* aStyleSheet,
|
|
|
|
|
nsIStyleRule* aStyleRule);
|
|
|
|
|
virtual void StyleRuleRemoved(nsIDocument* aDocument,
|
|
|
|
|
nsIStyleSheet* aStyleSheet,
|
|
|
|
|
nsIStyleRule* aStyleRule);
|
1999-12-23 05:02:33 +03:00
|
|
|
|
|
2004-07-18 05:16:27 +04:00
|
|
|
|
NS_DECL_NSIOBSERVER
|
|
|
|
|
|
2000-04-21 18:59:47 +04:00
|
|
|
|
#ifdef MOZ_REFLOW_PERF
|
2000-04-29 03:32:04 +04:00
|
|
|
|
NS_IMETHOD DumpReflows();
|
2001-02-22 16:58:17 +03:00
|
|
|
|
NS_IMETHOD CountReflows(const char * aName, PRUint32 aType, nsIFrame * aFrame);
|
2004-08-01 03:15:21 +04:00
|
|
|
|
NS_IMETHOD PaintCount(const char * aName, nsIRenderingContext* aRenderingContext, nsPresContext* aPresContext, nsIFrame * aFrame, PRUint32 aColor);
|
2001-03-13 04:47:22 +03:00
|
|
|
|
|
|
|
|
|
NS_IMETHOD SetPaintFrameCount(PRBool aOn);
|
|
|
|
|
|
2000-04-21 18:59:47 +04:00
|
|
|
|
#endif
|
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
virtual void ListStyleContexts(nsIFrame *aRootFrame, FILE *out,
|
|
|
|
|
PRInt32 aIndent = 0);
|
|
|
|
|
|
|
|
|
|
virtual void ListStyleSheets(FILE *out, PRInt32 aIndent = 0);
|
2005-11-06 21:01:17 +03:00
|
|
|
|
virtual void VerifyStyleTree();
|
2004-01-08 01:30:53 +03:00
|
|
|
|
#endif
|
|
|
|
|
|
2001-04-11 07:07:50 +04:00
|
|
|
|
#ifdef PR_LOGGING
|
|
|
|
|
static PRLogModuleInfo* gLog;
|
|
|
|
|
#endif
|
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
|
protected:
|
1999-02-12 20:45:58 +03:00
|
|
|
|
virtual ~PresShell();
|
1998-04-14 00:24:54 +04:00
|
|
|
|
|
2000-06-23 09:15:04 +04:00
|
|
|
|
void HandlePostedDOMEvents();
|
|
|
|
|
void HandlePostedAttributeChanges();
|
2000-07-14 03:00:59 +04:00
|
|
|
|
void HandlePostedReflowCallbacks();
|
2000-06-23 09:15:04 +04:00
|
|
|
|
|
2001-04-25 23:52:49 +04:00
|
|
|
|
void UnsuppressAndInvalidate();
|
2000-05-15 07:37:21 +04:00
|
|
|
|
|
2001-12-18 01:39:59 +03:00
|
|
|
|
nsresult ReflowCommandAdded(nsHTMLReflowCommand* aRC);
|
|
|
|
|
nsresult ReflowCommandRemoved(nsHTMLReflowCommand* aRC);
|
2000-09-20 11:20:23 +04:00
|
|
|
|
|
2005-08-23 05:29:02 +04:00
|
|
|
|
// This method should be called after reflow commands have been
|
2001-03-14 10:47:00 +03:00
|
|
|
|
// removed from the queue, but after the state in the presshell is
|
|
|
|
|
// such that it's safe to flush (i.e. mIsReflowing == PR_FALSE)
|
2005-08-23 05:29:02 +04:00
|
|
|
|
// If there are no load-created reflow commands and we blocked
|
|
|
|
|
// onload on the document, we'll unblock it.
|
2001-03-14 10:47:00 +03:00
|
|
|
|
void DoneRemovingReflowCommands();
|
|
|
|
|
|
2005-01-20 06:39:09 +03:00
|
|
|
|
void WillCauseReflow() { ++mChangeNestCount; }
|
2000-04-17 11:13:57 +04:00
|
|
|
|
nsresult DidCauseReflow();
|
2006-04-28 08:33:41 +04:00
|
|
|
|
void WillDoReflow();
|
2004-02-04 03:11:59 +03:00
|
|
|
|
void DidDoReflow();
|
2000-04-17 11:13:57 +04:00
|
|
|
|
nsresult ProcessReflowCommands(PRBool aInterruptible);
|
2006-05-10 21:30:15 +04:00
|
|
|
|
void ClearReflowEventStatus();
|
2000-04-17 11:13:57 +04:00
|
|
|
|
void PostReflowEvent();
|
2004-05-02 22:07:12 +04:00
|
|
|
|
|
|
|
|
|
// Note: when PR_FALSE is returned, AlreadyInQueue assumes the command will
|
|
|
|
|
// in fact be added to the queue. If it's not, it needs to be removed from
|
|
|
|
|
// mReflowCommandTable (AlreadyInQueue will insert it in that table).
|
|
|
|
|
PRBool AlreadyInQueue(nsHTMLReflowCommand* aReflowCommand);
|
2002-08-27 00:55:30 +04:00
|
|
|
|
|
2006-03-07 20:08:51 +03:00
|
|
|
|
friend class nsPresShellEventCB;
|
1999-11-02 01:12:45 +03:00
|
|
|
|
|
2006-05-10 21:30:15 +04:00
|
|
|
|
class ReflowEvent;
|
|
|
|
|
friend class ReflowEvent;
|
|
|
|
|
|
|
|
|
|
class ReflowEvent : public nsRunnable {
|
|
|
|
|
public:
|
|
|
|
|
NS_DECL_NSIRUNNABLE
|
|
|
|
|
ReflowEvent(PresShell *aPresShell) : mPresShell(aPresShell) {
|
|
|
|
|
NS_ASSERTION(aPresShell, "Null parameters!");
|
|
|
|
|
}
|
|
|
|
|
void Revoke() { mPresShell = nsnull; }
|
|
|
|
|
private:
|
|
|
|
|
PresShell *mPresShell;
|
|
|
|
|
};
|
|
|
|
|
|
2004-08-06 19:55:17 +04:00
|
|
|
|
// Utility to determine if we're in the middle of a drag.
|
2000-06-15 03:18:54 +04:00
|
|
|
|
PRBool IsDragInProgress ( ) const ;
|
|
|
|
|
|
2004-08-06 19:55:17 +04:00
|
|
|
|
// Utility to find which view to scroll.
|
2004-09-21 08:41:08 +04:00
|
|
|
|
nsIScrollableView* GetViewToScroll(nsLayoutUtils::Direction aDirection);
|
2004-08-06 19:55:17 +04:00
|
|
|
|
|
2003-03-12 06:22:11 +03:00
|
|
|
|
PRBool mCaretEnabled;
|
2001-03-09 06:29:00 +03:00
|
|
|
|
#ifdef IBMBIDI
|
|
|
|
|
PRUint8 mBidiLevel; // The Bidi level of the cursor
|
|
|
|
|
nsCOMPtr<nsIBidiKeyboard> mBidiKeyboard;
|
|
|
|
|
#endif // IBMBIDI
|
1999-11-02 01:12:45 +03:00
|
|
|
|
#ifdef NS_DEBUG
|
2004-01-08 01:30:53 +03:00
|
|
|
|
nsresult CloneStyleSet(nsStyleSet* aSet, nsStyleSet** aResult);
|
1999-09-10 22:49:23 +04:00
|
|
|
|
PRBool VerifyIncrementalReflow();
|
1998-11-26 21:11:02 +03:00
|
|
|
|
PRBool mInVerifyReflow;
|
2006-01-26 05:29:17 +03:00
|
|
|
|
void ShowEventTargetDebug();
|
1998-07-13 23:49:42 +04:00
|
|
|
|
#endif
|
1998-05-20 20:24:54 +04:00
|
|
|
|
|
2000-10-11 12:33:01 +04:00
|
|
|
|
/**
|
|
|
|
|
* methods that manage rules that are used to implement the associated preferences
|
|
|
|
|
* - initially created for bugs 31816, 20760, 22963
|
|
|
|
|
*/
|
|
|
|
|
nsresult ClearPreferenceStyleRules(void);
|
|
|
|
|
nsresult CreatePreferenceStyleSheet(void);
|
|
|
|
|
nsresult SetPrefColorRules(void);
|
|
|
|
|
nsresult SetPrefLinkRules(void);
|
2001-04-10 02:17:11 +04:00
|
|
|
|
nsresult SetPrefFocusRules(void);
|
2003-06-26 10:10:03 +04:00
|
|
|
|
nsresult SetPrefNoScriptRule();
|
2005-03-03 21:04:38 +03:00
|
|
|
|
nsresult SetPrefNoFramesRule(void);
|
|
|
|
|
|
2006-06-08 18:32:20 +04:00
|
|
|
|
/**
|
|
|
|
|
* Methods to handle changes to user and UA sheet lists that we get
|
|
|
|
|
* notified about.
|
|
|
|
|
*/
|
|
|
|
|
void AddUserSheet(nsISupports* aSheet);
|
|
|
|
|
void AddAgentSheet(nsISupports* aSheet);
|
|
|
|
|
void RemoveSheet(nsStyleSet::sheetType aType, nsISupports* aSheet);
|
|
|
|
|
|
2003-07-18 05:26:47 +04:00
|
|
|
|
nsICSSStyleSheet* mPrefStyleSheet; // mStyleSet owns it but we maintain a ref, may be null
|
2004-12-02 04:26:20 +03:00
|
|
|
|
#ifdef DEBUG
|
2001-12-15 02:13:08 +03:00
|
|
|
|
PRUint32 mUpdateCount;
|
2004-12-02 04:26:20 +03:00
|
|
|
|
#endif
|
2001-03-13 09:38:59 +03:00
|
|
|
|
// normal reflow commands
|
2004-05-02 22:07:12 +04:00
|
|
|
|
nsVoidArray mReflowCommands;
|
|
|
|
|
PLDHashTable mReflowCommandTable;
|
2001-03-13 09:38:59 +03:00
|
|
|
|
|
2000-05-16 05:11:29 +04:00
|
|
|
|
PRPackedBool mDocumentLoading;
|
2005-08-23 05:29:02 +04:00
|
|
|
|
PRPackedBool mDocumentOnloadBlocked;
|
2000-04-17 11:13:57 +04:00
|
|
|
|
PRPackedBool mIsReflowing;
|
2005-04-08 03:50:40 +04:00
|
|
|
|
PRPackedBool mIsReleasingAnonymousContent;
|
2001-12-15 02:13:08 +03:00
|
|
|
|
|
2001-12-01 03:22:00 +03:00
|
|
|
|
PRPackedBool mIgnoreFrameDestruction;
|
2004-02-25 12:10:06 +03:00
|
|
|
|
PRPackedBool mHaveShutDown;
|
2001-12-15 02:13:08 +03:00
|
|
|
|
|
2005-01-20 06:39:09 +03:00
|
|
|
|
// This is used to protect ourselves from triggering reflow while in the
|
|
|
|
|
// middle of frame construction and the like... it really shouldn't be
|
|
|
|
|
// needed, one hopes, but it is for now.
|
|
|
|
|
PRUint32 mChangeNestCount;
|
|
|
|
|
|
2001-12-15 02:13:08 +03:00
|
|
|
|
nsIFrame* mCurrentEventFrame;
|
2004-09-13 07:22:46 +04:00
|
|
|
|
nsCOMPtr<nsIContent> mCurrentEventContent;
|
1999-09-02 22:14:01 +04:00
|
|
|
|
nsVoidArray mCurrentEventFrameStack;
|
2004-09-13 07:22:46 +04:00
|
|
|
|
nsCOMArray<nsIContent> mCurrentEventContentStack;
|
2000-10-09 07:08:41 +04:00
|
|
|
|
nsSupportsHashtable* mAnonymousContentTable;
|
2000-04-24 08:41:27 +04:00
|
|
|
|
|
2000-02-03 05:49:58 +03:00
|
|
|
|
#ifdef NS_DEBUG
|
|
|
|
|
nsRect mCurrentTargetRect;
|
|
|
|
|
nsIView* mCurrentTargetView;
|
|
|
|
|
#endif
|
1999-02-12 03:02:56 +03:00
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsICaret> mCaret;
|
2001-12-19 00:05:55 +03:00
|
|
|
|
PRInt16 mSelectionFlags;
|
2005-03-03 07:46:03 +03:00
|
|
|
|
PRPackedBool mBatchReflows; // When set to true, the pres shell batches reflow commands.
|
1999-10-15 08:29:30 +04:00
|
|
|
|
PresShellViewEventListener *mViewEventListener;
|
1999-12-07 07:36:08 +03:00
|
|
|
|
FrameArena mFrameArena;
|
2000-03-31 11:02:06 +04:00
|
|
|
|
StackArena* mStackArena;
|
2000-06-15 03:18:54 +04:00
|
|
|
|
nsCOMPtr<nsIDragService> mDragService;
|
2000-09-12 04:35:11 +04:00
|
|
|
|
PRInt32 mRCCreatedDuringLoad; // Counter to keep track of reflow commands created during doc
|
2006-05-10 21:30:15 +04:00
|
|
|
|
|
|
|
|
|
nsRevocableEventPtr<ReflowEvent> mReflowEvent;
|
2000-06-23 09:15:04 +04:00
|
|
|
|
|
|
|
|
|
// used for list of posted events and attribute changes. To be done
|
|
|
|
|
// after reflow.
|
|
|
|
|
nsDOMEventRequest* mFirstDOMEventRequest;
|
|
|
|
|
nsDOMEventRequest* mLastDOMEventRequest;
|
|
|
|
|
nsAttributeChangeRequest* mFirstAttributeRequest;
|
|
|
|
|
nsAttributeChangeRequest* mLastAttributeRequest;
|
2000-07-14 03:00:59 +04:00
|
|
|
|
nsCallbackEventRequest* mFirstCallbackEventRequest;
|
|
|
|
|
nsCallbackEventRequest* mLastCallbackEventRequest;
|
2000-06-23 09:15:04 +04:00
|
|
|
|
|
2002-09-21 05:03:38 +04:00
|
|
|
|
PRPackedBool mIsThemeSupportDisabled; // Whether or not form controls should use nsITheme in this shell.
|
|
|
|
|
|
2001-12-15 02:13:08 +03:00
|
|
|
|
PRPackedBool mIsDocumentGone; // We've been disconnected from the document.
|
|
|
|
|
PRPackedBool mPaintingSuppressed; // For all documents we initially lock down painting.
|
|
|
|
|
// We will refuse to paint the document until either
|
|
|
|
|
// (a) our timer fires or (b) all frames are constructed.
|
|
|
|
|
PRPackedBool mShouldUnsuppressPainting; // Indicates that it is safe to unlock painting once all pending
|
|
|
|
|
// reflows have been processed.
|
2001-04-25 23:52:49 +04:00
|
|
|
|
nsCOMPtr<nsITimer> mPaintSuppressionTimer; // This timer controls painting suppression. Until it fires
|
|
|
|
|
// or all frames are constructed, we won't paint anything but
|
|
|
|
|
// our <body> background and scrollbars.
|
2002-12-27 00:03:23 +03:00
|
|
|
|
#define PAINTLOCK_EVENT_DELAY 250 // 250ms. This is actually
|
|
|
|
|
// pref-controlled, but we use this
|
|
|
|
|
// value if we fail to get the pref
|
|
|
|
|
// for any reason.
|
2001-04-25 23:52:49 +04:00
|
|
|
|
|
|
|
|
|
static void sPaintSuppressionCallback(nsITimer* aTimer, void* aPresShell); // A callback for the timer.
|
|
|
|
|
|
2000-04-17 11:13:57 +04:00
|
|
|
|
MOZ_TIMER_DECLARE(mReflowWatch) // Used for measuring time spent in reflow
|
|
|
|
|
MOZ_TIMER_DECLARE(mFrameCreationWatch) // Used for measuring time spent in frame creation
|
1999-12-23 05:02:33 +03:00
|
|
|
|
|
2000-04-21 18:59:47 +04:00
|
|
|
|
#ifdef MOZ_REFLOW_PERF
|
|
|
|
|
ReflowCountMgr * mReflowCountMgr;
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-04-18 10:06:31 +04:00
|
|
|
|
private:
|
|
|
|
|
|
2003-01-07 05:09:06 +03:00
|
|
|
|
PRBool InZombieDocument(nsIContent *aContent);
|
|
|
|
|
nsresult RetargetEventToParent(nsIView *aView, nsGUIEvent* aEvent,
|
2006-01-26 05:29:17 +03:00
|
|
|
|
nsEventStatus* aEventStatus,
|
|
|
|
|
nsIContent *aZombieFocusedContent);
|
2003-01-07 05:09:06 +03:00
|
|
|
|
|
2000-03-31 11:02:06 +04:00
|
|
|
|
void FreeDynamicStack();
|
|
|
|
|
|
1999-09-02 22:14:01 +04:00
|
|
|
|
//helper funcs for event handling
|
2006-03-07 20:08:51 +03:00
|
|
|
|
protected:
|
|
|
|
|
//protected because nsPresShellEventCB needs this.
|
1999-06-15 07:14:28 +04:00
|
|
|
|
nsIFrame* GetCurrentEventFrame();
|
2006-03-07 20:08:51 +03:00
|
|
|
|
private:
|
2000-04-24 08:41:27 +04:00
|
|
|
|
void PushCurrentEventInfo(nsIFrame* aFrame, nsIContent* aContent);
|
|
|
|
|
void PopCurrentEventInfo();
|
2006-03-07 20:08:51 +03:00
|
|
|
|
nsresult HandleEventInternal(nsEvent* aEvent, nsIView* aView,
|
|
|
|
|
nsEventStatus *aStatus);
|
2006-01-26 05:29:17 +03:00
|
|
|
|
nsresult HandlePositionedEvent(nsIView* aView,
|
|
|
|
|
nsIFrame* aTargetFrame,
|
|
|
|
|
nsGUIEvent* aEvent,
|
|
|
|
|
nsEventStatus* aEventStatus);
|
2001-04-18 03:25:21 +04:00
|
|
|
|
|
|
|
|
|
//help funcs for resize events
|
|
|
|
|
void CreateResizeEventTimer();
|
|
|
|
|
void KillResizeEventTimer();
|
|
|
|
|
void FireResizeEvent();
|
|
|
|
|
static void sResizeEventCallback(nsITimer* aTimer, void* aPresShell) ;
|
|
|
|
|
nsCOMPtr<nsITimer> mResizeEventTimer;
|
2005-05-05 00:22:32 +04:00
|
|
|
|
|
|
|
|
|
typedef void (*nsPluginEnumCallback)(PresShell*, nsIContent*);
|
|
|
|
|
void EnumeratePlugins(nsIDOMDocument *aDocument,
|
|
|
|
|
const nsString &aPluginTag,
|
|
|
|
|
nsPluginEnumCallback aCallback);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
};
|
|
|
|
|
|
2006-03-07 20:08:51 +03:00
|
|
|
|
class nsPresShellEventCB : public nsDispatchingCallback
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
nsPresShellEventCB(PresShell* aPresShell) : mPresShell(aPresShell) {}
|
|
|
|
|
|
|
|
|
|
virtual void HandleEvent(nsEventChainPostVisitor& aVisitor)
|
|
|
|
|
{
|
|
|
|
|
if (aVisitor.mPresContext && aVisitor.mEvent->eventStructType != NS_EVENT) {
|
|
|
|
|
nsIFrame* frame = mPresShell->GetCurrentEventFrame();
|
|
|
|
|
if (frame) {
|
|
|
|
|
frame->HandleEvent(aVisitor.mPresContext,
|
|
|
|
|
(nsGUIEvent*) aVisitor.mEvent,
|
|
|
|
|
&aVisitor.mEventStatus);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsRefPtr<PresShell> mPresShell;
|
|
|
|
|
};
|
|
|
|
|
|
2001-04-11 07:07:50 +04:00
|
|
|
|
#ifdef PR_LOGGING
|
|
|
|
|
PRLogModuleInfo* PresShell::gLog;
|
|
|
|
|
#endif
|
|
|
|
|
|
1999-09-21 11:53:49 +04:00
|
|
|
|
#ifdef NS_DEBUG
|
|
|
|
|
static void
|
2004-08-01 03:15:21 +04:00
|
|
|
|
VerifyStyleTree(nsPresContext* aPresContext, nsFrameManager* aFrameManager)
|
1999-09-21 11:53:49 +04:00
|
|
|
|
{
|
2004-02-24 00:29:06 +03:00
|
|
|
|
if (nsIFrameDebug::GetVerifyStyleTreeEnable()) {
|
|
|
|
|
nsIFrame* rootFrame = aFrameManager->GetRootFrame();
|
2003-06-20 05:05:04 +04:00
|
|
|
|
aFrameManager->DebugVerifyStyleTree(rootFrame);
|
1999-09-21 11:53:49 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
2005-11-06 21:01:17 +03:00
|
|
|
|
#define VERIFY_STYLE_TREE ::VerifyStyleTree(mPresContext, FrameManager())
|
1999-09-21 11:53:49 +04:00
|
|
|
|
#else
|
|
|
|
|
#define VERIFY_STYLE_TREE
|
|
|
|
|
#endif
|
|
|
|
|
|
1999-09-10 22:49:23 +04:00
|
|
|
|
static PRBool gVerifyReflowEnabled;
|
|
|
|
|
|
2001-10-23 05:37:21 +04:00
|
|
|
|
PRBool
|
1998-07-13 23:49:42 +04:00
|
|
|
|
nsIPresShell::GetVerifyReflowEnable()
|
|
|
|
|
{
|
|
|
|
|
#ifdef NS_DEBUG
|
1999-09-10 22:49:23 +04:00
|
|
|
|
static PRBool firstTime = PR_TRUE;
|
|
|
|
|
if (firstTime) {
|
|
|
|
|
firstTime = PR_FALSE;
|
2001-06-27 08:04:04 +04:00
|
|
|
|
char* flags = PR_GetEnv("GECKO_VERIFY_REFLOW_FLAGS");
|
|
|
|
|
if (flags) {
|
|
|
|
|
PRBool error = PR_FALSE;
|
|
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
|
char* comma = PL_strchr(flags, ',');
|
|
|
|
|
if (comma)
|
|
|
|
|
*comma = '\0';
|
|
|
|
|
|
|
|
|
|
PRBool found = PR_FALSE;
|
2004-01-21 07:15:00 +03:00
|
|
|
|
const VerifyReflowFlags* flag = gFlags;
|
|
|
|
|
const VerifyReflowFlags* limit = gFlags + NUM_VERIFY_REFLOW_FLAGS;
|
2001-06-27 08:04:04 +04:00
|
|
|
|
while (flag < limit) {
|
|
|
|
|
if (PL_strcasecmp(flag->name, flags) == 0) {
|
|
|
|
|
gVerifyReflowFlags |= flag->bit;
|
|
|
|
|
found = PR_TRUE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
++flag;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! found)
|
|
|
|
|
error = PR_TRUE;
|
|
|
|
|
|
|
|
|
|
if (! comma)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
*comma = ',';
|
|
|
|
|
flags = comma + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (error)
|
|
|
|
|
ShowVerifyReflowFlags();
|
|
|
|
|
}
|
|
|
|
|
|
1999-09-10 22:49:23 +04:00
|
|
|
|
if (VERIFY_REFLOW_ON & gVerifyReflowFlags) {
|
|
|
|
|
gVerifyReflowEnabled = PR_TRUE;
|
1998-11-25 21:41:02 +03:00
|
|
|
|
}
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("Note: verifyreflow is %sabled",
|
1999-09-10 22:49:23 +04:00
|
|
|
|
gVerifyReflowEnabled ? "en" : "dis");
|
|
|
|
|
if (VERIFY_REFLOW_NOISY & gVerifyReflowFlags) {
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf(" (noisy)");
|
1998-11-25 21:41:02 +03:00
|
|
|
|
}
|
1999-09-10 22:49:23 +04:00
|
|
|
|
if (VERIFY_REFLOW_ALL & gVerifyReflowFlags) {
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf(" (all)");
|
1998-11-25 21:41:02 +03:00
|
|
|
|
}
|
1999-09-15 04:27:05 +04:00
|
|
|
|
if (VERIFY_REFLOW_DUMP_COMMANDS & gVerifyReflowFlags) {
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf(" (show reflow commands)");
|
1999-09-15 04:27:05 +04:00
|
|
|
|
}
|
|
|
|
|
if (VERIFY_REFLOW_NOISY_RC & gVerifyReflowFlags) {
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf(" (noisy reflow commands)");
|
1999-10-05 18:51:12 +04:00
|
|
|
|
if (VERIFY_REFLOW_REALLY_NOISY_RC & gVerifyReflowFlags) {
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf(" (REALLY noisy reflow commands)");
|
1999-10-05 18:51:12 +04:00
|
|
|
|
}
|
1999-09-15 04:27:05 +04:00
|
|
|
|
}
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("\n");
|
1998-07-13 23:49:42 +04:00
|
|
|
|
}
|
|
|
|
|
#endif
|
1999-09-10 22:49:23 +04:00
|
|
|
|
return gVerifyReflowEnabled;
|
1998-07-13 23:49:42 +04:00
|
|
|
|
}
|
|
|
|
|
|
2001-10-23 05:37:21 +04:00
|
|
|
|
void
|
1998-07-13 23:49:42 +04:00
|
|
|
|
nsIPresShell::SetVerifyReflowEnable(PRBool aEnabled)
|
|
|
|
|
{
|
1999-09-10 22:49:23 +04:00
|
|
|
|
gVerifyReflowEnabled = aEnabled;
|
1998-07-13 23:49:42 +04:00
|
|
|
|
}
|
|
|
|
|
|
2001-10-23 05:37:21 +04:00
|
|
|
|
PRInt32
|
2000-03-23 02:19:10 +03:00
|
|
|
|
nsIPresShell::GetVerifyReflowFlags()
|
|
|
|
|
{
|
2000-03-23 03:10:26 +03:00
|
|
|
|
#ifdef NS_DEBUG
|
2000-03-23 02:19:10 +03:00
|
|
|
|
return gVerifyReflowFlags;
|
2000-03-23 03:10:26 +03:00
|
|
|
|
#else
|
|
|
|
|
return 0;
|
|
|
|
|
#endif
|
2000-03-23 02:19:10 +03:00
|
|
|
|
}
|
|
|
|
|
|
2006-07-12 11:41:11 +04:00
|
|
|
|
void
|
|
|
|
|
nsIPresShell::AddWeakFrame(nsWeakFrame* aWeakFrame)
|
|
|
|
|
{
|
|
|
|
|
if (aWeakFrame->GetFrame()) {
|
|
|
|
|
aWeakFrame->GetFrame()->AddStateBits(NS_FRAME_EXTERNAL_REFERENCE);
|
|
|
|
|
}
|
|
|
|
|
aWeakFrame->SetPreviousWeakFrame(mWeakFrames);
|
|
|
|
|
mWeakFrames = aWeakFrame;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nsIPresShell::RemoveWeakFrame(nsWeakFrame* aWeakFrame)
|
|
|
|
|
{
|
|
|
|
|
if (mWeakFrames == aWeakFrame) {
|
|
|
|
|
mWeakFrames = aWeakFrame->GetPreviousWeakFrame();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
nsWeakFrame* nextWeak = mWeakFrames;
|
|
|
|
|
while (nextWeak && nextWeak->GetPreviousWeakFrame() != aWeakFrame) {
|
|
|
|
|
nextWeak = nextWeak->GetPreviousWeakFrame();
|
|
|
|
|
}
|
|
|
|
|
if (nextWeak) {
|
|
|
|
|
nextWeak->SetPreviousWeakFrame(aWeakFrame->GetPreviousWeakFrame());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
|
2001-10-23 05:37:21 +04:00
|
|
|
|
nsresult
|
1998-07-13 23:49:42 +04:00
|
|
|
|
NS_NewPresShell(nsIPresShell** aInstancePtrResult)
|
|
|
|
|
{
|
|
|
|
|
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
|
|
|
|
|
if (nsnull == aInstancePtrResult) {
|
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
}
|
|
|
|
|
PresShell* it = new PresShell();
|
|
|
|
|
if (nsnull == it) {
|
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
2000-01-04 23:24:09 +03:00
|
|
|
|
return it->QueryInterface(NS_GET_IID(nsIPresShell),
|
|
|
|
|
(void **) aInstancePtrResult);
|
1998-07-13 23:49:42 +04:00
|
|
|
|
}
|
|
|
|
|
|
2004-08-29 07:08:44 +04:00
|
|
|
|
PresShell::PresShell()
|
2001-12-01 03:22:00 +03:00
|
|
|
|
#ifdef IBMBIDI
|
2004-08-29 07:08:44 +04:00
|
|
|
|
: mBidiLevel(BIDI_LEVEL_UNDEFINED)
|
2000-02-03 05:49:58 +03:00
|
|
|
|
#endif
|
2001-12-01 03:22:00 +03:00
|
|
|
|
{
|
2005-05-03 07:46:51 +04:00
|
|
|
|
mIsAccessibilityActive = PR_FALSE;
|
2004-08-29 07:08:44 +04:00
|
|
|
|
mSelection = nsnull;
|
2000-04-21 18:59:47 +04:00
|
|
|
|
#ifdef MOZ_REFLOW_PERF
|
|
|
|
|
mReflowCountMgr = new ReflowCountMgr();
|
2001-02-22 16:58:17 +03:00
|
|
|
|
mReflowCountMgr->SetPresContext(mPresContext);
|
|
|
|
|
mReflowCountMgr->SetPresShell(this);
|
2000-04-21 18:59:47 +04:00
|
|
|
|
#endif
|
2001-03-09 06:29:00 +03:00
|
|
|
|
#ifdef IBMBIDI
|
|
|
|
|
mBidiLevel = BIDI_LEVEL_UNDEFINED;
|
|
|
|
|
#endif
|
2001-04-11 07:07:50 +04:00
|
|
|
|
#ifdef PR_LOGGING
|
|
|
|
|
if (! gLog)
|
|
|
|
|
gLog = PR_NewLogModule("PresShell");
|
|
|
|
|
#endif
|
2002-09-11 07:03:49 +04:00
|
|
|
|
mSelectionFlags = nsISelectionDisplay::DISPLAY_TEXT | nsISelectionDisplay::DISPLAY_IMAGES;
|
2002-09-21 05:03:38 +04:00
|
|
|
|
mIsThemeSupportDisabled = PR_FALSE;
|
2005-04-08 03:50:40 +04:00
|
|
|
|
mIsReleasingAnonymousContent = PR_FALSE;
|
2004-03-06 07:46:11 +03:00
|
|
|
|
|
|
|
|
|
new (this) nsFrameManager();
|
1998-04-14 00:24:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
2006-07-02 11:23:10 +04:00
|
|
|
|
NS_IMPL_ISUPPORTS8(PresShell, nsIPresShell, nsIDocumentObserver,
|
2004-09-01 09:16:00 +04:00
|
|
|
|
nsIViewObserver, nsISelectionController,
|
2006-07-02 11:23:10 +04:00
|
|
|
|
nsISelectionDisplay, nsIObserver, nsISupportsWeakReference,
|
|
|
|
|
nsIMutationObserver)
|
1998-04-14 00:24:54 +04:00
|
|
|
|
|
|
|
|
|
PresShell::~PresShell()
|
|
|
|
|
{
|
2004-02-25 12:10:06 +03:00
|
|
|
|
if (!mHaveShutDown) {
|
2001-08-01 07:15:50 +04:00
|
|
|
|
NS_NOTREACHED("Someone did not call nsIPresShell::destroy");
|
|
|
|
|
Destroy();
|
2001-07-27 00:53:21 +04:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-21 00:14:59 +04:00
|
|
|
|
NS_ASSERTION(mCurrentEventContentStack.Count() == 0,
|
|
|
|
|
"Huh, event content left on the stack in pres shell dtor!");
|
2004-01-21 07:15:00 +03:00
|
|
|
|
NS_ASSERTION(mFirstDOMEventRequest == nsnull &&
|
|
|
|
|
mLastDOMEventRequest == nsnull &&
|
|
|
|
|
mFirstAttributeRequest == nsnull &&
|
|
|
|
|
mLastAttributeRequest == nsnull &&
|
|
|
|
|
mFirstCallbackEventRequest == nsnull &&
|
|
|
|
|
mLastCallbackEventRequest == nsnull,
|
|
|
|
|
"post-reflow queues not empty. This means we're leaking");
|
2004-02-25 12:10:06 +03:00
|
|
|
|
|
|
|
|
|
delete mStyleSet;
|
2004-01-22 02:05:10 +03:00
|
|
|
|
delete mFrameConstructor;
|
|
|
|
|
|
2004-09-13 07:22:46 +04:00
|
|
|
|
mCurrentEventContent = nsnull;
|
2002-06-21 00:14:59 +04:00
|
|
|
|
|
2001-07-27 00:53:21 +04:00
|
|
|
|
// if we allocated any stack memory free it.
|
|
|
|
|
FreeDynamicStack();
|
2003-06-19 22:16:53 +04:00
|
|
|
|
|
|
|
|
|
NS_IF_RELEASE(mPresContext);
|
|
|
|
|
NS_IF_RELEASE(mDocument);
|
2004-08-29 07:08:44 +04:00
|
|
|
|
NS_IF_RELEASE(mSelection);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Initialize the presentation shell. Create view manager and style
|
|
|
|
|
* manager.
|
|
|
|
|
*/
|
2001-08-01 07:15:50 +04:00
|
|
|
|
NS_IMETHODIMP
|
1998-05-09 07:22:41 +04:00
|
|
|
|
PresShell::Init(nsIDocument* aDocument,
|
2004-08-01 03:15:21 +04:00
|
|
|
|
nsPresContext* aPresContext,
|
1998-05-09 07:22:41 +04:00
|
|
|
|
nsIViewManager* aViewManager,
|
2004-01-08 01:30:53 +03:00
|
|
|
|
nsStyleSet* aStyleSet,
|
2002-06-26 01:16:17 +04:00
|
|
|
|
nsCompatibility aCompatMode)
|
1998-04-14 00:24:54 +04:00
|
|
|
|
{
|
|
|
|
|
NS_PRECONDITION(nsnull != aDocument, "null ptr");
|
|
|
|
|
NS_PRECONDITION(nsnull != aPresContext, "null ptr");
|
|
|
|
|
NS_PRECONDITION(nsnull != aViewManager, "null ptr");
|
1999-12-05 02:49:50 +03:00
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
|
if ((nsnull == aDocument) || (nsnull == aPresContext) ||
|
|
|
|
|
(nsnull == aViewManager)) {
|
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
}
|
1999-05-05 03:27:42 +04:00
|
|
|
|
if (mDocument) {
|
2006-03-30 04:27:42 +04:00
|
|
|
|
NS_WARNING("PresShell double init'ed");
|
1998-04-14 00:24:54 +04:00
|
|
|
|
return NS_ERROR_ALREADY_INITIALIZED;
|
|
|
|
|
}
|
|
|
|
|
|
2003-06-19 22:16:53 +04:00
|
|
|
|
mDocument = aDocument;
|
|
|
|
|
NS_ADDREF(mDocument);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
mViewManager = aViewManager;
|
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
|
// Create our frame constructor.
|
2005-02-18 19:11:53 +03:00
|
|
|
|
mFrameConstructor = new nsCSSFrameConstructor(mDocument, this);
|
2004-01-22 02:05:10 +03:00
|
|
|
|
NS_ENSURE_TRUE(mFrameConstructor, NS_ERROR_OUT_OF_MEMORY);
|
2004-01-08 01:30:53 +03:00
|
|
|
|
|
2002-04-11 07:24:18 +04:00
|
|
|
|
// The document viewer owns both view manager and pres shell.
|
|
|
|
|
mViewManager->SetViewObserver(this);
|
1998-08-28 06:54:06 +04:00
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
|
// Bind the context to the presentation shell.
|
2002-05-24 03:09:31 +04:00
|
|
|
|
mPresContext = aPresContext;
|
2003-06-19 22:16:53 +04:00
|
|
|
|
NS_ADDREF(mPresContext);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
aPresContext->SetShell(this);
|
|
|
|
|
|
2004-05-02 22:07:12 +04:00
|
|
|
|
// Create our reflow command hashtable
|
|
|
|
|
static PLDHashTableOps reflowCommandOps =
|
|
|
|
|
{
|
|
|
|
|
PL_DHashAllocTable,
|
|
|
|
|
PL_DHashFreeTable,
|
|
|
|
|
ReflowCommandHashGetKey,
|
|
|
|
|
ReflowCommandHashHashKey,
|
|
|
|
|
ReflowCommandHashMatchEntry,
|
|
|
|
|
PL_DHashMoveEntryStub,
|
|
|
|
|
PL_DHashClearEntryStub,
|
|
|
|
|
PL_DHashFinalizeStub
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (!PL_DHashTableInit(&mReflowCommandTable, &reflowCommandOps,
|
|
|
|
|
nsnull, sizeof(ReflowCommandEntry), 16)) {
|
|
|
|
|
mReflowCommandTable.ops = nsnull;
|
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
|
// Now we can initialize the style set.
|
|
|
|
|
nsresult result = aStyleSet->Init(aPresContext);
|
|
|
|
|
NS_ENSURE_SUCCESS(result, result);
|
|
|
|
|
|
2004-04-13 04:27:29 +04:00
|
|
|
|
// From this point on, any time we return an error we need to make
|
|
|
|
|
// sure to null out mStyleSet first, since an error return from this
|
|
|
|
|
// method will cause the caller to delete the style set, so we don't
|
|
|
|
|
// want to delete it in our destructor.
|
2001-08-01 07:15:50 +04:00
|
|
|
|
mStyleSet = aStyleSet;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
|
2002-05-24 03:09:31 +04:00
|
|
|
|
// Set the compatibility mode after attaching the pres context and
|
|
|
|
|
// style set, but before creating any frames.
|
2002-06-26 01:16:17 +04:00
|
|
|
|
mPresContext->SetCompatibilityMode(aCompatMode);
|
2002-05-24 03:09:31 +04:00
|
|
|
|
|
2002-06-26 01:21:48 +04:00
|
|
|
|
// setup the preference style rules (no forced reflow), and do it
|
|
|
|
|
// before creating any frames.
|
|
|
|
|
SetPreferenceStyleRules(PR_FALSE);
|
|
|
|
|
|
2004-08-29 07:08:44 +04:00
|
|
|
|
result = CallCreateInstance(kFrameSelectionCID, &mSelection);
|
2004-04-13 04:27:29 +04:00
|
|
|
|
if (NS_FAILED(result)) {
|
|
|
|
|
mStyleSet = nsnull;
|
1998-12-14 21:34:14 +03:00
|
|
|
|
return result;
|
2004-04-13 04:27:29 +04:00
|
|
|
|
}
|
1999-04-26 08:02:04 +04:00
|
|
|
|
|
1999-08-04 08:02:40 +04:00
|
|
|
|
// Create and initialize the frame manager
|
2004-03-06 07:46:11 +03:00
|
|
|
|
result = FrameManager()->Init(this, mStyleSet);
|
2004-04-13 04:27:29 +04:00
|
|
|
|
if (NS_FAILED(result)) {
|
|
|
|
|
NS_WARNING("Frame manager initialization failed");
|
|
|
|
|
mStyleSet = nsnull;
|
|
|
|
|
return result;
|
|
|
|
|
}
|
1999-08-04 08:02:40 +04:00
|
|
|
|
|
2006-04-26 06:01:07 +04:00
|
|
|
|
mSelection->Init(this, nsnull);
|
|
|
|
|
|
1999-02-12 03:02:56 +03:00
|
|
|
|
// Important: this has to happen after the selection has been set up
|
|
|
|
|
#ifdef SHOW_CARET
|
|
|
|
|
// make the caret
|
|
|
|
|
nsresult err = NS_NewCaret(getter_AddRefs(mCaret));
|
|
|
|
|
if (NS_SUCCEEDED(err))
|
1999-04-02 03:58:11 +04:00
|
|
|
|
{
|
1999-07-15 02:18:29 +04:00
|
|
|
|
mCaret->Init(this);
|
1999-04-02 03:58:11 +04:00
|
|
|
|
}
|
|
|
|
|
|
2003-03-12 06:22:11 +03:00
|
|
|
|
//SetCaretEnabled(PR_TRUE); // make it show in browser windows
|
1999-02-12 03:02:56 +03:00
|
|
|
|
#endif
|
2005-09-06 07:37:15 +04:00
|
|
|
|
//set up selection to be displayed in document
|
2006-02-07 05:52:40 +03:00
|
|
|
|
// Don't enable selection for print media
|
|
|
|
|
nsPresContext::nsPresContextType type = aPresContext->Type();
|
|
|
|
|
if (type != nsPresContext::eContext_PrintPreview &&
|
|
|
|
|
type != nsPresContext::eContext_Print)
|
|
|
|
|
SetDisplaySelection(nsISelectionController::SELECTION_DISABLED);
|
1999-11-30 03:32:43 +03:00
|
|
|
|
|
1999-12-23 06:47:02 +03:00
|
|
|
|
if (gMaxRCProcessingTime == -1) {
|
2004-04-30 03:34:19 +04:00
|
|
|
|
gMaxRCProcessingTime =
|
|
|
|
|
nsContentUtils::GetIntPref("layout.reflow.timeslice",
|
|
|
|
|
NS_MAX_REFLOW_TIME);
|
1999-12-23 05:02:33 +03:00
|
|
|
|
}
|
|
|
|
|
|
2004-07-18 05:16:27 +04:00
|
|
|
|
{
|
|
|
|
|
nsCOMPtr<nsIObserverService> os =
|
|
|
|
|
do_GetService("@mozilla.org/observer-service;1", &result);
|
2005-08-11 00:21:44 +04:00
|
|
|
|
if (os) {
|
|
|
|
|
os->AddObserver(this, NS_LINK_VISITED_EVENT_TOPIC, PR_FALSE);
|
2006-06-08 18:32:20 +04:00
|
|
|
|
os->AddObserver(this, "agent-sheet-added", PR_FALSE);
|
|
|
|
|
os->AddObserver(this, "user-sheet-added", PR_FALSE);
|
|
|
|
|
os->AddObserver(this, "agent-sheet-removed", PR_FALSE);
|
|
|
|
|
os->AddObserver(this, "user-sheet-removed", PR_FALSE);
|
2005-08-11 00:21:44 +04:00
|
|
|
|
#ifdef MOZ_XUL
|
2004-07-18 05:16:27 +04:00
|
|
|
|
os->AddObserver(this, "chrome-flush-skin-caches", PR_FALSE);
|
|
|
|
|
#endif
|
2005-08-11 00:21:44 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
2000-05-15 07:37:21 +04:00
|
|
|
|
|
2000-06-15 03:18:54 +04:00
|
|
|
|
// cache the drag service so we can check it during reflows
|
2000-09-14 03:57:52 +04:00
|
|
|
|
mDragService = do_GetService("@mozilla.org/widget/dragservice;1");
|
2000-06-15 03:18:54 +04:00
|
|
|
|
|
2001-03-09 06:29:00 +03:00
|
|
|
|
#ifdef IBMBIDI
|
|
|
|
|
mBidiKeyboard = do_GetService("@mozilla.org/widget/bidikeyboard;1");
|
|
|
|
|
#endif
|
2000-10-11 12:33:01 +04:00
|
|
|
|
|
2001-03-13 04:47:22 +03:00
|
|
|
|
#ifdef MOZ_REFLOW_PERF
|
2002-12-11 17:05:41 +03:00
|
|
|
|
if (mReflowCountMgr) {
|
2004-04-30 03:34:19 +04:00
|
|
|
|
PRBool paintFrameCounts =
|
|
|
|
|
nsContentUtils::GetBoolPref("layout.reflow.showframecounts");
|
|
|
|
|
|
|
|
|
|
PRBool dumpFrameCounts =
|
|
|
|
|
nsContentUtils::GetBoolPref("layout.reflow.dumpframecounts");
|
|
|
|
|
|
|
|
|
|
PRBool dumpFrameByFrameCounts =
|
|
|
|
|
nsContentUtils::GetBoolPref("layout.reflow.dumpframebyframecounts");
|
|
|
|
|
|
|
|
|
|
mReflowCountMgr->SetDumpFrameCounts(dumpFrameCounts);
|
|
|
|
|
mReflowCountMgr->SetDumpFrameByFrameCounts(dumpFrameByFrameCounts);
|
|
|
|
|
mReflowCountMgr->SetPaintFrameCounts(paintFrameCounts);
|
2001-03-13 04:47:22 +03:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-08-01 07:15:50 +04:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::Destroy()
|
|
|
|
|
{
|
|
|
|
|
#ifdef MOZ_REFLOW_PERF
|
|
|
|
|
DumpReflows();
|
|
|
|
|
if (mReflowCountMgr) {
|
|
|
|
|
delete mReflowCountMgr;
|
|
|
|
|
mReflowCountMgr = nsnull;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2004-02-25 12:10:06 +03:00
|
|
|
|
if (mHaveShutDown)
|
|
|
|
|
return NS_OK;
|
|
|
|
|
|
2006-04-11 20:37:58 +04:00
|
|
|
|
if (mPresContext) {
|
|
|
|
|
// We need to notify the destroying the nsPresContext to ESM for
|
|
|
|
|
// suppressing to use from ESM.
|
|
|
|
|
mPresContext->EventStateManager()->NotifyDestroyPresContext(mPresContext);
|
|
|
|
|
}
|
|
|
|
|
|
2004-07-18 05:16:27 +04:00
|
|
|
|
{
|
|
|
|
|
nsCOMPtr<nsIObserverService> os =
|
|
|
|
|
do_GetService("@mozilla.org/observer-service;1");
|
2005-08-11 07:59:04 +04:00
|
|
|
|
if (os) {
|
|
|
|
|
os->RemoveObserver(this, NS_LINK_VISITED_EVENT_TOPIC);
|
2006-06-08 18:32:20 +04:00
|
|
|
|
os->RemoveObserver(this, "agent-sheet-added");
|
|
|
|
|
os->RemoveObserver(this, "user-sheet-added");
|
|
|
|
|
os->RemoveObserver(this, "agent-sheet-removed");
|
|
|
|
|
os->RemoveObserver(this, "user-sheet-removed");
|
2005-08-11 07:59:04 +04:00
|
|
|
|
#ifdef MOZ_XUL
|
2004-07-18 05:16:27 +04:00
|
|
|
|
os->RemoveObserver(this, "chrome-flush-skin-caches");
|
|
|
|
|
#endif
|
2005-08-11 07:59:04 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
2004-07-18 05:16:27 +04:00
|
|
|
|
|
2001-08-01 07:15:50 +04:00
|
|
|
|
// If our paint suppression timer is still active, kill it.
|
|
|
|
|
if (mPaintSuppressionTimer) {
|
|
|
|
|
mPaintSuppressionTimer->Cancel();
|
|
|
|
|
mPaintSuppressionTimer = nsnull;
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-28 02:09:51 +03:00
|
|
|
|
if (mCaret) {
|
|
|
|
|
mCaret->Terminate();
|
|
|
|
|
mCaret = nsnull;
|
|
|
|
|
}
|
|
|
|
|
|
2001-08-01 07:15:50 +04:00
|
|
|
|
// release our pref style sheet, if we have one still
|
|
|
|
|
ClearPreferenceStyleRules();
|
|
|
|
|
|
|
|
|
|
// free our table of anonymous content
|
|
|
|
|
ReleaseAnonymousContent();
|
|
|
|
|
|
|
|
|
|
mIsDestroying = PR_TRUE;
|
|
|
|
|
|
2002-06-21 00:14:59 +04:00
|
|
|
|
// We can't release all the event content in
|
|
|
|
|
// mCurrentEventContentStack here since there might be code on the
|
|
|
|
|
// stack that will release the event content too. Double release
|
|
|
|
|
// bad!
|
|
|
|
|
|
|
|
|
|
// The frames will be torn down, so remove them from the current
|
|
|
|
|
// event frame stack (since they'd be dangling references if we'd
|
|
|
|
|
// leave them in) and null out the mCurrentEventFrame pointer as
|
|
|
|
|
// well.
|
|
|
|
|
|
|
|
|
|
mCurrentEventFrame = nsnull;
|
2001-08-01 07:15:50 +04:00
|
|
|
|
|
2002-06-21 00:14:59 +04:00
|
|
|
|
PRInt32 i, count = mCurrentEventFrameStack.Count();
|
2001-08-01 07:15:50 +04:00
|
|
|
|
for (i = 0; i < count; i++) {
|
2002-06-21 00:14:59 +04:00
|
|
|
|
mCurrentEventFrameStack.ReplaceElementAt(nsnull, i);
|
2001-08-01 07:15:50 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mViewManager) {
|
2002-04-11 07:24:18 +04:00
|
|
|
|
// Clear the view manager's weak pointer back to |this| in case it
|
|
|
|
|
// was leaked.
|
|
|
|
|
mViewManager->SetViewObserver(nsnull);
|
2001-08-01 07:15:50 +04:00
|
|
|
|
mViewManager = nsnull;
|
|
|
|
|
}
|
|
|
|
|
|
2003-03-06 22:14:17 +03:00
|
|
|
|
mStyleSet->BeginShutdown(mPresContext);
|
|
|
|
|
|
2001-08-01 07:15:50 +04:00
|
|
|
|
// This shell must be removed from the document before the frame
|
|
|
|
|
// hierarchy is torn down to avoid finding deleted frames through
|
|
|
|
|
// this presshell while the frames are being torn down
|
|
|
|
|
if (mDocument) {
|
|
|
|
|
mDocument->DeleteShell(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Destroy the frame manager. This will destroy the frame hierarchy
|
2004-04-13 01:53:22 +04:00
|
|
|
|
mFrameConstructor->WillDestroyFrameTree();
|
2004-03-06 07:46:11 +03:00
|
|
|
|
FrameManager()->Destroy();
|
2001-08-01 07:15:50 +04:00
|
|
|
|
|
2006-07-12 11:41:11 +04:00
|
|
|
|
NS_WARN_IF_FALSE(!mWeakFrames, "Weak frames alive after destroying FrameManager");
|
|
|
|
|
while (mWeakFrames) {
|
|
|
|
|
mWeakFrames->Clear(this);
|
|
|
|
|
}
|
|
|
|
|
|
2001-08-01 07:15:50 +04:00
|
|
|
|
// Let the style set do its cleanup.
|
2003-03-06 22:14:17 +03:00
|
|
|
|
mStyleSet->Shutdown(mPresContext);
|
2004-01-08 01:30:53 +03:00
|
|
|
|
|
2001-08-01 07:15:50 +04:00
|
|
|
|
if (mPresContext) {
|
2005-12-06 07:53:03 +03:00
|
|
|
|
// Clear out the prescontext's property table -- since our frame tree is
|
|
|
|
|
// now dead, we shouldn't be looking up any more properties in that table.
|
|
|
|
|
// We want to do this before we call SetShell() on the prescontext, so
|
|
|
|
|
// property destructors can usefully call GetPresShell() on the
|
|
|
|
|
// prescontext.
|
|
|
|
|
mPresContext->PropertyTable()->DeleteAllProperties();
|
|
|
|
|
|
|
|
|
|
// We hold a reference to the pres context, and it holds a weak link back
|
|
|
|
|
// to us. To avoid the pres context having a dangling reference, set its
|
|
|
|
|
// pres shell to NULL
|
2001-08-01 07:15:50 +04:00
|
|
|
|
mPresContext->SetShell(nsnull);
|
2004-08-19 02:13:10 +04:00
|
|
|
|
|
|
|
|
|
// Clear the link handler (weak reference) as well
|
|
|
|
|
mPresContext->SetLinkHandler(nsnull);
|
2001-08-01 07:15:50 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mViewEventListener) {
|
|
|
|
|
mViewEventListener->SetPresShell((nsIPresShell*)nsnull);
|
|
|
|
|
NS_RELEASE(mViewEventListener);
|
|
|
|
|
}
|
|
|
|
|
|
2006-05-10 21:30:15 +04:00
|
|
|
|
// Revoke any pending reflow event
|
|
|
|
|
mReflowEvent.Revoke();
|
2001-08-01 07:15:50 +04:00
|
|
|
|
|
2001-12-01 03:22:00 +03:00
|
|
|
|
CancelAllReflowCommands();
|
2004-05-05 01:59:56 +04:00
|
|
|
|
|
2005-08-23 05:29:02 +04:00
|
|
|
|
NS_ASSERTION(!mDocumentOnloadBlocked,
|
|
|
|
|
"CancelAllReflowCommands() didn't unblock onload?");
|
|
|
|
|
|
2001-08-01 07:15:50 +04:00
|
|
|
|
KillResizeEventTimer();
|
|
|
|
|
|
2004-05-05 01:59:56 +04:00
|
|
|
|
// Now that mReflowCommandTable won't be accessed anymore, finish it
|
|
|
|
|
if (mReflowCommandTable.ops) {
|
|
|
|
|
PL_DHashTableFinish(&mReflowCommandTable);
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-25 12:10:06 +03:00
|
|
|
|
mHaveShutDown = PR_TRUE;
|
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2000-03-31 11:02:06 +04:00
|
|
|
|
// Dynamic stack memory allocation
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::PushStackMemory()
|
|
|
|
|
{
|
2001-05-02 04:36:02 +04:00
|
|
|
|
if (!mStackArena) {
|
|
|
|
|
mStackArena = new StackArena();
|
|
|
|
|
if (!mStackArena)
|
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
2000-03-31 11:02:06 +04:00
|
|
|
|
return mStackArena->Push();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::PopStackMemory()
|
|
|
|
|
{
|
2002-08-14 16:49:24 +04:00
|
|
|
|
NS_ENSURE_TRUE(mStackArena, NS_ERROR_UNEXPECTED);
|
2000-03-31 11:02:06 +04:00
|
|
|
|
|
|
|
|
|
return mStackArena->Pop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::AllocateStackMemory(size_t aSize, void** aResult)
|
|
|
|
|
{
|
2001-05-02 04:36:02 +04:00
|
|
|
|
if (!mStackArena) {
|
|
|
|
|
mStackArena = new StackArena();
|
|
|
|
|
if (!mStackArena)
|
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
2000-03-31 11:02:06 +04:00
|
|
|
|
|
|
|
|
|
return mStackArena->Allocate(aSize, aResult);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PresShell::FreeDynamicStack()
|
|
|
|
|
{
|
|
|
|
|
if (mStackArena) {
|
|
|
|
|
delete mStackArena;
|
|
|
|
|
mStackArena = nsnull;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-04-13 04:28:44 +04:00
|
|
|
|
void
|
1999-12-05 02:49:50 +03:00
|
|
|
|
PresShell::FreeFrame(size_t aSize, void* aPtr)
|
|
|
|
|
{
|
1999-12-07 07:36:08 +03:00
|
|
|
|
mFrameArena.FreeFrame(aSize, aPtr);
|
1999-12-05 02:49:50 +03:00
|
|
|
|
}
|
|
|
|
|
|
2004-04-13 04:28:44 +04:00
|
|
|
|
void*
|
|
|
|
|
PresShell::AllocateFrame(size_t aSize)
|
1999-12-05 02:49:50 +03:00
|
|
|
|
{
|
2004-04-13 04:28:44 +04:00
|
|
|
|
return mFrameArena.AllocateFrame(aSize);
|
1999-12-05 02:49:50 +03:00
|
|
|
|
}
|
|
|
|
|
|
1999-01-23 10:03:46 +03:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::GetActiveAlternateStyleSheet(nsString& aSheetTitle)
|
|
|
|
|
{ // first non-html sheet in style set that has title
|
1999-04-30 13:04:36 +04:00
|
|
|
|
if (mStyleSet) {
|
2004-01-08 01:30:53 +03:00
|
|
|
|
PRInt32 count = mStyleSet->SheetCount(nsStyleSet::eDocSheet);
|
1999-01-23 10:03:46 +03:00
|
|
|
|
PRInt32 index;
|
2001-10-11 05:30:52 +04:00
|
|
|
|
NS_NAMED_LITERAL_STRING(textHtml, "text/html");
|
1999-01-23 10:03:46 +03:00
|
|
|
|
for (index = 0; index < count; index++) {
|
2004-01-08 01:30:53 +03:00
|
|
|
|
nsIStyleSheet* sheet = mStyleSet->StyleSheetAt(nsStyleSet::eDocSheet,
|
|
|
|
|
index);
|
1999-01-23 10:03:46 +03:00
|
|
|
|
if (nsnull != sheet) {
|
|
|
|
|
nsAutoString type;
|
|
|
|
|
sheet->GetType(type);
|
|
|
|
|
if (PR_FALSE == type.Equals(textHtml)) {
|
|
|
|
|
nsAutoString title;
|
|
|
|
|
sheet->GetTitle(title);
|
2003-05-24 01:34:47 +04:00
|
|
|
|
if (!title.IsEmpty()) {
|
1999-01-23 10:03:46 +03:00
|
|
|
|
aSheetTitle = title;
|
|
|
|
|
index = count; // stop looking
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::SelectAlternateStyleSheet(const nsString& aSheetTitle)
|
|
|
|
|
{
|
1999-05-05 03:27:42 +04:00
|
|
|
|
if (mDocument && mStyleSet) {
|
2004-01-08 01:30:53 +03:00
|
|
|
|
mStyleSet->BeginUpdate();
|
2004-07-28 11:08:41 +04:00
|
|
|
|
PRInt32 count = mDocument->GetNumberOfStyleSheets();
|
1999-01-23 10:03:46 +03:00
|
|
|
|
PRInt32 index;
|
2001-10-11 05:30:52 +04:00
|
|
|
|
NS_NAMED_LITERAL_STRING(textHtml,"text/html");
|
1999-01-23 10:03:46 +03:00
|
|
|
|
for (index = 0; index < count; index++) {
|
2004-07-28 11:08:41 +04:00
|
|
|
|
nsIStyleSheet *sheet = mDocument->GetStyleSheetAt(index);
|
2002-12-03 08:48:14 +03:00
|
|
|
|
PRBool complete;
|
|
|
|
|
sheet->GetComplete(complete);
|
|
|
|
|
if (complete) {
|
1999-01-23 10:03:46 +03:00
|
|
|
|
nsAutoString type;
|
|
|
|
|
sheet->GetType(type);
|
2002-12-03 08:48:14 +03:00
|
|
|
|
if (!type.Equals(textHtml)) {
|
|
|
|
|
nsAutoString title;
|
1999-01-23 10:03:46 +03:00
|
|
|
|
sheet->GetTitle(title);
|
2002-12-03 08:48:14 +03:00
|
|
|
|
if (!title.IsEmpty()) {
|
2001-10-11 05:30:52 +04:00
|
|
|
|
if (title.Equals(aSheetTitle)) {
|
1999-01-23 10:03:46 +03:00
|
|
|
|
mStyleSet->AddDocStyleSheet(sheet, mDocument);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2004-01-08 01:30:53 +03:00
|
|
|
|
mStyleSet->RemoveStyleSheet(nsStyleSet::eDocSheet, sheet);
|
1999-01-23 10:03:46 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2004-01-08 01:30:53 +03:00
|
|
|
|
|
|
|
|
|
mStyleSet->EndUpdate();
|
2004-08-29 07:08:44 +04:00
|
|
|
|
ReconstructStyleData();
|
1999-01-23 10:03:46 +03:00
|
|
|
|
}
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::ListAlternateStyleSheets(nsStringArray& aTitleList)
|
|
|
|
|
{
|
2002-12-03 08:48:14 +03:00
|
|
|
|
// XXX should this be returning incomplete sheets? Probably.
|
1999-05-05 03:27:42 +04:00
|
|
|
|
if (mDocument) {
|
2004-07-28 11:08:41 +04:00
|
|
|
|
PRInt32 count = mDocument->GetNumberOfStyleSheets();
|
1999-01-23 10:03:46 +03:00
|
|
|
|
PRInt32 index;
|
2001-10-11 05:30:52 +04:00
|
|
|
|
NS_NAMED_LITERAL_STRING(textHtml,"text/html");
|
1999-01-23 10:03:46 +03:00
|
|
|
|
for (index = 0; index < count; index++) {
|
2004-07-28 11:08:41 +04:00
|
|
|
|
nsIStyleSheet *sheet = mDocument->GetStyleSheetAt(index);
|
2001-06-20 07:27:48 +04:00
|
|
|
|
if (sheet) {
|
1999-01-23 10:03:46 +03:00
|
|
|
|
nsAutoString type;
|
|
|
|
|
sheet->GetType(type);
|
|
|
|
|
if (PR_FALSE == type.Equals(textHtml)) {
|
|
|
|
|
nsAutoString title;
|
|
|
|
|
sheet->GetTitle(title);
|
2003-05-24 01:34:47 +04:00
|
|
|
|
if (!title.IsEmpty()) {
|
2001-10-11 05:30:52 +04:00
|
|
|
|
if (-1 == aTitleList.IndexOf(title)) {
|
1999-01-23 10:03:46 +03:00
|
|
|
|
aTitleList.AppendString(title);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
1998-12-08 21:26:06 +03:00
|
|
|
|
|
2004-08-29 07:08:44 +04:00
|
|
|
|
void
|
|
|
|
|
nsIPresShell::SetAuthorStyleDisabled(PRBool aStyleDisabled)
|
2004-08-05 15:38:42 +04:00
|
|
|
|
{
|
|
|
|
|
if (aStyleDisabled != mStyleSet->GetAuthorStyleDisabled()) {
|
2004-08-29 07:08:44 +04:00
|
|
|
|
mStyleSet->SetAuthorStyleDisabled(aStyleDisabled);
|
|
|
|
|
ReconstructStyleData();
|
2004-08-05 15:38:42 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-08-29 07:08:44 +04:00
|
|
|
|
PRBool
|
|
|
|
|
nsIPresShell::GetAuthorStyleDisabled()
|
2000-10-11 12:33:01 +04:00
|
|
|
|
{
|
2004-08-29 07:08:44 +04:00
|
|
|
|
return mStyleSet->GetAuthorStyleDisabled();
|
2000-10-11 12:33:01 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::SetPreferenceStyleRules(PRBool aForceReflow)
|
|
|
|
|
{
|
2001-11-01 07:40:59 +03:00
|
|
|
|
if (!mDocument) {
|
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
}
|
|
|
|
|
|
2005-11-29 02:56:44 +03:00
|
|
|
|
nsPIDOMWindow *window = mDocument->GetWindow();
|
2001-11-01 07:40:59 +03:00
|
|
|
|
|
2005-11-29 02:56:44 +03:00
|
|
|
|
// If the document doesn't have a window there's no need to notify
|
|
|
|
|
// its presshell about changes to preferences since the document is
|
|
|
|
|
// in a state where it doesn't matter any more (see
|
2001-11-01 07:40:59 +03:00
|
|
|
|
// DocumentViewerImpl::Close()).
|
|
|
|
|
|
2005-11-29 02:56:44 +03:00
|
|
|
|
if (!window) {
|
2001-11-01 07:40:59 +03:00
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
}
|
|
|
|
|
|
2000-10-11 12:33:01 +04:00
|
|
|
|
NS_PRECONDITION(mPresContext, "presContext cannot be null");
|
|
|
|
|
if (mPresContext) {
|
|
|
|
|
nsresult result = NS_OK;
|
|
|
|
|
|
|
|
|
|
// first, make sure this is not a chrome shell
|
2004-02-01 13:09:07 +03:00
|
|
|
|
nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
|
|
|
|
|
if (container) {
|
2000-10-11 12:33:01 +04:00
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> docShell(do_QueryInterface(container, &result));
|
|
|
|
|
if (NS_SUCCEEDED(result) && docShell){
|
|
|
|
|
PRInt32 docShellType;
|
|
|
|
|
result = docShell->GetItemType(&docShellType);
|
|
|
|
|
if (NS_SUCCEEDED(result)){
|
|
|
|
|
if (nsIDocShellTreeItem::typeChrome == docShellType){
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (NS_SUCCEEDED(result)) {
|
|
|
|
|
|
2000-11-13 11:27:01 +03:00
|
|
|
|
#ifdef DEBUG_attinasi
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("Setting Preference Style Rules:\n");
|
|
|
|
|
#endif
|
2000-10-11 12:33:01 +04:00
|
|
|
|
// if here, we need to create rules for the prefs
|
|
|
|
|
// - this includes the background-color, the text-color,
|
|
|
|
|
// the link color, the visited link color and the link-underlining
|
|
|
|
|
|
|
|
|
|
// first clear any exising rules
|
|
|
|
|
result = ClearPreferenceStyleRules();
|
|
|
|
|
|
|
|
|
|
// now do the color rules
|
|
|
|
|
if (NS_SUCCEEDED(result)) {
|
|
|
|
|
result = SetPrefColorRules();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// now the link rules (must come after the color rules, or links will not be correct color!)
|
2001-11-06 13:04:05 +03:00
|
|
|
|
// XXX - when there is both an override and agent pref stylesheet this won't matter,
|
|
|
|
|
// as the color rules will be overrides and the links rules will be agent
|
2000-10-11 12:33:01 +04:00
|
|
|
|
if (NS_SUCCEEDED(result)) {
|
|
|
|
|
result = SetPrefLinkRules();
|
|
|
|
|
}
|
2001-04-10 02:17:11 +04:00
|
|
|
|
if (NS_SUCCEEDED(result)) {
|
|
|
|
|
result = SetPrefFocusRules();
|
|
|
|
|
}
|
2003-06-26 10:10:03 +04:00
|
|
|
|
if (NS_SUCCEEDED(result)) {
|
|
|
|
|
result = SetPrefNoScriptRule();
|
|
|
|
|
}
|
2005-03-03 21:04:38 +03:00
|
|
|
|
if (NS_SUCCEEDED(result)) {
|
|
|
|
|
result = SetPrefNoFramesRule();
|
|
|
|
|
}
|
2000-10-11 12:33:01 +04:00
|
|
|
|
}
|
2000-11-13 11:27:01 +03:00
|
|
|
|
#ifdef DEBUG_attinasi
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf( "Preference Style Rules set: error=%ld\n", (long)result);
|
|
|
|
|
#endif
|
2000-10-11 12:33:01 +04:00
|
|
|
|
|
|
|
|
|
if (aForceReflow){
|
2002-12-14 19:18:57 +03:00
|
|
|
|
mPresContext->ClearStyleDataAndReflow();
|
2000-10-11 12:33:01 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2001-11-01 07:40:59 +03:00
|
|
|
|
|
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
2000-10-11 12:33:01 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult PresShell::ClearPreferenceStyleRules(void)
|
|
|
|
|
{
|
|
|
|
|
nsresult result = NS_OK;
|
|
|
|
|
if (mPrefStyleSheet) {
|
|
|
|
|
NS_ASSERTION(mStyleSet, "null styleset entirely unexpected!");
|
|
|
|
|
if (mStyleSet) {
|
|
|
|
|
// remove the sheet from the styleset:
|
|
|
|
|
// - note that we have to check for success by comparing the count before and after...
|
|
|
|
|
#ifdef NS_DEBUG
|
2004-01-08 01:30:53 +03:00
|
|
|
|
PRInt32 numBefore = mStyleSet->SheetCount(nsStyleSet::eUserSheet);
|
2002-01-14 17:47:21 +03:00
|
|
|
|
NS_ASSERTION(numBefore > 0, "no user stylesheets in styleset, but we have one!");
|
2000-10-11 12:33:01 +04:00
|
|
|
|
#endif
|
2004-01-08 01:30:53 +03:00
|
|
|
|
mStyleSet->RemoveStyleSheet(nsStyleSet::eUserSheet, mPrefStyleSheet);
|
2000-10-11 12:33:01 +04:00
|
|
|
|
|
2000-11-13 11:27:01 +03:00
|
|
|
|
#ifdef DEBUG_attinasi
|
2002-01-14 17:47:21 +03:00
|
|
|
|
NS_ASSERTION((numBefore - 1) == mStyleSet->GetNumberOfUserStyleSheets(),
|
2000-10-11 12:33:01 +04:00
|
|
|
|
"Pref stylesheet was not removed");
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("PrefStyleSheet removed\n");
|
|
|
|
|
#endif
|
2000-10-11 12:33:01 +04:00
|
|
|
|
// clear the sheet pointer: it is strictly historical now
|
2003-07-18 05:26:47 +04:00
|
|
|
|
NS_RELEASE(mPrefStyleSheet);
|
2000-10-11 12:33:01 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult PresShell::CreatePreferenceStyleSheet(void)
|
|
|
|
|
{
|
2003-07-18 05:26:47 +04:00
|
|
|
|
NS_ASSERTION(!mPrefStyleSheet, "prefStyleSheet already exists");
|
|
|
|
|
nsresult result = CallCreateInstance(kCSSStyleSheetCID, &mPrefStyleSheet);
|
2000-10-11 12:33:01 +04:00
|
|
|
|
if (NS_SUCCEEDED(result)) {
|
|
|
|
|
NS_ASSERTION(mPrefStyleSheet, "null but no error");
|
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
|
result = NS_NewURI(getter_AddRefs(uri), "about:PreferenceStyleSheet", nsnull);
|
|
|
|
|
if (NS_SUCCEEDED(result)) {
|
|
|
|
|
NS_ASSERTION(uri, "null but no error");
|
2004-09-10 10:45:59 +04:00
|
|
|
|
result = mPrefStyleSheet->SetURIs(uri, uri);
|
2000-10-11 12:33:01 +04:00
|
|
|
|
if (NS_SUCCEEDED(result)) {
|
2002-12-03 08:48:14 +03:00
|
|
|
|
mPrefStyleSheet->SetComplete();
|
2003-07-18 05:26:47 +04:00
|
|
|
|
nsCOMPtr<nsIDOMCSSStyleSheet> sheet(do_QueryInterface(mPrefStyleSheet));
|
|
|
|
|
if (sheet) {
|
|
|
|
|
PRUint32 index;
|
|
|
|
|
result = sheet->InsertRule(NS_LITERAL_STRING("@namespace url(http://www.w3.org/1999/xhtml);"),
|
|
|
|
|
0, &index);
|
|
|
|
|
NS_ENSURE_SUCCESS(result, result);
|
|
|
|
|
}
|
2004-01-08 01:30:53 +03:00
|
|
|
|
mStyleSet->AppendStyleSheet(nsStyleSet::eUserSheet, mPrefStyleSheet);
|
2000-10-11 12:33:01 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
result = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
2000-11-13 11:27:01 +03:00
|
|
|
|
#ifdef DEBUG_attinasi
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("CreatePrefStyleSheet completed: error=%ld\n",(long)result);
|
|
|
|
|
#endif
|
2000-10-11 12:33:01 +04:00
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-18 05:26:47 +04:00
|
|
|
|
// XXX We want these after the @namespace rule. Does order matter
|
|
|
|
|
// for these rules, or can we call nsICSSStyleRule::StyleRuleCount()
|
|
|
|
|
// and just "append"?
|
|
|
|
|
static PRUint32 sInsertPrefSheetRulesAt = 1;
|
|
|
|
|
|
2000-10-11 12:33:01 +04:00
|
|
|
|
nsresult PresShell::SetPrefColorRules(void)
|
|
|
|
|
{
|
|
|
|
|
NS_ASSERTION(mPresContext,"null prescontext not allowed");
|
|
|
|
|
if (mPresContext) {
|
|
|
|
|
nsresult result = NS_OK;
|
|
|
|
|
|
|
|
|
|
// see if we need to create the rules first
|
2004-02-20 20:49:01 +03:00
|
|
|
|
PRBool useDocColors =
|
|
|
|
|
mPresContext->GetCachedBoolPref(kPresContext_UseDocumentColors);
|
|
|
|
|
if (!useDocColors) {
|
2000-10-11 12:33:01 +04:00
|
|
|
|
|
2000-11-13 11:27:01 +03:00
|
|
|
|
#ifdef DEBUG_attinasi
|
2004-02-20 20:49:01 +03:00
|
|
|
|
printf(" - Creating rules for document colors\n");
|
2000-10-29 02:17:53 +04:00
|
|
|
|
#endif
|
2000-10-11 12:33:01 +04:00
|
|
|
|
|
2004-02-20 20:49:01 +03:00
|
|
|
|
// OK, not using document colors, so we have to force the user's colors via style rules
|
|
|
|
|
if (!mPrefStyleSheet) {
|
|
|
|
|
result = CreatePreferenceStyleSheet();
|
|
|
|
|
}
|
|
|
|
|
if (NS_SUCCEEDED(result)) {
|
|
|
|
|
NS_ASSERTION(mPrefStyleSheet, "prefstylesheet should not be null");
|
|
|
|
|
|
|
|
|
|
nscolor bgColor = mPresContext->DefaultBackgroundColor();
|
|
|
|
|
nscolor textColor = mPresContext->DefaultColor();
|
|
|
|
|
|
|
|
|
|
// get the DOM interface to the stylesheet
|
|
|
|
|
nsCOMPtr<nsIDOMCSSStyleSheet> sheet(do_QueryInterface(mPrefStyleSheet,&result));
|
2000-10-11 12:33:01 +04:00
|
|
|
|
if (NS_SUCCEEDED(result)) {
|
2004-02-20 20:49:01 +03:00
|
|
|
|
PRUint32 index = 0;
|
|
|
|
|
nsAutoString strColor, strBackgroundColor;
|
|
|
|
|
|
|
|
|
|
// create a rule for background and foreground color and
|
|
|
|
|
// add it to the style sheet
|
|
|
|
|
// - the rule is !important so it overrides all but author
|
|
|
|
|
// important rules (when put into an agent stylesheet) and
|
|
|
|
|
// all (even author important) when put into an override stylesheet
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
|
// - default colors: ':root {color:#RRGGBB !important;
|
|
|
|
|
// background: #RRGGBB !important;}'
|
|
|
|
|
ColorToString(textColor,strColor);
|
|
|
|
|
ColorToString(bgColor,strBackgroundColor);
|
2005-09-23 12:08:09 +04:00
|
|
|
|
result = sheet->InsertRule(NS_LITERAL_STRING("*|*:root {color:") +
|
2004-02-20 20:49:01 +03:00
|
|
|
|
strColor +
|
|
|
|
|
NS_LITERAL_STRING(" !important; ") +
|
|
|
|
|
NS_LITERAL_STRING("border-color: -moz-use-text-color !important; ") +
|
|
|
|
|
NS_LITERAL_STRING("background:") +
|
|
|
|
|
strBackgroundColor +
|
|
|
|
|
NS_LITERAL_STRING(" !important; }"),
|
|
|
|
|
sInsertPrefSheetRulesAt, &index);
|
|
|
|
|
NS_ENSURE_SUCCESS(result, result);
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////
|
2005-09-23 12:08:09 +04:00
|
|
|
|
// - everything else inherits the color
|
|
|
|
|
// (the background color will be handled in
|
|
|
|
|
// nsRuleNode::ComputeBackgroundData)
|
|
|
|
|
result = sheet->InsertRule(NS_LITERAL_STRING("*|* {color: inherit !important; border-color: -moz-use-text-color !important; background-image: none !important; } "),
|
2004-02-20 20:49:01 +03:00
|
|
|
|
sInsertPrefSheetRulesAt, &index);
|
2000-10-11 12:33:01 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
} else {
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-06-26 10:10:03 +04:00
|
|
|
|
nsresult
|
|
|
|
|
PresShell::SetPrefNoScriptRule()
|
|
|
|
|
{
|
2005-01-03 22:37:54 +03:00
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
2006-07-25 04:29:26 +04:00
|
|
|
|
// also handle the case where print is done from print preview
|
|
|
|
|
// see bug #342439 for more details
|
2006-04-22 04:06:30 +04:00
|
|
|
|
PRBool scriptEnabled = mDocument->IsScriptEnabled() ||
|
2006-07-25 04:29:26 +04:00
|
|
|
|
((mPresContext->Type() == nsPresContext::eContext_PrintPreview ||
|
|
|
|
|
mPresContext->Type() == nsPresContext::eContext_Print) &&
|
2006-04-22 04:06:30 +04:00
|
|
|
|
NS_PTR_TO_INT32(mDocument->GetProperty(
|
|
|
|
|
nsLayoutAtoms::scriptEnabledBeforePrintPreview)));
|
|
|
|
|
|
|
|
|
|
if (scriptEnabled) {
|
2003-06-26 10:10:03 +04:00
|
|
|
|
if (!mPrefStyleSheet) {
|
|
|
|
|
rv = CreatePreferenceStyleSheet();
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
}
|
|
|
|
|
// get the DOM interface to the stylesheet
|
2005-01-03 22:37:54 +03:00
|
|
|
|
nsCOMPtr<nsIDOMCSSStyleSheet> sheet(do_QueryInterface(mPrefStyleSheet, &rv));
|
2003-06-26 10:10:03 +04:00
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
PRUint32 index = 0;
|
2005-01-03 22:37:54 +03:00
|
|
|
|
rv = sheet->InsertRule(NS_LITERAL_STRING("noscript{display:none!important}"),
|
|
|
|
|
sInsertPrefSheetRulesAt, &index);
|
2003-06-26 10:10:03 +04:00
|
|
|
|
}
|
2005-01-03 22:37:54 +03:00
|
|
|
|
|
|
|
|
|
return rv;
|
2003-06-26 10:10:03 +04:00
|
|
|
|
}
|
|
|
|
|
|
2005-03-03 21:04:38 +03:00
|
|
|
|
nsresult PresShell::SetPrefNoFramesRule(void)
|
|
|
|
|
{
|
|
|
|
|
NS_ASSERTION(mPresContext,"null prescontext not allowed");
|
|
|
|
|
if (!mPresContext) {
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
|
|
|
|
if (!mPrefStyleSheet) {
|
|
|
|
|
rv = CreatePreferenceStyleSheet();
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_ASSERTION(mPrefStyleSheet, "prefstylesheet should not be null");
|
|
|
|
|
|
|
|
|
|
// get the DOM interface to the stylesheet
|
|
|
|
|
nsCOMPtr<nsIDOMCSSStyleSheet> sheet(do_QueryInterface(mPrefStyleSheet, &rv));
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
PRBool allowSubframes = PR_TRUE;
|
|
|
|
|
nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
|
|
|
|
|
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
|
|
|
|
|
if (docShell) {
|
|
|
|
|
docShell->GetAllowSubframes(&allowSubframes);
|
|
|
|
|
}
|
|
|
|
|
if (!allowSubframes) {
|
|
|
|
|
PRUint32 index = 0;
|
|
|
|
|
rv = sheet->InsertRule(NS_LITERAL_STRING("noframes{display:block}"),
|
|
|
|
|
sInsertPrefSheetRulesAt, &index);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
rv = sheet->InsertRule(NS_LITERAL_STRING("frame, frameset, iframe {display:none!important}"),
|
|
|
|
|
sInsertPrefSheetRulesAt, &index);
|
|
|
|
|
}
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2000-10-11 12:33:01 +04:00
|
|
|
|
nsresult PresShell::SetPrefLinkRules(void)
|
|
|
|
|
{
|
|
|
|
|
NS_ASSERTION(mPresContext,"null prescontext not allowed");
|
2003-10-15 05:56:12 +04:00
|
|
|
|
if (!mPresContext) {
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
}
|
2000-10-11 12:33:01 +04:00
|
|
|
|
|
2003-10-15 05:56:12 +04:00
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
|
|
|
|
if (!mPrefStyleSheet) {
|
|
|
|
|
rv = CreatePreferenceStyleSheet();
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_ASSERTION(mPrefStyleSheet, "prefstylesheet should not be null");
|
|
|
|
|
|
|
|
|
|
// get the DOM interface to the stylesheet
|
|
|
|
|
nsCOMPtr<nsIDOMCSSStyleSheet> sheet(do_QueryInterface(mPrefStyleSheet, &rv));
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
// support default link colors:
|
|
|
|
|
// this means the link colors need to be overridable,
|
|
|
|
|
// which they are if we put them in the agent stylesheet,
|
|
|
|
|
// though if using an override sheet this will cause authors grief still
|
|
|
|
|
// In the agent stylesheet, they are !important when we are ignoring document colors
|
|
|
|
|
|
2004-02-01 01:41:40 +03:00
|
|
|
|
nscolor linkColor(mPresContext->DefaultLinkColor());
|
|
|
|
|
nscolor activeColor(mPresContext->DefaultActiveLinkColor());
|
|
|
|
|
nscolor visitedColor(mPresContext->DefaultVisitedLinkColor());
|
2003-10-15 05:56:12 +04:00
|
|
|
|
|
2004-02-20 20:49:01 +03:00
|
|
|
|
PRBool useDocColors =
|
|
|
|
|
mPresContext->GetCachedBoolPref(kPresContext_UseDocumentColors);
|
2003-10-15 05:56:12 +04:00
|
|
|
|
NS_NAMED_LITERAL_STRING(notImportantStr, "}");
|
|
|
|
|
NS_NAMED_LITERAL_STRING(importantStr, "!important}");
|
|
|
|
|
const nsAString& ruleClose = useDocColors ? notImportantStr : importantStr;
|
|
|
|
|
PRUint32 index = 0;
|
|
|
|
|
nsAutoString strColor;
|
|
|
|
|
|
|
|
|
|
// insert a rule to color links: '*|*:link {color: #RRGGBB [!important];}'
|
|
|
|
|
ColorToString(linkColor, strColor);
|
|
|
|
|
rv = sheet->InsertRule(NS_LITERAL_STRING("*|*:link{color:") +
|
|
|
|
|
strColor + ruleClose,
|
|
|
|
|
sInsertPrefSheetRulesAt, &index);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
// - visited links: '*|*:visited {color: #RRGGBB [!important];}'
|
|
|
|
|
ColorToString(visitedColor, strColor);
|
|
|
|
|
rv = sheet->InsertRule(NS_LITERAL_STRING("*|*:visited{color:") +
|
|
|
|
|
strColor + ruleClose,
|
|
|
|
|
sInsertPrefSheetRulesAt, &index);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
// - active links: '*|*:-moz-any-link:active {color: #RRGGBB [!important];}'
|
|
|
|
|
ColorToString(activeColor, strColor);
|
|
|
|
|
rv = sheet->InsertRule(NS_LITERAL_STRING("*|*:-moz-any-link:active{color:") +
|
|
|
|
|
strColor + ruleClose,
|
|
|
|
|
sInsertPrefSheetRulesAt, &index);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
2004-02-20 20:49:01 +03:00
|
|
|
|
PRBool underlineLinks =
|
|
|
|
|
mPresContext->GetCachedBoolPref(kPresContext_UnderlineLinks);
|
2003-10-15 05:56:12 +04:00
|
|
|
|
|
|
|
|
|
if (underlineLinks) {
|
|
|
|
|
// create a rule to make underlining happen
|
|
|
|
|
// '*|*:-moz-any-link {text-decoration:[underline|none];}'
|
|
|
|
|
// no need for important, we want these to be overridable
|
|
|
|
|
// NOTE: these must go in the agent stylesheet or they cannot be
|
|
|
|
|
// overridden by authors
|
|
|
|
|
rv = sheet->InsertRule(NS_LITERAL_STRING("*|*:-moz-any-link{text-decoration:underline}"),
|
|
|
|
|
sInsertPrefSheetRulesAt, &index);
|
2000-10-11 12:33:01 +04:00
|
|
|
|
} else {
|
2003-10-15 05:56:12 +04:00
|
|
|
|
rv = sheet->InsertRule(NS_LITERAL_STRING("*|*:-moz-any-link{text-decoration:none}"),
|
|
|
|
|
sInsertPrefSheetRulesAt, &index);
|
2000-10-11 12:33:01 +04:00
|
|
|
|
}
|
2003-10-15 05:56:12 +04:00
|
|
|
|
|
|
|
|
|
return rv;
|
2000-10-11 12:33:01 +04:00
|
|
|
|
}
|
|
|
|
|
|
2001-04-10 02:17:11 +04:00
|
|
|
|
nsresult PresShell::SetPrefFocusRules(void)
|
|
|
|
|
{
|
|
|
|
|
NS_ASSERTION(mPresContext,"null prescontext not allowed");
|
|
|
|
|
nsresult result = NS_OK;
|
|
|
|
|
|
|
|
|
|
if (!mPresContext)
|
|
|
|
|
result = NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(result) && !mPrefStyleSheet)
|
|
|
|
|
result = CreatePreferenceStyleSheet();
|
|
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(result)) {
|
|
|
|
|
NS_ASSERTION(mPrefStyleSheet, "prefstylesheet should not be null");
|
|
|
|
|
|
|
|
|
|
// get the DOM interface to the stylesheet
|
|
|
|
|
nsCOMPtr<nsIDOMCSSStyleSheet> sheet(do_QueryInterface(mPrefStyleSheet,&result));
|
|
|
|
|
if (NS_SUCCEEDED(result)) {
|
2004-02-20 20:49:01 +03:00
|
|
|
|
if (mPresContext->GetUseFocusColors()) {
|
2004-02-01 01:41:40 +03:00
|
|
|
|
nscolor focusBackground(mPresContext->FocusBackgroundColor());
|
|
|
|
|
nscolor focusText(mPresContext->FocusTextColor());
|
|
|
|
|
|
2001-04-10 02:17:11 +04:00
|
|
|
|
// insert a rule to make focus the preferred color
|
|
|
|
|
PRUint32 index = 0;
|
|
|
|
|
nsAutoString strRule, strColor;
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
|
// - focus: '*:focus
|
|
|
|
|
ColorToString(focusText,strColor);
|
2004-06-17 04:13:25 +04:00
|
|
|
|
strRule.AppendLiteral("*:focus,*:focus>font {color: ");
|
2001-04-10 02:17:11 +04:00
|
|
|
|
strRule.Append(strColor);
|
2004-06-17 04:13:25 +04:00
|
|
|
|
strRule.AppendLiteral(" !important; background-color: ");
|
2001-04-10 02:17:11 +04:00
|
|
|
|
ColorToString(focusBackground,strColor);
|
|
|
|
|
strRule.Append(strColor);
|
2004-06-17 04:13:25 +04:00
|
|
|
|
strRule.AppendLiteral(" !important; } ");
|
2001-04-10 02:17:11 +04:00
|
|
|
|
// insert the rules
|
2003-07-18 05:26:47 +04:00
|
|
|
|
result = sheet->InsertRule(strRule, sInsertPrefSheetRulesAt, &index);
|
2001-04-10 02:17:11 +04:00
|
|
|
|
}
|
2004-02-01 01:41:40 +03:00
|
|
|
|
PRUint8 focusRingWidth = mPresContext->FocusRingWidth();
|
2004-02-20 20:49:01 +03:00
|
|
|
|
PRBool focusRingOnAnything = mPresContext->GetFocusRingOnAnything();
|
2001-04-10 02:17:11 +04:00
|
|
|
|
|
|
|
|
|
if ((NS_SUCCEEDED(result) && focusRingWidth != 1 && focusRingWidth <= 4 ) || focusRingOnAnything) {
|
|
|
|
|
PRUint32 index = 0;
|
|
|
|
|
nsAutoString strRule;
|
|
|
|
|
if (!focusRingOnAnything)
|
2004-06-17 04:13:25 +04:00
|
|
|
|
strRule.AppendLiteral("*|*:link:focus, *|*:visited"); // If we only want focus rings on the normal things like links
|
2005-03-27 15:36:08 +04:00
|
|
|
|
strRule.AppendLiteral(":focus {outline: "); // For example 3px dotted WindowText (maximum 4)
|
2001-04-10 02:17:11 +04:00
|
|
|
|
strRule.AppendInt(focusRingWidth);
|
2004-06-17 04:13:25 +04:00
|
|
|
|
strRule.AppendLiteral("px dotted WindowText !important; } "); // For example 3px dotted WindowText
|
2001-04-10 02:17:11 +04:00
|
|
|
|
// insert the rules
|
2003-07-18 05:26:47 +04:00
|
|
|
|
result = sheet->InsertRule(strRule, sInsertPrefSheetRulesAt, &index);
|
2001-09-09 01:42:02 +04:00
|
|
|
|
NS_ENSURE_SUCCESS(result, result);
|
2001-04-10 02:17:11 +04:00
|
|
|
|
if (focusRingWidth != 1) {
|
|
|
|
|
// If the focus ring width is different from the default, fix buttons with rings
|
2004-06-17 04:13:25 +04:00
|
|
|
|
strRule.AssignLiteral("button::-moz-focus-inner, input[type=\"reset\"]::-moz-focus-inner,");
|
|
|
|
|
strRule.AppendLiteral("input[type=\"button\"]::-moz-focus-inner, ");
|
|
|
|
|
strRule.AppendLiteral("input[type=\"submit\"]::-moz-focus-inner { padding: 1px 2px 1px 2px; border: ");
|
2001-04-10 02:17:11 +04:00
|
|
|
|
strRule.AppendInt(focusRingWidth);
|
2004-06-17 04:13:25 +04:00
|
|
|
|
strRule.AppendLiteral("px dotted transparent !important; } ");
|
2003-07-18 05:26:47 +04:00
|
|
|
|
result = sheet->InsertRule(strRule, sInsertPrefSheetRulesAt, &index);
|
2001-09-09 01:42:02 +04:00
|
|
|
|
NS_ENSURE_SUCCESS(result, result);
|
|
|
|
|
|
2004-06-17 04:13:25 +04:00
|
|
|
|
strRule.AssignLiteral("button:focus::-moz-focus-inner, input[type=\"reset\"]:focus::-moz-focus-inner,");
|
|
|
|
|
strRule.AppendLiteral("input[type=\"button\"]:focus::-moz-focus-inner, input[type=\"submit\"]:focus::-moz-focus-inner {");
|
|
|
|
|
strRule.AppendLiteral("border-color: ButtonText !important; }");
|
2003-07-18 05:26:47 +04:00
|
|
|
|
result = sheet->InsertRule(strRule, sInsertPrefSheetRulesAt, &index);
|
2001-09-09 01:42:02 +04:00
|
|
|
|
}
|
2001-04-10 02:17:11 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2006-06-08 18:32:20 +04:00
|
|
|
|
void
|
|
|
|
|
PresShell::AddUserSheet(nsISupports* aSheet)
|
|
|
|
|
{
|
|
|
|
|
// Make sure this does what DocumentViewerImpl::CreateStyleSet does wrt
|
|
|
|
|
// ordering. We want this new sheet to come after all the existing stylesheet
|
|
|
|
|
// service sheets, but before other user sheets; see nsIStyleSheetService.idl
|
|
|
|
|
// for the ordering. Just remove and readd all the nsStyleSheetService
|
|
|
|
|
// sheets.
|
|
|
|
|
nsCOMPtr<nsIStyleSheetService> dummy =
|
|
|
|
|
do_GetService(NS_STYLESHEETSERVICE_CONTRACTID);
|
|
|
|
|
|
|
|
|
|
mStyleSet->BeginUpdate();
|
|
|
|
|
|
|
|
|
|
nsStyleSheetService *sheetService = nsStyleSheetService::gInstance;
|
|
|
|
|
nsCOMArray<nsIStyleSheet> & userSheets = *sheetService->UserStyleSheets();
|
|
|
|
|
PRInt32 i;
|
|
|
|
|
// Iterate forwards when removing so the searches for RemoveStyleSheet are as
|
|
|
|
|
// short as possible.
|
|
|
|
|
for (i = 0; i < userSheets.Count(); ++i) {
|
|
|
|
|
mStyleSet->RemoveStyleSheet(nsStyleSet::eUserSheet, userSheets[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now iterate backwards, so that the order of userSheets will be the same as
|
|
|
|
|
// the order of sheets from it in the style set.
|
|
|
|
|
for (i = userSheets.Count() - 1; i >= 0; --i) {
|
|
|
|
|
mStyleSet->PrependStyleSheet(nsStyleSet::eUserSheet, userSheets[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mStyleSet->EndUpdate();
|
|
|
|
|
|
|
|
|
|
ReconstructStyleData();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PresShell::AddAgentSheet(nsISupports* aSheet)
|
|
|
|
|
{
|
|
|
|
|
// Make sure this does what DocumentViewerImpl::CreateStyleSet does
|
|
|
|
|
// wrt ordering.
|
|
|
|
|
nsCOMPtr<nsIStyleSheet> sheet = do_QueryInterface(aSheet);
|
|
|
|
|
if (!sheet) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mStyleSet->AppendStyleSheet(nsStyleSet::eAgentSheet, sheet);
|
|
|
|
|
ReconstructStyleData();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PresShell::RemoveSheet(nsStyleSet::sheetType aType, nsISupports* aSheet)
|
|
|
|
|
{
|
|
|
|
|
nsCOMPtr<nsIStyleSheet> sheet = do_QueryInterface(aSheet);
|
|
|
|
|
if (!sheet) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mStyleSet->RemoveStyleSheet(aType, sheet);
|
|
|
|
|
ReconstructStyleData();
|
|
|
|
|
}
|
2001-04-10 02:17:11 +04:00
|
|
|
|
|
2000-04-28 10:21:31 +04:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::SetDisplaySelection(PRInt16 aToggle)
|
|
|
|
|
{
|
2006-04-26 06:01:07 +04:00
|
|
|
|
mSelection->SetDisplaySelection(aToggle);
|
|
|
|
|
return NS_OK;
|
2000-04-28 10:21:31 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::GetDisplaySelection(PRInt16 *aToggle)
|
|
|
|
|
{
|
2006-04-26 06:01:07 +04:00
|
|
|
|
*aToggle = mSelection->GetDisplaySelection();
|
|
|
|
|
return NS_OK;
|
2000-04-28 10:21:31 +04:00
|
|
|
|
}
|
|
|
|
|
|
1999-02-12 20:45:58 +03:00
|
|
|
|
NS_IMETHODIMP
|
2000-09-14 15:45:01 +04:00
|
|
|
|
PresShell::GetSelection(SelectionType aType, nsISelection **aSelection)
|
1998-12-08 21:26:06 +03:00
|
|
|
|
{
|
|
|
|
|
if (!aSelection || !mSelection)
|
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
2006-04-26 06:01:07 +04:00
|
|
|
|
|
|
|
|
|
*aSelection = mSelection->GetSelection(aType);
|
|
|
|
|
|
|
|
|
|
if (!(*aSelection))
|
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
|
|
|
|
|
NS_ADDREF(*aSelection);
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsISelection*
|
|
|
|
|
PresShell::GetCurrentSelection(SelectionType aType)
|
|
|
|
|
{
|
|
|
|
|
if (!mSelection)
|
|
|
|
|
return nsnull;
|
|
|
|
|
|
|
|
|
|
return mSelection->GetSelection(aType);
|
1998-12-08 21:26:06 +03:00
|
|
|
|
}
|
|
|
|
|
|
1999-08-31 01:54:40 +04:00
|
|
|
|
NS_IMETHODIMP
|
2002-06-14 00:35:12 +04:00
|
|
|
|
PresShell::ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion, PRBool aIsSynchronous)
|
1999-08-31 01:54:40 +04:00
|
|
|
|
{
|
|
|
|
|
if (!mSelection)
|
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
2002-06-14 00:35:12 +04:00
|
|
|
|
return mSelection->ScrollSelectionIntoView(aType, aRegion, aIsSynchronous);
|
1999-08-31 01:54:40 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::RepaintSelection(SelectionType aType)
|
|
|
|
|
{
|
|
|
|
|
if (!mSelection)
|
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
2006-04-26 06:01:07 +04:00
|
|
|
|
return mSelection->RepaintSelection(aType);
|
1999-08-31 01:54:40 +04:00
|
|
|
|
}
|
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
|
// Make shell be a document observer
|
1998-12-29 07:56:31 +03:00
|
|
|
|
NS_IMETHODIMP
|
1998-05-09 07:22:41 +04:00
|
|
|
|
PresShell::BeginObservingDocument()
|
1998-04-14 00:24:54 +04:00
|
|
|
|
{
|
1999-05-05 03:27:42 +04:00
|
|
|
|
if (mDocument) {
|
1998-04-14 00:24:54 +04:00
|
|
|
|
mDocument->AddObserver(this);
|
2005-03-25 07:27:21 +03:00
|
|
|
|
if (mIsDocumentGone) {
|
|
|
|
|
NS_WARNING("Adding a presshell that was disconnected from the document "
|
|
|
|
|
"as a document observer? Sounds wrong...");
|
|
|
|
|
mIsDocumentGone = PR_FALSE;
|
|
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
|
}
|
1998-12-29 07:56:31 +03:00
|
|
|
|
return NS_OK;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Make shell stop being a document observer
|
1998-12-29 07:56:31 +03:00
|
|
|
|
NS_IMETHODIMP
|
1998-05-09 07:22:41 +04:00
|
|
|
|
PresShell::EndObservingDocument()
|
1998-04-14 00:24:54 +04:00
|
|
|
|
{
|
2005-02-18 19:11:53 +03:00
|
|
|
|
// XXXbz do we need to tell the frame constructor that the document
|
|
|
|
|
// is gone, perhaps? Except for printing it's NOT gone, sometimes.
|
2001-05-02 02:54:11 +04:00
|
|
|
|
mIsDocumentGone = PR_TRUE;
|
1999-05-05 03:27:42 +04:00
|
|
|
|
if (mDocument) {
|
1998-04-14 00:24:54 +04:00
|
|
|
|
mDocument->RemoveObserver(this);
|
|
|
|
|
}
|
1998-12-29 07:56:31 +03:00
|
|
|
|
return NS_OK;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
1999-08-28 01:50:37 +04:00
|
|
|
|
#ifdef DEBUG_kipp
|
|
|
|
|
char* nsPresShell_ReflowStackPointerTop;
|
|
|
|
|
#endif
|
|
|
|
|
|
2003-04-03 12:14:51 +04:00
|
|
|
|
static void CheckForFocus(nsPIDOMWindow* aOurWindow,
|
|
|
|
|
nsIFocusController* aFocusController,
|
|
|
|
|
nsIDocument* aDocument)
|
|
|
|
|
{
|
2005-07-31 00:57:07 +04:00
|
|
|
|
NS_ASSERTION(aOurWindow->IsOuterWindow(),
|
|
|
|
|
"Uh, our window has to be an outer window!");
|
|
|
|
|
|
2003-04-03 12:14:51 +04:00
|
|
|
|
// Now that we have a root frame, we can set focus on the presshell.
|
|
|
|
|
// We do this only if our DOM window is currently focused or is an
|
|
|
|
|
// an ancestor of a previously focused window.
|
2000-02-13 09:07:38 +03:00
|
|
|
|
|
2003-04-03 12:14:51 +04:00
|
|
|
|
if (!aFocusController)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMWindowInternal> ourWin = do_QueryInterface(aOurWindow);
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMWindowInternal> focusedWindow;
|
|
|
|
|
aFocusController->GetFocusedWindow(getter_AddRefs(focusedWindow));
|
|
|
|
|
if (!focusedWindow) {
|
|
|
|
|
// This should never really happen, but if it does, assume
|
|
|
|
|
// we can focus ourself to keep the window from being keydead.
|
|
|
|
|
focusedWindow = ourWin;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Walk up the document chain, starting with focusedWindow's document.
|
|
|
|
|
// We stop walking when we find a document that has a null DOMWindow
|
|
|
|
|
// (meaning that the DOMWindow has a new document now) or find ourWin
|
2003-05-12 11:11:16 +04:00
|
|
|
|
// as the document's window. We also stop if we hit aDocument, since
|
|
|
|
|
// that means there is a child document which loaded before us that's
|
|
|
|
|
// already been given focus.
|
2003-04-03 12:14:51 +04:00
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMDocument> focusedDOMDoc;
|
|
|
|
|
focusedWindow->GetDocument(getter_AddRefs(focusedDOMDoc));
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocument> curDoc = do_QueryInterface(focusedDOMDoc);
|
2003-05-12 11:11:16 +04:00
|
|
|
|
if (!curDoc) {
|
|
|
|
|
// This can happen if the previously focused DOM window has been
|
|
|
|
|
// unhooked from its document during document teardown. We don't
|
2003-06-11 02:17:58 +04:00
|
|
|
|
// really have any other information to help us determine where
|
2003-05-12 11:11:16 +04:00
|
|
|
|
// focusedWindow fits into the DOM window hierarchy. For now, we'll
|
|
|
|
|
// go ahead and allow this window to take focus, so that something
|
|
|
|
|
// ends up focused.
|
|
|
|
|
|
|
|
|
|
curDoc = aDocument;
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-03 12:14:51 +04:00
|
|
|
|
while (curDoc) {
|
2005-08-12 08:11:00 +04:00
|
|
|
|
nsPIDOMWindow *curWin = curDoc->GetWindow();
|
2005-07-31 00:57:07 +04:00
|
|
|
|
|
2005-08-12 08:11:00 +04:00
|
|
|
|
if (!curWin || curWin == ourWin)
|
2003-04-03 12:14:51 +04:00
|
|
|
|
break;
|
|
|
|
|
|
2003-10-22 10:09:48 +04:00
|
|
|
|
curDoc = curDoc->GetParentDocument();
|
|
|
|
|
if (curDoc == aDocument)
|
2003-05-12 11:11:16 +04:00
|
|
|
|
return;
|
2000-02-13 09:07:38 +03:00
|
|
|
|
}
|
2003-04-03 12:14:51 +04:00
|
|
|
|
|
|
|
|
|
if (!curDoc) {
|
|
|
|
|
// We reached the top of the document chain, and did not encounter ourWin
|
|
|
|
|
// or a windowless document. So, focus should be unaffected by this
|
|
|
|
|
// document load.
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PRBool active;
|
|
|
|
|
aFocusController->GetActive(&active);
|
|
|
|
|
if (active)
|
|
|
|
|
ourWin->Focus();
|
|
|
|
|
|
|
|
|
|
// We need to ensure that the focus controller is updated, since it may be
|
|
|
|
|
// suppressed when this function is called.
|
|
|
|
|
aFocusController->SetFocusedWindow(ourWin);
|
2000-02-13 09:07:38 +03:00
|
|
|
|
}
|
2000-05-15 07:37:21 +04:00
|
|
|
|
|
2002-09-06 09:44:31 +04:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::GetDidInitialReflow(PRBool *aDidInitialReflow)
|
|
|
|
|
{
|
|
|
|
|
if (!aDidInitialReflow)
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
|
|
*aDidInitialReflow = mDidInitialReflow;
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
1998-08-28 06:54:06 +04:00
|
|
|
|
NS_IMETHODIMP
|
1998-09-10 23:32:14 +04:00
|
|
|
|
PresShell::InitialReflow(nscoord aWidth, nscoord aHeight)
|
1998-04-14 00:24:54 +04:00
|
|
|
|
{
|
2006-05-15 21:51:35 +04:00
|
|
|
|
nsCOMPtr<nsIPresShell> kungFuDeathGrip(this);
|
2001-08-07 22:57:15 +04:00
|
|
|
|
mDidInitialReflow = PR_TRUE;
|
1998-09-10 23:32:14 +04:00
|
|
|
|
|
1999-12-23 05:02:33 +03:00
|
|
|
|
#ifdef NS_DEBUG
|
|
|
|
|
if (VERIFY_REFLOW_NOISY_RC & gVerifyReflowFlags) {
|
|
|
|
|
if (mDocument) {
|
2004-01-10 02:54:21 +03:00
|
|
|
|
nsIURI *uri = mDocument->GetDocumentURI();
|
1999-12-23 05:02:33 +03:00
|
|
|
|
if (uri) {
|
2002-03-06 10:48:55 +03:00
|
|
|
|
nsCAutoString url;
|
|
|
|
|
uri->GetSpec(url);
|
|
|
|
|
printf("*** PresShell::InitialReflow (this=%p, url='%s')\n", (void*)this, url.get());
|
1999-12-23 05:02:33 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2003-02-28 02:09:51 +03:00
|
|
|
|
if (mCaret)
|
|
|
|
|
mCaret->EraseCaret();
|
2004-10-09 05:39:21 +04:00
|
|
|
|
|
|
|
|
|
NS_ASSERTION(mViewManager, "Should have view manager");
|
|
|
|
|
// Painting should be suppressed for the initial reflow, so this won't
|
|
|
|
|
// really do anything right now, but it will be useful when we
|
|
|
|
|
// start batching widget changes
|
|
|
|
|
mViewManager->BeginUpdateViewBatch();
|
|
|
|
|
|
2000-04-17 11:13:57 +04:00
|
|
|
|
WillCauseReflow();
|
2006-04-28 08:33:41 +04:00
|
|
|
|
WillDoReflow();
|
1998-06-03 19:46:54 +04:00
|
|
|
|
|
1999-05-05 03:27:42 +04:00
|
|
|
|
if (mPresContext) {
|
1998-04-14 00:24:54 +04:00
|
|
|
|
nsRect r(0, 0, aWidth, aHeight);
|
|
|
|
|
mPresContext->SetVisibleArea(r);
|
|
|
|
|
}
|
|
|
|
|
|
2003-10-22 10:09:48 +04:00
|
|
|
|
nsIContent *root = mDocument ? mDocument->GetRootContent() : nsnull;
|
1999-02-03 22:38:16 +03:00
|
|
|
|
|
1999-10-19 02:20:37 +04:00
|
|
|
|
// Get the root frame from the frame manager
|
2004-03-06 07:46:11 +03:00
|
|
|
|
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
|
1999-10-19 02:20:37 +04:00
|
|
|
|
|
2001-06-20 07:27:48 +04:00
|
|
|
|
if (root) {
|
2002-08-24 18:41:28 +04:00
|
|
|
|
MOZ_TIMER_DEBUGLOG(("Reset and start: Frame Creation: PresShell::InitialReflow(), this=%p\n",
|
|
|
|
|
(void*)this));
|
1999-11-10 06:41:09 +03:00
|
|
|
|
MOZ_TIMER_RESET(mFrameCreationWatch);
|
|
|
|
|
MOZ_TIMER_START(mFrameCreationWatch);
|
1999-10-19 02:20:37 +04:00
|
|
|
|
|
|
|
|
|
if (!rootFrame) {
|
1999-02-03 22:38:16 +03:00
|
|
|
|
// Have style sheet processor construct a frame for the
|
|
|
|
|
// precursors to the root content object's frame
|
2005-02-18 19:11:53 +03:00
|
|
|
|
mFrameConstructor->ConstructRootFrame(root, &rootFrame);
|
2004-03-06 07:46:11 +03:00
|
|
|
|
FrameManager()->SetRootFrame(rootFrame);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
}
|
1999-02-03 22:38:16 +03:00
|
|
|
|
|
|
|
|
|
// Have the style sheet processor construct frame for the root
|
|
|
|
|
// content object down
|
2005-08-17 01:35:58 +04:00
|
|
|
|
mFrameConstructor->ContentInserted(nsnull, root, 0,
|
2004-01-08 01:30:53 +03:00
|
|
|
|
nsnull, PR_FALSE);
|
1999-09-21 11:53:49 +04:00
|
|
|
|
VERIFY_STYLE_TREE;
|
2002-08-24 18:41:28 +04:00
|
|
|
|
MOZ_TIMER_DEBUGLOG(("Stop: Frame Creation: PresShell::InitialReflow(), this=%p\n",
|
|
|
|
|
(void*)this));
|
1999-11-10 06:41:09 +03:00
|
|
|
|
MOZ_TIMER_STOP(mFrameCreationWatch);
|
2006-05-15 21:51:35 +04:00
|
|
|
|
|
|
|
|
|
// Something in mFrameConstructor->ContentInserted may have caused
|
|
|
|
|
// Destroy() to get called, bug 337586.
|
|
|
|
|
NS_ENSURE_STATE(!mHaveShutDown);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
1999-10-19 02:20:37 +04:00
|
|
|
|
if (rootFrame) {
|
2002-08-24 18:41:28 +04:00
|
|
|
|
MOZ_TIMER_DEBUGLOG(("Reset and start: Reflow: PresShell::InitialReflow(), this=%p\n",
|
|
|
|
|
(void*)this));
|
1999-11-10 06:41:09 +03:00
|
|
|
|
MOZ_TIMER_RESET(mReflowWatch);
|
|
|
|
|
MOZ_TIMER_START(mReflowWatch);
|
1998-09-10 23:32:14 +04:00
|
|
|
|
// Kick off a top-down reflow
|
|
|
|
|
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
|
|
|
|
|
("enter nsPresShell::InitialReflow: %d,%d", aWidth, aHeight));
|
|
|
|
|
#ifdef NS_DEBUG
|
1999-11-02 01:12:45 +03:00
|
|
|
|
if (nsIFrameDebug::GetVerifyTreeEnable()) {
|
|
|
|
|
nsIFrameDebug* frameDebug;
|
|
|
|
|
|
2000-01-04 23:24:09 +03:00
|
|
|
|
if (NS_SUCCEEDED(rootFrame->QueryInterface(NS_GET_IID(nsIFrameDebug),
|
|
|
|
|
(void**)&frameDebug))) {
|
1999-11-02 01:12:45 +03:00
|
|
|
|
frameDebug->VerifyTree();
|
|
|
|
|
}
|
1998-09-10 23:32:14 +04:00
|
|
|
|
}
|
1999-08-28 01:50:37 +04:00
|
|
|
|
#endif
|
|
|
|
|
#ifdef DEBUG_kipp
|
|
|
|
|
nsPresShell_ReflowStackPointerTop = (char*) &aWidth;
|
1998-09-10 23:32:14 +04:00
|
|
|
|
#endif
|
2004-02-01 13:09:07 +03:00
|
|
|
|
nsRect bounds = mPresContext->GetVisibleArea();
|
1998-10-02 05:12:39 +04:00
|
|
|
|
nsSize maxSize(bounds.width, bounds.height);
|
|
|
|
|
nsHTMLReflowMetrics desiredSize(nsnull);
|
|
|
|
|
nsReflowStatus status;
|
|
|
|
|
nsIRenderingContext* rcx = nsnull;
|
|
|
|
|
|
2000-01-12 01:15:20 +03:00
|
|
|
|
nsresult rv=CreateRenderingContext(rootFrame, &rcx);
|
2003-03-12 06:22:11 +03:00
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
1998-10-02 05:12:39 +04:00
|
|
|
|
|
2006-04-18 09:44:02 +04:00
|
|
|
|
AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Reflow);
|
2000-08-22 00:10:07 +04:00
|
|
|
|
mIsReflowing = PR_TRUE;
|
|
|
|
|
|
1999-11-24 09:03:41 +03:00
|
|
|
|
nsHTMLReflowState reflowState(mPresContext, rootFrame,
|
1999-03-05 07:29:11 +03:00
|
|
|
|
eReflowReason_Initial, rcx, maxSize);
|
1999-11-24 09:03:41 +03:00
|
|
|
|
rootFrame->WillReflow(mPresContext);
|
2004-12-27 18:05:18 +03:00
|
|
|
|
nsContainerFrame::PositionFrameView(rootFrame);
|
1999-11-24 09:03:41 +03:00
|
|
|
|
rootFrame->Reflow(mPresContext, desiredSize, reflowState, status);
|
2003-06-30 14:46:59 +04:00
|
|
|
|
rootFrame->SetSize(nsSize(desiredSize.width, desiredSize.height));
|
1999-10-30 06:52:11 +04:00
|
|
|
|
mPresContext->SetVisibleArea(nsRect(0,0,desiredSize.width,desiredSize.height));
|
2001-09-06 00:27:19 +04:00
|
|
|
|
|
2003-06-30 14:46:59 +04:00
|
|
|
|
nsContainerFrame::SyncFrameViewAfterReflow(mPresContext, rootFrame, rootFrame->GetView(),
|
|
|
|
|
nsnull);
|
2001-12-07 17:51:12 +03:00
|
|
|
|
rootFrame->DidReflow(mPresContext, nsnull, NS_FRAME_REFLOW_FINISHED);
|
1999-07-08 02:34:31 +04:00
|
|
|
|
|
1998-09-10 23:32:14 +04:00
|
|
|
|
#ifdef NS_DEBUG
|
1999-11-02 01:12:45 +03:00
|
|
|
|
if (nsIFrameDebug::GetVerifyTreeEnable()) {
|
|
|
|
|
nsIFrameDebug* frameDebug;
|
|
|
|
|
|
2000-01-04 23:24:09 +03:00
|
|
|
|
if (NS_SUCCEEDED(rootFrame->QueryInterface(NS_GET_IID(nsIFrameDebug),
|
|
|
|
|
(void**)&frameDebug))) {
|
1999-11-02 01:12:45 +03:00
|
|
|
|
frameDebug->VerifyTree();
|
|
|
|
|
}
|
1998-10-01 08:46:11 +04:00
|
|
|
|
}
|
1999-10-30 06:52:11 +04:00
|
|
|
|
#endif
|
|
|
|
|
VERIFY_STYLE_TREE;
|
1998-10-02 05:12:39 +04:00
|
|
|
|
NS_IF_RELEASE(rcx);
|
1998-09-10 23:32:14 +04:00
|
|
|
|
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS, ("exit nsPresShell::InitialReflow"));
|
2002-08-24 18:41:28 +04:00
|
|
|
|
MOZ_TIMER_DEBUGLOG(("Stop: Reflow: PresShell::InitialReflow(), this=%p\n", (void*)this));
|
1999-11-10 06:41:09 +03:00
|
|
|
|
MOZ_TIMER_STOP(mReflowWatch);
|
2000-08-22 00:10:07 +04:00
|
|
|
|
|
|
|
|
|
mIsReflowing = PR_FALSE;
|
1998-09-10 23:32:14 +04:00
|
|
|
|
}
|
|
|
|
|
|
2000-04-17 11:13:57 +04:00
|
|
|
|
DidCauseReflow();
|
2004-02-04 03:11:59 +03:00
|
|
|
|
DidDoReflow();
|
2004-01-21 07:15:00 +03:00
|
|
|
|
|
2004-10-09 05:39:21 +04:00
|
|
|
|
mViewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
|
|
|
|
|
|
1999-10-15 08:29:30 +04:00
|
|
|
|
if (mViewManager && mCaret && !mViewEventListener) {
|
|
|
|
|
nsIScrollableView* scrollingView = nsnull;
|
|
|
|
|
mViewManager->GetRootScrollableView(&scrollingView);
|
|
|
|
|
|
|
|
|
|
if (scrollingView) {
|
|
|
|
|
mViewEventListener = new PresShellViewEventListener;
|
|
|
|
|
|
|
|
|
|
if (!mViewEventListener)
|
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
|
|
NS_ADDREF(mViewEventListener);
|
|
|
|
|
mViewEventListener->SetPresShell(this);
|
|
|
|
|
scrollingView->AddScrollPositionListener((nsIScrollPositionListener *)mViewEventListener);
|
|
|
|
|
mViewManager->AddCompositeListener((nsICompositeListener *)mViewEventListener);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-05-03 05:41:10 +04:00
|
|
|
|
// For printing, we just immediately unsuppress.
|
2004-03-03 21:24:20 +03:00
|
|
|
|
if (!mPresContext->IsPaginated()) {
|
2001-05-03 05:41:10 +04:00
|
|
|
|
// Kick off a one-shot timer based off our pref value. When this timer
|
|
|
|
|
// fires, if painting is still locked down, then we will go ahead and
|
|
|
|
|
// trigger a full invalidate and allow painting to proceed normally.
|
|
|
|
|
mPaintingSuppressed = PR_TRUE;
|
|
|
|
|
mPaintSuppressionTimer = do_CreateInstance("@mozilla.org/timer;1");
|
|
|
|
|
if (!mPaintSuppressionTimer)
|
|
|
|
|
// Uh-oh. We must be out of memory. No point in keeping painting locked down.
|
|
|
|
|
mPaintingSuppressed = PR_FALSE;
|
|
|
|
|
else {
|
|
|
|
|
// Initialize the timer.
|
2004-04-30 03:34:19 +04:00
|
|
|
|
|
|
|
|
|
// Default to PAINTLOCK_EVENT_DELAY if we can't get the pref value.
|
|
|
|
|
PRInt32 delay =
|
|
|
|
|
nsContentUtils::GetIntPref("nglayout.initialpaint.delay",
|
|
|
|
|
PAINTLOCK_EVENT_DELAY);
|
2002-09-07 09:38:16 +04:00
|
|
|
|
|
2004-04-30 03:34:19 +04:00
|
|
|
|
mPaintSuppressionTimer->InitWithFuncCallback(sPaintSuppressionCallback,
|
|
|
|
|
this, delay,
|
2002-09-07 09:38:16 +04:00
|
|
|
|
nsITimer::TYPE_ONE_SHOT);
|
2001-05-03 05:41:10 +04:00
|
|
|
|
}
|
2001-04-25 23:52:49 +04:00
|
|
|
|
}
|
|
|
|
|
|
1998-09-10 23:32:14 +04:00
|
|
|
|
return NS_OK; //XXX this needs to be real. MMP
|
|
|
|
|
}
|
|
|
|
|
|
2001-04-25 23:52:49 +04:00
|
|
|
|
void
|
|
|
|
|
PresShell::sPaintSuppressionCallback(nsITimer *aTimer, void* aPresShell)
|
|
|
|
|
{
|
|
|
|
|
PresShell* self = NS_STATIC_CAST(PresShell*, aPresShell);
|
|
|
|
|
if (self)
|
2001-05-02 02:54:11 +04:00
|
|
|
|
self->UnsuppressPainting();
|
2001-04-25 23:52:49 +04:00
|
|
|
|
}
|
|
|
|
|
|
1998-09-10 23:32:14 +04:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
|
|
|
|
|
{
|
2001-05-19 03:42:54 +04:00
|
|
|
|
PRBool firstReflow = PR_FALSE;
|
|
|
|
|
|
2004-10-09 05:39:21 +04:00
|
|
|
|
NS_ASSERTION(mViewManager, "Must have view manager");
|
|
|
|
|
mViewManager->BeginUpdateViewBatch();
|
|
|
|
|
|
2004-01-21 07:15:00 +03:00
|
|
|
|
WillCauseReflow();
|
2006-04-28 08:33:41 +04:00
|
|
|
|
WillDoReflow();
|
2003-02-28 02:09:51 +03:00
|
|
|
|
|
2005-05-13 23:47:38 +04:00
|
|
|
|
// If we don't have a root frame yet, that means we haven't had our initial
|
|
|
|
|
// reflow... If that's the case, and aWidth or aHeight is unconstrained,
|
|
|
|
|
// ignore them altogether.
|
|
|
|
|
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
|
|
|
|
|
|
|
|
|
|
if (!rootFrame &&
|
|
|
|
|
(aWidth == NS_UNCONSTRAINEDSIZE || aHeight == NS_UNCONSTRAINEDSIZE)) {
|
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
|
}
|
|
|
|
|
|
1999-05-05 03:27:42 +04:00
|
|
|
|
if (mPresContext) {
|
1998-09-10 23:32:14 +04:00
|
|
|
|
nsRect r(0, 0, aWidth, aHeight);
|
|
|
|
|
mPresContext->SetVisibleArea(r);
|
|
|
|
|
}
|
|
|
|
|
|
1999-10-19 02:20:37 +04:00
|
|
|
|
if (rootFrame) {
|
1998-04-14 00:24:54 +04:00
|
|
|
|
// Kick off a top-down reflow
|
1998-05-20 20:24:54 +04:00
|
|
|
|
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
|
|
|
|
|
("enter nsPresShell::ResizeReflow: %d,%d", aWidth, aHeight));
|
1998-04-14 00:24:54 +04:00
|
|
|
|
#ifdef NS_DEBUG
|
1999-11-02 01:12:45 +03:00
|
|
|
|
if (nsIFrameDebug::GetVerifyTreeEnable()) {
|
|
|
|
|
nsIFrameDebug* frameDebug;
|
|
|
|
|
|
2000-01-04 23:24:09 +03:00
|
|
|
|
if (NS_SUCCEEDED(rootFrame->QueryInterface(NS_GET_IID(nsIFrameDebug),
|
|
|
|
|
(void**)&frameDebug))) {
|
1999-11-02 01:12:45 +03:00
|
|
|
|
frameDebug->VerifyTree();
|
|
|
|
|
}
|
1998-05-20 20:24:54 +04:00
|
|
|
|
}
|
1999-08-28 01:50:37 +04:00
|
|
|
|
#endif
|
|
|
|
|
#ifdef DEBUG_kipp
|
|
|
|
|
nsPresShell_ReflowStackPointerTop = (char*) &aWidth;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
#endif
|
2004-02-01 13:09:07 +03:00
|
|
|
|
nsRect bounds = mPresContext->GetVisibleArea();
|
1998-10-02 05:12:39 +04:00
|
|
|
|
nsSize maxSize(bounds.width, bounds.height);
|
|
|
|
|
nsHTMLReflowMetrics desiredSize(nsnull);
|
|
|
|
|
nsReflowStatus status;
|
|
|
|
|
nsIRenderingContext* rcx = nsnull;
|
|
|
|
|
|
2000-01-12 01:15:20 +03:00
|
|
|
|
nsresult rv=CreateRenderingContext(rootFrame, &rcx);
|
2001-05-19 03:42:54 +04:00
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
1998-10-02 05:12:39 +04:00
|
|
|
|
|
2006-04-18 09:44:02 +04:00
|
|
|
|
AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Reflow);
|
|
|
|
|
// XXXldb Set mIsReflowing (and unset it later)?
|
|
|
|
|
|
1999-11-24 09:03:41 +03:00
|
|
|
|
nsHTMLReflowState reflowState(mPresContext, rootFrame,
|
1999-03-05 07:29:11 +03:00
|
|
|
|
eReflowReason_Resize, rcx, maxSize);
|
1998-10-01 08:46:11 +04:00
|
|
|
|
|
1999-11-24 09:03:41 +03:00
|
|
|
|
rootFrame->WillReflow(mPresContext);
|
2004-12-27 18:05:18 +03:00
|
|
|
|
nsContainerFrame::PositionFrameView(rootFrame);
|
1999-11-24 09:03:41 +03:00
|
|
|
|
rootFrame->Reflow(mPresContext, desiredSize, reflowState, status);
|
2003-09-23 21:05:29 +04:00
|
|
|
|
rootFrame->SetSize(nsSize(desiredSize.width, desiredSize.height));
|
2001-09-12 02:21:21 +04:00
|
|
|
|
mPresContext->SetVisibleArea(nsRect(0,0,desiredSize.width,desiredSize.height));
|
|
|
|
|
|
2003-06-30 14:46:59 +04:00
|
|
|
|
nsContainerFrame::SyncFrameViewAfterReflow(mPresContext, rootFrame, rootFrame->GetView(),
|
|
|
|
|
nsnull);
|
2001-12-07 17:51:12 +03:00
|
|
|
|
rootFrame->DidReflow(mPresContext, nsnull, NS_FRAME_REFLOW_FINISHED);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
#ifdef NS_DEBUG
|
1999-11-02 01:12:45 +03:00
|
|
|
|
if (nsIFrameDebug::GetVerifyTreeEnable()) {
|
|
|
|
|
nsIFrameDebug* frameDebug;
|
|
|
|
|
|
2000-01-04 23:24:09 +03:00
|
|
|
|
if (NS_SUCCEEDED(rootFrame->QueryInterface(NS_GET_IID(nsIFrameDebug),
|
|
|
|
|
(void**)&frameDebug))) {
|
1999-11-02 01:12:45 +03:00
|
|
|
|
frameDebug->VerifyTree();
|
|
|
|
|
}
|
1998-10-01 08:46:11 +04:00
|
|
|
|
}
|
1999-10-30 06:52:11 +04:00
|
|
|
|
#endif
|
|
|
|
|
VERIFY_STYLE_TREE;
|
1998-10-02 05:12:39 +04:00
|
|
|
|
NS_IF_RELEASE(rcx);
|
1998-05-20 20:24:54 +04:00
|
|
|
|
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS, ("exit nsPresShell::ResizeReflow"));
|
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
|
// XXX if debugging then we should assert that the cache is empty
|
|
|
|
|
} else {
|
2001-05-19 03:42:54 +04:00
|
|
|
|
firstReflow = PR_TRUE;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
#ifdef NOISY
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("PresShell::ResizeReflow: null root frame\n");
|
1998-04-14 00:24:54 +04:00
|
|
|
|
#endif
|
|
|
|
|
}
|
2000-04-17 11:13:57 +04:00
|
|
|
|
DidCauseReflow();
|
2000-03-23 02:19:10 +03:00
|
|
|
|
// if the proper flag is set, VerifyReflow now
|
2000-03-23 03:10:26 +03:00
|
|
|
|
#ifdef NS_DEBUG
|
2000-03-23 02:19:10 +03:00
|
|
|
|
if (GetVerifyReflowEnable() && (VERIFY_REFLOW_DURING_RESIZE_REFLOW & gVerifyReflowFlags))
|
|
|
|
|
{
|
|
|
|
|
mInVerifyReflow = PR_TRUE;
|
2000-08-29 02:28:56 +04:00
|
|
|
|
/*PRBool ok = */VerifyIncrementalReflow();
|
2000-03-23 02:19:10 +03:00
|
|
|
|
mInVerifyReflow = PR_FALSE;
|
|
|
|
|
}
|
2000-03-23 03:10:26 +03:00
|
|
|
|
#endif
|
1999-02-13 07:45:44 +03:00
|
|
|
|
|
2004-02-04 03:11:59 +03:00
|
|
|
|
DidDoReflow();
|
2000-04-03 07:55:38 +04:00
|
|
|
|
|
2004-10-09 05:39:21 +04:00
|
|
|
|
mViewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
|
|
|
|
|
|
2001-05-19 03:42:54 +04:00
|
|
|
|
if (!firstReflow) {
|
|
|
|
|
//Set resize event timer
|
|
|
|
|
CreateResizeEventTimer();
|
|
|
|
|
}
|
2001-04-18 03:25:21 +04:00
|
|
|
|
|
|
|
|
|
return NS_OK; //XXX this needs to be real. MMP
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define RESIZE_EVENT_DELAY 200
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PresShell::CreateResizeEventTimer ()
|
|
|
|
|
{
|
|
|
|
|
KillResizeEventTimer();
|
|
|
|
|
|
2001-05-02 02:54:11 +04:00
|
|
|
|
if (mIsDocumentGone)
|
|
|
|
|
return;
|
|
|
|
|
|
2001-04-18 03:25:21 +04:00
|
|
|
|
mResizeEventTimer = do_CreateInstance("@mozilla.org/timer;1");
|
|
|
|
|
if (mResizeEventTimer) {
|
2002-09-07 09:38:16 +04:00
|
|
|
|
mResizeEventTimer->InitWithFuncCallback(sResizeEventCallback, this, RESIZE_EVENT_DELAY,
|
|
|
|
|
nsITimer::TYPE_ONE_SHOT);
|
2001-04-18 03:25:21 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PresShell::KillResizeEventTimer()
|
|
|
|
|
{
|
|
|
|
|
if(mResizeEventTimer) {
|
|
|
|
|
mResizeEventTimer->Cancel();
|
|
|
|
|
mResizeEventTimer = nsnull;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PresShell::sResizeEventCallback(nsITimer *aTimer, void* aPresShell)
|
|
|
|
|
{
|
|
|
|
|
PresShell* self = NS_STATIC_CAST(PresShell*, aPresShell);
|
|
|
|
|
if (self) {
|
|
|
|
|
self->FireResizeEvent();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PresShell::FireResizeEvent()
|
|
|
|
|
{
|
2001-05-02 02:54:11 +04:00
|
|
|
|
if (mIsDocumentGone)
|
|
|
|
|
return;
|
|
|
|
|
|
2000-05-17 09:27:22 +04:00
|
|
|
|
//Send resize event from here.
|
2005-04-29 03:48:28 +04:00
|
|
|
|
nsEvent event(PR_TRUE, NS_RESIZE_EVENT);
|
2000-11-08 03:31:06 +03:00
|
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
2000-05-17 09:27:22 +04:00
|
|
|
|
|
2005-11-29 02:56:44 +03:00
|
|
|
|
nsPIDOMWindow *window = mDocument->GetWindow();
|
|
|
|
|
if (window) {
|
2006-03-07 20:08:51 +03:00
|
|
|
|
nsEventDispatcher::Dispatch(window, mPresContext, &event, nsnull, &status);
|
2001-05-04 07:04:40 +04:00
|
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
2001-12-01 03:22:00 +03:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::SetIgnoreFrameDestruction(PRBool aIgnore)
|
|
|
|
|
{
|
|
|
|
|
mIgnoreFrameDestruction = aIgnore;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
1999-07-17 03:27:46 +04:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::NotifyDestroyingFrame(nsIFrame* aFrame)
|
|
|
|
|
{
|
2001-12-01 03:22:00 +03:00
|
|
|
|
if (!mIgnoreFrameDestruction) {
|
2005-04-02 03:07:00 +04:00
|
|
|
|
mFrameConstructor->NotifyDestroyingFrame(aFrame);
|
|
|
|
|
|
2001-12-01 03:22:00 +03:00
|
|
|
|
// Cancel any pending reflow commands targeted at this frame
|
2002-05-10 22:22:41 +04:00
|
|
|
|
CancelReflowCommandInternal(aFrame, nsnull);
|
1999-07-17 03:27:46 +04:00
|
|
|
|
|
2001-12-01 03:22:00 +03:00
|
|
|
|
// Notify the frame manager
|
2004-03-06 07:46:11 +03:00
|
|
|
|
FrameManager()->NotifyDestroyingFrame(aFrame);
|
2004-08-24 22:50:29 +04:00
|
|
|
|
|
|
|
|
|
// Remove frame properties
|
|
|
|
|
mPresContext->PropertyTable()->DeleteAllPropertiesFor(aFrame);
|
1999-08-06 00:17:44 +04:00
|
|
|
|
}
|
|
|
|
|
|
1999-07-17 03:27:46 +04:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
1999-02-13 07:45:44 +03:00
|
|
|
|
|
2003-02-28 02:09:51 +03:00
|
|
|
|
// note that this can return a null caret, but NS_OK
|
1999-02-13 07:45:44 +03:00
|
|
|
|
NS_IMETHODIMP PresShell::GetCaret(nsICaret **outCaret)
|
|
|
|
|
{
|
2003-02-28 02:09:51 +03:00
|
|
|
|
NS_ENSURE_ARG_POINTER(outCaret);
|
|
|
|
|
|
|
|
|
|
*outCaret = mCaret;
|
|
|
|
|
NS_IF_ADDREF(*outCaret);
|
|
|
|
|
return NS_OK;
|
1999-02-13 07:45:44 +03:00
|
|
|
|
}
|
|
|
|
|
|
2006-04-18 03:16:46 +04:00
|
|
|
|
already_AddRefed<nsICaret> PresShell::SetCaret(nsICaret *aNewCaret)
|
|
|
|
|
{
|
|
|
|
|
nsICaret *oldCaret = nsnull;
|
|
|
|
|
mCaret.swap(oldCaret);
|
|
|
|
|
mCaret = aNewCaret;
|
|
|
|
|
return oldCaret;
|
|
|
|
|
}
|
|
|
|
|
|
1999-08-05 00:46:16 +04:00
|
|
|
|
NS_IMETHODIMP PresShell::SetCaretEnabled(PRBool aInEnable)
|
1999-04-02 03:58:11 +04:00
|
|
|
|
{
|
2000-06-16 18:05:03 +04:00
|
|
|
|
nsresult result = NS_OK;
|
|
|
|
|
PRBool oldEnabled = mCaretEnabled;
|
2003-03-12 06:22:11 +03:00
|
|
|
|
|
2000-06-16 18:05:03 +04:00
|
|
|
|
mCaretEnabled = aInEnable;
|
2003-03-12 06:22:11 +03:00
|
|
|
|
|
2000-06-16 18:05:03 +04:00
|
|
|
|
if (mCaret && (mCaretEnabled != oldEnabled))
|
|
|
|
|
{
|
2000-09-07 09:26:25 +04:00
|
|
|
|
/* Don't change the caret's selection here! This was an evil side-effect of SetCaretEnabled()
|
2000-06-01 06:39:52 +04:00
|
|
|
|
nsCOMPtr<nsIDOMSelection> domSel;
|
|
|
|
|
if (NS_SUCCEEDED(GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSel))) && domSel)
|
|
|
|
|
mCaret->SetCaretDOMSelection(domSel);
|
2000-09-07 09:26:25 +04:00
|
|
|
|
*/
|
2000-06-01 06:39:52 +04:00
|
|
|
|
result = mCaret->SetCaretVisible(mCaretEnabled);
|
2000-06-16 18:05:03 +04:00
|
|
|
|
}
|
2003-03-12 06:22:11 +03:00
|
|
|
|
|
2000-06-16 18:05:03 +04:00
|
|
|
|
return result;
|
1999-04-02 03:58:11 +04:00
|
|
|
|
}
|
|
|
|
|
|
2000-05-11 08:25:43 +04:00
|
|
|
|
NS_IMETHODIMP PresShell::SetCaretReadOnly(PRBool aReadOnly)
|
|
|
|
|
{
|
2003-02-28 02:09:51 +03:00
|
|
|
|
if (mCaret)
|
|
|
|
|
mCaret->SetCaretReadOnly(aReadOnly);
|
|
|
|
|
return NS_OK;
|
2000-05-11 08:25:43 +04:00
|
|
|
|
}
|
|
|
|
|
|
1999-08-05 00:46:16 +04:00
|
|
|
|
NS_IMETHODIMP PresShell::GetCaretEnabled(PRBool *aOutEnabled)
|
|
|
|
|
{
|
2003-02-28 02:09:51 +03:00
|
|
|
|
NS_ENSURE_ARG_POINTER(aOutEnabled);
|
1999-08-05 00:46:16 +04:00
|
|
|
|
*aOutEnabled = mCaretEnabled;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2003-06-25 05:14:25 +04:00
|
|
|
|
NS_IMETHODIMP PresShell::SetCaretVisibilityDuringSelection(PRBool aVisibility)
|
|
|
|
|
{
|
|
|
|
|
if (mCaret)
|
|
|
|
|
mCaret->SetVisibilityDuringSelection(aVisibility);
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-18 04:29:49 +03:00
|
|
|
|
NS_IMETHODIMP PresShell::SetSelectionFlags(PRInt16 aInEnable)
|
1999-05-17 04:21:18 +04:00
|
|
|
|
{
|
2001-12-19 00:05:55 +03:00
|
|
|
|
mSelectionFlags = aInEnable;
|
1999-05-17 04:21:18 +04:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-18 04:29:49 +03:00
|
|
|
|
NS_IMETHODIMP PresShell::GetSelectionFlags(PRInt16 *aOutEnable)
|
1999-05-17 04:21:18 +04:00
|
|
|
|
{
|
1999-08-05 00:46:16 +04:00
|
|
|
|
if (!aOutEnable)
|
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
2001-12-19 00:05:55 +03:00
|
|
|
|
*aOutEnable = mSelectionFlags;
|
1999-05-17 04:21:18 +04:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
1999-12-03 00:45:21 +03:00
|
|
|
|
//implementation of nsISelectionController
|
1999-04-02 03:58:11 +04:00
|
|
|
|
|
1999-10-22 04:19:18 +04:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::CharacterMove(PRBool aForward, PRBool aExtend)
|
1999-02-20 02:47:36 +03:00
|
|
|
|
{
|
1999-12-11 03:02:08 +03:00
|
|
|
|
return mSelection->CharacterMove(aForward, aExtend);
|
1999-10-22 04:19:18 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::WordMove(PRBool aForward, PRBool aExtend)
|
|
|
|
|
{
|
1999-12-11 03:02:08 +03:00
|
|
|
|
return mSelection->WordMove(aForward, aExtend);
|
1999-10-22 04:19:18 +04:00
|
|
|
|
}
|
|
|
|
|
|
2006-07-18 11:28:38 +04:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::WordExtendForDelete(PRBool aForward)
|
|
|
|
|
{
|
|
|
|
|
return mSelection->WordExtendForDelete(aForward);
|
|
|
|
|
}
|
|
|
|
|
|
1999-10-22 04:19:18 +04:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::LineMove(PRBool aForward, PRBool aExtend)
|
|
|
|
|
{
|
2001-06-20 08:48:10 +04:00
|
|
|
|
nsresult result = mSelection->LineMove(aForward, aExtend);
|
2005-11-21 01:05:24 +03:00
|
|
|
|
// if we can't go down/up any more we must then move caret completely to
|
2001-06-20 08:48:10 +04:00
|
|
|
|
// end/beginning respectively.
|
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
|
result = CompleteMove(aForward,aExtend);
|
|
|
|
|
return result;
|
1999-10-22 04:19:18 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::IntraLineMove(PRBool aForward, PRBool aExtend)
|
|
|
|
|
{
|
1999-12-11 03:02:08 +03:00
|
|
|
|
return mSelection->IntraLineMove(aForward, aExtend);
|
1999-10-22 04:19:18 +04:00
|
|
|
|
}
|
|
|
|
|
|
2002-08-27 00:55:30 +04:00
|
|
|
|
|
|
|
|
|
|
1999-10-22 04:19:18 +04:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::PageMove(PRBool aForward, PRBool aExtend)
|
|
|
|
|
{
|
2002-08-27 00:55:30 +04:00
|
|
|
|
nsresult result;
|
2003-06-30 14:46:59 +04:00
|
|
|
|
nsIViewManager* viewManager = GetViewManager();
|
2002-08-27 00:55:30 +04:00
|
|
|
|
nsIScrollableView *scrollableView;
|
|
|
|
|
if (!viewManager)
|
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
|
result = viewManager->GetRootScrollableView(&scrollableView);
|
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
|
return result;
|
|
|
|
|
if (!scrollableView)
|
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
|
nsIView *scrolledView;
|
|
|
|
|
result = scrollableView->GetScrolledView(scrolledView);
|
2006-04-26 06:01:07 +04:00
|
|
|
|
mSelection->CommonPageMove(aForward, aExtend, scrollableView);
|
2002-08-27 00:55:30 +04:00
|
|
|
|
// do ScrollSelectionIntoView()
|
|
|
|
|
return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION, PR_TRUE);
|
1999-10-22 04:19:18 +04:00
|
|
|
|
}
|
|
|
|
|
|
2002-08-27 00:55:30 +04:00
|
|
|
|
|
|
|
|
|
|
1999-10-22 04:19:18 +04:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::ScrollPage(PRBool aForward)
|
1999-12-11 03:02:08 +03:00
|
|
|
|
{
|
2004-09-21 08:41:08 +04:00
|
|
|
|
nsIScrollableView* scrollView = GetViewToScroll(nsLayoutUtils::eVertical);
|
2004-08-06 19:55:17 +04:00
|
|
|
|
if (scrollView) {
|
|
|
|
|
scrollView->ScrollByPages(0, aForward ? 1 : -1);
|
1999-12-11 03:02:08 +03:00
|
|
|
|
}
|
2004-08-06 19:55:17 +04:00
|
|
|
|
return NS_OK;
|
1999-12-11 03:02:08 +03:00
|
|
|
|
}
|
|
|
|
|
|
1999-12-15 06:54:52 +03:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::ScrollLine(PRBool aForward)
|
|
|
|
|
{
|
2004-09-21 08:41:08 +04:00
|
|
|
|
nsIScrollableView* scrollView = GetViewToScroll(nsLayoutUtils::eVertical);
|
2004-08-06 19:55:17 +04:00
|
|
|
|
if (scrollView) {
|
2002-04-12 06:05:12 +04:00
|
|
|
|
#ifdef MOZ_WIDGET_COCOA
|
2004-08-06 19:55:17 +04:00
|
|
|
|
// Emulate the Mac IE behavior of scrolling a minimum of 2 lines
|
|
|
|
|
// rather than 1. This vastly improves scrolling speed.
|
|
|
|
|
scrollView->ScrollByLines(0, aForward ? 2 : -2);
|
2002-04-12 06:05:12 +04:00
|
|
|
|
#else
|
2004-08-06 19:55:17 +04:00
|
|
|
|
scrollView->ScrollByLines(0, aForward ? 1 : -1);
|
2002-04-12 06:05:12 +04:00
|
|
|
|
#endif
|
|
|
|
|
|
1999-12-15 06:54:52 +03:00
|
|
|
|
//NEW FOR LINES
|
2004-08-06 19:55:17 +04:00
|
|
|
|
// force the update to happen now, otherwise multiple scrolls can
|
|
|
|
|
// occur before the update is processed. (bug #7354)
|
1999-12-15 06:54:52 +03:00
|
|
|
|
|
2004-08-06 19:55:17 +04:00
|
|
|
|
// I'd use Composite here, but it doesn't always work.
|
|
|
|
|
// vm->Composite();
|
|
|
|
|
nsIViewManager* viewManager = GetViewManager();
|
|
|
|
|
if (viewManager) {
|
2000-01-27 02:04:40 +03:00
|
|
|
|
viewManager->ForceUpdate();
|
1999-12-15 06:54:52 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
2004-08-06 19:55:17 +04:00
|
|
|
|
return NS_OK;
|
1999-12-15 06:54:52 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::ScrollHorizontal(PRBool aLeft)
|
|
|
|
|
{
|
2004-09-21 08:41:08 +04:00
|
|
|
|
nsIScrollableView* scrollView = GetViewToScroll(nsLayoutUtils::eHorizontal);
|
2004-08-06 19:55:17 +04:00
|
|
|
|
if (scrollView) {
|
|
|
|
|
scrollView->ScrollByLines(aLeft ? -1 : 1, 0);
|
2000-05-16 15:35:12 +04:00
|
|
|
|
//NEW FOR LINES
|
2004-08-06 19:55:17 +04:00
|
|
|
|
// force the update to happen now, otherwise multiple scrolls can
|
|
|
|
|
// occur before the update is processed. (bug #7354)
|
2000-05-16 15:35:12 +04:00
|
|
|
|
|
2004-08-06 19:55:17 +04:00
|
|
|
|
// I'd use Composite here, but it doesn't always work.
|
|
|
|
|
// vm->Composite();
|
|
|
|
|
nsIViewManager* viewManager = GetViewManager();
|
|
|
|
|
if (viewManager) {
|
2000-05-16 15:35:12 +04:00
|
|
|
|
viewManager->ForceUpdate();
|
|
|
|
|
}
|
|
|
|
|
}
|
2004-08-06 19:55:17 +04:00
|
|
|
|
return NS_OK;
|
1999-12-15 06:54:52 +03:00
|
|
|
|
}
|
|
|
|
|
|
1999-12-11 03:02:08 +03:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::CompleteScroll(PRBool aForward)
|
|
|
|
|
{
|
2004-09-21 08:41:08 +04:00
|
|
|
|
nsIScrollableView* scrollView = GetViewToScroll(nsLayoutUtils::eVertical);
|
2004-08-06 19:55:17 +04:00
|
|
|
|
if (scrollView) {
|
|
|
|
|
scrollView->ScrollByWhole(!aForward);//TRUE = top, aForward TRUE=bottom
|
1999-12-17 01:48:02 +03:00
|
|
|
|
}
|
2004-08-06 19:55:17 +04:00
|
|
|
|
return NS_OK;
|
1999-12-11 03:02:08 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::CompleteMove(PRBool aForward, PRBool aExtend)
|
1999-10-22 04:19:18 +04:00
|
|
|
|
{
|
2002-08-27 00:55:30 +04:00
|
|
|
|
nsIScrollableView *scrollableView;
|
|
|
|
|
if (!mViewManager)
|
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
|
nsresult result = mViewManager->GetRootScrollableView(&scrollableView);
|
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
|
return result;
|
|
|
|
|
if (!scrollableView)
|
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
|
nsIView *scrolledView;
|
|
|
|
|
result = scrollableView->GetScrolledView(scrolledView);
|
|
|
|
|
// get a frame
|
2003-06-30 14:46:59 +04:00
|
|
|
|
nsIFrame *frame = (nsIFrame*)scrolledView->GetClientData();
|
2002-08-27 00:55:30 +04:00
|
|
|
|
if (!frame)
|
2000-09-14 15:45:01 +04:00
|
|
|
|
return NS_ERROR_FAILURE;
|
2002-09-10 04:10:09 +04:00
|
|
|
|
//we need to get to the area frame.
|
2003-10-31 23:19:18 +03:00
|
|
|
|
nsIAtom* frameType;
|
2002-09-10 04:10:09 +04:00
|
|
|
|
do
|
|
|
|
|
{
|
2003-10-31 23:19:18 +03:00
|
|
|
|
frameType = frame->GetType();
|
2002-09-10 04:10:09 +04:00
|
|
|
|
if (frameType != nsLayoutAtoms::areaFrame)
|
|
|
|
|
{
|
2004-01-09 17:20:53 +03:00
|
|
|
|
frame = frame->GetFirstChild(nsnull);
|
|
|
|
|
if (!frame)
|
2002-09-10 04:10:09 +04:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}while(frameType != nsLayoutAtoms::areaFrame);
|
|
|
|
|
|
|
|
|
|
if (!frame)
|
|
|
|
|
return NS_ERROR_FAILURE; //could not find an area frame.
|
2000-09-14 15:45:01 +04:00
|
|
|
|
|
2004-11-29 23:28:46 +03:00
|
|
|
|
nsPeekOffsetStruct pos = frame->GetExtremeCaretPosition(!aForward);
|
|
|
|
|
|
2006-07-13 10:06:29 +04:00
|
|
|
|
mSelection->HandleClick(pos.mResultContent ,pos.mContentOffset ,pos.mContentOffset/*End*/ ,aExtend, PR_FALSE, aForward);
|
2002-08-27 00:55:30 +04:00
|
|
|
|
return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION, PR_TRUE);
|
1999-10-22 04:19:18 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::SelectAll()
|
|
|
|
|
{
|
1999-12-11 03:02:08 +03:00
|
|
|
|
return mSelection->SelectAll();
|
1999-02-20 02:47:36 +03:00
|
|
|
|
}
|
|
|
|
|
|
2000-07-26 15:31:12 +04:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::CheckVisibility(nsIDOMNode *node, PRInt16 startOffset, PRInt16 EndOffset, PRBool *_retval)
|
|
|
|
|
{
|
|
|
|
|
if (!node || startOffset>EndOffset || !_retval || startOffset<0 || EndOffset<0)
|
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
*_retval = PR_FALSE; //initialize return parameter
|
|
|
|
|
nsCOMPtr<nsIContent> content(do_QueryInterface(node));
|
|
|
|
|
if (!content)
|
|
|
|
|
return NS_ERROR_FAILURE;
|
2005-08-23 02:24:29 +04:00
|
|
|
|
nsIFrame *frame = GetPrimaryFrameFor(content);
|
2000-08-18 03:55:32 +04:00
|
|
|
|
if (!frame) //no frame to look at so it must not be visible
|
|
|
|
|
return NS_OK;
|
2000-07-26 15:31:12 +04:00
|
|
|
|
//start process now to go through all frames to find startOffset. then check chars after that to see
|
|
|
|
|
//if anything until EndOffset is visible.
|
|
|
|
|
PRBool finished = PR_FALSE;
|
|
|
|
|
frame->CheckVisibility(mPresContext,startOffset,EndOffset,PR_TRUE,&finished, _retval);
|
|
|
|
|
return NS_OK;//dont worry about other return val
|
|
|
|
|
}
|
|
|
|
|
|
1999-12-03 00:45:21 +03:00
|
|
|
|
//end implementations nsISelectionController
|
1999-10-22 04:19:18 +04:00
|
|
|
|
|
|
|
|
|
|
2004-08-01 03:15:21 +04:00
|
|
|
|
static void UpdateViewProperties(nsPresContext* aPresContext, nsIViewManager* aVM,
|
2002-12-14 19:18:57 +03:00
|
|
|
|
nsIView* aView) {
|
2003-06-30 14:46:59 +04:00
|
|
|
|
nsIViewManager* thisVM = aView->GetViewManager();
|
2002-12-14 19:18:57 +03:00
|
|
|
|
if (thisVM != aVM) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2003-06-30 14:46:59 +04:00
|
|
|
|
nsIFrame* frame = NS_STATIC_CAST(nsIFrame*, aView->GetClientData());
|
2002-12-14 19:18:57 +03:00
|
|
|
|
if (frame) {
|
|
|
|
|
nsContainerFrame::SyncFrameViewProperties(aPresContext, frame, nsnull, aView);
|
|
|
|
|
}
|
|
|
|
|
|
2003-06-30 14:46:59 +04:00
|
|
|
|
for (nsIView* child = aView->GetFirstChild(); child;
|
|
|
|
|
child = child->GetNextSibling()) {
|
2002-12-14 19:18:57 +03:00
|
|
|
|
UpdateViewProperties(aPresContext, aVM, child);
|
|
|
|
|
}
|
|
|
|
|
}
|
1999-10-22 04:19:18 +04:00
|
|
|
|
|
1998-11-06 19:16:01 +03:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::StyleChangeReflow()
|
|
|
|
|
{
|
2000-04-17 11:13:57 +04:00
|
|
|
|
WillCauseReflow();
|
2006-04-28 08:33:41 +04:00
|
|
|
|
WillDoReflow();
|
2006-04-18 03:16:46 +04:00
|
|
|
|
|
2004-03-06 07:46:11 +03:00
|
|
|
|
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
|
1999-10-19 02:20:37 +04:00
|
|
|
|
if (rootFrame) {
|
1998-11-06 19:16:01 +03:00
|
|
|
|
// Kick off a top-down reflow
|
|
|
|
|
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
|
|
|
|
|
("enter nsPresShell::StyleChangeReflow"));
|
|
|
|
|
#ifdef NS_DEBUG
|
1999-11-02 01:12:45 +03:00
|
|
|
|
if (nsIFrameDebug::GetVerifyTreeEnable()) {
|
|
|
|
|
nsIFrameDebug* frameDebug;
|
|
|
|
|
|
2000-01-04 23:24:09 +03:00
|
|
|
|
if (NS_SUCCEEDED(rootFrame->QueryInterface(NS_GET_IID(nsIFrameDebug),
|
|
|
|
|
(void**)&frameDebug))) {
|
1999-11-02 01:12:45 +03:00
|
|
|
|
frameDebug->VerifyTree();
|
|
|
|
|
}
|
1998-11-06 19:16:01 +03:00
|
|
|
|
}
|
|
|
|
|
#endif
|
2004-02-01 13:09:07 +03:00
|
|
|
|
nsRect bounds = mPresContext->GetVisibleArea();
|
1998-11-06 19:16:01 +03:00
|
|
|
|
nsSize maxSize(bounds.width, bounds.height);
|
|
|
|
|
nsHTMLReflowMetrics desiredSize(nsnull);
|
|
|
|
|
nsReflowStatus status;
|
|
|
|
|
nsIRenderingContext* rcx = nsnull;
|
|
|
|
|
|
2000-01-12 01:15:20 +03:00
|
|
|
|
nsresult rv=CreateRenderingContext(rootFrame, &rcx);
|
2003-03-12 06:22:11 +03:00
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
1998-11-06 19:16:01 +03:00
|
|
|
|
|
2006-04-18 09:44:02 +04:00
|
|
|
|
AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Reflow);
|
|
|
|
|
// XXXldb Set mIsReflowing (and unset it later)?
|
|
|
|
|
|
1999-11-24 09:03:41 +03:00
|
|
|
|
nsHTMLReflowState reflowState(mPresContext, rootFrame,
|
2000-03-15 18:16:03 +03:00
|
|
|
|
eReflowReason_StyleChange, rcx, maxSize);
|
1998-11-06 19:16:01 +03:00
|
|
|
|
|
1999-11-24 09:03:41 +03:00
|
|
|
|
rootFrame->WillReflow(mPresContext);
|
2004-12-27 18:05:18 +03:00
|
|
|
|
nsContainerFrame::PositionFrameView(rootFrame);
|
1999-11-24 09:03:41 +03:00
|
|
|
|
rootFrame->Reflow(mPresContext, desiredSize, reflowState, status);
|
2003-06-30 14:46:59 +04:00
|
|
|
|
rootFrame->SetSize(nsSize(desiredSize.width, desiredSize.height));
|
1999-11-19 18:33:29 +03:00
|
|
|
|
mPresContext->SetVisibleArea(nsRect(0,0,desiredSize.width,desiredSize.height));
|
2003-06-30 14:46:59 +04:00
|
|
|
|
nsIView* view = rootFrame->GetView();
|
|
|
|
|
nsContainerFrame::SyncFrameViewAfterReflow(mPresContext, rootFrame, view,
|
|
|
|
|
nsnull);
|
2001-12-07 17:51:12 +03:00
|
|
|
|
rootFrame->DidReflow(mPresContext, nsnull, NS_FRAME_REFLOW_FINISHED);
|
1998-11-06 19:16:01 +03:00
|
|
|
|
#ifdef NS_DEBUG
|
1999-11-02 01:12:45 +03:00
|
|
|
|
if (nsIFrameDebug::GetVerifyTreeEnable()) {
|
|
|
|
|
nsIFrameDebug* frameDebug;
|
|
|
|
|
|
2000-01-04 23:24:09 +03:00
|
|
|
|
if (NS_SUCCEEDED(rootFrame->QueryInterface(NS_GET_IID(nsIFrameDebug),
|
|
|
|
|
(void**)&frameDebug))) {
|
1999-11-02 01:12:45 +03:00
|
|
|
|
frameDebug->VerifyTree();
|
|
|
|
|
}
|
1998-11-06 19:16:01 +03:00
|
|
|
|
}
|
1999-10-30 06:52:11 +04:00
|
|
|
|
#endif
|
|
|
|
|
VERIFY_STYLE_TREE;
|
1998-11-06 19:16:01 +03:00
|
|
|
|
NS_IF_RELEASE(rcx);
|
|
|
|
|
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS, ("exit nsPresShell::StyleChangeReflow"));
|
2002-12-14 19:18:57 +03:00
|
|
|
|
|
|
|
|
|
// The following two calls are needed to make sure we reacquire any needed
|
|
|
|
|
// style structs that were cleared by the caller
|
|
|
|
|
|
|
|
|
|
// Update properties of all views to reflect style changes
|
|
|
|
|
UpdateViewProperties(mPresContext, mViewManager, view);
|
|
|
|
|
|
|
|
|
|
// Repaint everything just to be sure
|
|
|
|
|
mViewManager->UpdateAllViews(NS_VMREFRESH_NO_SYNC);
|
1998-11-06 19:16:01 +03:00
|
|
|
|
}
|
|
|
|
|
|
2000-04-17 11:13:57 +04:00
|
|
|
|
DidCauseReflow();
|
2004-02-04 03:11:59 +03:00
|
|
|
|
DidDoReflow();
|
2004-01-21 07:15:00 +03:00
|
|
|
|
|
1998-11-06 19:16:01 +03:00
|
|
|
|
return NS_OK; //XXX this needs to be real. MMP
|
|
|
|
|
}
|
|
|
|
|
|
2004-09-02 07:08:51 +04:00
|
|
|
|
nsIFrame*
|
|
|
|
|
nsIPresShell::GetRootFrame() const
|
1998-04-14 00:24:54 +04:00
|
|
|
|
{
|
2004-09-02 07:08:51 +04:00
|
|
|
|
return FrameManager()->GetRootFrame();
|
1998-04-14 00:24:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
2006-02-01 22:55:35 +03:00
|
|
|
|
nsIFrame*
|
|
|
|
|
nsIPresShell::GetRootScrollFrame() const
|
|
|
|
|
{
|
|
|
|
|
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
|
|
|
|
|
// Ensure root frame is a viewport frame
|
|
|
|
|
if (!rootFrame || nsLayoutAtoms::viewportFrame != rootFrame->GetType())
|
|
|
|
|
return nsnull;
|
|
|
|
|
nsIFrame* theFrame = rootFrame->GetFirstChild(nsnull);
|
|
|
|
|
if (!theFrame || nsLayoutAtoms::scrollFrame != theFrame->GetType())
|
|
|
|
|
return nsnull;
|
|
|
|
|
return theFrame;
|
|
|
|
|
}
|
|
|
|
|
|
1998-12-07 06:43:02 +03:00
|
|
|
|
NS_IMETHODIMP
|
1999-02-12 20:45:58 +03:00
|
|
|
|
PresShell::GetPageSequenceFrame(nsIPageSequenceFrame** aResult) const
|
1998-12-07 06:43:02 +03:00
|
|
|
|
{
|
1999-02-12 20:45:58 +03:00
|
|
|
|
NS_PRECONDITION(nsnull != aResult, "null ptr");
|
|
|
|
|
if (nsnull == aResult) {
|
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*aResult = nsnull;
|
2005-04-06 02:46:56 +04:00
|
|
|
|
nsIFrame* frame = mFrameConstructor->GetPageSequenceFrame();
|
|
|
|
|
if (frame) {
|
|
|
|
|
CallQueryInterface(frame, aResult);
|
|
|
|
|
}
|
|
|
|
|
return *aResult ? NS_OK : NS_ERROR_FAILURE;
|
1998-12-07 06:43:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
2004-01-24 03:46:17 +03:00
|
|
|
|
void
|
2003-10-03 01:29:40 +04:00
|
|
|
|
PresShell::BeginUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
|
1998-04-14 00:24:54 +04:00
|
|
|
|
{
|
2004-12-02 04:26:20 +03:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
mUpdateCount++;
|
|
|
|
|
#endif
|
2004-04-13 01:53:22 +04:00
|
|
|
|
mFrameConstructor->BeginUpdate();
|
|
|
|
|
|
2004-12-02 04:26:20 +03:00
|
|
|
|
if (aUpdateType & UPDATE_STYLE)
|
2004-01-08 22:23:12 +03:00
|
|
|
|
mStyleSet->BeginUpdate();
|
1998-04-14 00:24:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
2004-01-24 03:46:17 +03:00
|
|
|
|
void
|
2003-10-03 01:29:40 +04:00
|
|
|
|
PresShell::EndUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
|
1998-04-14 00:24:54 +04:00
|
|
|
|
{
|
2004-12-02 04:26:20 +03:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
NS_PRECONDITION(0 != mUpdateCount, "too many EndUpdate's");
|
|
|
|
|
--mUpdateCount;
|
|
|
|
|
#endif
|
|
|
|
|
|
2004-04-13 01:53:22 +04:00
|
|
|
|
if (aUpdateType & UPDATE_STYLE) {
|
2004-01-08 22:23:12 +03:00
|
|
|
|
mStyleSet->EndUpdate();
|
2004-12-02 04:26:20 +03:00
|
|
|
|
if (mStylesHaveChanged)
|
2004-04-13 01:53:22 +04:00
|
|
|
|
ReconstructStyleData();
|
|
|
|
|
}
|
2004-01-08 22:23:12 +03:00
|
|
|
|
|
2004-04-13 01:53:22 +04:00
|
|
|
|
mFrameConstructor->EndUpdate();
|
1998-06-03 19:46:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
2004-01-24 03:46:17 +03:00
|
|
|
|
void
|
1998-07-23 03:32:19 +04:00
|
|
|
|
PresShell::BeginLoad(nsIDocument *aDocument)
|
1999-09-20 10:55:24 +04:00
|
|
|
|
{
|
1999-10-20 02:27:20 +04:00
|
|
|
|
#ifdef MOZ_PERF_METRICS
|
1999-09-20 10:55:24 +04:00
|
|
|
|
// Reset style resolution stopwatch maintained by style set
|
2002-08-24 18:41:28 +04:00
|
|
|
|
MOZ_TIMER_DEBUGLOG(("Reset: Style Resolution: PresShell::BeginLoad(), this=%p\n", (void*)this));
|
2000-04-17 11:13:57 +04:00
|
|
|
|
#endif
|
2000-05-16 05:11:29 +04:00
|
|
|
|
mDocumentLoading = PR_TRUE;
|
1998-06-03 19:46:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
2004-01-24 03:46:17 +03:00
|
|
|
|
void
|
1998-07-23 03:32:19 +04:00
|
|
|
|
PresShell::EndLoad(nsIDocument *aDocument)
|
1998-06-03 19:46:54 +04:00
|
|
|
|
{
|
2000-06-15 04:35:46 +04:00
|
|
|
|
|
|
|
|
|
// Restore frame state for the root scroll frame
|
2005-05-13 00:53:33 +04:00
|
|
|
|
nsCOMPtr<nsILayoutHistoryState> historyState =
|
|
|
|
|
aDocument->GetLayoutHistoryState();
|
2005-01-28 00:18:30 +03:00
|
|
|
|
// Make sure we don't reenter reflow via the sync paint that happens while
|
|
|
|
|
// we're scrolling to our restored position. Entering reflow for the
|
|
|
|
|
// scrollable frame will cause it to reenter ScrollToRestoredPosition(), and
|
|
|
|
|
// it'll get all confused.
|
|
|
|
|
++mChangeNestCount;
|
|
|
|
|
|
2006-02-01 22:55:35 +03:00
|
|
|
|
if (historyState) {
|
|
|
|
|
nsIFrame* scrollFrame = GetRootScrollFrame();
|
2000-06-15 04:35:46 +04:00
|
|
|
|
if (scrollFrame) {
|
2004-07-24 01:39:47 +04:00
|
|
|
|
nsIScrollableFrame* scrollableFrame;
|
|
|
|
|
CallQueryInterface(scrollFrame, &scrollableFrame);
|
|
|
|
|
if (scrollableFrame) {
|
2004-09-13 06:10:29 +04:00
|
|
|
|
FrameManager()->RestoreFrameStateFor(scrollFrame, historyState,
|
|
|
|
|
nsIStatefulFrame::eDocumentScrollState);
|
2004-07-24 01:39:47 +04:00
|
|
|
|
scrollableFrame->ScrollToRestoredPosition();
|
|
|
|
|
}
|
2000-06-15 04:35:46 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-28 00:18:30 +03:00
|
|
|
|
--mChangeNestCount;
|
|
|
|
|
|
1999-10-20 02:27:20 +04:00
|
|
|
|
#ifdef MOZ_PERF_METRICS
|
1999-09-20 10:55:24 +04:00
|
|
|
|
// Dump reflow, style resolution and frame construction times here.
|
1999-11-10 06:41:09 +03:00
|
|
|
|
MOZ_TIMER_DEBUGLOG(("Stop: Reflow: PresShell::EndLoad(), this=%p\n", this));
|
|
|
|
|
MOZ_TIMER_STOP(mReflowWatch);
|
|
|
|
|
MOZ_TIMER_LOG(("Reflow time (this=%p): ", this));
|
|
|
|
|
MOZ_TIMER_PRINT(mReflowWatch);
|
|
|
|
|
|
|
|
|
|
MOZ_TIMER_DEBUGLOG(("Stop: Frame Creation: PresShell::EndLoad(), this=%p\n", this));
|
|
|
|
|
MOZ_TIMER_STOP(mFrameCreationWatch);
|
|
|
|
|
MOZ_TIMER_LOG(("Frame construction plus style resolution time (this=%p): ", this));
|
|
|
|
|
MOZ_TIMER_PRINT(mFrameCreationWatch);
|
1999-09-20 10:55:24 +04:00
|
|
|
|
|
|
|
|
|
// Print style resolution stopwatch maintained by style set
|
2000-02-11 04:21:05 +03:00
|
|
|
|
MOZ_TIMER_DEBUGLOG(("Stop: Style Resolution: PresShell::EndLoad(), this=%p\n", this));
|
2000-04-17 11:13:57 +04:00
|
|
|
|
#endif
|
2000-05-16 05:11:29 +04:00
|
|
|
|
mDocumentLoading = PR_FALSE;
|
1998-06-03 19:46:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
1999-11-09 06:23:26 +03:00
|
|
|
|
// aReflowCommand is considered to be already in the queue if the
|
|
|
|
|
// frame it targets is targeted by a pre-existing reflow command in
|
|
|
|
|
// the queue.
|
|
|
|
|
PRBool
|
2004-05-02 22:07:12 +04:00
|
|
|
|
PresShell::AlreadyInQueue(nsHTMLReflowCommand* aReflowCommand)
|
|
|
|
|
{
|
|
|
|
|
if (!mReflowCommandTable.ops) {
|
|
|
|
|
// We're already destroyed
|
|
|
|
|
NS_ERROR("We really shouldn't be posting reflow commands here");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ReflowCommandEntry* e =
|
|
|
|
|
NS_STATIC_CAST(ReflowCommandEntry*,
|
|
|
|
|
PL_DHashTableOperate(&mReflowCommandTable, aReflowCommand,
|
|
|
|
|
PL_DHASH_ADD));
|
|
|
|
|
|
|
|
|
|
if (!e) {
|
|
|
|
|
// We lie no matter what we say here
|
|
|
|
|
return PR_FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We're using the stub ClearEntry, which zeros out entries, so a
|
|
|
|
|
// non-null mCommand means we're in the queue already.
|
|
|
|
|
if (e->mCommand) {
|
1999-12-23 05:02:33 +03:00
|
|
|
|
#ifdef DEBUG
|
2004-05-02 22:07:12 +04:00
|
|
|
|
if (VERIFY_REFLOW_NOISY_RC & gVerifyReflowFlags) {
|
|
|
|
|
printf("*** PresShell::AlreadyInQueue(): Discarding reflow command: this=%p\n", (void*)this);
|
|
|
|
|
aReflowCommand->List(stdout);
|
1999-11-09 06:23:26 +03:00
|
|
|
|
}
|
2004-05-02 22:07:12 +04:00
|
|
|
|
#endif
|
|
|
|
|
return PR_TRUE;
|
1999-11-09 06:23:26 +03:00
|
|
|
|
}
|
|
|
|
|
|
2004-05-02 22:07:12 +04:00
|
|
|
|
e->mCommand = aReflowCommand;
|
|
|
|
|
return PR_FALSE;
|
1999-11-09 06:23:26 +03:00
|
|
|
|
}
|
|
|
|
|
|
1998-12-29 07:56:31 +03:00
|
|
|
|
NS_IMETHODIMP
|
2005-02-08 03:59:52 +03:00
|
|
|
|
PresShell::AppendReflowCommand(nsIFrame* aTargetFrame,
|
|
|
|
|
nsReflowType aReflowType,
|
|
|
|
|
nsIAtom* aChildListName)
|
1998-04-14 00:24:54 +04:00
|
|
|
|
{
|
2001-08-07 22:57:15 +04:00
|
|
|
|
// If we've not yet done the initial reflow, then don't bother
|
|
|
|
|
// enqueuing a reflow command yet.
|
|
|
|
|
if (! mDidInitialReflow)
|
|
|
|
|
return NS_OK;
|
|
|
|
|
|
2005-07-07 21:10:40 +04:00
|
|
|
|
// If we're already destroying, don't bother with this either.
|
|
|
|
|
if (mIsDestroying)
|
|
|
|
|
return NS_OK;
|
|
|
|
|
|
1999-09-15 04:27:05 +04:00
|
|
|
|
#ifdef DEBUG
|
2000-10-29 02:17:53 +04:00
|
|
|
|
//printf("gShellCounter: %d\n", gShellCounter++);
|
1998-11-26 21:11:02 +03:00
|
|
|
|
if (mInVerifyReflow) {
|
1998-12-29 07:56:31 +03:00
|
|
|
|
return NS_OK;
|
2005-02-08 03:59:52 +03:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
nsHTMLReflowCommand* command = new nsHTMLReflowCommand(aTargetFrame,
|
|
|
|
|
aReflowType,
|
|
|
|
|
aChildListName);
|
|
|
|
|
if (!command) {
|
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
1999-12-23 05:02:33 +03:00
|
|
|
|
if (VERIFY_REFLOW_NOISY_RC & gVerifyReflowFlags) {
|
2001-04-18 10:06:31 +04:00
|
|
|
|
printf("\nPresShell@%p: adding reflow command\n", (void*)this);
|
2005-02-08 03:59:52 +03:00
|
|
|
|
command->List(stdout);
|
1999-12-23 05:02:33 +03:00
|
|
|
|
if (VERIFY_REFLOW_REALLY_NOISY_RC & gVerifyReflowFlags) {
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("Current content model:\n");
|
2003-10-22 10:09:48 +04:00
|
|
|
|
nsIContent *rootContent = mDocument->GetRootContent();
|
1999-12-23 05:02:33 +03:00
|
|
|
|
if (rootContent) {
|
|
|
|
|
rootContent->List(stdout, 0);
|
1999-09-15 04:27:05 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
1999-12-23 05:02:33 +03:00
|
|
|
|
}
|
1998-11-26 21:11:02 +03:00
|
|
|
|
#endif
|
2000-09-12 04:35:11 +04:00
|
|
|
|
|
2000-04-17 11:13:57 +04:00
|
|
|
|
// Add the reflow command to the queue
|
1999-11-09 06:23:26 +03:00
|
|
|
|
nsresult rv = NS_OK;
|
2005-02-08 03:59:52 +03:00
|
|
|
|
if (!AlreadyInQueue(command)) {
|
|
|
|
|
if (mReflowCommands.AppendElement(command)) {
|
|
|
|
|
ReflowCommandAdded(command);
|
2004-05-02 22:07:12 +04:00
|
|
|
|
} else {
|
|
|
|
|
// Drop this command.... we're out of memory
|
2005-02-08 03:59:52 +03:00
|
|
|
|
PL_DHashTableOperate(&mReflowCommandTable, command,
|
2004-05-02 22:07:12 +04:00
|
|
|
|
PL_DHASH_REMOVE);
|
2005-02-08 03:59:52 +03:00
|
|
|
|
delete command;
|
2004-05-02 22:07:12 +04:00
|
|
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
1999-11-09 06:23:26 +03:00
|
|
|
|
}
|
2001-12-18 01:39:59 +03:00
|
|
|
|
else {
|
|
|
|
|
// We're not going to process this reflow command.
|
2005-02-08 03:59:52 +03:00
|
|
|
|
delete command;
|
2001-12-18 01:39:59 +03:00
|
|
|
|
}
|
1999-11-09 06:23:26 +03:00
|
|
|
|
|
2006-04-19 19:08:44 +04:00
|
|
|
|
// Post a reflow event if we are not batching reflow commands.
|
|
|
|
|
if (!mBatchReflows) {
|
2000-09-12 12:59:01 +04:00
|
|
|
|
// If we're in the middle of a drag, process it right away (needed for mac,
|
|
|
|
|
// might as well do it on all platforms just to keep the code paths the same).
|
2006-04-19 19:08:44 +04:00
|
|
|
|
// XXXbz but how does this actually "process it right away"?
|
|
|
|
|
// Isn't this more like "never process it"?
|
2000-10-30 12:26:53 +03:00
|
|
|
|
if ( !IsDragInProgress() )
|
2000-06-15 03:18:54 +04:00
|
|
|
|
PostReflowEvent();
|
2000-04-17 11:13:57 +04:00
|
|
|
|
}
|
|
|
|
|
|
1999-11-09 06:23:26 +03:00
|
|
|
|
return rv;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
2000-06-15 03:18:54 +04:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// IsDragInProgress
|
|
|
|
|
//
|
|
|
|
|
// Ask the drag service if we're in the middle of a drag
|
|
|
|
|
//
|
|
|
|
|
PRBool
|
|
|
|
|
PresShell :: IsDragInProgress ( ) const
|
|
|
|
|
{
|
|
|
|
|
PRBool dragInProgress = PR_FALSE;
|
|
|
|
|
if ( mDragService ) {
|
|
|
|
|
nsCOMPtr<nsIDragSession> session;
|
|
|
|
|
mDragService->GetCurrentSession ( getter_AddRefs(session) );
|
|
|
|
|
if ( session )
|
|
|
|
|
dragInProgress = PR_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return dragInProgress;
|
|
|
|
|
|
|
|
|
|
} // IsDragInProgress
|
|
|
|
|
|
2004-08-06 19:55:17 +04:00
|
|
|
|
nsIScrollableView*
|
2004-09-21 08:41:08 +04:00
|
|
|
|
PresShell::GetViewToScroll(nsLayoutUtils::Direction aDirection)
|
2004-08-06 19:55:17 +04:00
|
|
|
|
{
|
|
|
|
|
nsCOMPtr<nsIEventStateManager> esm = mPresContext->EventStateManager();
|
|
|
|
|
nsIScrollableView* scrollView = nsnull;
|
2004-09-01 18:58:34 +04:00
|
|
|
|
nsCOMPtr<nsIContent> focusedContent;
|
|
|
|
|
esm->GetFocusedContent(getter_AddRefs(focusedContent));
|
2004-10-19 06:24:27 +04:00
|
|
|
|
if (!focusedContent && mSelection) {
|
2006-04-26 06:01:07 +04:00
|
|
|
|
nsISelection* domSelection = mSelection->
|
|
|
|
|
GetSelection(nsISelectionController::SELECTION_NORMAL);
|
2004-10-19 06:24:27 +04:00
|
|
|
|
if (domSelection) {
|
|
|
|
|
nsCOMPtr<nsIDOMNode> focusedNode;
|
|
|
|
|
domSelection->GetFocusNode(getter_AddRefs(focusedNode));
|
|
|
|
|
focusedContent = do_QueryInterface(focusedNode);
|
|
|
|
|
}
|
|
|
|
|
}
|
2004-09-01 18:58:34 +04:00
|
|
|
|
if (focusedContent) {
|
2005-08-23 02:24:29 +04:00
|
|
|
|
nsIFrame* startFrame = GetPrimaryFrameFor(focusedContent);
|
2004-09-01 18:58:34 +04:00
|
|
|
|
if (startFrame) {
|
|
|
|
|
nsCOMPtr<nsIScrollableViewProvider> svp = do_QueryInterface(startFrame);
|
2004-10-19 06:24:27 +04:00
|
|
|
|
// If this very frame provides a scroll view, start there instead of frame's
|
|
|
|
|
// closest view, because the scroll view may be inside a child frame.
|
|
|
|
|
// For example, this happens in the case of overflow:scroll.
|
|
|
|
|
// In that case we still use GetNearestScrollingView() because
|
|
|
|
|
// we need a scrolling view that matches aDirection.
|
2005-01-17 00:25:15 +03:00
|
|
|
|
nsIScrollableView* sv;
|
|
|
|
|
nsIView* startView = svp && (sv = svp->GetScrollableView()) ? sv->View() : startFrame->GetClosestView();
|
2004-10-19 06:24:27 +04:00
|
|
|
|
NS_ASSERTION(startView, "No view to start searching for scrollable view from");
|
|
|
|
|
scrollView = nsLayoutUtils::GetNearestScrollingView(startView, aDirection);
|
2004-08-06 19:55:17 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!scrollView) {
|
|
|
|
|
nsIViewManager* viewManager = GetViewManager();
|
|
|
|
|
if (viewManager) {
|
|
|
|
|
viewManager->GetRootScrollableView(&scrollView);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return scrollView;
|
|
|
|
|
}
|
2000-06-15 03:18:54 +04:00
|
|
|
|
|
2005-08-23 05:29:02 +04:00
|
|
|
|
void
|
2001-12-18 01:54:28 +03:00
|
|
|
|
PresShell::CancelReflowCommandInternal(nsIFrame* aTargetFrame,
|
2005-08-23 05:29:02 +04:00
|
|
|
|
nsReflowType* aCmdType)
|
1999-04-24 00:01:20 +04:00
|
|
|
|
{
|
2002-05-10 22:22:41 +04:00
|
|
|
|
PRInt32 i, n = mReflowCommands.Count();
|
1999-04-24 00:01:20 +04:00
|
|
|
|
for (i = 0; i < n; i++) {
|
2002-05-10 22:22:41 +04:00
|
|
|
|
nsHTMLReflowCommand* rc = (nsHTMLReflowCommand*) mReflowCommands.ElementAt(i);
|
2004-05-02 22:07:12 +04:00
|
|
|
|
if (rc && rc->GetTarget() == aTargetFrame &&
|
2005-02-08 03:59:52 +03:00
|
|
|
|
(!aCmdType || rc->Type() == *aCmdType)) {
|
1999-12-23 05:02:33 +03:00
|
|
|
|
#ifdef DEBUG
|
2004-05-02 22:07:12 +04:00
|
|
|
|
if (VERIFY_REFLOW_NOISY_RC & gVerifyReflowFlags) {
|
|
|
|
|
printf("PresShell: removing rc=%p for frame ", (void*)rc);
|
|
|
|
|
nsFrame::ListTag(stdout, aTargetFrame);
|
|
|
|
|
printf("\n");
|
1999-04-24 00:01:20 +04:00
|
|
|
|
}
|
2004-05-02 22:07:12 +04:00
|
|
|
|
#endif
|
|
|
|
|
mReflowCommands.RemoveElementAt(i);
|
|
|
|
|
ReflowCommandRemoved(rc);
|
|
|
|
|
delete rc;
|
|
|
|
|
n--;
|
|
|
|
|
i--;
|
1999-04-24 00:01:20 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
2001-03-14 10:47:00 +03:00
|
|
|
|
|
2005-08-23 05:29:02 +04:00
|
|
|
|
DoneRemovingReflowCommands();
|
1999-04-24 00:01:20 +04:00
|
|
|
|
}
|
|
|
|
|
|
2001-03-13 09:38:59 +03:00
|
|
|
|
NS_IMETHODIMP
|
2001-12-18 01:54:28 +03:00
|
|
|
|
PresShell::CancelReflowCommand(nsIFrame* aTargetFrame,
|
2001-12-18 01:39:59 +03:00
|
|
|
|
nsReflowType* aCmdType)
|
2001-03-13 09:38:59 +03:00
|
|
|
|
{
|
2005-08-23 05:29:02 +04:00
|
|
|
|
CancelReflowCommandInternal(aTargetFrame, aCmdType);
|
|
|
|
|
return NS_OK;
|
2001-03-13 09:38:59 +03:00
|
|
|
|
}
|
|
|
|
|
|
1999-11-09 06:23:26 +03:00
|
|
|
|
|
2000-09-20 11:20:23 +04:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::CancelAllReflowCommands()
|
|
|
|
|
{
|
|
|
|
|
PRInt32 n = mReflowCommands.Count();
|
2001-12-18 01:39:59 +03:00
|
|
|
|
nsHTMLReflowCommand* rc;
|
2001-03-13 09:38:59 +03:00
|
|
|
|
PRInt32 i;
|
|
|
|
|
for (i = 0; i < n; i++) {
|
2001-12-22 01:15:16 +03:00
|
|
|
|
rc = NS_STATIC_CAST(nsHTMLReflowCommand*, mReflowCommands.ElementAt(i));
|
2000-09-20 11:20:23 +04:00
|
|
|
|
ReflowCommandRemoved(rc);
|
2001-12-18 01:39:59 +03:00
|
|
|
|
delete rc;
|
2000-09-20 11:20:23 +04:00
|
|
|
|
}
|
2001-12-21 04:10:07 +03:00
|
|
|
|
NS_ASSERTION(n == mReflowCommands.Count(),"reflow command list changed during cancel!");
|
|
|
|
|
mReflowCommands.Clear();
|
2001-03-14 10:47:00 +03:00
|
|
|
|
|
|
|
|
|
DoneRemovingReflowCommands();
|
|
|
|
|
|
2000-09-20 11:20:23 +04:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2005-06-10 17:57:27 +04:00
|
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
|
void nsIPresShell::InvalidateAccessibleSubtree(nsIContent *aContent)
|
|
|
|
|
{
|
|
|
|
|
if (mIsAccessibilityActive) {
|
|
|
|
|
nsCOMPtr<nsIAccessibilityService> accService =
|
|
|
|
|
do_GetService("@mozilla.org/accessibilityService;1");
|
|
|
|
|
if (accService) {
|
|
|
|
|
accService->InvalidateSubtreeFor(this, aContent,
|
|
|
|
|
nsIAccessibleEvent::EVENT_REORDER);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-10-22 10:07:52 +04:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::RecreateFramesFor(nsIContent* aContent)
|
|
|
|
|
{
|
|
|
|
|
NS_ENSURE_TRUE(mPresContext, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
|
|
// Don't call RecreateFramesForContent since that is not exported and we want
|
|
|
|
|
// to keep the number of entrypoints down.
|
|
|
|
|
|
2005-10-26 02:32:13 +04:00
|
|
|
|
NS_ASSERTION(mViewManager, "Should have view manager");
|
|
|
|
|
mViewManager->BeginUpdateViewBatch();
|
|
|
|
|
|
|
|
|
|
// Have to make sure that the content notifications are flushed before we
|
|
|
|
|
// start messing with the frame model; otherwise we can get content doubling.
|
|
|
|
|
mDocument->FlushPendingNotifications(Flush_ContentAndNotify);
|
|
|
|
|
|
2002-10-22 10:07:52 +04:00
|
|
|
|
nsStyleChangeList changeList;
|
|
|
|
|
changeList.AppendChange(nsnull, aContent, nsChangeHint_ReconstructFrame);
|
2004-10-09 05:39:21 +04:00
|
|
|
|
|
2005-02-18 19:11:53 +03:00
|
|
|
|
nsresult rv = mFrameConstructor->ProcessRestyledFrames(changeList);
|
2004-10-09 05:39:21 +04:00
|
|
|
|
mViewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
|
2005-06-10 17:57:27 +04:00
|
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
|
InvalidateAccessibleSubtree(aContent);
|
|
|
|
|
#endif
|
2004-10-09 05:39:21 +04:00
|
|
|
|
return rv;
|
2002-10-22 10:07:52 +04:00
|
|
|
|
}
|
|
|
|
|
|
1999-02-12 20:45:58 +03:00
|
|
|
|
NS_IMETHODIMP
|
1998-11-19 03:43:36 +03:00
|
|
|
|
PresShell::ClearFrameRefs(nsIFrame* aFrame)
|
|
|
|
|
{
|
2004-02-27 20:17:37 +03:00
|
|
|
|
mPresContext->EventStateManager()->ClearFrameRefs(aFrame);
|
1999-04-02 03:58:11 +04:00
|
|
|
|
|
1998-11-21 03:19:36 +03:00
|
|
|
|
if (aFrame == mCurrentEventFrame) {
|
2003-06-30 14:46:59 +04:00
|
|
|
|
mCurrentEventContent = aFrame->GetContent();
|
1998-11-21 03:19:36 +03:00
|
|
|
|
mCurrentEventFrame = nsnull;
|
|
|
|
|
}
|
1999-09-02 22:14:01 +04:00
|
|
|
|
|
|
|
|
|
for (int i=0; i<mCurrentEventFrameStack.Count(); i++) {
|
|
|
|
|
if (aFrame == (nsIFrame*)mCurrentEventFrameStack.ElementAt(i)) {
|
2000-04-24 08:41:27 +04:00
|
|
|
|
//One of our stack frames was deleted. Get its content so that when we
|
|
|
|
|
//pop it we can still get its new frame from its content
|
2003-06-30 14:46:59 +04:00
|
|
|
|
nsIContent *currentEventContent = aFrame->GetContent();
|
2004-09-13 07:22:46 +04:00
|
|
|
|
mCurrentEventContentStack.ReplaceObjectAt(currentEventContent, i);
|
1999-09-02 22:14:01 +04:00
|
|
|
|
mCurrentEventFrameStack.ReplaceElementAt(nsnull, i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2006-07-12 11:41:11 +04:00
|
|
|
|
nsWeakFrame* weakFrame = mWeakFrames;
|
|
|
|
|
while (weakFrame) {
|
|
|
|
|
nsWeakFrame* prev = weakFrame->GetPreviousWeakFrame();
|
|
|
|
|
if (weakFrame->GetFrame() == aFrame) {
|
|
|
|
|
// This removes weakFrame from mWeakFrames.
|
|
|
|
|
weakFrame->Clear(this);
|
|
|
|
|
}
|
|
|
|
|
weakFrame = prev;
|
|
|
|
|
}
|
|
|
|
|
|
1999-02-12 20:45:58 +03:00
|
|
|
|
return NS_OK;
|
1998-11-19 03:43:36 +03:00
|
|
|
|
}
|
|
|
|
|
|
1999-02-05 21:25:29 +03:00
|
|
|
|
NS_IMETHODIMP
|
1999-02-12 20:45:58 +03:00
|
|
|
|
PresShell::CreateRenderingContext(nsIFrame *aFrame,
|
|
|
|
|
nsIRenderingContext** aResult)
|
1998-10-02 05:12:39 +04:00
|
|
|
|
{
|
1999-02-12 20:45:58 +03:00
|
|
|
|
NS_PRECONDITION(nsnull != aResult, "null ptr");
|
|
|
|
|
if (nsnull == aResult) {
|
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
}
|
|
|
|
|
|
2006-06-15 07:19:32 +04:00
|
|
|
|
nsIWidget* widget = nsnull;
|
|
|
|
|
// Never pass a widget to a print rendering context
|
|
|
|
|
if (mPresContext->IsScreen())
|
|
|
|
|
widget = aFrame->GetWindow();
|
1998-10-02 05:12:39 +04:00
|
|
|
|
|
2006-06-15 07:19:32 +04:00
|
|
|
|
nsresult rv;
|
1999-02-12 20:45:58 +03:00
|
|
|
|
nsIRenderingContext* result = nsnull;
|
2004-02-03 01:17:21 +03:00
|
|
|
|
nsIDeviceContext *deviceContext = mPresContext->DeviceContext();
|
|
|
|
|
if (widget) {
|
2004-05-18 05:13:45 +04:00
|
|
|
|
rv = deviceContext->CreateRenderingContext(widget, result);
|
2004-02-03 01:17:21 +03:00
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
rv = deviceContext->CreateRenderingContext(result);
|
1999-02-12 20:45:58 +03:00
|
|
|
|
}
|
|
|
|
|
*aResult = result;
|
1998-10-02 05:12:39 +04:00
|
|
|
|
|
|
|
|
|
return rv;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
1999-02-12 08:39:33 +03:00
|
|
|
|
NS_IMETHODIMP
|
2003-01-14 02:10:53 +03:00
|
|
|
|
PresShell::GoToAnchor(const nsAString& aAnchorName, PRBool aScroll)
|
1999-02-12 08:39:33 +03:00
|
|
|
|
{
|
2004-05-28 02:08:42 +04:00
|
|
|
|
if (!mDocument) {
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-27 20:17:37 +03:00
|
|
|
|
// Hold a reference to the ESM in case event dispatch tears us down.
|
|
|
|
|
nsCOMPtr<nsIEventStateManager> esm = mPresContext->EventStateManager();
|
|
|
|
|
|
2003-01-14 02:10:53 +03:00
|
|
|
|
if (aAnchorName.IsEmpty()) {
|
|
|
|
|
NS_ASSERTION(!aScroll, "can't scroll to empty anchor name");
|
2004-02-27 20:17:37 +03:00
|
|
|
|
esm->SetContentState(nsnull, NS_EVENT_STATE_URLTARGET);
|
2003-01-14 02:10:53 +03:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2000-10-11 17:50:45 +04:00
|
|
|
|
nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(mDocument);
|
|
|
|
|
nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
|
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
nsCOMPtr<nsIContent> content;
|
1999-02-12 08:39:33 +03:00
|
|
|
|
|
2000-10-11 17:50:45 +04:00
|
|
|
|
// Search for an element with a matching "id" attribute
|
|
|
|
|
if (doc) {
|
1999-02-12 08:39:33 +03:00
|
|
|
|
nsCOMPtr<nsIDOMElement> element;
|
2000-07-29 01:48:08 +04:00
|
|
|
|
rv = doc->GetElementById(aAnchorName, getter_AddRefs(element));
|
1999-04-09 08:28:15 +04:00
|
|
|
|
if (NS_SUCCEEDED(rv) && element) {
|
1999-02-12 08:39:33 +03:00
|
|
|
|
// Get the nsIContent interface, because that's what we need to
|
|
|
|
|
// get the primary frame
|
2000-10-11 17:50:45 +04:00
|
|
|
|
content = do_QueryInterface(element);
|
1999-03-20 04:51:00 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
1999-02-12 08:39:33 +03:00
|
|
|
|
|
2000-10-11 17:50:45 +04:00
|
|
|
|
// Search for an anchor element with a matching "name" attribute
|
|
|
|
|
if (!content && htmlDoc) {
|
|
|
|
|
nsCOMPtr<nsIDOMNodeList> list;
|
|
|
|
|
// Find a matching list of named nodes
|
|
|
|
|
rv = htmlDoc->GetElementsByName(aAnchorName, getter_AddRefs(list));
|
|
|
|
|
if (NS_SUCCEEDED(rv) && list) {
|
|
|
|
|
PRUint32 i;
|
|
|
|
|
// Loop through the named nodes looking for the first anchor
|
2003-03-15 19:30:09 +03:00
|
|
|
|
for (i = 0; PR_TRUE; i++) {
|
2000-10-11 17:50:45 +04:00
|
|
|
|
nsCOMPtr<nsIDOMNode> node;
|
|
|
|
|
rv = list->Item(i, getter_AddRefs(node));
|
2003-03-15 19:30:09 +03:00
|
|
|
|
if (!node) { // End of list
|
2000-10-11 17:50:45 +04:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
// Ensure it's an anchor element
|
2003-03-15 19:30:09 +03:00
|
|
|
|
content = do_QueryInterface(node);
|
|
|
|
|
if (content) {
|
2003-11-19 04:20:56 +03:00
|
|
|
|
if (content->Tag() == nsHTMLAtoms::a &&
|
2006-05-05 10:52:21 +04:00
|
|
|
|
content->IsNodeOfType(nsINode::eHTML)) {
|
2000-10-11 17:50:45 +04:00
|
|
|
|
break;
|
|
|
|
|
}
|
2003-03-15 19:30:09 +03:00
|
|
|
|
content = nsnull;
|
2000-10-11 17:50:45 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Search for anchor in the HTML namespace with a matching name
|
|
|
|
|
if (!content && !htmlDoc)
|
|
|
|
|
{
|
|
|
|
|
nsCOMPtr<nsIDOMNodeList> list;
|
|
|
|
|
NS_NAMED_LITERAL_STRING(nameSpace, "http://www.w3.org/1999/xhtml");
|
|
|
|
|
// Get the list of anchor elements
|
|
|
|
|
rv = doc->GetElementsByTagNameNS(nameSpace, NS_LITERAL_STRING("a"), getter_AddRefs(list));
|
|
|
|
|
if (NS_SUCCEEDED(rv) && list) {
|
|
|
|
|
PRUint32 i;
|
|
|
|
|
// Loop through the named nodes looking for the first anchor
|
2003-03-15 19:30:09 +03:00
|
|
|
|
for (i = 0; PR_TRUE; i++) {
|
2000-10-11 17:50:45 +04:00
|
|
|
|
nsCOMPtr<nsIDOMNode> node;
|
|
|
|
|
rv = list->Item(i, getter_AddRefs(node));
|
2003-03-15 19:30:09 +03:00
|
|
|
|
if (!node) { // End of list
|
2000-10-11 17:50:45 +04:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
// Compare the name attribute
|
|
|
|
|
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(node);
|
|
|
|
|
nsAutoString value;
|
|
|
|
|
if (element && NS_SUCCEEDED(element->GetAttribute(NS_LITERAL_STRING("name"), value))) {
|
2002-02-20 01:49:12 +03:00
|
|
|
|
if (value.Equals(aAnchorName)) {
|
2000-10-11 17:50:45 +04:00
|
|
|
|
content = do_QueryInterface(element);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Fixes bug 66597, bug 103284, bug 114440, bug 120023, bug 128741, bug 19259. Cleans up browse with caret, makes it work with XML content docs, creates keyboard toggle for it (Accel+shift+K), synchronizes focus and document selection so that users can tab navigate relative to their last find or click in text, or vice versa, makes tabbing move relative to named anchor that has been jumped to. r=bryner, sr=alecf, a=asa
2002-03-10 09:21:48 +03:00
|
|
|
|
nsCOMPtr<nsIDOMRange> jumpToRange;
|
2003-03-20 02:45:42 +03:00
|
|
|
|
nsCOMPtr<nsIXPointerResult> xpointerResult;
|
|
|
|
|
if (!content) {
|
|
|
|
|
nsCOMPtr<nsIDOMXMLDocument> xmldoc = do_QueryInterface(mDocument);
|
|
|
|
|
if (xmldoc) {
|
2005-02-20 12:55:02 +03:00
|
|
|
|
// Try XPointer
|
2003-03-20 02:45:42 +03:00
|
|
|
|
xmldoc->EvaluateXPointer(aAnchorName, getter_AddRefs(xpointerResult));
|
|
|
|
|
if (xpointerResult) {
|
|
|
|
|
xpointerResult->Item(0, getter_AddRefs(jumpToRange));
|
|
|
|
|
if (!jumpToRange) {
|
|
|
|
|
// We know it was an XPointer, so there is no point in
|
|
|
|
|
// trying any other pointer types, let's just return
|
|
|
|
|
// an error.
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-02-20 12:55:02 +03:00
|
|
|
|
// Finally try FIXptr
|
|
|
|
|
if (!jumpToRange) {
|
|
|
|
|
xmldoc->EvaluateFIXptr(aAnchorName,getter_AddRefs(jumpToRange));
|
|
|
|
|
}
|
|
|
|
|
|
Fixes bug 66597, bug 103284, bug 114440, bug 120023, bug 128741, bug 19259. Cleans up browse with caret, makes it work with XML content docs, creates keyboard toggle for it (Accel+shift+K), synchronizes focus and document selection so that users can tab navigate relative to their last find or click in text, or vice versa, makes tabbing move relative to named anchor that has been jumped to. r=bryner, sr=alecf, a=asa
2002-03-10 09:21:48 +03:00
|
|
|
|
if (jumpToRange) {
|
2001-12-20 08:15:52 +03:00
|
|
|
|
nsCOMPtr<nsIDOMNode> node;
|
Fixes bug 66597, bug 103284, bug 114440, bug 120023, bug 128741, bug 19259. Cleans up browse with caret, makes it work with XML content docs, creates keyboard toggle for it (Accel+shift+K), synchronizes focus and document selection so that users can tab navigate relative to their last find or click in text, or vice versa, makes tabbing move relative to named anchor that has been jumped to. r=bryner, sr=alecf, a=asa
2002-03-10 09:21:48 +03:00
|
|
|
|
jumpToRange->GetStartContainer(getter_AddRefs(node));
|
2001-12-20 08:15:52 +03:00
|
|
|
|
if (node) {
|
2005-02-20 12:55:02 +03:00
|
|
|
|
PRUint16 nodeType;
|
|
|
|
|
node->GetNodeType(&nodeType);
|
|
|
|
|
PRInt32 offset = -1;
|
|
|
|
|
jumpToRange->GetStartOffset(&offset);
|
|
|
|
|
switch (nodeType) {
|
|
|
|
|
case nsIDOMNode::ATTRIBUTE_NODE:
|
|
|
|
|
{
|
|
|
|
|
// XXX Assuming jumping to the ownerElement is the sanest action.
|
|
|
|
|
nsCOMPtr<nsIAttribute> attr = do_QueryInterface(node);
|
|
|
|
|
content = attr->GetContent();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case nsIDOMNode::DOCUMENT_NODE:
|
|
|
|
|
{
|
|
|
|
|
if (offset >= 0) {
|
|
|
|
|
nsCOMPtr<nsIDocument> document = do_QueryInterface(node);
|
|
|
|
|
content = document->GetChildAt(offset);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case nsIDOMNode::DOCUMENT_FRAGMENT_NODE:
|
|
|
|
|
case nsIDOMNode::ELEMENT_NODE:
|
|
|
|
|
case nsIDOMNode::ENTITY_REFERENCE_NODE:
|
|
|
|
|
{
|
|
|
|
|
if (offset >= 0) {
|
|
|
|
|
nsCOMPtr<nsIContent> parent = do_QueryInterface(node);
|
|
|
|
|
content = parent->GetChildAt(offset);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case nsIDOMNode::CDATA_SECTION_NODE:
|
|
|
|
|
case nsIDOMNode::COMMENT_NODE:
|
|
|
|
|
case nsIDOMNode::TEXT_NODE:
|
|
|
|
|
case nsIDOMNode::PROCESSING_INSTRUCTION_NODE:
|
|
|
|
|
{
|
|
|
|
|
// XXX This should scroll to a specific position in the text.
|
|
|
|
|
content = do_QueryInterface(node);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-12-20 08:15:52 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-02-20 12:55:02 +03:00
|
|
|
|
|
2004-02-27 20:17:37 +03:00
|
|
|
|
esm->SetContentState(content, NS_EVENT_STATE_URLTARGET);
|
2000-10-11 17:50:45 +04:00
|
|
|
|
|
2003-01-14 02:10:53 +03:00
|
|
|
|
if (content) {
|
2003-04-26 05:13:28 +04:00
|
|
|
|
// Flush notifications so we scroll to the right place
|
2003-05-06 09:46:46 +04:00
|
|
|
|
if (aScroll) {
|
2004-11-13 00:58:12 +03:00
|
|
|
|
mDocument->FlushPendingNotifications(Flush_Layout);
|
|
|
|
|
// Get the primary frame
|
2005-08-23 02:24:29 +04:00
|
|
|
|
nsIFrame* frame = GetPrimaryFrameFor(content);
|
2004-11-13 00:58:12 +03:00
|
|
|
|
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
|
1999-07-19 22:38:33 +04:00
|
|
|
|
rv = ScrollFrameIntoView(frame, NS_PRESSHELL_SCROLL_TOP,
|
|
|
|
|
NS_PRESSHELL_SCROLL_ANYWHERE);
|
2004-11-13 00:58:12 +03:00
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
}
|
2001-03-28 03:59:56 +04:00
|
|
|
|
|
2004-11-13 00:58:12 +03:00
|
|
|
|
// Should we select the target? This action is controlled by a
|
|
|
|
|
// preference: the default is to not select.
|
|
|
|
|
PRBool selectAnchor = nsContentUtils::GetBoolPref("layout.selectanchor");
|
2004-04-30 03:34:19 +04:00
|
|
|
|
|
2004-11-13 00:58:12 +03:00
|
|
|
|
// Even if select anchor pref is false, we must still move the
|
|
|
|
|
// caret there. That way tabbing will start from the new
|
|
|
|
|
// location
|
|
|
|
|
if (!jumpToRange) {
|
|
|
|
|
jumpToRange = do_CreateInstance(kRangeCID);
|
|
|
|
|
if (jumpToRange) {
|
|
|
|
|
while (content && content->GetChildCount() > 0) {
|
|
|
|
|
content = content->GetChildAt(0);
|
Fixes bug 66597, bug 103284, bug 114440, bug 120023, bug 128741, bug 19259. Cleans up browse with caret, makes it work with XML content docs, creates keyboard toggle for it (Accel+shift+K), synchronizes focus and document selection so that users can tab navigate relative to their last find or click in text, or vice versa, makes tabbing move relative to named anchor that has been jumped to. r=bryner, sr=alecf, a=asa
2002-03-10 09:21:48 +03:00
|
|
|
|
}
|
2004-11-13 00:58:12 +03:00
|
|
|
|
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(content));
|
2005-11-21 01:05:24 +03:00
|
|
|
|
NS_ASSERTION(node, "No nsIDOMNode for descendant of anchor");
|
2004-11-13 00:58:12 +03:00
|
|
|
|
jumpToRange->SelectNodeContents(node);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (jumpToRange) {
|
|
|
|
|
// Select the anchor
|
2006-04-26 06:01:07 +04:00
|
|
|
|
nsISelection* sel = mSelection->
|
|
|
|
|
GetSelection(nsISelectionController::SELECTION_NORMAL);
|
|
|
|
|
if (sel) {
|
2004-11-13 00:58:12 +03:00
|
|
|
|
sel->RemoveAllRanges();
|
|
|
|
|
sel->AddRange(jumpToRange);
|
|
|
|
|
if (!selectAnchor) {
|
|
|
|
|
// Use a caret (collapsed selection) at the start of the anchor
|
|
|
|
|
sel->CollapseToStart();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (selectAnchor && xpointerResult) {
|
|
|
|
|
// Select the rest (if any) of the ranges in XPointerResult
|
|
|
|
|
PRUint32 count, i;
|
|
|
|
|
xpointerResult->GetLength(&count);
|
|
|
|
|
for (i = 1; i < count; i++) { // jumpToRange is i = 0
|
|
|
|
|
nsCOMPtr<nsIDOMRange> range;
|
|
|
|
|
xpointerResult->Item(i, getter_AddRefs(range));
|
|
|
|
|
sel->AddRange(range);
|
Fixes bug 66597, bug 103284, bug 114440, bug 120023, bug 128741, bug 19259. Cleans up browse with caret, makes it work with XML content docs, creates keyboard toggle for it (Accel+shift+K), synchronizes focus and document selection so that users can tab navigate relative to their last find or click in text, or vice versa, makes tabbing move relative to named anchor that has been jumped to. r=bryner, sr=alecf, a=asa
2002-03-10 09:21:48 +03:00
|
|
|
|
}
|
2001-03-28 03:59:56 +04:00
|
|
|
|
}
|
2005-04-13 00:25:49 +04:00
|
|
|
|
// Selection is at anchor.
|
|
|
|
|
// Now focus the document itself if focus is on an element within it.
|
2005-08-12 08:11:00 +04:00
|
|
|
|
nsPIDOMWindow *win = mDocument->GetWindow();
|
2005-07-31 00:57:07 +04:00
|
|
|
|
|
2005-04-13 00:25:49 +04:00
|
|
|
|
if (win) {
|
|
|
|
|
nsCOMPtr<nsIFocusController> focusController = win->GetRootFocusController();
|
|
|
|
|
if (focusController) {
|
|
|
|
|
nsCOMPtr<nsIDOMWindowInternal> focusedWin;
|
|
|
|
|
focusController->GetFocusedWindow(getter_AddRefs(focusedWin));
|
2005-08-12 08:11:00 +04:00
|
|
|
|
if (SameCOMIdentity(win, focusedWin)) {
|
2005-04-13 00:25:49 +04:00
|
|
|
|
esm->ChangeFocusWith(nsnull, nsIEventStateManager::eEventFocusedByApplication);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
1999-02-12 08:39:33 +03:00
|
|
|
|
}
|
|
|
|
|
} else {
|
2001-10-17 05:06:19 +04:00
|
|
|
|
rv = NS_ERROR_FAILURE; //changed to NS_OK in quirks mode if ScrollTo is called
|
|
|
|
|
|
|
|
|
|
// Scroll to the top/left if the anchor can not be
|
2001-10-20 07:12:33 +04:00
|
|
|
|
// found and it is labelled top (quirks mode only). @see bug 80784
|
2006-02-03 17:18:39 +03:00
|
|
|
|
if ((NS_LossyConvertUTF16toASCII(aAnchorName).LowerCaseEqualsLiteral("top")) &&
|
2003-12-25 00:51:50 +03:00
|
|
|
|
(mPresContext->CompatibilityMode() == eCompatibility_NavQuirks)) {
|
2003-01-14 02:10:53 +03:00
|
|
|
|
rv = NS_OK;
|
|
|
|
|
// Check |aScroll| after setting |rv| so we set |rv| to the same
|
|
|
|
|
// thing whether or not |aScroll| is true.
|
|
|
|
|
if (aScroll && mViewManager) {
|
|
|
|
|
// Get the viewport scroller
|
|
|
|
|
nsIScrollableView* scrollingView;
|
|
|
|
|
mViewManager->GetRootScrollableView(&scrollingView);
|
|
|
|
|
if (scrollingView) {
|
|
|
|
|
// Scroll to the top of the page
|
|
|
|
|
scrollingView->ScrollTo(0, 0, NS_VMREFRESH_IMMEDIATE);
|
|
|
|
|
}
|
2001-10-17 05:06:19 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
1999-02-12 08:39:33 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2002-11-12 07:38:28 +03:00
|
|
|
|
/**
|
|
|
|
|
* This function takes a scrolling view, a rect, and a scroll position and
|
|
|
|
|
* attempts to scroll that rect to that position in that view. The rect
|
|
|
|
|
* should be in the coordinate system of the _scrolled_ view.
|
|
|
|
|
*/
|
|
|
|
|
static void ScrollViewToShowRect(nsIScrollableView* aScrollingView,
|
|
|
|
|
nsRect & aRect,
|
|
|
|
|
PRIntn aVPercent,
|
|
|
|
|
PRIntn aHPercent)
|
|
|
|
|
{
|
|
|
|
|
// Determine the visible rect in the scrolling view's coordinate space.
|
|
|
|
|
// The size of the visible area is the clip view size
|
2004-09-21 02:25:07 +04:00
|
|
|
|
nsRect visibleRect = aScrollingView->View()->GetBounds(); // get width and height
|
2002-11-12 07:38:28 +03:00
|
|
|
|
aScrollingView->GetScrollPosition(visibleRect.x, visibleRect.y);
|
|
|
|
|
|
|
|
|
|
// The actual scroll offsets
|
|
|
|
|
nscoord scrollOffsetX = visibleRect.x;
|
|
|
|
|
nscoord scrollOffsetY = visibleRect.y;
|
|
|
|
|
|
|
|
|
|
nscoord lineHeight;
|
|
|
|
|
aScrollingView->GetLineHeight(&lineHeight);
|
|
|
|
|
|
|
|
|
|
// See how the rect should be positioned vertically
|
|
|
|
|
if (NS_PRESSHELL_SCROLL_ANYWHERE == aVPercent) {
|
|
|
|
|
// The caller doesn't care where the frame is positioned vertically,
|
|
|
|
|
// so long as it's fully visible
|
|
|
|
|
if (aRect.y < visibleRect.y) {
|
|
|
|
|
// Scroll up so the frame's top edge is visible
|
|
|
|
|
scrollOffsetY = aRect.y;
|
|
|
|
|
} else if (aRect.YMost() > visibleRect.YMost()) {
|
|
|
|
|
// Scroll down so the frame's bottom edge is visible. Make sure the
|
|
|
|
|
// frame's top edge is still visible
|
|
|
|
|
scrollOffsetY += aRect.YMost() - visibleRect.YMost();
|
|
|
|
|
if (scrollOffsetY > aRect.y) {
|
|
|
|
|
scrollOffsetY = aRect.y;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE == aVPercent) {
|
|
|
|
|
// Scroll only if no part of the frame is visible in this view
|
|
|
|
|
if (aRect.YMost() - lineHeight < visibleRect.y) {
|
|
|
|
|
// Scroll up so the frame's top edge is visible
|
|
|
|
|
scrollOffsetY = aRect.y;
|
|
|
|
|
} else if (aRect.y + lineHeight > visibleRect.YMost()) {
|
|
|
|
|
// Scroll down so the frame's bottom edge is visible. Make sure the
|
|
|
|
|
// frame's top edge is still visible
|
|
|
|
|
scrollOffsetY += aRect.YMost() - visibleRect.YMost();
|
|
|
|
|
if (scrollOffsetY > aRect.y) {
|
|
|
|
|
scrollOffsetY = aRect.y;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Align the frame edge according to the specified percentage
|
|
|
|
|
nscoord frameAlignY =
|
2003-02-27 04:38:20 +03:00
|
|
|
|
NSToCoordRound(aRect.y + aRect.height * (aVPercent / 100.0f));
|
2002-11-12 07:38:28 +03:00
|
|
|
|
scrollOffsetY =
|
2003-02-27 04:38:20 +03:00
|
|
|
|
NSToCoordRound(frameAlignY - visibleRect.height * (aVPercent / 100.0f));
|
2002-11-12 07:38:28 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// See how the frame should be positioned horizontally
|
|
|
|
|
if (NS_PRESSHELL_SCROLL_ANYWHERE == aHPercent) {
|
|
|
|
|
// The caller doesn't care where the frame is positioned horizontally,
|
|
|
|
|
// so long as it's fully visible
|
|
|
|
|
if (aRect.x < visibleRect.x) {
|
|
|
|
|
// Scroll left so the frame's left edge is visible
|
|
|
|
|
scrollOffsetX = aRect.x;
|
|
|
|
|
} else if (aRect.XMost() > visibleRect.XMost()) {
|
|
|
|
|
// Scroll right so the frame's right edge is visible. Make sure the
|
|
|
|
|
// frame's left edge is still visible
|
|
|
|
|
scrollOffsetX += aRect.XMost() - visibleRect.XMost();
|
|
|
|
|
if (scrollOffsetX > aRect.x) {
|
|
|
|
|
scrollOffsetX = aRect.x;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE == aHPercent) {
|
|
|
|
|
// Scroll only if no part of the frame is visible in this view
|
|
|
|
|
// XXXbz using the line height here is odd, but there are no
|
|
|
|
|
// natural dimensions to use here, really....
|
|
|
|
|
if (aRect.XMost() - lineHeight < visibleRect.x) {
|
|
|
|
|
// Scroll left so the frame's left edge is visible
|
|
|
|
|
scrollOffsetX = aRect.x;
|
|
|
|
|
} else if (aRect.x + lineHeight > visibleRect.XMost()) {
|
|
|
|
|
// Scroll right so the frame's right edge is visible. Make sure the
|
|
|
|
|
// frame's left edge is still visible
|
|
|
|
|
scrollOffsetX += aRect.XMost() - visibleRect.XMost();
|
|
|
|
|
if (scrollOffsetX > aRect.x) {
|
|
|
|
|
scrollOffsetX = aRect.x;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Align the frame edge according to the specified percentage
|
|
|
|
|
nscoord frameAlignX =
|
2003-02-27 04:38:20 +03:00
|
|
|
|
NSToCoordRound(aRect.x + (aRect.width) * (aHPercent / 100.0f));
|
2002-11-12 07:38:28 +03:00
|
|
|
|
scrollOffsetX =
|
2003-02-27 04:38:20 +03:00
|
|
|
|
NSToCoordRound(frameAlignX - visibleRect.width * (aHPercent / 100.0f));
|
2002-11-12 07:38:28 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
aScrollingView->ScrollTo(scrollOffsetX, scrollOffsetY,
|
|
|
|
|
NS_VMREFRESH_IMMEDIATE);
|
|
|
|
|
}
|
|
|
|
|
|
1999-02-19 01:52:21 +03:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::ScrollFrameIntoView(nsIFrame *aFrame,
|
1999-07-19 22:38:33 +04:00
|
|
|
|
PRIntn aVPercent,
|
|
|
|
|
PRIntn aHPercent) const
|
1999-02-19 01:52:21 +03:00
|
|
|
|
{
|
1999-07-19 22:38:33 +04:00
|
|
|
|
if (!aFrame) {
|
1999-02-19 01:52:21 +03:00
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
1999-07-19 22:38:33 +04:00
|
|
|
|
}
|
2000-11-04 11:21:20 +03:00
|
|
|
|
|
2000-05-12 02:40:51 +04:00
|
|
|
|
// Before we scroll the frame into view, ask the command dispatcher
|
|
|
|
|
// if we're resetting focus because a window just got an activate
|
|
|
|
|
// event. If we are, we do not want to scroll the frame into view.
|
|
|
|
|
// Example: The user clicks on an anchor, and then deactivates the
|
|
|
|
|
// window. When they reactivate the window, the expected behavior
|
|
|
|
|
// is not for the anchor link to scroll back into view. That is what
|
|
|
|
|
// this check is preventing.
|
|
|
|
|
// XXX: The dependency on the command dispatcher needs to be fixed.
|
2003-06-30 14:46:59 +04:00
|
|
|
|
nsIContent* content = aFrame->GetContent();
|
|
|
|
|
if (content) {
|
2003-07-29 01:25:13 +04:00
|
|
|
|
nsIDocument* document = content->GetDocument();
|
|
|
|
|
if (document){
|
2005-11-29 02:56:44 +03:00
|
|
|
|
nsPIDOMWindow *ourWindow = document->GetWindow();
|
2000-05-12 02:40:51 +04:00
|
|
|
|
if(ourWindow) {
|
2004-05-04 01:48:36 +04:00
|
|
|
|
nsIFocusController *focusController =
|
|
|
|
|
ourWindow->GetRootFocusController();
|
2000-11-04 11:21:20 +03:00
|
|
|
|
if (focusController) {
|
|
|
|
|
PRBool dontScroll;
|
|
|
|
|
focusController->GetSuppressFocusScroll(&dontScroll);
|
|
|
|
|
if(dontScroll)
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
}
|
2000-05-12 02:40:51 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
2000-11-04 11:21:20 +03:00
|
|
|
|
|
2004-06-01 00:56:55 +04:00
|
|
|
|
// Flush out pending reflows to make sure we scroll to the right place
|
|
|
|
|
mDocument->FlushPendingNotifications(Flush_OnlyReflow);
|
|
|
|
|
|
2002-11-12 07:38:28 +03:00
|
|
|
|
// This is a two-step process.
|
|
|
|
|
// Step 1: Find the bounds of the rect we want to scroll into view. For
|
2003-10-10 06:35:05 +04:00
|
|
|
|
// example, for an inline frame we may want to scroll in the whole
|
|
|
|
|
// line.
|
2002-11-12 07:38:28 +03:00
|
|
|
|
// Step 2: Walk the views that are parents of the frame and scroll them
|
|
|
|
|
// appropriately.
|
|
|
|
|
|
2003-06-30 14:46:59 +04:00
|
|
|
|
nsRect frameBounds = aFrame->GetRect();
|
2002-11-12 07:38:28 +03:00
|
|
|
|
nsPoint offset;
|
|
|
|
|
nsIView* closestView;
|
2004-12-26 22:48:54 +03:00
|
|
|
|
aFrame->GetOffsetFromView(offset, &closestView);
|
2002-11-12 07:38:28 +03:00
|
|
|
|
frameBounds.MoveTo(offset);
|
|
|
|
|
|
2003-10-10 06:35:05 +04:00
|
|
|
|
// If this is an inline frame and either the bounds height is 0 (quirks
|
|
|
|
|
// layout model) or aVPercent is not NS_PRESSHELL_SCROLL_ANYWHERE, we need to
|
|
|
|
|
// change the top of the bounds to include the whole line.
|
|
|
|
|
if (frameBounds.height == 0 || aVPercent != NS_PRESSHELL_SCROLL_ANYWHERE) {
|
2004-04-13 07:13:46 +04:00
|
|
|
|
nsIAtom* frameType = NULL;
|
2003-10-10 06:35:05 +04:00
|
|
|
|
nsIFrame *prevFrame = aFrame;
|
|
|
|
|
nsIFrame *frame = aFrame;
|
|
|
|
|
|
2003-10-31 23:19:18 +03:00
|
|
|
|
while (frame &&
|
|
|
|
|
(frameType = frame->GetType()) == nsLayoutAtoms::inlineFrame) {
|
2003-10-10 06:35:05 +04:00
|
|
|
|
prevFrame = frame;
|
|
|
|
|
frame = prevFrame->GetParent();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (frame != aFrame &&
|
|
|
|
|
frame &&
|
|
|
|
|
frameType == nsLayoutAtoms::blockFrame) {
|
|
|
|
|
// find the line containing aFrame and increase the top of |offset|.
|
|
|
|
|
nsCOMPtr<nsILineIterator> lines( do_QueryInterface(frame) );
|
|
|
|
|
|
|
|
|
|
if (lines) {
|
|
|
|
|
PRInt32 index = -1;
|
|
|
|
|
lines->FindLineContaining(prevFrame, &index);
|
|
|
|
|
if (index >= 0) {
|
|
|
|
|
nsIFrame *trash1;
|
|
|
|
|
PRInt32 trash2;
|
|
|
|
|
nsRect lineBounds;
|
|
|
|
|
PRUint32 trash3;
|
|
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(lines->GetLine(index, &trash1, &trash2,
|
|
|
|
|
lineBounds, &trash3))) {
|
|
|
|
|
nsPoint blockOffset;
|
|
|
|
|
nsIView* blockView;
|
2004-12-26 22:48:54 +03:00
|
|
|
|
frame->GetOffsetFromView(blockOffset, &blockView);
|
2003-10-10 06:35:05 +04:00
|
|
|
|
|
|
|
|
|
if (blockView == closestView) {
|
|
|
|
|
// XXX If views not equal, this is hard. Do we want to bother?
|
|
|
|
|
nscoord newoffset = lineBounds.y + blockOffset.y;
|
|
|
|
|
|
|
|
|
|
if (newoffset < frameBounds.y)
|
|
|
|
|
frameBounds.y = newoffset;
|
|
|
|
|
}
|
1999-02-20 02:43:41 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
1999-07-19 22:38:33 +04:00
|
|
|
|
}
|
2002-11-12 07:38:28 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
1999-07-19 22:38:33 +04:00
|
|
|
|
|
2004-11-24 03:19:21 +03:00
|
|
|
|
NS_ASSERTION(closestView && !closestView->ToScrollableView(),
|
|
|
|
|
"What happened to the scrolled view? "
|
|
|
|
|
"The frame should not be directly in the scrolling view!");
|
2002-11-12 07:38:28 +03:00
|
|
|
|
|
|
|
|
|
// Walk up the view hierarchy. Make sure to add the view's position
|
|
|
|
|
// _after_ we get the parent and see whether it's scrollable. We want to
|
|
|
|
|
// make sure to get the scrolled view's position after it has been scrolled.
|
|
|
|
|
nsIScrollableView* scrollingView = nsnull;
|
|
|
|
|
while (closestView) {
|
2003-06-30 14:46:59 +04:00
|
|
|
|
nsIView* parent = closestView->GetParent();
|
2002-11-12 07:38:28 +03:00
|
|
|
|
if (parent) {
|
2004-11-24 03:19:21 +03:00
|
|
|
|
scrollingView = parent->ToScrollableView();
|
2002-11-12 07:38:28 +03:00
|
|
|
|
if (scrollingView) {
|
|
|
|
|
ScrollViewToShowRect(scrollingView, frameBounds, aVPercent, aHPercent);
|
2001-11-18 09:04:17 +03:00
|
|
|
|
}
|
1999-02-19 01:52:21 +03:00
|
|
|
|
}
|
2003-06-30 14:46:59 +04:00
|
|
|
|
frameBounds += closestView->GetPosition();;
|
2002-11-12 07:38:28 +03:00
|
|
|
|
closestView = parent;
|
1999-02-19 01:52:21 +03:00
|
|
|
|
}
|
2001-11-18 09:04:17 +03:00
|
|
|
|
|
2002-11-12 07:38:28 +03:00
|
|
|
|
return NS_OK;
|
1999-02-19 01:52:21 +03:00
|
|
|
|
}
|
|
|
|
|
|
2002-08-02 01:36:02 +04:00
|
|
|
|
// GetLinkLocation: copy link location to clipboard
|
|
|
|
|
NS_IMETHODIMP PresShell::GetLinkLocation(nsIDOMNode* aNode, nsAString& aLocationString)
|
2001-04-18 10:06:31 +04:00
|
|
|
|
{
|
|
|
|
|
#ifdef DEBUG_dr
|
2002-08-02 01:36:02 +04:00
|
|
|
|
printf("dr :: PresShell::GetLinkLocation\n");
|
2001-04-18 10:06:31 +04:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
NS_ENSURE_ARG_POINTER(aNode);
|
|
|
|
|
nsresult rv;
|
2001-09-13 03:31:37 +04:00
|
|
|
|
nsAutoString anchorText;
|
2002-03-12 08:29:31 +03:00
|
|
|
|
static char strippedChars[] = {'\t','\r','\n'};
|
2001-04-18 10:06:31 +04:00
|
|
|
|
|
|
|
|
|
// are we an anchor?
|
2001-09-13 03:31:37 +04:00
|
|
|
|
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(aNode));
|
|
|
|
|
nsCOMPtr<nsIDOMHTMLAreaElement> area;
|
|
|
|
|
nsCOMPtr<nsIDOMHTMLLinkElement> link;
|
|
|
|
|
nsAutoString xlinkType;
|
2001-04-18 10:06:31 +04:00
|
|
|
|
if (anchor) {
|
|
|
|
|
rv = anchor->GetHref(anchorText);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2001-09-13 03:31:37 +04:00
|
|
|
|
} else {
|
|
|
|
|
// area?
|
|
|
|
|
area = do_QueryInterface(aNode);
|
|
|
|
|
if (area) {
|
|
|
|
|
rv = area->GetHref(anchorText);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
} else {
|
|
|
|
|
// link?
|
|
|
|
|
link = do_QueryInterface(aNode);
|
|
|
|
|
if (link) {
|
|
|
|
|
rv = link->GetHref(anchorText);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
} else {
|
|
|
|
|
// Xlink?
|
|
|
|
|
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(aNode));
|
|
|
|
|
if (element) {
|
|
|
|
|
NS_NAMED_LITERAL_STRING(xlinkNS,"http://www.w3.org/1999/xlink");
|
|
|
|
|
element->GetAttributeNS(xlinkNS,NS_LITERAL_STRING("type"),xlinkType);
|
2004-04-28 21:48:02 +04:00
|
|
|
|
if (xlinkType.EqualsLiteral("simple")) {
|
2001-09-13 03:31:37 +04:00
|
|
|
|
element->GetAttributeNS(xlinkNS,NS_LITERAL_STRING("href"),anchorText);
|
|
|
|
|
if (!anchorText.IsEmpty()) {
|
|
|
|
|
// Resolve the full URI using baseURI property
|
|
|
|
|
|
|
|
|
|
nsAutoString base;
|
|
|
|
|
nsCOMPtr<nsIDOM3Node> node(do_QueryInterface(aNode,&rv));
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
node->GetBaseURI(base);
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIIOService>
|
|
|
|
|
ios(do_GetService("@mozilla.org/network/io-service;1", &rv));
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> baseURI;
|
2006-02-03 17:18:39 +03:00
|
|
|
|
rv = ios->NewURI(NS_ConvertUTF16toUTF8(base),nsnull,nsnull,getter_AddRefs(baseURI));
|
2001-09-13 03:31:37 +04:00
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2001-11-18 09:04:17 +03:00
|
|
|
|
|
2002-03-06 10:48:55 +03:00
|
|
|
|
nsCAutoString spec;
|
2006-02-03 17:18:39 +03:00
|
|
|
|
rv = baseURI->Resolve(NS_ConvertUTF16toUTF8(anchorText),spec);
|
2001-09-13 03:31:37 +04:00
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
2003-06-24 05:46:50 +04:00
|
|
|
|
CopyUTF8toUTF16(spec, anchorText);
|
2001-09-13 03:31:37 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-05-10 06:35:00 +04:00
|
|
|
|
|
2004-04-30 17:23:43 +04:00
|
|
|
|
if (anchor || area || link || xlinkType.EqualsLiteral("simple")) {
|
2002-03-12 08:29:31 +03:00
|
|
|
|
//Remove all the '\t', '\r' and '\n' from 'anchorText'
|
|
|
|
|
anchorText.StripChars(strippedChars);
|
2001-05-10 06:35:00 +04:00
|
|
|
|
|
2002-08-02 01:36:02 +04:00
|
|
|
|
aLocationString = anchorText;
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
2001-04-18 10:06:31 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if no link, fail.
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
2005-08-29 19:19:13 +04:00
|
|
|
|
NS_IMETHODIMP
|
2003-04-22 22:11:12 +04:00
|
|
|
|
PresShell::GetSelectionForCopy(nsISelection** outSelection)
|
1999-04-07 07:56:07 +04:00
|
|
|
|
{
|
2006-04-26 06:01:07 +04:00
|
|
|
|
nsresult rv;
|
2003-11-26 13:23:03 +03:00
|
|
|
|
|
2003-04-22 22:11:12 +04:00
|
|
|
|
*outSelection = nsnull;
|
|
|
|
|
|
2004-08-02 08:52:55 +04:00
|
|
|
|
if (!mDocument) return NS_ERROR_FAILURE;
|
2001-11-18 09:04:17 +03:00
|
|
|
|
|
2003-11-26 13:23:03 +03:00
|
|
|
|
nsCOMPtr<nsIContent> content;
|
2005-11-29 02:56:44 +03:00
|
|
|
|
nsPIDOMWindow *ourWindow = mDocument->GetWindow();
|
2003-11-26 13:23:03 +03:00
|
|
|
|
if (ourWindow) {
|
2004-05-04 01:48:36 +04:00
|
|
|
|
nsIFocusController *focusController = ourWindow->GetRootFocusController();
|
2003-11-26 13:23:03 +03:00
|
|
|
|
if (focusController) {
|
|
|
|
|
nsCOMPtr<nsIDOMElement> focusedElement;
|
|
|
|
|
focusController->GetFocusedElement(getter_AddRefs(focusedElement));
|
|
|
|
|
content = do_QueryInterface(focusedElement);
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-10-13 13:27:46 +04:00
|
|
|
|
|
2003-04-22 22:11:12 +04:00
|
|
|
|
nsCOMPtr<nsISelection> sel;
|
2003-11-26 13:23:03 +03:00
|
|
|
|
if (content)
|
2000-07-15 01:58:50 +04:00
|
|
|
|
{
|
|
|
|
|
//check to see if we need to get selection from frame
|
|
|
|
|
//optimization that MAY need to be expanded as more things implement their own "selection"
|
|
|
|
|
nsCOMPtr<nsIDOMNSHTMLInputElement> htmlInputElement(do_QueryInterface(content));
|
|
|
|
|
nsCOMPtr<nsIDOMNSHTMLTextAreaElement> htmlTextAreaElement(do_QueryInterface(content));
|
|
|
|
|
if (htmlInputElement || htmlTextAreaElement)
|
2000-06-14 06:57:26 +04:00
|
|
|
|
{
|
2005-08-23 02:24:29 +04:00
|
|
|
|
nsIFrame *htmlInputFrame = GetPrimaryFrameFor(content);
|
2003-04-22 22:11:12 +04:00
|
|
|
|
if (!htmlInputFrame) return NS_ERROR_FAILURE;
|
2001-10-13 13:27:46 +04:00
|
|
|
|
|
2000-07-15 01:58:50 +04:00
|
|
|
|
nsCOMPtr<nsISelectionController> selCon;
|
2006-04-26 06:01:07 +04:00
|
|
|
|
rv = htmlInputFrame->
|
|
|
|
|
GetSelectionController(mPresContext,getter_AddRefs(selCon));
|
2003-04-22 22:11:12 +04:00
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
if (!selCon) return NS_ERROR_FAILURE;
|
2001-10-13 13:27:46 +04:00
|
|
|
|
|
2006-04-26 06:01:07 +04:00
|
|
|
|
rv = selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
|
|
|
|
|
getter_AddRefs(sel));
|
2000-06-14 06:57:26 +04:00
|
|
|
|
}
|
2000-07-15 01:58:50 +04:00
|
|
|
|
}
|
2006-04-26 06:01:07 +04:00
|
|
|
|
if (!sel) {
|
|
|
|
|
sel = mSelection->GetSelection(nsISelectionController::SELECTION_NORMAL);
|
|
|
|
|
rv = NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-22 22:11:12 +04:00
|
|
|
|
*outSelection = sel;
|
|
|
|
|
NS_IF_ADDREF(*outSelection);
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::DoGetContents(const nsACString& aMimeType, PRUint32 aFlags, PRBool aSelectionOnly, nsAString& aOutValue)
|
|
|
|
|
{
|
|
|
|
|
aOutValue.Truncate();
|
|
|
|
|
|
2004-08-02 08:52:55 +04:00
|
|
|
|
if (!mDocument) return NS_ERROR_FAILURE;
|
2003-04-22 22:11:12 +04:00
|
|
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsISelection> sel;
|
|
|
|
|
|
|
|
|
|
// Now we have the selection. Make sure it's nonzero:
|
|
|
|
|
if (aSelectionOnly)
|
|
|
|
|
{
|
|
|
|
|
rv = GetSelectionForCopy(getter_AddRefs(sel));
|
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
if (!sel) return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
|
|
PRBool isCollapsed;
|
|
|
|
|
sel->GetIsCollapsed(&isCollapsed);
|
|
|
|
|
if (isCollapsed)
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// call the copy code
|
2004-08-02 08:52:55 +04:00
|
|
|
|
return nsCopySupport::GetContents(aMimeType, aFlags, sel,
|
|
|
|
|
mDocument, aOutValue);
|
2003-04-22 22:11:12 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::DoCopy()
|
|
|
|
|
{
|
2004-08-02 08:52:55 +04:00
|
|
|
|
if (!mDocument) return NS_ERROR_FAILURE;
|
2003-04-22 22:11:12 +04:00
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsISelection> sel;
|
|
|
|
|
nsresult rv = GetSelectionForCopy(getter_AddRefs(sel));
|
2001-10-13 13:27:46 +04:00
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
|
return rv;
|
|
|
|
|
if (!sel)
|
|
|
|
|
return NS_ERROR_FAILURE;
|
2000-07-15 01:58:50 +04:00
|
|
|
|
|
2000-08-29 02:28:56 +04:00
|
|
|
|
// Now we have the selection. Make sure it's nonzero:
|
|
|
|
|
PRBool isCollapsed;
|
|
|
|
|
sel->GetIsCollapsed(&isCollapsed);
|
|
|
|
|
if (isCollapsed)
|
|
|
|
|
return NS_OK;
|
|
|
|
|
|
2001-02-15 16:22:26 +03:00
|
|
|
|
// call the copy code
|
2004-08-02 08:52:55 +04:00
|
|
|
|
rv = nsCopySupport::HTMLCopy(sel, mDocument, nsIClipboard::kGlobalClipboard);
|
2001-02-15 16:22:26 +03:00
|
|
|
|
if (NS_FAILED(rv))
|
2000-07-15 01:58:50 +04:00
|
|
|
|
return rv;
|
2001-02-20 00:50:04 +03:00
|
|
|
|
|
2000-07-15 01:58:50 +04:00
|
|
|
|
// Now that we have copied, update the Paste menu item
|
2005-11-29 02:56:44 +03:00
|
|
|
|
nsPIDOMWindow *domWindow = mDocument->GetWindow();
|
2000-07-15 01:58:50 +04:00
|
|
|
|
if (domWindow)
|
|
|
|
|
{
|
2001-11-14 04:33:42 +03:00
|
|
|
|
domWindow->UpdateCommands(NS_LITERAL_STRING("clipboard"));
|
2000-07-15 01:58:50 +04:00
|
|
|
|
}
|
|
|
|
|
|
1999-04-07 07:56:07 +04:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
1999-08-31 02:38:58 +04:00
|
|
|
|
NS_IMETHODIMP
|
2000-06-15 04:35:46 +04:00
|
|
|
|
PresShell::CaptureHistoryState(nsILayoutHistoryState** aState, PRBool aLeavingPage)
|
1999-08-31 02:38:58 +04:00
|
|
|
|
{
|
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
|
|
|
|
NS_PRECONDITION(nsnull != aState, "null state pointer");
|
|
|
|
|
|
2005-05-13 00:53:33 +04:00
|
|
|
|
// We actually have to mess with the docshell here, since we want to
|
|
|
|
|
// store the state back in it.
|
|
|
|
|
// XXXbz this isn't really right, since this is being called in the
|
|
|
|
|
// content viewer's Hide() method... by that point the docshell's
|
|
|
|
|
// state could be wrong. We should sort out a better ownership
|
|
|
|
|
// model for the layout history state.
|
2004-02-01 13:09:07 +03:00
|
|
|
|
nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
|
2003-05-30 04:21:01 +04:00
|
|
|
|
if (!container)
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
|
|
|
|
|
if (!docShell)
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsILayoutHistoryState> historyState;
|
|
|
|
|
docShell->GetLayoutHistoryState(getter_AddRefs(historyState));
|
2001-05-12 19:52:06 +04:00
|
|
|
|
if (!historyState) {
|
2000-01-14 12:28:54 +03:00
|
|
|
|
// Create the document state object
|
2001-05-12 19:52:06 +04:00
|
|
|
|
rv = NS_NewLayoutHistoryState(getter_AddRefs(historyState));
|
1999-08-31 02:38:58 +04:00
|
|
|
|
|
2000-01-14 12:28:54 +03:00
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
|
*aState = nsnull;
|
|
|
|
|
return rv;
|
2000-02-12 01:54:37 +03:00
|
|
|
|
}
|
1999-08-31 02:38:58 +04:00
|
|
|
|
|
2003-05-30 04:21:01 +04:00
|
|
|
|
docShell->SetLayoutHistoryState(historyState);
|
2000-01-14 12:28:54 +03:00
|
|
|
|
}
|
2001-05-12 19:52:06 +04:00
|
|
|
|
|
|
|
|
|
*aState = historyState;
|
|
|
|
|
NS_IF_ADDREF(*aState);
|
2000-01-14 12:28:54 +03:00
|
|
|
|
|
2000-02-12 01:54:37 +03:00
|
|
|
|
// Capture frame state for the entire frame hierarchy
|
2004-03-06 07:46:11 +03:00
|
|
|
|
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
|
2004-02-24 00:29:06 +03:00
|
|
|
|
if (!rootFrame) return NS_OK;
|
2000-06-15 04:35:46 +04:00
|
|
|
|
// Capture frame state for the root scroll frame
|
2005-11-21 01:05:24 +03:00
|
|
|
|
// Don't capture state when first creating doc element hierarchy
|
2000-06-15 04:35:46 +04:00
|
|
|
|
// As the scroll position is 0 and this will cause us to loose
|
|
|
|
|
// our previously saved place!
|
|
|
|
|
if (aLeavingPage) {
|
2006-02-01 22:55:35 +03:00
|
|
|
|
nsIFrame* scrollFrame = GetRootScrollFrame();
|
2000-06-15 04:35:46 +04:00
|
|
|
|
if (scrollFrame) {
|
2004-09-13 06:10:29 +04:00
|
|
|
|
FrameManager()->CaptureFrameStateFor(scrollFrame, historyState,
|
|
|
|
|
nsIStatefulFrame::eDocumentScrollState);
|
2000-06-15 04:35:46 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-03-06 07:46:11 +03:00
|
|
|
|
FrameManager()->CaptureFrameState(rootFrame, historyState);
|
2000-01-14 12:28:54 +03:00
|
|
|
|
|
2004-02-24 00:29:06 +03:00
|
|
|
|
return NS_OK;
|
1999-08-31 02:38:58 +04:00
|
|
|
|
}
|
|
|
|
|
|
2000-03-23 03:34:54 +03:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::GetGeneratedContentIterator(nsIContent* aContent,
|
|
|
|
|
GeneratedContentType aType,
|
|
|
|
|
nsIContentIterator** aIterator) const
|
|
|
|
|
{
|
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
|
|
|
|
// Initialize OUT parameter
|
|
|
|
|
*aIterator = nsnull;
|
|
|
|
|
|
|
|
|
|
// Get the primary frame associated with the content object
|
2005-08-23 02:24:29 +04:00
|
|
|
|
nsIFrame* primaryFrame = GetPrimaryFrameFor(aContent);
|
2000-03-23 03:34:54 +03:00
|
|
|
|
if (primaryFrame) {
|
|
|
|
|
// See whether it's a request for the before or after generated content
|
|
|
|
|
if (Before == aType) {
|
2005-02-18 09:06:47 +03:00
|
|
|
|
nsIFrame* beforeFrame = nsLayoutUtils::GetBeforeFrame(primaryFrame);
|
2003-01-05 08:05:17 +03:00
|
|
|
|
if (beforeFrame) {
|
2000-03-23 03:34:54 +03:00
|
|
|
|
// Create an iterator
|
2003-01-05 08:05:17 +03:00
|
|
|
|
rv = NS_NewFrameContentIterator(mPresContext, beforeFrame, aIterator);
|
2000-03-23 03:34:54 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
2003-01-05 08:05:17 +03:00
|
|
|
|
// Avoid finding the :after frame unless we need to (it's
|
|
|
|
|
// expensive). Instead probe for the existence of the pseudo-element
|
2003-02-22 03:32:13 +03:00
|
|
|
|
nsStyleContext *styleContext;
|
2000-03-23 03:34:54 +03:00
|
|
|
|
|
2003-02-22 03:32:13 +03:00
|
|
|
|
styleContext = primaryFrame->GetStyleContext();
|
2003-04-22 03:06:40 +04:00
|
|
|
|
if (nsLayoutUtils::HasPseudoStyle(aContent, styleContext,
|
|
|
|
|
nsCSSPseudoElements::after,
|
|
|
|
|
mPresContext)) {
|
2005-02-18 09:06:47 +03:00
|
|
|
|
nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(primaryFrame);
|
2003-01-05 08:05:17 +03:00
|
|
|
|
if (afterFrame)
|
|
|
|
|
{
|
|
|
|
|
NS_ASSERTION(afterFrame->IsGeneratedContentFrame(),
|
2000-09-14 09:40:48 +04:00
|
|
|
|
"can't find generated content frame");
|
|
|
|
|
// Create an iterator
|
2003-01-05 08:05:17 +03:00
|
|
|
|
rv = NS_NewFrameContentIterator(mPresContext, afterFrame, aIterator);
|
2000-09-14 09:40:48 +04:00
|
|
|
|
}
|
2000-03-23 03:34:54 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
1999-11-09 06:23:26 +03:00
|
|
|
|
|
2000-10-09 07:08:41 +04:00
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::SetAnonymousContentFor(nsIContent* aContent, nsISupportsArray* aAnonymousElements)
|
|
|
|
|
{
|
|
|
|
|
NS_PRECONDITION(aContent != nsnull, "null ptr");
|
|
|
|
|
if (! aContent)
|
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
|
|
if (! mAnonymousContentTable) {
|
|
|
|
|
mAnonymousContentTable = new nsSupportsHashtable;
|
|
|
|
|
if (! mAnonymousContentTable)
|
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsISupportsKey key(aContent);
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsISupportsArray> oldAnonymousElements =
|
|
|
|
|
getter_AddRefs(NS_STATIC_CAST(nsISupportsArray*, mAnonymousContentTable->Get(&key)));
|
|
|
|
|
|
2003-03-12 06:22:11 +03:00
|
|
|
|
if (!oldAnonymousElements) {
|
|
|
|
|
if (aAnonymousElements) {
|
|
|
|
|
mAnonymousContentTable->Put(&key, aAnonymousElements);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (aAnonymousElements) {
|
|
|
|
|
oldAnonymousElements->AppendElements(aAnonymousElements);
|
|
|
|
|
} else {
|
|
|
|
|
// If we're trying to clear anonymous content for an element that
|
|
|
|
|
// already had anonymous content, then we need to be sure to clean
|
|
|
|
|
// up after the old content. (This can happen, for example, when a
|
|
|
|
|
// reframe occurs.)
|
|
|
|
|
PRUint32 count;
|
|
|
|
|
oldAnonymousElements->Count(&count);
|
|
|
|
|
|
|
|
|
|
while (PRInt32(--count) >= 0) {
|
2003-07-08 01:57:01 +04:00
|
|
|
|
nsCOMPtr<nsIContent> content = do_QueryElementAt(oldAnonymousElements,
|
|
|
|
|
count);
|
2003-03-12 06:22:11 +03:00
|
|
|
|
NS_ASSERTION(content != nsnull, "not an nsIContent");
|
|
|
|
|
if (! content)
|
|
|
|
|
continue;
|
|
|
|
|
|
2005-04-06 03:54:35 +04:00
|
|
|
|
content->UnbindFromTree();
|
2003-03-12 06:22:11 +03:00
|
|
|
|
}
|
2005-04-08 03:50:40 +04:00
|
|
|
|
|
|
|
|
|
if (!mIsReleasingAnonymousContent)
|
|
|
|
|
mAnonymousContentTable->Remove(&key);
|
2000-10-09 07:08:41 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::GetAnonymousContentFor(nsIContent* aContent, nsISupportsArray** aAnonymousElements)
|
|
|
|
|
{
|
|
|
|
|
if (! mAnonymousContentTable) {
|
|
|
|
|
*aAnonymousElements = nsnull;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsISupportsKey key(aContent);
|
|
|
|
|
*aAnonymousElements =
|
|
|
|
|
NS_REINTERPRET_CAST(nsISupportsArray*, mAnonymousContentTable->Get(&key)); // addrefs
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static PRBool PR_CALLBACK
|
|
|
|
|
ClearDocumentEnumerator(nsHashKey* aKey, void* aData, void* aClosure)
|
|
|
|
|
{
|
|
|
|
|
nsISupportsArray* anonymousElements =
|
|
|
|
|
NS_STATIC_CAST(nsISupportsArray*, aData);
|
|
|
|
|
|
|
|
|
|
PRUint32 count;
|
|
|
|
|
anonymousElements->Count(&count);
|
|
|
|
|
while (PRInt32(--count) >= 0) {
|
2003-07-08 01:57:01 +04:00
|
|
|
|
nsCOMPtr<nsIContent> content = do_QueryElementAt(anonymousElements, count);
|
2000-10-09 07:08:41 +04:00
|
|
|
|
NS_ASSERTION(content != nsnull, "not an nsIContent");
|
|
|
|
|
if (! content)
|
|
|
|
|
continue;
|
|
|
|
|
|
2005-04-06 03:54:35 +04:00
|
|
|
|
content->UnbindFromTree();
|
2000-10-09 07:08:41 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return PR_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::ReleaseAnonymousContent()
|
|
|
|
|
{
|
|
|
|
|
if (mAnonymousContentTable) {
|
2005-04-08 03:50:40 +04:00
|
|
|
|
mIsReleasingAnonymousContent = PR_TRUE;
|
2000-10-09 07:08:41 +04:00
|
|
|
|
mAnonymousContentTable->Enumerate(ClearDocumentEnumerator);
|
|
|
|
|
delete mAnonymousContentTable;
|
|
|
|
|
mAnonymousContentTable = nsnull;
|
|
|
|
|
}
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2001-04-25 23:52:49 +04:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::IsPaintingSuppressed(PRBool* aResult)
|
|
|
|
|
{
|
|
|
|
|
*aResult = mPaintingSuppressed;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PresShell::UnsuppressAndInvalidate()
|
|
|
|
|
{
|
2005-01-20 06:39:09 +03:00
|
|
|
|
if (!mPresContext->EnsureVisible(PR_FALSE)) {
|
|
|
|
|
// No point; we're about to be torn down anyway.
|
|
|
|
|
return;
|
2001-05-02 02:54:11 +04:00
|
|
|
|
}
|
2005-01-20 06:39:09 +03:00
|
|
|
|
|
2004-02-24 00:29:06 +03:00
|
|
|
|
mPaintingSuppressed = PR_FALSE;
|
2004-03-06 07:46:11 +03:00
|
|
|
|
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
|
2004-02-24 00:29:06 +03:00
|
|
|
|
if (rootFrame) {
|
2004-03-10 06:09:05 +03:00
|
|
|
|
// let's assume that outline on a root frame is not supported
|
|
|
|
|
nsRect rect(nsPoint(0, 0), rootFrame->GetSize());
|
|
|
|
|
rootFrame->Invalidate(rect, PR_FALSE);
|
2001-04-25 23:52:49 +04:00
|
|
|
|
}
|
2001-06-01 02:19:43 +04:00
|
|
|
|
|
2005-01-20 06:39:09 +03:00
|
|
|
|
// This makes sure to get the same thing that nsPresContext::EnsureVisible()
|
|
|
|
|
// got.
|
|
|
|
|
nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
|
|
|
|
|
nsCOMPtr<nsPIDOMWindow> ourWindow = do_GetInterface(container);
|
2006-05-15 21:18:59 +04:00
|
|
|
|
nsCOMPtr<nsIFocusController> focusController =
|
2005-01-20 06:39:09 +03:00
|
|
|
|
ourWindow ? ourWindow->GetRootFocusController() : nsnull;
|
|
|
|
|
|
2001-06-05 03:23:35 +04:00
|
|
|
|
if (ourWindow)
|
|
|
|
|
CheckForFocus(ourWindow, focusController, mDocument);
|
2001-06-04 04:22:43 +04:00
|
|
|
|
|
|
|
|
|
if (focusController) // Unsuppress now that we've shown the new window and focused it.
|
|
|
|
|
focusController->SetSuppressFocus(PR_FALSE, "PresShell suppression on Web page loads");
|
2004-06-22 08:32:52 +04:00
|
|
|
|
|
2004-06-25 01:56:29 +04:00
|
|
|
|
if (mViewManager)
|
|
|
|
|
mViewManager->SynthesizeMouseMove(PR_FALSE);
|
2001-04-25 23:52:49 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2001-05-02 02:54:11 +04:00
|
|
|
|
PresShell::UnsuppressPainting()
|
2001-04-25 23:52:49 +04:00
|
|
|
|
{
|
2001-05-02 02:54:11 +04:00
|
|
|
|
if (mPaintSuppressionTimer) {
|
2001-04-25 23:52:49 +04:00
|
|
|
|
mPaintSuppressionTimer->Cancel();
|
|
|
|
|
mPaintSuppressionTimer = nsnull;
|
|
|
|
|
}
|
|
|
|
|
|
2001-05-02 02:54:11 +04:00
|
|
|
|
if (mIsDocumentGone || !mPaintingSuppressed)
|
2001-04-25 23:52:49 +04:00
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
|
|
// If we have reflows pending, just wait until we process
|
|
|
|
|
// the reflows and get all the frames where we want them
|
|
|
|
|
// before actually unlocking the painting. Otherwise
|
|
|
|
|
// go ahead and unlock now.
|
|
|
|
|
if (mReflowCommands.Count() > 0)
|
|
|
|
|
mShouldUnsuppressPainting = PR_TRUE;
|
|
|
|
|
else
|
|
|
|
|
UnsuppressAndInvalidate();
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
2000-10-09 07:08:41 +04:00
|
|
|
|
|
2002-09-21 05:03:38 +04:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::DisableThemeSupport()
|
|
|
|
|
{
|
|
|
|
|
// Doesn't have to be dynamic. Just set the bool.
|
|
|
|
|
mIsThemeSupportDisabled = PR_TRUE;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
|
PresShell::IsThemeSupportEnabled()
|
|
|
|
|
{
|
|
|
|
|
return !mIsThemeSupportDisabled;
|
|
|
|
|
}
|
|
|
|
|
|
2000-07-14 03:00:59 +04:00
|
|
|
|
// Post a request to handle an arbitrary callback after reflow has finished.
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::PostReflowCallback(nsIReflowCallback* aCallback)
|
|
|
|
|
{
|
2004-04-13 04:28:44 +04:00
|
|
|
|
void* result = AllocateFrame(sizeof(nsCallbackEventRequest));
|
2006-02-11 07:14:48 +03:00
|
|
|
|
if (NS_UNLIKELY(!result)) {
|
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
nsCallbackEventRequest* request = (nsCallbackEventRequest*)result;
|
2000-07-14 03:00:59 +04:00
|
|
|
|
|
|
|
|
|
request->callback = aCallback;
|
|
|
|
|
NS_ADDREF(aCallback);
|
|
|
|
|
request->next = nsnull;
|
|
|
|
|
|
|
|
|
|
if (mLastCallbackEventRequest) {
|
|
|
|
|
mLastCallbackEventRequest = mLastCallbackEventRequest->next = request;
|
|
|
|
|
} else {
|
|
|
|
|
mFirstCallbackEventRequest = request;
|
|
|
|
|
mLastCallbackEventRequest = request;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2000-10-07 04:49:08 +04:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::CancelReflowCallback(nsIReflowCallback* aCallback)
|
|
|
|
|
{
|
|
|
|
|
nsCallbackEventRequest* before = nsnull;
|
|
|
|
|
nsCallbackEventRequest* node = mFirstCallbackEventRequest;
|
|
|
|
|
while(node)
|
|
|
|
|
{
|
|
|
|
|
nsIReflowCallback* callback = node->callback;
|
|
|
|
|
|
|
|
|
|
if (callback == aCallback)
|
|
|
|
|
{
|
|
|
|
|
nsCallbackEventRequest* toFree = node;
|
|
|
|
|
if (node == mFirstCallbackEventRequest) {
|
2003-10-15 03:29:07 +04:00
|
|
|
|
node = node->next;
|
|
|
|
|
mFirstCallbackEventRequest = node;
|
|
|
|
|
NS_ASSERTION(before == nsnull, "impossible");
|
2000-10-07 04:49:08 +04:00
|
|
|
|
} else {
|
2003-10-15 03:29:07 +04:00
|
|
|
|
node = node->next;
|
|
|
|
|
before->next = node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (toFree == mLastCallbackEventRequest) {
|
|
|
|
|
mLastCallbackEventRequest = before;
|
2000-10-07 04:49:08 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FreeFrame(sizeof(nsCallbackEventRequest), toFree);
|
|
|
|
|
NS_RELEASE(callback);
|
|
|
|
|
} else {
|
|
|
|
|
before = node;
|
|
|
|
|
node = node->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2000-06-23 09:15:04 +04:00
|
|
|
|
/**
|
|
|
|
|
* Post a request to handle a DOM event after Reflow has finished.
|
|
|
|
|
* The event must have been created with the "new" operator.
|
|
|
|
|
*/
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::PostDOMEvent(nsIContent* aContent, nsEvent* aEvent)
|
|
|
|
|
{
|
|
|
|
|
// ok we have a list of events to handle. Queue them up and handle them
|
|
|
|
|
// after we finish reflow.
|
2006-02-11 07:14:48 +03:00
|
|
|
|
|
2004-04-13 04:28:44 +04:00
|
|
|
|
void* result = AllocateFrame(sizeof(nsDOMEventRequest));
|
2006-02-11 07:14:48 +03:00
|
|
|
|
if (NS_UNLIKELY(!result)) {
|
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
nsDOMEventRequest* request = (nsDOMEventRequest*)result;
|
2000-06-23 09:15:04 +04:00
|
|
|
|
|
|
|
|
|
request->content = aContent;
|
|
|
|
|
NS_ADDREF(aContent);
|
|
|
|
|
|
|
|
|
|
request->event = aEvent;
|
|
|
|
|
request->next = nsnull;
|
|
|
|
|
|
|
|
|
|
if (mLastDOMEventRequest) {
|
|
|
|
|
mLastDOMEventRequest = mLastDOMEventRequest->next = request;
|
|
|
|
|
} else {
|
|
|
|
|
mFirstDOMEventRequest = request;
|
|
|
|
|
mLastDOMEventRequest = request;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Post a request to set and attribute after reflow has finished.
|
|
|
|
|
*/
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::PostAttributeChange(nsIContent* aContent,
|
|
|
|
|
PRInt32 aNameSpaceID,
|
|
|
|
|
nsIAtom* aName,
|
|
|
|
|
const nsString& aValue,
|
|
|
|
|
PRBool aNotify,
|
|
|
|
|
nsAttributeChangeType aType)
|
|
|
|
|
{
|
|
|
|
|
// ok we have a list of events to handle. Queue them up and handle them
|
|
|
|
|
// after we finish reflow.
|
|
|
|
|
|
2004-04-13 04:28:44 +04:00
|
|
|
|
void* result = AllocateFrame(sizeof(nsAttributeChangeRequest));
|
2006-02-11 07:14:48 +03:00
|
|
|
|
if (NS_UNLIKELY(!result)) {
|
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
nsAttributeChangeRequest* request = new (result) nsAttributeChangeRequest();
|
2000-06-23 09:15:04 +04:00
|
|
|
|
|
|
|
|
|
request->content = aContent;
|
|
|
|
|
NS_ADDREF(aContent);
|
|
|
|
|
|
|
|
|
|
request->nameSpaceID = aNameSpaceID;
|
|
|
|
|
request->name = aName;
|
|
|
|
|
request->value = aValue;
|
|
|
|
|
request->notify = aNotify;
|
|
|
|
|
request->type = aType;
|
|
|
|
|
request->next = nsnull;
|
|
|
|
|
|
|
|
|
|
if (mLastAttributeRequest) {
|
|
|
|
|
mLastAttributeRequest = mLastAttributeRequest->next = request;
|
|
|
|
|
} else {
|
|
|
|
|
mFirstAttributeRequest = request;
|
|
|
|
|
mLastAttributeRequest = request;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2000-10-07 04:49:08 +04:00
|
|
|
|
|
2000-07-14 03:00:59 +04:00
|
|
|
|
void
|
|
|
|
|
PresShell::HandlePostedReflowCallbacks()
|
|
|
|
|
{
|
|
|
|
|
PRBool shouldFlush = PR_FALSE;
|
|
|
|
|
|
2003-10-15 03:29:07 +04:00
|
|
|
|
while (mFirstCallbackEventRequest) {
|
|
|
|
|
nsCallbackEventRequest* node = mFirstCallbackEventRequest;
|
|
|
|
|
mFirstCallbackEventRequest = node->next;
|
|
|
|
|
if (!mFirstCallbackEventRequest) {
|
|
|
|
|
mLastCallbackEventRequest = nsnull;
|
|
|
|
|
}
|
|
|
|
|
nsIReflowCallback* callback = node->callback;
|
|
|
|
|
FreeFrame(sizeof(nsCallbackEventRequest), node);
|
|
|
|
|
if (callback)
|
|
|
|
|
callback->ReflowFinished(this, &shouldFlush);
|
|
|
|
|
NS_IF_RELEASE(callback);
|
|
|
|
|
}
|
2000-07-14 03:00:59 +04:00
|
|
|
|
|
|
|
|
|
if (shouldFlush)
|
2004-05-28 02:08:42 +04:00
|
|
|
|
FlushPendingNotifications(Flush_Layout);
|
2000-07-14 03:00:59 +04:00
|
|
|
|
}
|
|
|
|
|
|
2000-06-23 09:15:04 +04:00
|
|
|
|
void
|
|
|
|
|
PresShell::HandlePostedDOMEvents()
|
|
|
|
|
{
|
2000-07-20 00:09:59 +04:00
|
|
|
|
while(mFirstDOMEventRequest)
|
2000-06-23 09:15:04 +04:00
|
|
|
|
{
|
2000-07-20 00:09:59 +04:00
|
|
|
|
/* pull the node from the event request list. Be prepared for reentrant access to the list
|
2006-03-07 20:08:51 +03:00
|
|
|
|
from within Dispatch and its callees! */
|
2000-07-20 00:09:59 +04:00
|
|
|
|
nsDOMEventRequest* node = mFirstDOMEventRequest;
|
2000-06-23 09:15:04 +04:00
|
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
2000-07-20 00:09:59 +04:00
|
|
|
|
|
|
|
|
|
mFirstDOMEventRequest = node->next;
|
|
|
|
|
if (nsnull == mFirstDOMEventRequest) {
|
|
|
|
|
mLastDOMEventRequest = nsnull;
|
|
|
|
|
}
|
|
|
|
|
|
2006-03-07 20:08:51 +03:00
|
|
|
|
nsEventDispatcher::Dispatch(node->content, mPresContext, node->event,
|
|
|
|
|
nsnull, &status);
|
2000-06-23 09:15:04 +04:00
|
|
|
|
NS_RELEASE(node->content);
|
|
|
|
|
delete node->event;
|
2000-07-20 00:09:59 +04:00
|
|
|
|
node->nsDOMEventRequest::~nsDOMEventRequest(); // doesn't do anything, but just in case
|
|
|
|
|
FreeFrame(sizeof(nsDOMEventRequest), node);
|
2000-06-23 09:15:04 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PresShell::HandlePostedAttributeChanges()
|
|
|
|
|
{
|
2000-07-20 00:09:59 +04:00
|
|
|
|
while(mFirstAttributeRequest)
|
2000-06-23 09:15:04 +04:00
|
|
|
|
{
|
2000-07-20 00:09:59 +04:00
|
|
|
|
/* pull the node from the request list. Be prepared for reentrant access to the list
|
|
|
|
|
from within SetAttribute/UnsetAttribute and its callees! */
|
|
|
|
|
nsAttributeChangeRequest* node = mFirstAttributeRequest;
|
|
|
|
|
|
|
|
|
|
mFirstAttributeRequest = node->next;
|
|
|
|
|
if (nsnull == mFirstAttributeRequest) {
|
|
|
|
|
mLastAttributeRequest = nsnull;
|
|
|
|
|
}
|
|
|
|
|
|
2000-06-23 09:15:04 +04:00
|
|
|
|
if (node->type == eChangeType_Set)
|
2001-08-17 12:14:14 +04:00
|
|
|
|
node->content->SetAttr(node->nameSpaceID, node->name, node->value, node->notify);
|
2000-06-23 09:15:04 +04:00
|
|
|
|
else
|
2001-08-17 12:14:14 +04:00
|
|
|
|
node->content->UnsetAttr(node->nameSpaceID, node->name, node->notify);
|
2000-06-23 09:15:04 +04:00
|
|
|
|
|
|
|
|
|
NS_RELEASE(node->content);
|
2000-07-20 00:09:59 +04:00
|
|
|
|
node->nsAttributeChangeRequest::~nsAttributeChangeRequest();
|
|
|
|
|
FreeFrame(sizeof(nsAttributeChangeRequest), node);
|
2000-06-23 09:15:04 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2000-10-17 09:07:39 +04:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::IsSafeToFlush(PRBool& aIsSafeToFlush)
|
|
|
|
|
{
|
|
|
|
|
aIsSafeToFlush = PR_TRUE;
|
|
|
|
|
|
2005-01-20 06:39:09 +03:00
|
|
|
|
if (mIsReflowing || mChangeNestCount) {
|
|
|
|
|
// Not safe if we are reflowing or in the middle of frame construction
|
2000-10-17 09:07:39 +04:00
|
|
|
|
aIsSafeToFlush = PR_FALSE;
|
|
|
|
|
} else {
|
|
|
|
|
// Not safe if we are painting
|
2003-06-30 14:46:59 +04:00
|
|
|
|
nsIViewManager* viewManager = GetViewManager();
|
|
|
|
|
if (viewManager) {
|
2000-10-17 09:07:39 +04:00
|
|
|
|
PRBool isPainting = PR_FALSE;
|
|
|
|
|
viewManager->IsPainting(isPainting);
|
|
|
|
|
if (isPainting) {
|
|
|
|
|
aIsSafeToFlush = PR_FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2000-01-29 01:58:17 +03:00
|
|
|
|
NS_IMETHODIMP
|
2004-05-28 02:08:42 +04:00
|
|
|
|
PresShell::FlushPendingNotifications(mozFlushType aType)
|
2000-01-29 01:58:17 +03:00
|
|
|
|
{
|
2004-05-28 02:08:42 +04:00
|
|
|
|
NS_ASSERTION(aType & (Flush_StyleReresolves | Flush_OnlyReflow |
|
|
|
|
|
Flush_OnlyPaint),
|
|
|
|
|
"Why did we get called?");
|
|
|
|
|
|
2000-10-17 09:07:39 +04:00
|
|
|
|
PRBool isSafeToFlush;
|
|
|
|
|
IsSafeToFlush(isSafeToFlush);
|
|
|
|
|
|
2004-10-09 05:39:21 +04:00
|
|
|
|
NS_ASSERTION(!isSafeToFlush || mViewManager, "Must have view manager");
|
|
|
|
|
if (isSafeToFlush && mViewManager) {
|
|
|
|
|
// Style reresolves not in conjunction with reflows can't cause
|
|
|
|
|
// painting or geometry changes, so don't bother with view update
|
|
|
|
|
// batching if we only have style reresolve
|
|
|
|
|
mViewManager->BeginUpdateViewBatch();
|
2001-08-31 08:28:26 +04:00
|
|
|
|
|
2004-08-10 07:24:41 +04:00
|
|
|
|
if (aType & Flush_StyleReresolves) {
|
|
|
|
|
mFrameConstructor->ProcessPendingRestyles();
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-28 02:08:42 +04:00
|
|
|
|
if (aType & Flush_OnlyReflow) {
|
|
|
|
|
ProcessReflowCommands(PR_FALSE);
|
|
|
|
|
}
|
2001-08-31 08:28:26 +04:00
|
|
|
|
|
2004-10-09 05:39:21 +04:00
|
|
|
|
PRUint32 updateFlags = NS_VMREFRESH_NO_SYNC;
|
|
|
|
|
if (aType & Flush_OnlyPaint) {
|
|
|
|
|
// Flushing paints, so perform the invalidates and drawing
|
|
|
|
|
// immediately
|
|
|
|
|
updateFlags = NS_VMREFRESH_IMMEDIATE;
|
2001-08-31 08:28:26 +04:00
|
|
|
|
}
|
2005-01-28 00:17:08 +03:00
|
|
|
|
else if (!(aType & Flush_OnlyReflow)) {
|
|
|
|
|
// Not flushing reflows, so do deferred invalidates. This will keep us
|
|
|
|
|
// from possibly flushing out reflows due to invalidates being processed
|
|
|
|
|
// at the end of this view batch.
|
|
|
|
|
updateFlags = NS_VMREFRESH_DEFERRED;
|
|
|
|
|
}
|
2004-10-09 05:39:21 +04:00
|
|
|
|
mViewManager->EndUpdateViewBatch(updateFlags);
|
2000-01-29 01:58:17 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2000-02-09 18:48:01 +03:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::IsReflowLocked(PRBool* aIsReflowLocked)
|
|
|
|
|
{
|
2000-04-17 11:13:57 +04:00
|
|
|
|
*aIsReflowLocked = mIsReflowing;
|
2000-02-09 18:48:01 +03:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2000-01-28 03:48:02 +03:00
|
|
|
|
NS_IMETHODIMP
|
2000-04-17 11:13:57 +04:00
|
|
|
|
PresShell::BeginReflowBatching()
|
2000-01-28 03:48:02 +03:00
|
|
|
|
{
|
|
|
|
|
mBatchReflows = PR_TRUE;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2000-04-17 11:13:57 +04:00
|
|
|
|
PresShell::EndReflowBatching(PRBool aFlushPendingReflows)
|
2000-01-28 03:48:02 +03:00
|
|
|
|
{
|
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
mBatchReflows = PR_FALSE;
|
|
|
|
|
if (aFlushPendingReflows) {
|
2004-09-13 08:19:58 +04:00
|
|
|
|
rv = FlushPendingNotifications(Flush_OnlyReflow);
|
2000-01-28 03:48:02 +03:00
|
|
|
|
}
|
2002-06-14 00:35:12 +04:00
|
|
|
|
else {
|
|
|
|
|
PostReflowEvent();
|
|
|
|
|
}
|
2000-01-28 03:48:02 +03:00
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::GetReflowBatchingStatus(PRBool* aIsBatching)
|
|
|
|
|
{
|
|
|
|
|
*aIsBatching = mBatchReflows;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-24 03:46:17 +03:00
|
|
|
|
void
|
2004-02-21 00:38:31 +03:00
|
|
|
|
PresShell::CharacterDataChanged(nsIDocument *aDocument,
|
|
|
|
|
nsIContent* aContent,
|
|
|
|
|
PRBool aAppend)
|
1998-04-14 00:24:54 +04:00
|
|
|
|
{
|
2005-03-25 07:27:21 +03:00
|
|
|
|
NS_PRECONDITION(!mIsDocumentGone, "Unexpected CharacterDataChanged");
|
2005-02-18 19:11:53 +03:00
|
|
|
|
NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
|
|
|
|
|
|
2000-04-17 11:13:57 +04:00
|
|
|
|
WillCauseReflow();
|
2005-02-18 19:11:53 +03:00
|
|
|
|
mFrameConstructor->CharacterDataChanged(aContent, aAppend);
|
1999-09-21 11:53:49 +04:00
|
|
|
|
VERIFY_STYLE_TREE;
|
2000-04-17 11:13:57 +04:00
|
|
|
|
DidCauseReflow();
|
1998-04-14 00:24:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
2004-01-24 03:46:17 +03:00
|
|
|
|
void
|
1999-04-20 04:06:58 +04:00
|
|
|
|
PresShell::ContentStatesChanged(nsIDocument* aDocument,
|
|
|
|
|
nsIContent* aContent1,
|
2002-03-07 06:34:29 +03:00
|
|
|
|
nsIContent* aContent2,
|
2002-04-11 07:49:30 +04:00
|
|
|
|
PRInt32 aStateMask)
|
1999-02-27 10:15:09 +03:00
|
|
|
|
{
|
2005-02-18 19:11:53 +03:00
|
|
|
|
NS_PRECONDITION(!mIsDocumentGone, "Unexpected ContentStatesChanged");
|
|
|
|
|
NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
|
|
|
|
|
|
2000-04-17 11:13:57 +04:00
|
|
|
|
WillCauseReflow();
|
2005-02-18 19:11:53 +03:00
|
|
|
|
mFrameConstructor->ContentStatesChanged(aContent1, aContent2, aStateMask);
|
1999-09-21 11:53:49 +04:00
|
|
|
|
VERIFY_STYLE_TREE;
|
2000-04-17 11:13:57 +04:00
|
|
|
|
DidCauseReflow();
|
1999-02-27 10:15:09 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-01-24 03:46:17 +03:00
|
|
|
|
void
|
2005-11-02 03:41:51 +03:00
|
|
|
|
PresShell::AttributeChanged(nsIDocument* aDocument,
|
|
|
|
|
nsIContent* aContent,
|
|
|
|
|
PRInt32 aNameSpaceID,
|
|
|
|
|
nsIAtom* aAttribute,
|
|
|
|
|
PRInt32 aModType)
|
1998-09-18 23:53:27 +04:00
|
|
|
|
{
|
2005-03-25 07:27:21 +03:00
|
|
|
|
NS_PRECONDITION(!mIsDocumentGone, "Unexpected AttributeChanged");
|
2005-02-18 19:11:53 +03:00
|
|
|
|
NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
|
|
|
|
|
|
2001-10-17 09:34:35 +04:00
|
|
|
|
// XXXwaterson it might be more elegant to wait until after the
|
|
|
|
|
// initial reflow to begin observing the document. That would
|
|
|
|
|
// squelch any other inappropriate notifications as well.
|
|
|
|
|
if (mDidInitialReflow) {
|
|
|
|
|
WillCauseReflow();
|
2005-02-18 19:11:53 +03:00
|
|
|
|
mFrameConstructor->AttributeChanged(aContent, aNameSpaceID,
|
2004-01-24 03:46:17 +03:00
|
|
|
|
aAttribute, aModType);
|
2001-10-17 09:34:35 +04:00
|
|
|
|
VERIFY_STYLE_TREE;
|
|
|
|
|
DidCauseReflow();
|
|
|
|
|
}
|
1998-09-18 23:53:27 +04:00
|
|
|
|
}
|
|
|
|
|
|
2004-01-24 03:46:17 +03:00
|
|
|
|
void
|
1998-07-23 03:32:19 +04:00
|
|
|
|
PresShell::ContentAppended(nsIDocument *aDocument,
|
1998-09-10 23:32:14 +04:00
|
|
|
|
nsIContent* aContainer,
|
|
|
|
|
PRInt32 aNewIndexInContainer)
|
1998-04-14 00:24:54 +04:00
|
|
|
|
{
|
2005-02-18 19:11:53 +03:00
|
|
|
|
NS_PRECONDITION(!mIsDocumentGone, "Unexpected ContentAppended");
|
|
|
|
|
NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
|
|
|
|
|
|
2003-10-11 04:27:45 +04:00
|
|
|
|
if (!mDidInitialReflow) {
|
2004-01-24 03:46:17 +03:00
|
|
|
|
return;
|
2003-10-11 04:27:45 +04:00
|
|
|
|
}
|
|
|
|
|
|
2000-04-17 11:13:57 +04:00
|
|
|
|
WillCauseReflow();
|
1999-11-10 06:41:09 +03:00
|
|
|
|
MOZ_TIMER_DEBUGLOG(("Start: Frame Creation: PresShell::ContentAppended(), this=%p\n", this));
|
|
|
|
|
MOZ_TIMER_START(mFrameCreationWatch);
|
2001-05-02 02:54:11 +04:00
|
|
|
|
|
2005-02-18 19:11:53 +03:00
|
|
|
|
mFrameConstructor->ContentAppended(aContainer, aNewIndexInContainer);
|
1999-09-21 11:53:49 +04:00
|
|
|
|
VERIFY_STYLE_TREE;
|
1999-08-31 18:35:50 +04:00
|
|
|
|
|
1999-11-10 06:41:09 +03:00
|
|
|
|
MOZ_TIMER_DEBUGLOG(("Stop: Frame Creation: PresShell::ContentAppended(), this=%p\n", this));
|
|
|
|
|
MOZ_TIMER_STOP(mFrameCreationWatch);
|
2000-04-17 11:13:57 +04:00
|
|
|
|
DidCauseReflow();
|
1998-04-14 00:24:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
2004-01-24 03:46:17 +03:00
|
|
|
|
void
|
1998-09-10 23:32:14 +04:00
|
|
|
|
PresShell::ContentInserted(nsIDocument* aDocument,
|
|
|
|
|
nsIContent* aContainer,
|
|
|
|
|
nsIContent* aChild,
|
|
|
|
|
PRInt32 aIndexInContainer)
|
1998-04-14 00:24:54 +04:00
|
|
|
|
{
|
2005-03-25 07:27:21 +03:00
|
|
|
|
NS_PRECONDITION(!mIsDocumentGone, "Unexpected ContentInserted");
|
2005-02-18 19:11:53 +03:00
|
|
|
|
NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
|
|
|
|
|
|
2003-10-11 04:27:45 +04:00
|
|
|
|
if (!mDidInitialReflow) {
|
2004-01-24 03:46:17 +03:00
|
|
|
|
return;
|
2003-10-11 04:27:45 +04:00
|
|
|
|
}
|
|
|
|
|
|
2000-04-17 11:13:57 +04:00
|
|
|
|
WillCauseReflow();
|
2005-08-17 01:35:58 +04:00
|
|
|
|
mFrameConstructor->ContentInserted(aContainer, aChild,
|
2004-01-24 03:46:17 +03:00
|
|
|
|
aIndexInContainer, nsnull, PR_FALSE);
|
1999-09-21 11:53:49 +04:00
|
|
|
|
VERIFY_STYLE_TREE;
|
2000-04-17 11:13:57 +04:00
|
|
|
|
DidCauseReflow();
|
1998-04-14 00:24:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
2004-01-24 03:46:17 +03:00
|
|
|
|
void
|
1998-09-25 01:39:47 +04:00
|
|
|
|
PresShell::ContentRemoved(nsIDocument *aDocument,
|
|
|
|
|
nsIContent* aContainer,
|
|
|
|
|
nsIContent* aChild,
|
|
|
|
|
PRInt32 aIndexInContainer)
|
1998-04-14 00:24:54 +04:00
|
|
|
|
{
|
2005-03-25 07:27:21 +03:00
|
|
|
|
NS_PRECONDITION(!mIsDocumentGone, "Unexpected ContentRemoved");
|
2005-02-18 19:11:53 +03:00
|
|
|
|
NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
|
|
|
|
|
|
2006-04-18 03:16:46 +04:00
|
|
|
|
// Make sure that the caret doesn't leave a turd where the child used to be.
|
2005-08-22 04:25:20 +04:00
|
|
|
|
if (mCaret) {
|
2006-04-28 08:33:41 +04:00
|
|
|
|
mCaret->InvalidateOutsideCaret();
|
2005-08-22 04:25:20 +04:00
|
|
|
|
}
|
|
|
|
|
|
2001-11-29 03:04:31 +03:00
|
|
|
|
// Notify the ESM that the content has been removed, so that
|
|
|
|
|
// it can clean up any state related to the content.
|
2004-02-27 20:17:37 +03:00
|
|
|
|
mPresContext->EventStateManager()->ContentRemoved(aChild);
|
2001-11-29 03:04:31 +03:00
|
|
|
|
|
2000-04-17 11:13:57 +04:00
|
|
|
|
WillCauseReflow();
|
2005-02-18 19:11:53 +03:00
|
|
|
|
mFrameConstructor->ContentRemoved(aContainer, aChild,
|
2004-01-24 03:46:17 +03:00
|
|
|
|
aIndexInContainer, PR_FALSE);
|
2002-09-10 08:36:00 +04:00
|
|
|
|
|
1999-09-21 11:53:49 +04:00
|
|
|
|
VERIFY_STYLE_TREE;
|
2000-04-17 11:13:57 +04:00
|
|
|
|
DidCauseReflow();
|
1998-04-14 00:24:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
1998-11-26 04:34:53 +03:00
|
|
|
|
nsresult
|
|
|
|
|
PresShell::ReconstructFrames(void)
|
1998-11-17 05:14:38 +03:00
|
|
|
|
{
|
|
|
|
|
nsresult rv = NS_OK;
|
1999-01-26 03:05:21 +03:00
|
|
|
|
|
2000-04-17 11:13:57 +04:00
|
|
|
|
WillCauseReflow();
|
2005-02-18 19:11:53 +03:00
|
|
|
|
rv = mFrameConstructor->ReconstructDocElementHierarchy();
|
1999-09-21 11:53:49 +04:00
|
|
|
|
VERIFY_STYLE_TREE;
|
2000-04-17 11:13:57 +04:00
|
|
|
|
DidCauseReflow();
|
1999-03-01 19:57:35 +03:00
|
|
|
|
|
1998-11-17 05:14:38 +03:00
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2004-08-29 07:08:44 +04:00
|
|
|
|
void
|
|
|
|
|
nsIPresShell::ReconstructStyleDataInternal()
|
2001-12-18 01:51:39 +03:00
|
|
|
|
{
|
2004-01-08 01:30:53 +03:00
|
|
|
|
mStylesHaveChanged = PR_FALSE;
|
|
|
|
|
|
2005-11-06 21:01:17 +03:00
|
|
|
|
if (!mDidInitialReflow) {
|
|
|
|
|
// Nothing to do here, since we have no frames yet
|
2004-08-29 07:08:44 +04:00
|
|
|
|
return;
|
2005-11-06 21:01:17 +03:00
|
|
|
|
}
|
2001-12-18 01:51:39 +03:00
|
|
|
|
|
2005-11-08 07:07:13 +03:00
|
|
|
|
if (mIsDestroying) {
|
|
|
|
|
// We don't want to mess with restyles at this point
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2005-11-06 21:01:17 +03:00
|
|
|
|
nsIContent* root = mDocument->GetRootContent();
|
|
|
|
|
if (!root) {
|
|
|
|
|
// No content to restyle
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mFrameConstructor->PostRestyleEvent(root, eReStyle_Self, NS_STYLE_HINT_NONE);
|
2005-06-10 17:57:27 +04:00
|
|
|
|
|
|
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
|
InvalidateAccessibleSubtree(nsnull);
|
|
|
|
|
#endif
|
2004-08-29 07:08:44 +04:00
|
|
|
|
}
|
2004-01-24 03:46:17 +03:00
|
|
|
|
|
2004-08-29 07:08:44 +04:00
|
|
|
|
void
|
|
|
|
|
nsIPresShell::ReconstructStyleDataExternal()
|
|
|
|
|
{
|
|
|
|
|
ReconstructStyleDataInternal();
|
2001-12-18 01:51:39 +03:00
|
|
|
|
}
|
|
|
|
|
|
2004-01-24 03:46:17 +03:00
|
|
|
|
void
|
1998-11-26 04:34:53 +03:00
|
|
|
|
PresShell::StyleSheetAdded(nsIDocument *aDocument,
|
2004-07-28 11:08:41 +04:00
|
|
|
|
nsIStyleSheet* aStyleSheet,
|
|
|
|
|
PRBool aDocumentSheet)
|
1998-11-26 04:34:53 +03:00
|
|
|
|
{
|
2002-12-03 08:48:14 +03:00
|
|
|
|
// We only care when enabled sheets are added
|
|
|
|
|
NS_PRECONDITION(aStyleSheet, "Must have a style sheet!");
|
|
|
|
|
PRBool applicable;
|
|
|
|
|
aStyleSheet->GetApplicable(applicable);
|
|
|
|
|
|
2003-10-03 01:29:40 +04:00
|
|
|
|
if (applicable && aStyleSheet->HasRules()) {
|
|
|
|
|
mStylesHaveChanged = PR_TRUE;
|
2003-07-04 05:44:24 +04:00
|
|
|
|
}
|
1998-11-26 04:34:53 +03:00
|
|
|
|
}
|
|
|
|
|
|
2004-01-24 03:46:17 +03:00
|
|
|
|
void
|
1999-02-03 22:38:16 +03:00
|
|
|
|
PresShell::StyleSheetRemoved(nsIDocument *aDocument,
|
2004-07-28 11:08:41 +04:00
|
|
|
|
nsIStyleSheet* aStyleSheet,
|
|
|
|
|
PRBool aDocumentSheet)
|
1999-02-03 22:38:16 +03:00
|
|
|
|
{
|
2002-12-03 08:48:14 +03:00
|
|
|
|
// We only care when enabled sheets are removed
|
|
|
|
|
NS_PRECONDITION(aStyleSheet, "Must have a style sheet!");
|
|
|
|
|
PRBool applicable;
|
|
|
|
|
aStyleSheet->GetApplicable(applicable);
|
2003-10-03 01:29:40 +04:00
|
|
|
|
if (applicable && aStyleSheet->HasRules()) {
|
|
|
|
|
mStylesHaveChanged = PR_TRUE;
|
2002-12-03 08:48:14 +03:00
|
|
|
|
}
|
1999-02-03 22:38:16 +03:00
|
|
|
|
}
|
|
|
|
|
|
2004-01-24 03:46:17 +03:00
|
|
|
|
void
|
2002-12-03 08:48:14 +03:00
|
|
|
|
PresShell::StyleSheetApplicableStateChanged(nsIDocument *aDocument,
|
|
|
|
|
nsIStyleSheet* aStyleSheet,
|
|
|
|
|
PRBool aApplicable)
|
1998-11-26 04:34:53 +03:00
|
|
|
|
{
|
2003-10-03 01:29:40 +04:00
|
|
|
|
if (aStyleSheet->HasRules()) {
|
|
|
|
|
mStylesHaveChanged = PR_TRUE;
|
2003-07-04 05:44:24 +04:00
|
|
|
|
}
|
1998-11-26 04:34:53 +03:00
|
|
|
|
}
|
|
|
|
|
|
2004-01-24 03:46:17 +03:00
|
|
|
|
void
|
1998-11-26 04:34:53 +03:00
|
|
|
|
PresShell::StyleRuleChanged(nsIDocument *aDocument,
|
|
|
|
|
nsIStyleSheet* aStyleSheet,
|
2003-06-18 05:59:57 +04:00
|
|
|
|
nsIStyleRule* aOldStyleRule,
|
|
|
|
|
nsIStyleRule* aNewStyleRule)
|
1998-11-26 04:34:53 +03:00
|
|
|
|
{
|
2003-10-03 01:29:40 +04:00
|
|
|
|
mStylesHaveChanged = PR_TRUE;
|
1998-11-26 04:34:53 +03:00
|
|
|
|
}
|
|
|
|
|
|
2004-01-24 03:46:17 +03:00
|
|
|
|
void
|
1998-11-26 04:34:53 +03:00
|
|
|
|
PresShell::StyleRuleAdded(nsIDocument *aDocument,
|
|
|
|
|
nsIStyleSheet* aStyleSheet,
|
|
|
|
|
nsIStyleRule* aStyleRule)
|
2003-10-03 01:29:40 +04:00
|
|
|
|
{
|
|
|
|
|
mStylesHaveChanged = PR_TRUE;
|
1998-11-26 04:34:53 +03:00
|
|
|
|
}
|
|
|
|
|
|
2004-01-24 03:46:17 +03:00
|
|
|
|
void
|
1998-11-26 04:34:53 +03:00
|
|
|
|
PresShell::StyleRuleRemoved(nsIDocument *aDocument,
|
|
|
|
|
nsIStyleSheet* aStyleSheet,
|
|
|
|
|
nsIStyleRule* aStyleRule)
|
2003-10-03 01:29:40 +04:00
|
|
|
|
{
|
|
|
|
|
mStylesHaveChanged = PR_TRUE;
|
1998-11-26 04:34:53 +03:00
|
|
|
|
}
|
|
|
|
|
|
2005-08-23 02:24:29 +04:00
|
|
|
|
nsIFrame*
|
|
|
|
|
PresShell::GetPrimaryFrameFor(nsIContent* aContent) const
|
1998-04-14 00:24:54 +04:00
|
|
|
|
{
|
2005-08-23 02:24:29 +04:00
|
|
|
|
return FrameManager()->GetPrimaryFrameFor(aContent);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
1999-02-11 02:21:22 +03:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::GetLayoutObjectFor(nsIContent* aContent,
|
|
|
|
|
nsISupports** aResult) const
|
|
|
|
|
{
|
|
|
|
|
nsresult result = NS_ERROR_NULL_POINTER;
|
|
|
|
|
if ((nsnull!=aResult) && (nsnull!=aContent))
|
|
|
|
|
{
|
|
|
|
|
*aResult = nsnull;
|
2005-08-23 02:24:29 +04:00
|
|
|
|
nsIFrame *primaryFrame = GetPrimaryFrameFor(aContent);
|
|
|
|
|
if (primaryFrame)
|
1999-02-11 02:21:22 +03:00
|
|
|
|
{
|
2000-01-04 23:24:09 +03:00
|
|
|
|
result = primaryFrame->QueryInterface(NS_GET_IID(nsISupports),
|
|
|
|
|
(void**)aResult);
|
1999-02-11 02:21:22 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2000-03-04 02:15:29 +03:00
|
|
|
|
|
1998-12-29 06:38:16 +03:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::GetPlaceholderFrameFor(nsIFrame* aFrame,
|
1999-02-12 20:45:58 +03:00
|
|
|
|
nsIFrame** aResult) const
|
1998-12-29 06:38:16 +03:00
|
|
|
|
{
|
2004-03-06 07:46:11 +03:00
|
|
|
|
*aResult = FrameManager()->GetPlaceholderFrameFor(aFrame);
|
2004-02-24 00:29:06 +03:00
|
|
|
|
return NS_OK;
|
1998-12-29 06:38:16 +03:00
|
|
|
|
}
|
2001-12-06 08:45:07 +03:00
|
|
|
|
|
2001-03-09 06:29:00 +03:00
|
|
|
|
#ifdef IBMBIDI
|
|
|
|
|
NS_IMETHODIMP
|
2001-10-01 00:35:55 +04:00
|
|
|
|
PresShell::SetCaretBidiLevel(PRUint8 aLevel)
|
2001-03-09 06:29:00 +03:00
|
|
|
|
{
|
|
|
|
|
// If the current level is undefined, we have just inserted new text.
|
|
|
|
|
// In this case, we don't want to reset the keyboard language
|
|
|
|
|
PRBool afterInsert = mBidiLevel & BIDI_LEVEL_UNDEFINED;
|
|
|
|
|
mBidiLevel = aLevel;
|
|
|
|
|
|
|
|
|
|
// PRBool parityChange = ((mBidiLevel ^ aLevel) & 1); // is the parity of the new level different from the current level?
|
|
|
|
|
// if (parityChange) // if so, change the keyboard language
|
|
|
|
|
if (mBidiKeyboard && !afterInsert)
|
|
|
|
|
mBidiKeyboard->SetLangFromBidiLevel(aLevel);
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2001-10-01 00:35:55 +04:00
|
|
|
|
PresShell::GetCaretBidiLevel(PRUint8 *aOutLevel)
|
2001-03-09 06:29:00 +03:00
|
|
|
|
{
|
|
|
|
|
if (!aOutLevel) { return NS_ERROR_INVALID_ARG; }
|
|
|
|
|
*aOutLevel = mBidiLevel;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2001-10-01 00:35:55 +04:00
|
|
|
|
PresShell::UndefineCaretBidiLevel()
|
2001-03-09 06:29:00 +03:00
|
|
|
|
{
|
|
|
|
|
mBidiLevel |= BIDI_LEVEL_UNDEFINED;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::BidiStyleChangeReflow()
|
|
|
|
|
{
|
|
|
|
|
// Have the root frame's style context remap its style
|
2004-03-06 07:46:11 +03:00
|
|
|
|
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
|
2001-12-18 11:10:49 +03:00
|
|
|
|
if (rootFrame) {
|
2003-06-18 05:59:57 +04:00
|
|
|
|
mStyleSet->ClearStyleData(mPresContext);
|
2001-12-18 11:10:49 +03:00
|
|
|
|
ReconstructFrames();
|
|
|
|
|
}
|
|
|
|
|
return NS_OK;
|
2001-03-09 06:29:00 +03:00
|
|
|
|
}
|
|
|
|
|
#endif // IBMBIDI
|
1998-12-29 06:38:16 +03:00
|
|
|
|
|
1998-08-28 06:54:06 +04:00
|
|
|
|
//nsIViewObserver
|
|
|
|
|
|
2006-01-26 05:29:17 +03:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::ComputeRepaintRegionForCopy(nsIView* aRootView,
|
|
|
|
|
nsIView* aMovingView,
|
|
|
|
|
nsPoint aDelta,
|
|
|
|
|
const nsRect& aCopyRect,
|
|
|
|
|
nsRegion* aRepaintRegion)
|
|
|
|
|
{
|
|
|
|
|
return nsLayoutUtils::ComputeRepaintRegionForCopy(
|
|
|
|
|
NS_STATIC_CAST(nsIFrame*, aRootView->GetClientData()),
|
|
|
|
|
NS_STATIC_CAST(nsIFrame*, aMovingView->GetClientData()),
|
|
|
|
|
aDelta, aCopyRect, aRepaintRegion);
|
|
|
|
|
}
|
2000-04-25 08:43:11 +04:00
|
|
|
|
|
2006-01-26 05:29:17 +03:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::RenderOffscreen(nsRect aRect, PRBool aUntrusted,
|
|
|
|
|
PRBool aIgnoreViewportScrolling,
|
|
|
|
|
nscolor aBackgroundColor,
|
|
|
|
|
nsIRenderingContext** aRenderedContext)
|
|
|
|
|
{
|
|
|
|
|
nsIView* rootView;
|
|
|
|
|
mViewManager->GetRootView(rootView);
|
|
|
|
|
NS_ASSERTION(rootView, "No root view?");
|
|
|
|
|
nsIWidget* rootWidget = rootView->GetWidget();
|
|
|
|
|
NS_ASSERTION(rootWidget, "No root widget?");
|
|
|
|
|
|
|
|
|
|
*aRenderedContext = nsnull;
|
|
|
|
|
|
|
|
|
|
NS_ASSERTION(!aUntrusted, "We don't support untrusted yet");
|
|
|
|
|
if (aUntrusted)
|
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIRenderingContext> tmpContext;
|
|
|
|
|
mPresContext->DeviceContext()->CreateRenderingContext(rootWidget,
|
|
|
|
|
*getter_AddRefs(tmpContext));
|
|
|
|
|
if (!tmpContext)
|
|
|
|
|
return NS_ERROR_FAILURE;
|
2002-03-07 10:03:03 +03:00
|
|
|
|
|
2006-01-26 05:29:17 +03:00
|
|
|
|
nsRect bounds(nsPoint(0, 0), aRect.Size());
|
|
|
|
|
bounds.ScaleRoundOut(mPresContext->TwipsToPixels());
|
|
|
|
|
|
|
|
|
|
nsIDrawingSurface* surface;
|
|
|
|
|
nsresult rv
|
|
|
|
|
= tmpContext->CreateDrawingSurface(bounds, NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS,
|
|
|
|
|
surface);
|
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
nsCOMPtr<nsIRenderingContext> localcx;
|
|
|
|
|
rv = nsLayoutUtils::CreateOffscreenContext(mPresContext->DeviceContext(),
|
|
|
|
|
surface, aRect, getter_AddRefs(localcx));
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
|
tmpContext->DestroyDrawingSurface(surface);
|
|
|
|
|
return NS_ERROR_FAILURE;
|
2002-03-07 10:03:03 +03:00
|
|
|
|
}
|
2006-01-26 05:29:17 +03:00
|
|
|
|
// clipping and translation is set by CreateOffscreenContext
|
2002-03-07 10:03:03 +03:00
|
|
|
|
|
2006-01-26 05:29:17 +03:00
|
|
|
|
localcx->SetColor(aBackgroundColor);
|
|
|
|
|
localcx->FillRect(aRect);
|
2002-03-07 10:03:03 +03:00
|
|
|
|
|
2006-01-26 05:29:17 +03:00
|
|
|
|
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
|
|
|
|
|
if (!rootFrame) {
|
|
|
|
|
localcx.swap(*aRenderedContext);
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2006-04-18 03:16:46 +04:00
|
|
|
|
nsDisplayListBuilder builder(rootFrame, PR_FALSE, PR_FALSE);
|
2006-01-26 05:29:17 +03:00
|
|
|
|
nsDisplayList list;
|
|
|
|
|
nsIScrollableView* scrollingView = nsnull;
|
|
|
|
|
mViewManager->GetRootScrollableView(&scrollingView);
|
|
|
|
|
nsRect r = aRect;
|
|
|
|
|
if (aIgnoreViewportScrolling && scrollingView) {
|
|
|
|
|
nscoord x, y;
|
|
|
|
|
scrollingView->GetScrollPosition(x, y);
|
|
|
|
|
localcx->Translate(x, y);
|
|
|
|
|
r.MoveBy(-x, -y);
|
2006-02-01 23:33:20 +03:00
|
|
|
|
builder.SetIgnoreScrollFrame(GetRootScrollFrame());
|
2000-04-25 08:43:11 +04:00
|
|
|
|
}
|
|
|
|
|
|
2006-04-18 03:16:46 +04:00
|
|
|
|
builder.EnterPresShell(rootFrame, r);
|
|
|
|
|
|
2006-01-26 05:29:17 +03:00
|
|
|
|
rv = rootFrame->BuildDisplayListForStackingContext(&builder, r, &list);
|
2006-04-18 03:16:46 +04:00
|
|
|
|
|
|
|
|
|
builder.LeavePresShell(rootFrame, r);
|
2006-01-26 05:29:17 +03:00
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2000-04-25 08:43:11 +04:00
|
|
|
|
|
2006-01-26 05:29:17 +03:00
|
|
|
|
nsRegion region(r);
|
|
|
|
|
list.OptimizeVisibility(&builder, ®ion);
|
|
|
|
|
list.Paint(&builder, localcx, r);
|
|
|
|
|
// Flush the list so we don't trigger the IsEmpty-on-destruction assertion
|
|
|
|
|
list.DeleteAll();
|
2002-03-07 10:03:03 +03:00
|
|
|
|
|
2006-01-26 05:29:17 +03:00
|
|
|
|
localcx.swap(*aRenderedContext);
|
|
|
|
|
return NS_OK;
|
2002-03-07 10:03:03 +03:00
|
|
|
|
}
|
|
|
|
|
|
1998-12-18 18:54:23 +03:00
|
|
|
|
NS_IMETHODIMP
|
2006-01-26 05:29:17 +03:00
|
|
|
|
PresShell::Paint(nsIView* aView,
|
|
|
|
|
nsIRenderingContext* aRenderingContext,
|
|
|
|
|
const nsRegion& aDirtyRegion)
|
1998-08-28 06:54:06 +04:00
|
|
|
|
{
|
2006-04-18 09:44:02 +04:00
|
|
|
|
AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Paint);
|
1998-08-30 23:16:11 +04:00
|
|
|
|
nsIFrame* frame;
|
1998-10-31 01:06:14 +03:00
|
|
|
|
nsresult rv = NS_OK;
|
1998-08-28 06:54:06 +04:00
|
|
|
|
|
2002-04-27 00:44:38 +04:00
|
|
|
|
if (mIsDestroying) {
|
|
|
|
|
NS_ASSERTION(PR_FALSE, "A paint message was dispatched to a destroyed PresShell");
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
1998-08-28 06:54:06 +04:00
|
|
|
|
NS_ASSERTION(!(nsnull == aView), "null view");
|
|
|
|
|
|
2003-06-30 14:46:59 +04:00
|
|
|
|
frame = NS_STATIC_CAST(nsIFrame*, aView->GetClientData());
|
2006-02-06 23:38:47 +03:00
|
|
|
|
nscolor backgroundColor;
|
|
|
|
|
mViewManager->GetDefaultBackgroundColor(&backgroundColor);
|
|
|
|
|
nsIView* rootView;
|
|
|
|
|
mViewManager->GetRootView(rootView);
|
|
|
|
|
if (!rootView->GetParent() && rootView->HasWidget()) {
|
|
|
|
|
PRBool widgetIsTranslucent;
|
|
|
|
|
rootView->GetWidget()->GetWindowTranslucency(widgetIsTranslucent);
|
|
|
|
|
if (widgetIsTranslucent) {
|
|
|
|
|
backgroundColor = NS_RGBA(0,0,0,0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!frame) {
|
|
|
|
|
if (NS_GET_A(backgroundColor) > 0) {
|
|
|
|
|
aRenderingContext->SetColor(backgroundColor);
|
|
|
|
|
aRenderingContext->FillRect(aDirtyRegion.GetBounds());
|
|
|
|
|
}
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
1998-08-28 06:54:06 +04:00
|
|
|
|
|
2006-02-06 23:38:47 +03:00
|
|
|
|
nsLayoutUtils::PaintFrame(aRenderingContext, frame, aDirtyRegion,
|
|
|
|
|
backgroundColor);
|
2000-10-11 17:50:45 +04:00
|
|
|
|
|
1998-10-31 01:06:14 +03:00
|
|
|
|
#ifdef NS_DEBUG
|
2006-02-06 23:38:47 +03:00
|
|
|
|
// Draw a border around the frame
|
|
|
|
|
if (nsIFrameDebug::GetShowFrameBorders()) {
|
|
|
|
|
nsRect r = frame->GetRect();
|
|
|
|
|
aRenderingContext->SetColor(NS_RGB(0,0,255));
|
|
|
|
|
aRenderingContext->DrawRect(0, 0, r.width, r.height);
|
1998-10-31 01:06:14 +03:00
|
|
|
|
}
|
2006-02-06 23:38:47 +03:00
|
|
|
|
// Draw a border around the current event target
|
|
|
|
|
if ((nsIFrameDebug::GetShowEventTargetFrameBorder()) && (aView == mCurrentTargetView)) {
|
|
|
|
|
aRenderingContext->SetColor(NS_RGB(128,0,128));
|
|
|
|
|
aRenderingContext->DrawRect(mCurrentTargetRect.x, mCurrentTargetRect.y, mCurrentTargetRect.width, mCurrentTargetRect.height);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
1999-09-15 03:43:35 +04:00
|
|
|
|
|
1998-08-28 06:54:06 +04:00
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
1999-06-15 07:14:28 +04:00
|
|
|
|
nsIFrame*
|
|
|
|
|
PresShell::GetCurrentEventFrame()
|
|
|
|
|
{
|
|
|
|
|
if (!mCurrentEventFrame && mCurrentEventContent) {
|
1999-11-03 10:11:45 +03:00
|
|
|
|
// Make sure the content still has a document reference. If not,
|
|
|
|
|
// then we assume it is no longer in the content tree and the
|
|
|
|
|
// frame shouldn't get an event, nor should we even assume its
|
|
|
|
|
// safe to try and find the frame.
|
2003-07-29 01:25:13 +04:00
|
|
|
|
if (mCurrentEventContent->GetDocument()) {
|
2005-08-23 02:24:29 +04:00
|
|
|
|
mCurrentEventFrame = GetPrimaryFrameFor(mCurrentEventContent);
|
1999-11-03 10:11:45 +03:00
|
|
|
|
}
|
1999-06-15 07:14:28 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return mCurrentEventFrame;
|
|
|
|
|
}
|
|
|
|
|
|
2000-06-24 07:58:13 +04:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::GetEventTargetFrame(nsIFrame** aFrame)
|
|
|
|
|
{
|
2003-03-12 06:22:11 +03:00
|
|
|
|
*aFrame = GetCurrentEventFrame();
|
|
|
|
|
return NS_OK;
|
2000-06-24 07:58:13 +04:00
|
|
|
|
}
|
|
|
|
|
|
2003-02-15 00:43:06 +03:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::GetEventTargetContent(nsEvent* aEvent, nsIContent** aContent)
|
|
|
|
|
{
|
|
|
|
|
if (mCurrentEventContent) {
|
|
|
|
|
*aContent = mCurrentEventContent;
|
|
|
|
|
NS_IF_ADDREF(*aContent);
|
|
|
|
|
} else {
|
|
|
|
|
nsIFrame* currentEventFrame = GetCurrentEventFrame();
|
|
|
|
|
if (currentEventFrame) {
|
|
|
|
|
currentEventFrame->GetContentForEvent(mPresContext, aEvent, aContent);
|
|
|
|
|
} else {
|
|
|
|
|
*aContent = nsnull;
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-03-12 06:22:11 +03:00
|
|
|
|
return NS_OK;
|
2003-02-15 00:43:06 +03:00
|
|
|
|
}
|
|
|
|
|
|
1999-09-02 22:14:01 +04:00
|
|
|
|
void
|
2000-04-24 08:41:27 +04:00
|
|
|
|
PresShell::PushCurrentEventInfo(nsIFrame* aFrame, nsIContent* aContent)
|
1999-09-02 22:14:01 +04:00
|
|
|
|
{
|
2000-04-24 08:41:27 +04:00
|
|
|
|
if (mCurrentEventFrame || mCurrentEventContent) {
|
1999-09-02 22:14:01 +04:00
|
|
|
|
mCurrentEventFrameStack.InsertElementAt((void*)mCurrentEventFrame, 0);
|
2004-09-13 07:22:46 +04:00
|
|
|
|
mCurrentEventContentStack.InsertObjectAt(mCurrentEventContent, 0);
|
1999-09-02 22:14:01 +04:00
|
|
|
|
}
|
2000-04-24 08:41:27 +04:00
|
|
|
|
mCurrentEventFrame = aFrame;
|
|
|
|
|
mCurrentEventContent = aContent;
|
1999-09-02 22:14:01 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2000-04-24 08:41:27 +04:00
|
|
|
|
PresShell::PopCurrentEventInfo()
|
1999-09-02 22:14:01 +04:00
|
|
|
|
{
|
|
|
|
|
mCurrentEventFrame = nsnull;
|
2004-09-13 07:22:46 +04:00
|
|
|
|
mCurrentEventContent = nsnull;
|
1999-09-02 22:14:01 +04:00
|
|
|
|
|
1999-09-02 23:21:45 +04:00
|
|
|
|
if (0 != mCurrentEventFrameStack.Count()) {
|
1999-09-02 22:14:01 +04:00
|
|
|
|
mCurrentEventFrame = (nsIFrame*)mCurrentEventFrameStack.ElementAt(0);
|
|
|
|
|
mCurrentEventFrameStack.RemoveElementAt(0);
|
2004-09-13 07:22:46 +04:00
|
|
|
|
mCurrentEventContent = mCurrentEventContentStack.ObjectAt(0);
|
|
|
|
|
mCurrentEventContentStack.RemoveObjectAt(0);
|
1999-09-02 22:14:01 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-07 05:09:06 +03:00
|
|
|
|
PRBool PresShell::InZombieDocument(nsIContent *aContent)
|
|
|
|
|
{
|
2005-08-06 00:01:52 +04:00
|
|
|
|
// If a content node points to a null document, or the document is not
|
|
|
|
|
// attached to a window, then it is possibly in a zombie document,
|
|
|
|
|
// about to be replaced by a newly loading document.
|
2003-01-07 05:09:06 +03:00
|
|
|
|
// Such documents cannot handle DOM events.
|
|
|
|
|
// It might actually be in a node not attached to any document,
|
|
|
|
|
// in which case there is not parent presshell to retarget it to.
|
2005-08-06 00:01:52 +04:00
|
|
|
|
nsIDocument *doc = aContent->GetDocument();
|
2005-11-29 02:56:44 +03:00
|
|
|
|
return !doc || !doc->GetWindow();
|
2003-01-07 05:09:06 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult PresShell::RetargetEventToParent(nsIView *aView,
|
|
|
|
|
nsGUIEvent* aEvent,
|
|
|
|
|
nsEventStatus* aEventStatus,
|
|
|
|
|
nsIContent* aZombieFocusedContent)
|
|
|
|
|
{
|
2005-02-05 20:00:46 +03:00
|
|
|
|
// Send this events straight up to the parent pres shell.
|
2003-01-07 05:09:06 +03:00
|
|
|
|
// We do this for non-mouse events in zombie documents.
|
|
|
|
|
// That way at least the UI key bindings can work.
|
|
|
|
|
|
2005-02-05 20:00:46 +03:00
|
|
|
|
// First, eliminate the focus ring in the current docshell, which
|
|
|
|
|
// is now a zombie. If we key navigate, it won't be within this
|
|
|
|
|
// docshell, until the newly loading document is displayed.
|
|
|
|
|
|
2003-01-07 05:09:06 +03:00
|
|
|
|
nsCOMPtr<nsIPresShell> kungFuDeathGrip(this);
|
2004-02-27 20:17:37 +03:00
|
|
|
|
// hold a reference to the ESM across event dispatch
|
|
|
|
|
nsCOMPtr<nsIEventStateManager> esm = mPresContext->EventStateManager();
|
2005-02-05 20:00:46 +03:00
|
|
|
|
|
|
|
|
|
esm->SetContentState(nsnull, NS_EVENT_STATE_FOCUS);
|
|
|
|
|
esm->SetFocusedContent(nsnull);
|
|
|
|
|
ContentStatesChanged(mDocument, aZombieFocusedContent,
|
|
|
|
|
nsnull, NS_EVENT_STATE_FOCUS);
|
|
|
|
|
|
|
|
|
|
// Next, update the display so the old focus ring is no longer visible
|
|
|
|
|
|
2004-02-01 13:09:07 +03:00
|
|
|
|
nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
|
2005-08-22 05:55:34 +04:00
|
|
|
|
if (!container)
|
|
|
|
|
container = do_QueryReferent(mForwardingContainer);
|
2003-01-07 05:09:06 +03:00
|
|
|
|
|
2005-02-05 20:00:46 +03:00
|
|
|
|
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
|
2005-08-22 05:55:34 +04:00
|
|
|
|
if (!docShell) {
|
|
|
|
|
// We don't have any place to send this event.
|
|
|
|
|
NS_WARNING("dropping event, no forwarding shell");
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2005-02-05 20:00:46 +03:00
|
|
|
|
nsCOMPtr<nsIContentViewer> contentViewer;
|
|
|
|
|
docShell->GetContentViewer(getter_AddRefs(contentViewer));
|
|
|
|
|
if (contentViewer) {
|
|
|
|
|
nsCOMPtr<nsIContentViewer> zombieViewer;
|
|
|
|
|
contentViewer->GetPreviousViewer(getter_AddRefs(zombieViewer));
|
|
|
|
|
if (zombieViewer) {
|
|
|
|
|
zombieViewer->Show();
|
2003-01-07 05:09:06 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now, find the parent pres shell and send the event there
|
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> treeItem =
|
|
|
|
|
do_QueryInterface(container);
|
|
|
|
|
NS_ASSERTION(treeItem, "No tree item for container.");
|
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
|
|
|
|
|
treeItem->GetParent(getter_AddRefs(parentTreeItem));
|
|
|
|
|
nsCOMPtr<nsIDocShell> parentDocShell =
|
|
|
|
|
do_QueryInterface(parentTreeItem);
|
|
|
|
|
if (!parentDocShell || treeItem == parentTreeItem) {
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPresShell> parentPresShell;
|
|
|
|
|
parentDocShell->GetPresShell(getter_AddRefs(parentPresShell));
|
|
|
|
|
nsCOMPtr<nsIViewObserver> parentViewObserver =
|
|
|
|
|
do_QueryInterface(parentPresShell);
|
|
|
|
|
if (!parentViewObserver) {
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PopCurrentEventInfo();
|
|
|
|
|
return parentViewObserver->HandleEvent(aView, aEvent,
|
2006-01-26 05:29:17 +03:00
|
|
|
|
aEventStatus);
|
2003-01-07 05:09:06 +03:00
|
|
|
|
}
|
|
|
|
|
|
1998-12-18 18:54:23 +03:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::HandleEvent(nsIView *aView,
|
|
|
|
|
nsGUIEvent* aEvent,
|
2006-01-26 05:29:17 +03:00
|
|
|
|
nsEventStatus* aEventStatus)
|
1998-08-28 06:54:06 +04:00
|
|
|
|
{
|
2003-05-12 11:11:16 +04:00
|
|
|
|
NS_ASSERTION(aView, "null view");
|
2000-03-22 05:43:08 +03:00
|
|
|
|
|
2005-01-20 06:39:09 +03:00
|
|
|
|
if (mIsDestroying || mIsReflowing || mChangeNestCount) {
|
1998-11-18 08:25:26 +03:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2001-08-17 07:13:07 +04:00
|
|
|
|
#ifdef ACCESSIBILITY
|
2003-05-12 11:11:16 +04:00
|
|
|
|
if (aEvent->eventStructType == NS_ACCESSIBLE_EVENT) {
|
2006-03-07 20:08:51 +03:00
|
|
|
|
return HandleEventInternal(aEvent, aView, aEventStatus);
|
2003-05-12 11:11:16 +04:00
|
|
|
|
}
|
2001-08-17 07:13:07 +04:00
|
|
|
|
#endif
|
2001-04-01 05:01:33 +04:00
|
|
|
|
|
2001-12-18 01:51:39 +03:00
|
|
|
|
// Check for a theme change up front, since the frame type is irrelevant
|
2003-05-12 11:11:16 +04:00
|
|
|
|
if (aEvent->message == NS_THEMECHANGED && mPresContext) {
|
2004-07-29 23:41:39 +04:00
|
|
|
|
mPresContext->ThemeChanged();
|
|
|
|
|
return NS_OK;
|
2003-05-12 11:11:16 +04:00
|
|
|
|
}
|
2001-04-01 05:01:33 +04:00
|
|
|
|
|
2003-05-12 11:11:16 +04:00
|
|
|
|
// Check for a system color change up front, since the frame type is
|
|
|
|
|
// irrelevant
|
2002-06-04 21:47:54 +04:00
|
|
|
|
if ((aEvent->message == NS_SYSCOLORCHANGED) && mPresContext) {
|
2003-06-30 14:46:59 +04:00
|
|
|
|
nsIViewManager* vm = GetViewManager();
|
|
|
|
|
if (vm) {
|
2002-06-04 21:47:54 +04:00
|
|
|
|
// Only dispatch system color change when the message originates from
|
|
|
|
|
// from the root views widget. This is necessary to prevent us from
|
|
|
|
|
// dispatching the SysColorChanged notification for each child window
|
|
|
|
|
// which may be redundant.
|
2004-05-17 20:29:13 +04:00
|
|
|
|
nsIView *view;
|
|
|
|
|
vm->GetRootView(view);
|
|
|
|
|
if (view == aView) {
|
2002-06-04 21:47:54 +04:00
|
|
|
|
*aEventStatus = nsEventStatus_eConsumeDoDefault;
|
2004-07-29 23:41:39 +04:00
|
|
|
|
mPresContext->SysColorChanged();
|
|
|
|
|
return NS_OK;
|
2002-06-04 21:47:54 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
2006-01-26 05:29:17 +03:00
|
|
|
|
|
2003-06-30 14:46:59 +04:00
|
|
|
|
nsIFrame* frame = NS_STATIC_CAST(nsIFrame*, aView->GetClientData());
|
1998-08-28 06:54:06 +04:00
|
|
|
|
|
2006-01-26 05:29:17 +03:00
|
|
|
|
PRBool dispatchUsingCoordinates =
|
|
|
|
|
!NS_IS_KEY_EVENT(aEvent) && !NS_IS_IME_EVENT(aEvent) &&
|
|
|
|
|
aEvent->message != NS_CONTEXTMENU_KEY && !NS_IS_FOCUS_EVENT(aEvent);
|
2006-02-27 05:47:13 +03:00
|
|
|
|
|
|
|
|
|
// if this event has no frame, we need to retarget it at a parent
|
|
|
|
|
// view that has a frame.
|
|
|
|
|
if (!frame &&
|
|
|
|
|
(dispatchUsingCoordinates || NS_IS_KEY_EVENT(aEvent) ||
|
|
|
|
|
NS_IS_IME_EVENT(aEvent))) {
|
|
|
|
|
nsIView* targetView = aView;
|
|
|
|
|
while (targetView && !targetView->GetClientData()) {
|
|
|
|
|
targetView = targetView->GetParent();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (targetView) {
|
|
|
|
|
aView = targetView;
|
|
|
|
|
frame = NS_STATIC_CAST(nsIFrame*, aView->GetClientData());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dispatchUsingCoordinates) {
|
|
|
|
|
NS_ASSERTION(frame, "Nothing to handle this event!");
|
|
|
|
|
if (!frame)
|
|
|
|
|
return NS_OK;
|
|
|
|
|
|
2006-01-26 05:29:17 +03:00
|
|
|
|
nsPoint eventPoint
|
|
|
|
|
= nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, frame);
|
2006-04-26 06:01:07 +04:00
|
|
|
|
nsIFrame* targetFrame = nsLayoutUtils::GetFrameForPoint(frame, eventPoint);
|
2006-01-26 05:29:17 +03:00
|
|
|
|
if (targetFrame) {
|
|
|
|
|
PresShell* shell =
|
|
|
|
|
NS_STATIC_CAST(PresShell*, targetFrame->GetPresContext()->PresShell());
|
|
|
|
|
if (shell != this) {
|
2006-05-12 07:49:38 +04:00
|
|
|
|
// Handle the event in the correct shell.
|
|
|
|
|
// Prevent deletion until we're done with event handling (bug 336582).
|
|
|
|
|
nsRefPtr<nsIPresShell> kungFuDeathGrip(shell);
|
2006-01-26 05:29:17 +03:00
|
|
|
|
nsIView* subshellRootView;
|
|
|
|
|
shell->GetViewManager()->GetRootView(subshellRootView);
|
|
|
|
|
// We pass the subshell's root view as the view to start from. This is
|
|
|
|
|
// the only correct alternative; if the event was captured then it
|
|
|
|
|
// must have been captured by us or some ancestor shell and we
|
|
|
|
|
// now ask the subshell to dispatch it normally.
|
|
|
|
|
return shell->HandlePositionedEvent(subshellRootView, targetFrame,
|
|
|
|
|
aEvent, aEventStatus);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!targetFrame) {
|
|
|
|
|
targetFrame = frame;
|
|
|
|
|
}
|
|
|
|
|
return HandlePositionedEvent(aView, targetFrame, aEvent, aEventStatus);
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-12 11:11:16 +04:00
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
|
|
|
|
if (frame) {
|
2000-04-24 08:41:27 +04:00
|
|
|
|
PushCurrentEventInfo(nsnull, nsnull);
|
1999-05-21 03:16:53 +04:00
|
|
|
|
|
2003-05-12 11:11:16 +04:00
|
|
|
|
// key and IME events go to the focused frame
|
2006-01-26 05:29:17 +03:00
|
|
|
|
nsIEventStateManager *esm = mPresContext->EventStateManager();
|
2004-03-22 21:13:11 +03:00
|
|
|
|
|
2006-01-26 05:29:17 +03:00
|
|
|
|
if (NS_IS_KEY_EVENT(aEvent) || NS_IS_IME_EVENT(aEvent) ||
|
|
|
|
|
aEvent->message == NS_CONTEXTMENU_KEY) {
|
2004-03-22 21:13:11 +03:00
|
|
|
|
esm->GetFocusedFrame(&mCurrentEventFrame);
|
2005-09-23 21:55:12 +04:00
|
|
|
|
if (mCurrentEventFrame) {
|
|
|
|
|
esm->GetFocusedContent(getter_AddRefs(mCurrentEventContent));
|
2006-01-26 05:29:17 +03:00
|
|
|
|
} else {
|
2005-04-29 22:30:23 +04:00
|
|
|
|
#if defined(MOZ_X11) || defined(XP_WIN)
|
2002-09-11 06:02:29 +04:00
|
|
|
|
#if defined(MOZ_X11)
|
2003-05-12 11:11:16 +04:00
|
|
|
|
if (NS_IS_IME_EVENT(aEvent)) {
|
2005-04-29 22:30:23 +04:00
|
|
|
|
// bug 52416 (MOZ_X11)
|
2003-05-12 11:11:16 +04:00
|
|
|
|
// Lookup region (candidate window) of UNIX IME grabs
|
|
|
|
|
// input focus from Mozilla but wants to send IME event
|
|
|
|
|
// to redraw pre-edit (composed) string
|
|
|
|
|
// If Mozilla does not have input focus and event is IME,
|
|
|
|
|
// sends IME event to pre-focused element
|
2005-04-29 22:30:23 +04:00
|
|
|
|
#else
|
|
|
|
|
if (NS_IS_KEY_EVENT(aEvent) || NS_IS_IME_EVENT(aEvent)) {
|
|
|
|
|
// bug 292263 (XP_WIN)
|
|
|
|
|
// If software keyboard has focus, it may send the key messages and
|
|
|
|
|
// the IME messages to pre-focused window. Therefore, if Mozilla
|
|
|
|
|
// doesn't have focus and event is key event or IME event, we should
|
|
|
|
|
// send the events to pre-focused element.
|
|
|
|
|
#endif /* defined(MOZ_X11) */
|
2005-11-29 02:56:44 +03:00
|
|
|
|
nsPIDOMWindow *ourWindow = mDocument->GetWindow();
|
2003-05-12 11:11:16 +04:00
|
|
|
|
if (ourWindow) {
|
2004-05-04 01:48:36 +04:00
|
|
|
|
nsIFocusController *focusController =
|
|
|
|
|
ourWindow->GetRootFocusController();
|
2003-05-12 11:11:16 +04:00
|
|
|
|
if (focusController) {
|
|
|
|
|
PRBool active = PR_FALSE;
|
|
|
|
|
// check input focus is in Mozilla
|
|
|
|
|
focusController->GetActive(&active);
|
|
|
|
|
if (!active) {
|
|
|
|
|
// if not, search for pre-focused element
|
|
|
|
|
nsCOMPtr<nsIDOMElement> focusedElement;
|
|
|
|
|
focusController->GetFocusedElement(getter_AddRefs(focusedElement));
|
|
|
|
|
if (focusedElement) {
|
|
|
|
|
// get mCurrentEventContent from focusedElement
|
2004-09-13 07:22:46 +04:00
|
|
|
|
mCurrentEventContent = do_QueryInterface(focusedElement);
|
2002-09-11 06:02:29 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2000-03-22 05:43:08 +03:00
|
|
|
|
}
|
2005-04-29 22:30:23 +04:00
|
|
|
|
#endif /* defined(MOZ_X11) || defined(XP_WIN) */
|
2003-05-12 11:11:16 +04:00
|
|
|
|
if (!mCurrentEventContent) {
|
2004-09-13 07:22:46 +04:00
|
|
|
|
mCurrentEventContent = mDocument->GetRootContent();
|
2003-01-07 05:09:06 +03:00
|
|
|
|
}
|
2004-01-08 01:18:37 +03:00
|
|
|
|
mCurrentEventFrame = nsnull; // XXXldb Isn't it already?
|
1999-07-26 19:02:19 +04:00
|
|
|
|
}
|
2003-05-12 11:11:16 +04:00
|
|
|
|
if (mCurrentEventContent && InZombieDocument(mCurrentEventContent)) {
|
2006-01-26 05:29:17 +03:00
|
|
|
|
return RetargetEventToParent(aView, aEvent, aEventStatus,
|
|
|
|
|
mCurrentEventContent);
|
2003-05-12 11:11:16 +04:00
|
|
|
|
}
|
|
|
|
|
} else {
|
2006-01-26 05:29:17 +03:00
|
|
|
|
mCurrentEventFrame = frame;
|
1998-11-18 08:25:26 +03:00
|
|
|
|
}
|
2003-05-12 11:11:16 +04:00
|
|
|
|
if (GetCurrentEventFrame()) {
|
2006-03-07 20:08:51 +03:00
|
|
|
|
rv = HandleEventInternal(aEvent, aView, aEventStatus);
|
2003-05-12 11:11:16 +04:00
|
|
|
|
}
|
2006-01-26 05:29:17 +03:00
|
|
|
|
|
2000-02-03 05:49:58 +03:00
|
|
|
|
#ifdef NS_DEBUG
|
2006-01-26 05:29:17 +03:00
|
|
|
|
ShowEventTargetDebug();
|
2000-02-03 05:49:58 +03:00
|
|
|
|
#endif
|
2000-04-24 08:41:27 +04:00
|
|
|
|
PopCurrentEventInfo();
|
2006-01-26 05:29:17 +03:00
|
|
|
|
} else {
|
2003-05-12 11:11:16 +04:00
|
|
|
|
// Focus events need to be dispatched even if no frame was found, since
|
|
|
|
|
// we don't want the focus controller to be out of sync.
|
|
|
|
|
|
|
|
|
|
if (!NS_EVENT_NEEDS_FRAME(aEvent)) {
|
|
|
|
|
mCurrentEventFrame = nsnull;
|
2006-03-07 20:08:51 +03:00
|
|
|
|
return HandleEventInternal(aEvent, aView, aEventStatus);
|
2003-05-12 11:11:16 +04:00
|
|
|
|
}
|
2003-07-24 12:48:59 +04:00
|
|
|
|
else if (NS_IS_KEY_EVENT(aEvent)) {
|
|
|
|
|
// Keypress events in new blank tabs should not be completely thrown away.
|
|
|
|
|
// Retarget them -- the parent chrome shell might make use of them.
|
2006-01-26 05:29:17 +03:00
|
|
|
|
return RetargetEventToParent(aView, aEvent, aEventStatus,
|
|
|
|
|
mCurrentEventContent);
|
2003-07-24 12:48:59 +04:00
|
|
|
|
}
|
2006-01-26 05:29:17 +03:00
|
|
|
|
}
|
2003-05-12 11:11:16 +04:00
|
|
|
|
|
2006-01-26 05:29:17 +03:00
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef NS_DEBUG
|
|
|
|
|
void
|
|
|
|
|
PresShell::ShowEventTargetDebug()
|
|
|
|
|
{
|
|
|
|
|
if ((nsIFrameDebug::GetShowEventTargetFrameBorder()) &&
|
|
|
|
|
(GetCurrentEventFrame())) {
|
|
|
|
|
nsIView *oldView = mCurrentTargetView;
|
|
|
|
|
nsPoint offset(0,0);
|
|
|
|
|
nsRect oldTargetRect(mCurrentTargetRect);
|
|
|
|
|
mCurrentTargetRect = mCurrentEventFrame->GetRect();
|
|
|
|
|
mCurrentTargetView = mCurrentEventFrame->GetView();
|
|
|
|
|
if (!mCurrentTargetView ) {
|
|
|
|
|
mCurrentEventFrame->GetOffsetFromView(offset, &mCurrentTargetView);
|
|
|
|
|
}
|
|
|
|
|
if (mCurrentTargetView) {
|
|
|
|
|
mCurrentTargetRect.x = offset.x;
|
|
|
|
|
mCurrentTargetRect.y = offset.y;
|
|
|
|
|
// use aView or mCurrentTargetView??
|
|
|
|
|
if ((mCurrentTargetRect != oldTargetRect) ||
|
|
|
|
|
(mCurrentTargetView != oldView)) {
|
|
|
|
|
|
|
|
|
|
nsIViewManager* vm = GetViewManager();
|
|
|
|
|
if (vm) {
|
|
|
|
|
vm->UpdateView(mCurrentTargetView,mCurrentTargetRect,0);
|
|
|
|
|
if (oldView)
|
|
|
|
|
vm->UpdateView(oldView,oldTargetRect,0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
|
PresShell::HandlePositionedEvent(nsIView* aView,
|
|
|
|
|
nsIFrame* aTargetFrame,
|
|
|
|
|
nsGUIEvent* aEvent,
|
|
|
|
|
nsEventStatus* aEventStatus)
|
|
|
|
|
{
|
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
|
|
|
|
PushCurrentEventInfo(nsnull, nsnull);
|
|
|
|
|
|
|
|
|
|
mCurrentEventFrame = aTargetFrame;
|
|
|
|
|
|
|
|
|
|
if (mCurrentEventFrame) {
|
|
|
|
|
nsCOMPtr<nsIContent> targetElement;
|
|
|
|
|
mCurrentEventFrame->GetContentForEvent(mPresContext, aEvent,
|
|
|
|
|
getter_AddRefs(targetElement));
|
|
|
|
|
|
|
|
|
|
// If there is no content for this frame, target it anyway. Some
|
|
|
|
|
// frames can be targeted but do not have content, particularly
|
|
|
|
|
// windows with scrolling off.
|
|
|
|
|
if (targetElement) {
|
|
|
|
|
// Bug 103055, bug 185889: mouse events apply to *elements*, not all
|
|
|
|
|
// nodes. Thus we get the nearest element parent here.
|
|
|
|
|
// XXX we leave the frame the same even if we find an element
|
|
|
|
|
// parent, so that the text frame will receive the event (selection
|
|
|
|
|
// and friends are the ones who care about that anyway)
|
|
|
|
|
//
|
|
|
|
|
// We use weak pointers because during this tight loop, the node
|
|
|
|
|
// will *not* go away. And this happens on every mousemove.
|
|
|
|
|
while (targetElement &&
|
2006-05-05 10:52:21 +04:00
|
|
|
|
!targetElement->IsNodeOfType(nsINode::eELEMENT)) {
|
2006-01-26 05:29:17 +03:00
|
|
|
|
targetElement = targetElement->GetParent();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If we found an element, target it. Otherwise, target *nothing*.
|
|
|
|
|
if (!targetElement) {
|
|
|
|
|
mCurrentEventContent = nsnull;
|
|
|
|
|
mCurrentEventFrame = nsnull;
|
|
|
|
|
} else if (targetElement != mCurrentEventContent) {
|
|
|
|
|
mCurrentEventContent = targetElement;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (GetCurrentEventFrame()) {
|
2006-03-07 20:08:51 +03:00
|
|
|
|
rv = HandleEventInternal(aEvent, aView, aEventStatus);
|
1998-11-21 03:19:36 +03:00
|
|
|
|
}
|
1998-08-28 06:54:06 +04:00
|
|
|
|
|
2006-01-26 05:29:17 +03:00
|
|
|
|
#ifdef NS_DEBUG
|
|
|
|
|
ShowEventTargetDebug();
|
|
|
|
|
#endif
|
|
|
|
|
PopCurrentEventInfo();
|
1998-08-28 06:54:06 +04:00
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-24 08:41:27 +04:00
|
|
|
|
NS_IMETHODIMP
|
2006-03-07 20:08:51 +03:00
|
|
|
|
PresShell::HandleEventWithTarget(nsEvent* aEvent, nsIFrame* aFrame,
|
|
|
|
|
nsIContent* aContent, nsEventStatus* aStatus)
|
2000-04-24 08:41:27 +04:00
|
|
|
|
{
|
|
|
|
|
nsresult ret;
|
|
|
|
|
|
|
|
|
|
PushCurrentEventInfo(aFrame, aContent);
|
2006-03-07 20:08:51 +03:00
|
|
|
|
ret = HandleEventInternal(aEvent, nsnull, aStatus);
|
2000-04-24 08:41:27 +04:00
|
|
|
|
PopCurrentEventInfo();
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 08:32:52 +04:00
|
|
|
|
inline PRBool
|
|
|
|
|
IsSynthesizedMouseMove(nsEvent* aEvent)
|
|
|
|
|
{
|
|
|
|
|
return aEvent->eventStructType == NS_MOUSE_EVENT &&
|
|
|
|
|
NS_STATIC_CAST(nsMouseEvent*, aEvent)->reason != nsMouseEvent::eReal;
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-24 08:41:27 +04:00
|
|
|
|
nsresult
|
2003-05-12 11:11:16 +04:00
|
|
|
|
PresShell::HandleEventInternal(nsEvent* aEvent, nsIView *aView,
|
2006-03-07 20:08:51 +03:00
|
|
|
|
nsEventStatus* aStatus)
|
2000-04-24 08:41:27 +04:00
|
|
|
|
{
|
2001-08-17 07:13:07 +04:00
|
|
|
|
#ifdef ACCESSIBILITY
|
2001-04-01 05:01:33 +04:00
|
|
|
|
if (aEvent->eventStructType == NS_ACCESSIBLE_EVENT)
|
|
|
|
|
{
|
2005-07-15 06:35:19 +04:00
|
|
|
|
NS_STATIC_CAST(nsAccessibleEvent*, aEvent)->accessible = nsnull;
|
2003-04-15 12:45:55 +04:00
|
|
|
|
nsCOMPtr<nsIAccessibilityService> accService =
|
|
|
|
|
do_GetService("@mozilla.org/accessibilityService;1");
|
|
|
|
|
if (accService) {
|
2005-07-15 06:35:19 +04:00
|
|
|
|
nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
|
|
|
|
|
if (!container) {
|
|
|
|
|
// This presshell is not active. This often happens when a
|
|
|
|
|
// preshell is being held onto for fastback.
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
2003-04-15 12:45:55 +04:00
|
|
|
|
nsIAccessible* acc;
|
|
|
|
|
nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(mDocument));
|
|
|
|
|
NS_ASSERTION(domNode, "No dom node for doc");
|
|
|
|
|
accService->GetAccessibleInShell(domNode, this, &acc);
|
|
|
|
|
// Addref this - it's not a COM Ptr
|
|
|
|
|
// We'll make sure the right number of Addref's occur before
|
|
|
|
|
// handing this back to the accessibility client
|
|
|
|
|
NS_STATIC_CAST(nsAccessibleEvent*, aEvent)->accessible = acc;
|
2005-05-03 07:46:51 +04:00
|
|
|
|
mIsAccessibilityActive = PR_TRUE;
|
2003-04-15 12:45:55 +04:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
2001-04-01 05:01:33 +04:00
|
|
|
|
}
|
2001-08-17 07:13:07 +04:00
|
|
|
|
#endif
|
2001-04-01 05:01:33 +04:00
|
|
|
|
|
2004-02-27 20:17:37 +03:00
|
|
|
|
nsCOMPtr<nsIEventStateManager> manager = mPresContext->EventStateManager();
|
|
|
|
|
nsresult rv = NS_OK;
|
2000-04-24 08:41:27 +04:00
|
|
|
|
|
2005-02-14 23:09:14 +03:00
|
|
|
|
// Grab the offset of aView from our root view. We can use this to adjust
|
|
|
|
|
// coordinates as needed. Note that we can't just adjust them later, because
|
|
|
|
|
// event dispatch can destroy aView. Also note that at times aView is null
|
|
|
|
|
// here. When that happens, there isn't much we can do about getting
|
|
|
|
|
// coordinates right....
|
|
|
|
|
nsPoint offsetOfaView(0,0);
|
|
|
|
|
if (aView) {
|
|
|
|
|
nsIView* rootView;
|
|
|
|
|
mViewManager->GetRootView(rootView);
|
|
|
|
|
offsetOfaView = aView->GetOffsetTo(rootView);
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-27 20:17:37 +03:00
|
|
|
|
if (!NS_EVENT_NEEDS_FRAME(aEvent) || GetCurrentEventFrame()) {
|
2004-09-04 23:28:46 +04:00
|
|
|
|
PRBool isHandlingUserInput = PR_FALSE;
|
|
|
|
|
|
2006-04-10 21:04:54 +04:00
|
|
|
|
if (NS_IS_TRUSTED_EVENT(aEvent)) {
|
2004-09-04 23:28:46 +04:00
|
|
|
|
switch (aEvent->message) {
|
|
|
|
|
case NS_GOTFOCUS:
|
|
|
|
|
case NS_LOSTFOCUS:
|
|
|
|
|
case NS_ACTIVATE:
|
|
|
|
|
case NS_DEACTIVATE:
|
|
|
|
|
// Treat focus/blur events as user input if they happen while
|
|
|
|
|
// executing trusted script, or no script at all. If they
|
|
|
|
|
// happen during execution of non-trusted script, then they
|
2005-11-21 01:05:24 +03:00
|
|
|
|
// should not be considered user input.
|
2004-09-04 23:28:46 +04:00
|
|
|
|
if (!nsContentUtils::IsCallerChrome()) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case NS_MOUSE_LEFT_BUTTON_DOWN:
|
|
|
|
|
case NS_MOUSE_MIDDLE_BUTTON_DOWN:
|
|
|
|
|
case NS_MOUSE_RIGHT_BUTTON_DOWN:
|
|
|
|
|
case NS_MOUSE_LEFT_BUTTON_UP:
|
|
|
|
|
case NS_MOUSE_RIGHT_BUTTON_UP:
|
|
|
|
|
case NS_MOUSE_MIDDLE_BUTTON_UP:
|
|
|
|
|
case NS_KEY_PRESS:
|
|
|
|
|
case NS_KEY_DOWN:
|
|
|
|
|
case NS_KEY_UP:
|
|
|
|
|
isHandlingUserInput = PR_TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsAutoHandlingUserInputStatePusher userInpStatePusher(isHandlingUserInput);
|
|
|
|
|
|
|
|
|
|
nsAutoPopupStatePusher popupStatePusher(nsDOMEvent::GetEventPopupControlState(aEvent));
|
2000-04-24 08:41:27 +04:00
|
|
|
|
|
2006-03-12 23:12:36 +03:00
|
|
|
|
// FIXME. If the event was reused, we need to clear the old target,
|
|
|
|
|
// bug 329430
|
|
|
|
|
aEvent->target = nsnull;
|
|
|
|
|
|
2003-05-12 11:11:16 +04:00
|
|
|
|
// 1. Give event to event manager for pre event state changes and
|
|
|
|
|
// generation of synthetic events.
|
|
|
|
|
rv = manager->PreHandleEvent(mPresContext, aEvent, mCurrentEventFrame,
|
|
|
|
|
aStatus, aView);
|
|
|
|
|
|
|
|
|
|
// 2. Give event to the DOM for third party and JS use.
|
2005-09-16 10:04:25 +04:00
|
|
|
|
if ((GetCurrentEventFrame()) && NS_SUCCEEDED(rv)) {
|
|
|
|
|
// We want synthesized mouse moves to cause mouseover and mouseout
|
|
|
|
|
// DOM events (PreHandleEvent above), but not mousemove DOM events.
|
|
|
|
|
if (!IsSynthesizedMouseMove(aEvent)) {
|
2006-03-07 20:08:51 +03:00
|
|
|
|
nsPresShellEventCB eventCB(this);
|
2005-09-16 10:04:25 +04:00
|
|
|
|
if (mCurrentEventContent) {
|
2006-03-07 20:08:51 +03:00
|
|
|
|
nsEventDispatcher::Dispatch(mCurrentEventContent, mPresContext,
|
|
|
|
|
aEvent, nsnull, aStatus, &eventCB);
|
2005-09-16 10:04:25 +04:00
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
nsCOMPtr<nsIContent> targetContent;
|
|
|
|
|
rv = mCurrentEventFrame->GetContentForEvent(mPresContext, aEvent,
|
|
|
|
|
getter_AddRefs(targetContent));
|
|
|
|
|
if (NS_SUCCEEDED(rv) && targetContent) {
|
2006-03-07 20:08:51 +03:00
|
|
|
|
nsEventDispatcher::Dispatch(targetContent, mPresContext, aEvent,
|
|
|
|
|
nsnull, aStatus, &eventCB);
|
2005-09-16 10:04:25 +04:00
|
|
|
|
}
|
2002-11-09 03:25:25 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2006-03-07 20:08:51 +03:00
|
|
|
|
// 3. Give event to event manager for post event state changes and
|
2003-05-12 11:11:16 +04:00
|
|
|
|
// generation of synthetic events.
|
|
|
|
|
if (NS_SUCCEEDED (rv) &&
|
|
|
|
|
(GetCurrentEventFrame() || !NS_EVENT_NEEDS_FRAME(aEvent))) {
|
|
|
|
|
rv = manager->PostHandleEvent(mPresContext, aEvent, mCurrentEventFrame,
|
|
|
|
|
aStatus, aView);
|
2000-04-24 08:41:27 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2000-06-29 06:02:43 +04:00
|
|
|
|
// Dispatch event to content only (NOT full processing)
|
|
|
|
|
// See also HandleEventWithTarget which does full event processing.
|
|
|
|
|
NS_IMETHODIMP
|
2006-03-07 20:08:51 +03:00
|
|
|
|
PresShell::HandleDOMEventWithTarget(nsIContent* aTargetContent, nsEvent* aEvent,
|
|
|
|
|
nsEventStatus* aStatus)
|
2000-06-29 06:02:43 +04:00
|
|
|
|
{
|
|
|
|
|
PushCurrentEventInfo(nsnull, aTargetContent);
|
|
|
|
|
|
|
|
|
|
// Bug 41013: Check if the event should be dispatched to content.
|
|
|
|
|
// It's possible that we are in the middle of destroying the window
|
|
|
|
|
// and the js context is out of date. This check detects the case
|
|
|
|
|
// that caused a crash in bug 41013, but there may be a better way
|
|
|
|
|
// to handle this situation!
|
2004-02-01 13:09:07 +03:00
|
|
|
|
nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
|
|
|
|
|
if (container) {
|
2000-06-29 06:02:43 +04:00
|
|
|
|
|
|
|
|
|
// Dispatch event to content
|
2006-03-07 20:08:51 +03:00
|
|
|
|
nsEventDispatcher::Dispatch(aTargetContent, mPresContext, aEvent, nsnull,
|
|
|
|
|
aStatus);
|
2000-06-29 06:02:43 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PopCurrentEventInfo();
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
1998-12-18 18:54:23 +03:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::ResizeReflow(nsIView *aView, nscoord aWidth, nscoord aHeight)
|
1998-08-28 06:54:06 +04:00
|
|
|
|
{
|
|
|
|
|
return ResizeReflow(aWidth, aHeight);
|
|
|
|
|
}
|
|
|
|
|
|
2004-10-15 01:51:00 +04:00
|
|
|
|
NS_IMETHODIMP_(PRBool)
|
|
|
|
|
PresShell::IsVisible()
|
|
|
|
|
{
|
|
|
|
|
nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
|
|
|
|
|
nsCOMPtr<nsIBaseWindow> bw = do_QueryInterface(container);
|
|
|
|
|
if (!bw)
|
|
|
|
|
return PR_FALSE;
|
|
|
|
|
PRBool res = PR_TRUE;
|
|
|
|
|
bw->GetVisibility(&res);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-20 06:39:09 +03:00
|
|
|
|
NS_IMETHODIMP_(void)
|
|
|
|
|
PresShell::WillPaint()
|
|
|
|
|
{
|
2005-02-25 07:03:13 +03:00
|
|
|
|
// Don't reenter reflow and don't reflow during frame construction. Also
|
|
|
|
|
// don't bother reflowing if some viewmanager in our tree is painting while
|
|
|
|
|
// we still have painting suppressed.
|
|
|
|
|
if (mIsReflowing || mChangeNestCount || mPaintingSuppressed) {
|
2005-01-20 06:39:09 +03:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Process reflows, if we have them, to reduce flicker due to invalidates and
|
|
|
|
|
// reflow being interspersed. Note that we _do_ allow this to be
|
|
|
|
|
// interruptible; if we can't do all the reflows it's better to flicker a bit
|
|
|
|
|
// than to freeze up.
|
|
|
|
|
// XXXbz this update batch may not be strictly necessary, but it's good form.
|
|
|
|
|
// XXXbz should we be flushing out style changes here? Probably not, I'd say.
|
|
|
|
|
NS_ASSERTION(mViewManager, "Something weird is going on");
|
|
|
|
|
mViewManager->BeginUpdateViewBatch();
|
|
|
|
|
ProcessReflowCommands(PR_TRUE);
|
|
|
|
|
mViewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
|
nsresult
|
|
|
|
|
PresShell::GetAgentStyleSheets(nsCOMArray<nsIStyleSheet>& aSheets)
|
|
|
|
|
{
|
|
|
|
|
aSheets.Clear();
|
|
|
|
|
PRInt32 sheetCount = mStyleSet->SheetCount(nsStyleSet::eAgentSheet);
|
|
|
|
|
|
|
|
|
|
for (PRInt32 i = 0; i < sheetCount; ++i) {
|
|
|
|
|
nsIStyleSheet *sheet = mStyleSet->StyleSheetAt(nsStyleSet::eAgentSheet, i);
|
|
|
|
|
if (!aSheets.AppendObject(sheet))
|
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
|
PresShell::SetAgentStyleSheets(const nsCOMArray<nsIStyleSheet>& aSheets)
|
|
|
|
|
{
|
|
|
|
|
return mStyleSet->ReplaceSheets(nsStyleSet::eAgentSheet, aSheets);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
|
PresShell::AddOverrideStyleSheet(nsIStyleSheet *aSheet)
|
|
|
|
|
{
|
2004-07-28 11:08:41 +04:00
|
|
|
|
return mStyleSet->PrependStyleSheet(nsStyleSet::eOverrideSheet, aSheet);
|
2004-01-08 01:30:53 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
|
PresShell::RemoveOverrideStyleSheet(nsIStyleSheet *aSheet)
|
|
|
|
|
{
|
|
|
|
|
return mStyleSet->RemoveStyleSheet(nsStyleSet::eOverrideSheet, aSheet);
|
|
|
|
|
}
|
|
|
|
|
|
2005-05-05 00:22:32 +04:00
|
|
|
|
static void
|
|
|
|
|
StopPluginInstance(PresShell *aShell, nsIContent *aContent)
|
|
|
|
|
{
|
|
|
|
|
nsIFrame *frame = aShell->FrameManager()->GetPrimaryFrameFor(aContent);
|
|
|
|
|
|
|
|
|
|
nsIObjectFrame *objectFrame = nsnull;
|
|
|
|
|
if (frame)
|
|
|
|
|
CallQueryInterface(frame, &objectFrame);
|
|
|
|
|
if (!objectFrame)
|
|
|
|
|
return;
|
|
|
|
|
|
2005-11-01 14:37:25 +03:00
|
|
|
|
objectFrame->StopPlugin();
|
2005-05-05 00:22:32 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PR_STATIC_CALLBACK(PRBool)
|
|
|
|
|
FreezeSubDocument(nsIDocument *aDocument, void *aData)
|
|
|
|
|
{
|
|
|
|
|
nsIPresShell *shell = aDocument->GetShellAt(0);
|
|
|
|
|
if (shell)
|
|
|
|
|
shell->Freeze();
|
|
|
|
|
|
|
|
|
|
return PR_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PresShell::Freeze()
|
|
|
|
|
{
|
|
|
|
|
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(mDocument);
|
|
|
|
|
if (domDoc) {
|
|
|
|
|
EnumeratePlugins(domDoc, NS_LITERAL_STRING("object"), StopPluginInstance);
|
|
|
|
|
EnumeratePlugins(domDoc, NS_LITERAL_STRING("applet"), StopPluginInstance);
|
|
|
|
|
EnumeratePlugins(domDoc, NS_LITERAL_STRING("embed"), StopPluginInstance);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mCaret)
|
|
|
|
|
mCaret->SetCaretVisible(PR_FALSE);
|
|
|
|
|
|
2005-07-01 11:12:02 +04:00
|
|
|
|
mPaintingSuppressed = PR_TRUE;
|
|
|
|
|
|
2005-05-05 00:22:32 +04:00
|
|
|
|
if (mDocument)
|
|
|
|
|
mDocument->EnumerateSubDocuments(FreezeSubDocument, nsnull);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
StartPluginInstance(PresShell *aShell, nsIContent *aContent)
|
|
|
|
|
{
|
2005-12-03 14:27:42 +03:00
|
|
|
|
nsCOMPtr<nsIObjectLoadingContent> objlc(do_QueryInterface(aContent));
|
2006-01-15 16:31:10 +03:00
|
|
|
|
if (!objlc)
|
|
|
|
|
return;
|
|
|
|
|
|
2005-12-03 14:27:42 +03:00
|
|
|
|
nsCOMPtr<nsIPluginInstance> inst;
|
|
|
|
|
objlc->EnsureInstantiation(getter_AddRefs(inst));
|
2005-05-05 00:22:32 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PR_STATIC_CALLBACK(PRBool)
|
|
|
|
|
ThawSubDocument(nsIDocument *aDocument, void *aData)
|
|
|
|
|
{
|
|
|
|
|
nsIPresShell *shell = aDocument->GetShellAt(0);
|
|
|
|
|
if (shell)
|
2005-07-19 21:07:40 +04:00
|
|
|
|
shell->Thaw();
|
2005-05-05 00:22:32 +04:00
|
|
|
|
|
|
|
|
|
return PR_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2005-07-19 21:07:40 +04:00
|
|
|
|
PresShell::Thaw()
|
2005-05-05 00:22:32 +04:00
|
|
|
|
{
|
|
|
|
|
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(mDocument);
|
|
|
|
|
if (domDoc) {
|
|
|
|
|
EnumeratePlugins(domDoc, NS_LITERAL_STRING("object"), StartPluginInstance);
|
|
|
|
|
EnumeratePlugins(domDoc, NS_LITERAL_STRING("applet"), StartPluginInstance);
|
|
|
|
|
EnumeratePlugins(domDoc, NS_LITERAL_STRING("embed"), StartPluginInstance);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mDocument)
|
|
|
|
|
mDocument->EnumerateSubDocuments(ThawSubDocument, nsnull);
|
2005-07-01 11:12:02 +04:00
|
|
|
|
|
2005-07-19 21:07:40 +04:00
|
|
|
|
UnsuppressPainting();
|
2005-05-05 00:22:32 +04:00
|
|
|
|
}
|
|
|
|
|
|
2000-04-17 11:13:57 +04:00
|
|
|
|
//--------------------------------------------------------
|
|
|
|
|
// Start of protected and private methods on the PresShell
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
//-------------- Begin Reflow Event Definition ------------------------
|
|
|
|
|
|
2006-05-10 21:30:15 +04:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::ReflowEvent::Run() {
|
|
|
|
|
// Take an owning reference to the PresShell during this call to ensure
|
|
|
|
|
// that it doesn't get killed off prematurely.
|
|
|
|
|
nsRefPtr<PresShell> ps = mPresShell;
|
|
|
|
|
if (ps) {
|
2000-04-17 11:13:57 +04:00
|
|
|
|
#ifdef DEBUG
|
2006-05-10 21:30:15 +04:00
|
|
|
|
if (VERIFY_REFLOW_NOISY_RC & gVerifyReflowFlags) {
|
|
|
|
|
printf("\n*** Handling reflow event: PresShell=%p, event=%p\n", (void*)ps, (void*)this);
|
|
|
|
|
}
|
2000-04-17 11:13:57 +04:00
|
|
|
|
#endif
|
2006-05-10 21:30:15 +04:00
|
|
|
|
// NOTE: the ReflowEvent class is a friend of the PresShell class
|
|
|
|
|
PRBool isBatching;
|
|
|
|
|
ps->ClearReflowEventStatus();
|
|
|
|
|
ps->GetReflowBatchingStatus(&isBatching);
|
|
|
|
|
if (!isBatching) {
|
|
|
|
|
// Set a kung fu death grip on the view manager associated with the pres shell
|
|
|
|
|
// before processing that pres shell's reflow commands. Fixes bug 54868.
|
|
|
|
|
nsCOMPtr<nsIViewManager> viewManager = ps->GetViewManager();
|
|
|
|
|
|
|
|
|
|
viewManager->BeginUpdateViewBatch();
|
|
|
|
|
ps->ProcessReflowCommands(PR_TRUE);
|
|
|
|
|
viewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
|
|
|
|
|
|
|
|
|
|
// Now, explicitly release the pres shell before the view manager
|
|
|
|
|
ps = nsnull;
|
|
|
|
|
viewManager = nsnull;
|
2000-04-17 11:13:57 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
2006-05-10 21:30:15 +04:00
|
|
|
|
return NS_OK;
|
2000-04-17 11:13:57 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-------------- End Reflow Event Definition ---------------------------
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PresShell::PostReflowEvent()
|
|
|
|
|
{
|
2006-05-10 21:30:15 +04:00
|
|
|
|
if (mReflowEvent.IsPending() || mIsDestroying || mIsReflowing ||
|
|
|
|
|
mReflowCommands.Count() == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
nsRefPtr<ReflowEvent> ev = new ReflowEvent(this);
|
|
|
|
|
if (NS_FAILED(NS_DispatchToCurrentThread(ev))) {
|
|
|
|
|
NS_WARNING("failed to dispatch reflow event");
|
|
|
|
|
} else {
|
|
|
|
|
mReflowEvent = ev;
|
2003-10-06 05:46:31 +04:00
|
|
|
|
#ifdef DEBUG
|
2006-05-10 21:30:15 +04:00
|
|
|
|
if (VERIFY_REFLOW_NOISY_RC & gVerifyReflowFlags) {
|
|
|
|
|
printf("\n*** PresShell::PostReflowEvent(), this=%p, event=%p\n", (void*)this, (void*)ev);
|
2003-10-06 05:46:31 +04:00
|
|
|
|
}
|
2006-05-10 21:30:15 +04:00
|
|
|
|
#endif
|
2000-04-17 11:13:57 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
|
PresShell::DidCauseReflow()
|
2001-09-19 11:08:15 +04:00
|
|
|
|
{
|
2005-01-20 06:39:09 +03:00
|
|
|
|
NS_ASSERTION(mChangeNestCount != 0, "Unexpected call to DidCauseReflow()");
|
|
|
|
|
if (--mChangeNestCount == 0) {
|
|
|
|
|
// We may have had more reflow commands appended to the queue during
|
|
|
|
|
// our reflow. Make sure these get processed at some point.
|
2006-04-19 19:08:44 +04:00
|
|
|
|
PostReflowEvent();
|
2000-05-16 05:11:29 +04:00
|
|
|
|
}
|
2000-09-12 04:35:11 +04:00
|
|
|
|
|
2000-04-17 11:13:57 +04:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2006-04-28 08:33:41 +04:00
|
|
|
|
void
|
|
|
|
|
PresShell::WillDoReflow()
|
|
|
|
|
{
|
|
|
|
|
// We just reflowed, tell the caret that its frame might have moved.
|
|
|
|
|
if (mCaret) {
|
|
|
|
|
mCaret->UpdateCaretPosition();
|
|
|
|
|
mCaret->InvalidateOutsideCaret();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-04 03:11:59 +03:00
|
|
|
|
void
|
|
|
|
|
PresShell::DidDoReflow()
|
|
|
|
|
{
|
|
|
|
|
HandlePostedDOMEvents();
|
|
|
|
|
HandlePostedAttributeChanges();
|
|
|
|
|
HandlePostedReflowCallbacks();
|
2004-06-22 08:32:52 +04:00
|
|
|
|
// Null-check mViewManager in case this happens during Destroy. See
|
|
|
|
|
// bugs 244435 and 238546.
|
|
|
|
|
if (!mPaintingSuppressed && mViewManager)
|
|
|
|
|
mViewManager->SynthesizeMouseMove(PR_FALSE);
|
2006-04-28 08:33:41 +04:00
|
|
|
|
if (mCaret)
|
|
|
|
|
mCaret->InvalidateOutsideCaret();
|
2004-02-04 03:11:59 +03:00
|
|
|
|
}
|
|
|
|
|
|
2000-04-17 11:13:57 +04:00
|
|
|
|
nsresult
|
|
|
|
|
PresShell::ProcessReflowCommands(PRBool aInterruptible)
|
|
|
|
|
{
|
|
|
|
|
MOZ_TIMER_DEBUGLOG(("Start: Reflow: PresShell::ProcessReflowCommands(), this=%p\n", this));
|
|
|
|
|
MOZ_TIMER_START(mReflowWatch);
|
|
|
|
|
|
|
|
|
|
if (0 != mReflowCommands.Count()) {
|
|
|
|
|
nsHTMLReflowMetrics desiredSize(nsnull);
|
|
|
|
|
nsIRenderingContext* rcx;
|
2004-03-06 07:46:11 +03:00
|
|
|
|
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
|
2003-06-30 14:46:59 +04:00
|
|
|
|
nsSize maxSize = rootFrame->GetSize();
|
2001-03-13 09:38:59 +03:00
|
|
|
|
|
2000-04-17 11:13:57 +04:00
|
|
|
|
nsresult rv=CreateRenderingContext(rootFrame, &rcx);
|
2003-03-12 06:22:11 +03:00
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
2000-04-17 11:13:57 +04:00
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
if (GetVerifyReflowEnable()) {
|
|
|
|
|
if (VERIFY_REFLOW_ALL & gVerifyReflowFlags) {
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("ProcessReflowCommands: begin incremental reflow\n");
|
2000-04-17 11:13:57 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (VERIFY_REFLOW_DUMP_COMMANDS & gVerifyReflowFlags) {
|
|
|
|
|
PRInt32 i, n = mReflowCommands.Count();
|
2001-04-18 10:06:31 +04:00
|
|
|
|
printf("\nPresShell::ProcessReflowCommands: this=%p, count=%d\n", (void*)this, n);
|
2000-04-17 11:13:57 +04:00
|
|
|
|
for (i = 0; i < n; i++) {
|
2001-12-18 01:39:59 +03:00
|
|
|
|
nsHTMLReflowCommand* rc = (nsHTMLReflowCommand*)
|
2000-04-17 11:13:57 +04:00
|
|
|
|
mReflowCommands.ElementAt(i);
|
|
|
|
|
rc->List(stdout);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2002-05-10 22:22:41 +04:00
|
|
|
|
|
2006-04-28 08:33:41 +04:00
|
|
|
|
WillDoReflow();
|
|
|
|
|
|
2002-05-10 22:22:41 +04:00
|
|
|
|
// If reflow is interruptible, then make a note of our deadline.
|
2004-04-13 07:13:46 +04:00
|
|
|
|
const PRIntervalTime deadline = aInterruptible
|
|
|
|
|
? PR_IntervalNow() + PR_MicrosecondsToInterval(gMaxRCProcessingTime)
|
|
|
|
|
: (PRIntervalTime)0;
|
2002-05-10 22:22:41 +04:00
|
|
|
|
|
2003-09-14 16:07:11 +04:00
|
|
|
|
// force flushing of any pending notifications
|
2003-10-03 01:29:40 +04:00
|
|
|
|
mDocument->BeginUpdate(UPDATE_ALL);
|
|
|
|
|
mDocument->EndUpdate(UPDATE_ALL);
|
2003-09-14 16:07:11 +04:00
|
|
|
|
|
2006-04-19 01:48:12 +04:00
|
|
|
|
// Scope for the reflow entry point
|
|
|
|
|
{
|
|
|
|
|
AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Reflow);
|
|
|
|
|
mIsReflowing = PR_TRUE;
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
// Coalesce the reflow commands into a tree.
|
|
|
|
|
IncrementalReflow reflow;
|
|
|
|
|
for (PRInt32 i = mReflowCommands.Count() - 1; i >= 0; --i) {
|
|
|
|
|
nsHTMLReflowCommand *command =
|
|
|
|
|
NS_STATIC_CAST(nsHTMLReflowCommand *, mReflowCommands[i]);
|
|
|
|
|
|
|
|
|
|
IncrementalReflow::AddCommandResult res =
|
|
|
|
|
reflow.AddCommand(mPresContext, command);
|
|
|
|
|
if (res == IncrementalReflow::eEnqueued ||
|
|
|
|
|
res == IncrementalReflow::eCancel) {
|
|
|
|
|
// Remove the command from the queue.
|
|
|
|
|
mReflowCommands.RemoveElementAt(i);
|
|
|
|
|
ReflowCommandRemoved(command);
|
|
|
|
|
if (res == IncrementalReflow::eCancel)
|
|
|
|
|
delete command;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// The reflow command couldn't be added to the tree; leave
|
|
|
|
|
// it in the queue, and we'll handle it next time.
|
2002-06-26 01:21:48 +04:00
|
|
|
|
#ifdef DEBUG
|
2006-04-19 01:48:12 +04:00
|
|
|
|
printf("WARNING: Couldn't add reflow command, so splitting.\n");
|
2002-06-26 01:21:48 +04:00
|
|
|
|
#endif
|
2006-04-19 01:48:12 +04:00
|
|
|
|
}
|
2002-05-10 22:22:41 +04:00
|
|
|
|
}
|
|
|
|
|
|
2000-04-17 11:13:57 +04:00
|
|
|
|
#ifdef DEBUG
|
2006-04-19 01:48:12 +04:00
|
|
|
|
if (VERIFY_REFLOW_NOISY_RC & gVerifyReflowFlags) {
|
|
|
|
|
printf("Incremental reflow tree:\n");
|
|
|
|
|
reflow.Dump(mPresContext);
|
|
|
|
|
}
|
2000-04-17 11:13:57 +04:00
|
|
|
|
#endif
|
2002-05-10 22:22:41 +04:00
|
|
|
|
|
2006-04-19 01:48:12 +04:00
|
|
|
|
// Dispatch an incremental reflow.
|
|
|
|
|
reflow.Dispatch(mPresContext, desiredSize, maxSize, *rcx);
|
2002-05-10 22:22:41 +04:00
|
|
|
|
|
2006-04-19 01:48:12 +04:00
|
|
|
|
// Keep going until we're out of reflow commands, or we've run
|
|
|
|
|
// past our deadline.
|
|
|
|
|
} while (mReflowCommands.Count() &&
|
|
|
|
|
(!aInterruptible || PR_IntervalNow() < deadline));
|
2002-05-10 22:22:41 +04:00
|
|
|
|
|
2006-04-19 01:48:12 +04:00
|
|
|
|
// XXXwaterson for interruptible reflow, examine the tree and
|
|
|
|
|
// re-enqueue any unflowed reflow targets.
|
2002-05-10 22:22:41 +04:00
|
|
|
|
|
2006-04-19 01:48:12 +04:00
|
|
|
|
mIsReflowing = PR_FALSE;
|
|
|
|
|
}
|
2002-05-10 22:22:41 +04:00
|
|
|
|
|
2001-03-13 09:38:59 +03:00
|
|
|
|
NS_IF_RELEASE(rcx);
|
2002-05-10 22:22:41 +04:00
|
|
|
|
|
|
|
|
|
// If any new reflow commands were enqueued during the reflow,
|
|
|
|
|
// schedule another reflow event to process them.
|
|
|
|
|
if (mReflowCommands.Count())
|
|
|
|
|
PostReflowEvent();
|
2000-04-17 11:13:57 +04:00
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
if (VERIFY_REFLOW_DUMP_COMMANDS & gVerifyReflowFlags) {
|
2001-04-18 10:06:31 +04:00
|
|
|
|
printf("\nPresShell::ProcessReflowCommands() finished: this=%p\n", (void*)this);
|
2000-04-17 11:13:57 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nsIFrameDebug::GetVerifyTreeEnable()) {
|
|
|
|
|
nsIFrameDebug* frameDebug;
|
|
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rootFrame->QueryInterface(NS_GET_IID(nsIFrameDebug),
|
|
|
|
|
(void**)&frameDebug))) {
|
|
|
|
|
frameDebug->VerifyTree();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (GetVerifyReflowEnable()) {
|
|
|
|
|
// First synchronously render what we have so far so that we can
|
|
|
|
|
// see it.
|
2004-05-17 20:29:13 +04:00
|
|
|
|
nsIView* rootView;
|
|
|
|
|
mViewManager->GetRootView(rootView);
|
|
|
|
|
mViewManager->UpdateView(rootView, NS_VMREFRESH_IMMEDIATE);
|
2000-04-17 11:13:57 +04:00
|
|
|
|
|
|
|
|
|
mInVerifyReflow = PR_TRUE;
|
|
|
|
|
PRBool ok = VerifyIncrementalReflow();
|
|
|
|
|
mInVerifyReflow = PR_FALSE;
|
|
|
|
|
if (VERIFY_REFLOW_ALL & gVerifyReflowFlags) {
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("ProcessReflowCommands: finished (%s)\n",
|
2000-04-17 11:13:57 +04:00
|
|
|
|
ok ? "ok" : "failed");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (0 != mReflowCommands.Count()) {
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("XXX yikes! reflow commands queued during verify-reflow\n");
|
2000-04-17 11:13:57 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2001-05-30 23:28:37 +04:00
|
|
|
|
|
|
|
|
|
// If there are no more reflow commands in the queue, we'll want
|
2005-08-23 05:29:02 +04:00
|
|
|
|
// to unblock onload.
|
2001-05-30 23:28:37 +04:00
|
|
|
|
DoneRemovingReflowCommands();
|
2004-02-04 03:11:59 +03:00
|
|
|
|
|
|
|
|
|
DidDoReflow();
|
2000-04-17 11:13:57 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MOZ_TIMER_DEBUGLOG(("Stop: Reflow: PresShell::ProcessReflowCommands(), this=%p\n", this));
|
|
|
|
|
MOZ_TIMER_STOP(mReflowWatch);
|
|
|
|
|
|
2001-04-25 23:52:49 +04:00
|
|
|
|
if (mShouldUnsuppressPainting && mReflowCommands.Count() == 0) {
|
|
|
|
|
// We only unlock if we're out of reflows. It's pointless
|
|
|
|
|
// to unlock if reflows are still pending, since reflows
|
|
|
|
|
// are just going to thrash the frames around some more. By
|
|
|
|
|
// waiting we avoid an overeager "jitter" effect.
|
|
|
|
|
mShouldUnsuppressPainting = PR_FALSE;
|
|
|
|
|
UnsuppressAndInvalidate();
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-17 11:13:57 +04:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2006-05-10 21:30:15 +04:00
|
|
|
|
void
|
2002-07-26 07:29:07 +04:00
|
|
|
|
PresShell::ClearReflowEventStatus()
|
2000-04-17 11:13:57 +04:00
|
|
|
|
{
|
2006-05-10 21:30:15 +04:00
|
|
|
|
mReflowEvent.Forget();
|
2000-04-17 11:13:57 +04:00
|
|
|
|
}
|
|
|
|
|
|
2000-09-12 04:35:11 +04:00
|
|
|
|
nsresult
|
2001-12-18 01:39:59 +03:00
|
|
|
|
PresShell::ReflowCommandAdded(nsHTMLReflowCommand* aRC)
|
2000-09-12 04:35:11 +04:00
|
|
|
|
{
|
|
|
|
|
|
2006-04-19 19:08:44 +04:00
|
|
|
|
NS_PRECONDITION(mRCCreatedDuringLoad >= 0, "PresShell's reflow command queue is in a bad state.");
|
|
|
|
|
if (mDocumentLoading) {
|
|
|
|
|
aRC->AddFlagBits(NS_RC_CREATED_DURING_DOCUMENT_LOAD);
|
|
|
|
|
mRCCreatedDuringLoad++;
|
2000-09-12 04:35:11 +04:00
|
|
|
|
|
2001-04-14 03:24:25 +04:00
|
|
|
|
#ifdef PR_LOGGING
|
2006-04-19 19:08:44 +04:00
|
|
|
|
if (PR_LOG_TEST(gLog, PR_LOG_DEBUG)) {
|
|
|
|
|
nsIFrame* target;
|
|
|
|
|
aRC->GetTarget(target);
|
2001-04-14 03:24:25 +04:00
|
|
|
|
|
2006-04-19 19:08:44 +04:00
|
|
|
|
nsIAtom* type = target->GetType();
|
|
|
|
|
NS_ASSERTION(type, "frame didn't override GetType()");
|
2001-04-14 03:24:25 +04:00
|
|
|
|
|
2006-04-19 19:08:44 +04:00
|
|
|
|
nsAutoString typeStr(NS_LITERAL_STRING("unknown"));
|
|
|
|
|
if (type)
|
|
|
|
|
type->ToString(typeStr);
|
2001-04-14 03:24:25 +04:00
|
|
|
|
|
2006-04-19 19:08:44 +04:00
|
|
|
|
PR_LOG(gLog, PR_LOG_DEBUG,
|
|
|
|
|
("presshell=%p, ReflowCommandAdded(%p) target=%p[%s] mRCCreatedDuringLoad=%d\n",
|
|
|
|
|
this, aRC, target, NS_ConvertUTF16toUTF8(typeStr).get(), mRCCreatedDuringLoad));
|
|
|
|
|
}
|
2001-04-14 03:24:25 +04:00
|
|
|
|
#endif
|
|
|
|
|
|
2006-04-19 19:08:44 +04:00
|
|
|
|
if (!mDocumentOnloadBlocked) {
|
|
|
|
|
mDocument->BlockOnload();
|
|
|
|
|
mDocumentOnloadBlocked = PR_TRUE;
|
2000-09-12 12:59:01 +04:00
|
|
|
|
}
|
2000-09-12 04:35:11 +04:00
|
|
|
|
}
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult
|
2001-12-18 01:39:59 +03:00
|
|
|
|
PresShell::ReflowCommandRemoved(nsHTMLReflowCommand* aRC)
|
2000-09-12 04:35:11 +04:00
|
|
|
|
{
|
2004-05-02 22:07:12 +04:00
|
|
|
|
NS_PRECONDITION(mReflowCommandTable.ops, "How did that happen?");
|
|
|
|
|
|
|
|
|
|
PL_DHashTableOperate(&mReflowCommandTable, aRC, PL_DHASH_REMOVE);
|
|
|
|
|
|
2006-04-19 19:08:44 +04:00
|
|
|
|
NS_PRECONDITION(mRCCreatedDuringLoad >= 0, "PresShell's reflow command queue is in a bad state.");
|
|
|
|
|
if (aRC->GetFlagBits() & NS_RC_CREATED_DURING_DOCUMENT_LOAD) {
|
|
|
|
|
mRCCreatedDuringLoad--;
|
2001-04-14 03:24:25 +04:00
|
|
|
|
|
2006-04-19 19:08:44 +04:00
|
|
|
|
PR_LOG(gLog, PR_LOG_DEBUG,
|
|
|
|
|
("presshell=%p, ReflowCommandRemoved(%p) mRCCreatedDuringLoad=%d\n",
|
|
|
|
|
this, aRC, mRCCreatedDuringLoad));
|
2000-09-12 12:59:01 +04:00
|
|
|
|
}
|
2000-09-12 04:35:11 +04:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2001-03-14 10:47:00 +03:00
|
|
|
|
void
|
|
|
|
|
PresShell::DoneRemovingReflowCommands()
|
|
|
|
|
{
|
2005-08-23 05:29:02 +04:00
|
|
|
|
// We want to unblock here even if we're destroying, since onload
|
|
|
|
|
// can well fire with no presentation in sight. So just check
|
|
|
|
|
// whether we actually blocked onload.
|
|
|
|
|
if (mRCCreatedDuringLoad == 0 && mDocumentOnloadBlocked) {
|
2005-08-24 03:24:30 +04:00
|
|
|
|
mDocument->UnblockOnload(PR_FALSE);
|
2005-08-23 05:29:02 +04:00
|
|
|
|
mDocumentOnloadBlocked = PR_FALSE;
|
2000-09-12 12:59:01 +04:00
|
|
|
|
}
|
2000-09-12 04:35:11 +04:00
|
|
|
|
}
|
2000-04-17 11:13:57 +04:00
|
|
|
|
|
2004-07-18 05:16:27 +04:00
|
|
|
|
#ifdef MOZ_XUL
|
|
|
|
|
/*
|
|
|
|
|
* It's better to add stuff to the |DidSetStyleContext| method of the
|
|
|
|
|
* relevant frames than adding it here. These methods should (ideally,
|
|
|
|
|
* anyway) go away.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// Return value says whether to walk children.
|
|
|
|
|
typedef PRBool (* PR_CALLBACK frameWalkerFn)(nsIFrame *aFrame, void *aClosure);
|
|
|
|
|
|
|
|
|
|
PR_STATIC_CALLBACK(PRBool)
|
|
|
|
|
ReResolveMenusAndTrees(nsIFrame *aFrame, void *aClosure)
|
|
|
|
|
{
|
|
|
|
|
// Trees have a special style cache that needs to be flushed when
|
|
|
|
|
// the theme changes.
|
|
|
|
|
nsCOMPtr<nsITreeBoxObject> treeBox(do_QueryInterface(aFrame));
|
|
|
|
|
if (treeBox)
|
|
|
|
|
treeBox->ClearStyleAndImageCaches();
|
|
|
|
|
|
|
|
|
|
// We deliberately don't re-resolve style on a menu's popup
|
|
|
|
|
// sub-content, since doing so slows menus to a crawl. That means we
|
|
|
|
|
// have to special-case them on a skin switch, and ensure that the
|
|
|
|
|
// popup frames just get destroyed completely.
|
|
|
|
|
nsCOMPtr<nsIMenuFrame> menuFrame(do_QueryInterface(aFrame));
|
|
|
|
|
if (menuFrame) {
|
|
|
|
|
menuFrame->UngenerateMenu();
|
|
|
|
|
menuFrame->OpenMenu(PR_FALSE);
|
|
|
|
|
}
|
|
|
|
|
return PR_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2004-07-28 03:31:08 +04:00
|
|
|
|
PR_STATIC_CALLBACK(PRBool)
|
2004-12-02 04:26:20 +03:00
|
|
|
|
ReframeImageBoxes(nsIFrame *aFrame, void *aClosure)
|
|
|
|
|
{
|
|
|
|
|
nsStyleChangeList *list = NS_STATIC_CAST(nsStyleChangeList*, aClosure);
|
|
|
|
|
if (aFrame->GetType() == nsLayoutAtoms::imageBoxFrame) {
|
|
|
|
|
list->AppendChange(aFrame, aFrame->GetContent(),
|
|
|
|
|
NS_STYLE_HINT_FRAMECHANGE);
|
|
|
|
|
return PR_FALSE; // don't walk descendants
|
2004-07-28 03:31:08 +04:00
|
|
|
|
}
|
|
|
|
|
return PR_TRUE; // walk descendants
|
|
|
|
|
}
|
|
|
|
|
|
2004-07-18 05:16:27 +04:00
|
|
|
|
static void
|
2004-08-01 03:15:21 +04:00
|
|
|
|
WalkFramesThroughPlaceholders(nsPresContext *aPresContext, nsIFrame *aFrame,
|
2004-07-18 05:16:27 +04:00
|
|
|
|
frameWalkerFn aFunc, void *aClosure)
|
|
|
|
|
{
|
|
|
|
|
PRBool walkChildren = (*aFunc)(aFrame, aClosure);
|
|
|
|
|
if (!walkChildren)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
PRInt32 listIndex = 0;
|
|
|
|
|
nsIAtom* childList = nsnull;
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
nsIFrame *child = aFrame->GetFirstChild(childList);
|
|
|
|
|
while (child) {
|
|
|
|
|
if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
|
2005-04-14 19:30:35 +04:00
|
|
|
|
// only do frames that are in flow, and recur through the
|
|
|
|
|
// out-of-flows of placeholders.
|
|
|
|
|
WalkFramesThroughPlaceholders(aPresContext,
|
|
|
|
|
nsPlaceholderFrame::GetRealFrameFor(child),
|
|
|
|
|
aFunc, aClosure);
|
2004-07-18 05:16:27 +04:00
|
|
|
|
}
|
|
|
|
|
child = child->GetNextSibling();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
childList = aFrame->GetAdditionalChildListName(listIndex++);
|
|
|
|
|
} while (childList);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::Observe(nsISupports* aSubject,
|
|
|
|
|
const char* aTopic,
|
|
|
|
|
const PRUnichar* aData)
|
|
|
|
|
{
|
|
|
|
|
#ifdef MOZ_XUL
|
|
|
|
|
if (!nsCRT::strcmp(aTopic, "chrome-flush-skin-caches")) {
|
2004-09-02 07:08:51 +04:00
|
|
|
|
nsIFrame *rootFrame = FrameManager()->GetRootFrame();
|
2004-07-19 01:55:24 +04:00
|
|
|
|
// Need to null-check because "chrome-flush-skin-caches" can happen
|
|
|
|
|
// at interesting times during startup.
|
2004-07-28 03:31:08 +04:00
|
|
|
|
if (rootFrame) {
|
2004-10-09 05:39:21 +04:00
|
|
|
|
NS_ASSERTION(mViewManager, "View manager must exist");
|
|
|
|
|
mViewManager->BeginUpdateViewBatch();
|
|
|
|
|
|
2004-07-19 01:55:24 +04:00
|
|
|
|
WalkFramesThroughPlaceholders(mPresContext, rootFrame,
|
|
|
|
|
&ReResolveMenusAndTrees, nsnull);
|
2004-07-28 03:31:08 +04:00
|
|
|
|
|
2004-12-02 04:26:20 +03:00
|
|
|
|
// Because "chrome:" URL equality is messy, reframe image box
|
|
|
|
|
// frames (hack!).
|
|
|
|
|
nsStyleChangeList changeList;
|
2004-07-28 03:31:08 +04:00
|
|
|
|
WalkFramesThroughPlaceholders(mPresContext, rootFrame,
|
2004-12-02 04:26:20 +03:00
|
|
|
|
ReframeImageBoxes, &changeList);
|
2005-02-18 19:11:53 +03:00
|
|
|
|
mFrameConstructor->ProcessRestyledFrames(changeList);
|
2004-10-09 05:39:21 +04:00
|
|
|
|
|
|
|
|
|
mViewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
|
2005-06-10 17:57:27 +04:00
|
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
|
InvalidateAccessibleSubtree(nsnull);
|
|
|
|
|
#endif
|
2004-07-28 03:31:08 +04:00
|
|
|
|
}
|
2004-07-18 05:16:27 +04:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2005-08-11 00:21:44 +04:00
|
|
|
|
if (!nsCRT::strcmp(aTopic, NS_LINK_VISITED_EVENT_TOPIC)) {
|
|
|
|
|
nsCOMPtr<nsIURI> uri = do_QueryInterface(aSubject);
|
|
|
|
|
if (uri && mDocument) {
|
|
|
|
|
mDocument->NotifyURIVisitednessChanged(uri);
|
|
|
|
|
}
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2006-06-08 18:32:20 +04:00
|
|
|
|
if (!nsCRT::strcmp(aTopic, "agent-sheet-added") && mStyleSet) {
|
|
|
|
|
AddAgentSheet(aSubject);
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!nsCRT::strcmp(aTopic, "user-sheet-added") && mStyleSet) {
|
|
|
|
|
AddUserSheet(aSubject);
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!nsCRT::strcmp(aTopic, "agent-sheet-removed") && mStyleSet) {
|
|
|
|
|
RemoveSheet(nsStyleSet::eAgentSheet, aSubject);
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!nsCRT::strcmp(aTopic, "user-sheet-removed") && mStyleSet) {
|
|
|
|
|
RemoveSheet(nsStyleSet::eUserSheet, aSubject);
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2004-07-18 05:16:27 +04:00
|
|
|
|
NS_WARNING("unrecognized topic in PresShell::Observe");
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
2005-05-05 00:22:32 +04:00
|
|
|
|
void
|
|
|
|
|
PresShell::EnumeratePlugins(nsIDOMDocument *aDocument,
|
|
|
|
|
const nsString &aPluginTag,
|
|
|
|
|
nsPluginEnumCallback aCallback)
|
|
|
|
|
{
|
|
|
|
|
nsCOMPtr<nsIDOMNodeList> nodes;
|
|
|
|
|
aDocument->GetElementsByTagName(aPluginTag, getter_AddRefs(nodes));
|
|
|
|
|
if (!nodes)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
PRUint32 length;
|
|
|
|
|
nodes->GetLength(&length);
|
|
|
|
|
|
|
|
|
|
for (PRUint32 i = 0; i < length; ++i) {
|
|
|
|
|
nsCOMPtr<nsIDOMNode> node;
|
|
|
|
|
nodes->Item(i, getter_AddRefs(node));
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> content = do_QueryInterface(node);
|
|
|
|
|
if (content)
|
|
|
|
|
aCallback(this, content);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-17 11:13:57 +04:00
|
|
|
|
//------------------------------------------------------
|
|
|
|
|
// End of protected and private methods on the PresShell
|
|
|
|
|
//------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
// Start of DEBUG only code
|
|
|
|
|
|
1998-07-13 23:49:42 +04:00
|
|
|
|
#ifdef NS_DEBUG
|
|
|
|
|
#include "nsViewsCID.h"
|
|
|
|
|
#include "nsWidgetsCID.h"
|
|
|
|
|
#include "nsIDeviceContext.h"
|
|
|
|
|
#include "nsIURL.h"
|
1999-04-04 01:54:32 +04:00
|
|
|
|
#include "nsILinkHandler.h"
|
1998-07-13 23:49:42 +04:00
|
|
|
|
|
2000-01-04 23:24:09 +03:00
|
|
|
|
static NS_DEFINE_CID(kViewManagerCID, NS_VIEW_MANAGER_CID);
|
|
|
|
|
static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
|
1998-07-13 23:49:42 +04:00
|
|
|
|
|
|
|
|
|
static void
|
1998-11-25 21:41:02 +03:00
|
|
|
|
LogVerifyMessage(nsIFrame* k1, nsIFrame* k2, const char* aMsg)
|
|
|
|
|
{
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("verifyreflow: ");
|
1998-11-25 21:41:02 +03:00
|
|
|
|
nsAutoString name;
|
|
|
|
|
if (nsnull != k1) {
|
1999-11-02 01:12:45 +03:00
|
|
|
|
nsIFrameDebug* frameDebug;
|
|
|
|
|
|
2000-01-04 23:24:09 +03:00
|
|
|
|
if (NS_SUCCEEDED(k1->QueryInterface(NS_GET_IID(nsIFrameDebug),
|
|
|
|
|
(void**)&frameDebug))) {
|
1999-11-02 01:12:45 +03:00
|
|
|
|
frameDebug->GetFrameName(name);
|
|
|
|
|
}
|
1998-11-25 21:41:02 +03:00
|
|
|
|
}
|
|
|
|
|
else {
|
2001-10-11 05:30:52 +04:00
|
|
|
|
name.Assign(NS_LITERAL_STRING("(null)"));
|
1998-11-25 21:41:02 +03:00
|
|
|
|
}
|
2006-02-03 17:18:39 +03:00
|
|
|
|
fputs(NS_LossyConvertUTF16toASCII(name).get(), stdout);
|
2000-10-29 02:17:53 +04:00
|
|
|
|
|
|
|
|
|
printf(" != ");
|
1998-11-25 21:41:02 +03:00
|
|
|
|
|
|
|
|
|
if (nsnull != k2) {
|
1999-11-02 01:12:45 +03:00
|
|
|
|
nsIFrameDebug* frameDebug;
|
|
|
|
|
|
2000-01-04 23:24:09 +03:00
|
|
|
|
if (NS_SUCCEEDED(k2->QueryInterface(NS_GET_IID(nsIFrameDebug),
|
|
|
|
|
(void**)&frameDebug))) {
|
1999-11-02 01:12:45 +03:00
|
|
|
|
frameDebug->GetFrameName(name);
|
|
|
|
|
}
|
1998-11-25 21:41:02 +03:00
|
|
|
|
}
|
|
|
|
|
else {
|
2001-10-11 05:30:52 +04:00
|
|
|
|
name.Assign(NS_LITERAL_STRING("(null)"));
|
1998-11-25 21:41:02 +03:00
|
|
|
|
}
|
2006-02-03 17:18:39 +03:00
|
|
|
|
fputs(NS_LossyConvertUTF16toASCII(name).get(), stdout);
|
1998-11-25 21:41:02 +03:00
|
|
|
|
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf(" %s", aMsg);
|
1998-11-25 21:41:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
LogVerifyMessage(nsIFrame* k1, nsIFrame* k2, const char* aMsg,
|
|
|
|
|
const nsRect& r1, const nsRect& r2)
|
1998-07-13 23:49:42 +04:00
|
|
|
|
{
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("VerifyReflow Error:\n");
|
1998-11-19 20:22:29 +03:00
|
|
|
|
nsAutoString name;
|
1999-11-02 01:12:45 +03:00
|
|
|
|
nsIFrameDebug* frameDebug;
|
|
|
|
|
|
2000-01-04 23:24:09 +03:00
|
|
|
|
if (NS_SUCCEEDED(k1->QueryInterface(NS_GET_IID(nsIFrameDebug),
|
|
|
|
|
(void**)&frameDebug))) {
|
2000-10-29 02:17:53 +04:00
|
|
|
|
fprintf(stdout, " ");
|
1999-11-02 01:12:45 +03:00
|
|
|
|
frameDebug->GetFrameName(name);
|
2006-02-03 17:18:39 +03:00
|
|
|
|
fputs(NS_LossyConvertUTF16toASCII(name).get(), stdout);
|
2001-04-18 10:06:31 +04:00
|
|
|
|
fprintf(stdout, " %p ", (void*)k1);
|
1999-11-02 01:12:45 +03:00
|
|
|
|
}
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("{%d, %d, %d, %d}", r1.x, r1.y, r1.width, r1.height);
|
1998-11-25 21:41:02 +03:00
|
|
|
|
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf(" != \n");
|
1998-11-25 21:41:02 +03:00
|
|
|
|
|
2000-01-04 23:24:09 +03:00
|
|
|
|
if (NS_SUCCEEDED(k2->QueryInterface(NS_GET_IID(nsIFrameDebug),
|
|
|
|
|
(void**)&frameDebug))) {
|
2000-10-29 02:17:53 +04:00
|
|
|
|
fprintf(stdout, " ");
|
1999-11-02 01:12:45 +03:00
|
|
|
|
frameDebug->GetFrameName(name);
|
2006-02-03 17:18:39 +03:00
|
|
|
|
fputs(NS_LossyConvertUTF16toASCII(name).get(), stdout);
|
2001-04-18 10:06:31 +04:00
|
|
|
|
fprintf(stdout, " %p ", (void*)k2);
|
1999-11-02 01:12:45 +03:00
|
|
|
|
}
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("{%d, %d, %d, %d}\n", r2.x, r2.y, r2.width, r2.height);
|
1998-11-25 21:41:02 +03:00
|
|
|
|
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf(" %s\n", aMsg);
|
1998-07-13 23:49:42 +04:00
|
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
|
|
1999-04-03 22:58:04 +04:00
|
|
|
|
static PRBool
|
2004-08-01 03:15:21 +04:00
|
|
|
|
CompareTrees(nsPresContext* aFirstPresContext, nsIFrame* aFirstFrame,
|
|
|
|
|
nsPresContext* aSecondPresContext, nsIFrame* aSecondFrame)
|
1998-04-14 00:24:54 +04:00
|
|
|
|
{
|
2000-03-23 02:19:10 +03:00
|
|
|
|
if (!aFirstPresContext || !aFirstFrame || !aSecondPresContext || !aSecondFrame)
|
|
|
|
|
return PR_TRUE;
|
1999-04-03 22:58:04 +04:00
|
|
|
|
PRBool ok = PR_TRUE;
|
1998-11-25 21:41:02 +03:00
|
|
|
|
nsIAtom* listName = nsnull;
|
|
|
|
|
PRInt32 listIndex = 0;
|
|
|
|
|
do {
|
2004-01-09 17:20:53 +03:00
|
|
|
|
nsIFrame* k1 = aFirstFrame->GetFirstChild(listName);
|
|
|
|
|
nsIFrame* k2 = aSecondFrame->GetFirstChild(listName);
|
1998-11-25 21:41:02 +03:00
|
|
|
|
PRInt32 l1 = nsContainerFrame::LengthOf(k1);
|
|
|
|
|
PRInt32 l2 = nsContainerFrame::LengthOf(k2);
|
|
|
|
|
if (l1 != l2) {
|
1999-04-03 22:58:04 +04:00
|
|
|
|
ok = PR_FALSE;
|
1998-11-25 21:41:02 +03:00
|
|
|
|
LogVerifyMessage(k1, k2, "child counts don't match: ");
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("%d != %d\n", l1, l2);
|
1999-09-10 22:49:23 +04:00
|
|
|
|
if (0 == (VERIFY_REFLOW_ALL & gVerifyReflowFlags)) {
|
1998-11-25 21:41:02 +03:00
|
|
|
|
break;
|
1998-07-13 23:49:42 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1998-11-25 21:41:02 +03:00
|
|
|
|
nsRect r1, r2;
|
|
|
|
|
nsIView* v1, *v2;
|
|
|
|
|
for (;;) {
|
|
|
|
|
if (((nsnull == k1) && (nsnull != k2)) ||
|
|
|
|
|
((nsnull != k1) && (nsnull == k2))) {
|
1999-04-03 22:58:04 +04:00
|
|
|
|
ok = PR_FALSE;
|
1998-11-25 21:41:02 +03:00
|
|
|
|
LogVerifyMessage(k1, k2, "child lists are different\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if (nsnull != k1) {
|
|
|
|
|
// Verify that the frames are the same size
|
2003-06-30 14:46:59 +04:00
|
|
|
|
if (k1->GetRect() != k2->GetRect()) {
|
1999-04-03 22:58:04 +04:00
|
|
|
|
ok = PR_FALSE;
|
2003-06-30 14:46:59 +04:00
|
|
|
|
LogVerifyMessage(k1, k2, "(frame rects)", k1->GetRect(), k2->GetRect());
|
1998-11-25 21:41:02 +03:00
|
|
|
|
}
|
1998-07-13 23:49:42 +04:00
|
|
|
|
|
1998-11-25 21:41:02 +03:00
|
|
|
|
// Make sure either both have views or neither have views; if they
|
|
|
|
|
// do have views, make sure the views are the same size. If the
|
|
|
|
|
// views have widgets, make sure they both do or neither does. If
|
|
|
|
|
// they do, make sure the widgets are the same size.
|
2003-06-30 14:46:59 +04:00
|
|
|
|
v1 = k1->GetView();
|
|
|
|
|
v2 = k2->GetView();
|
1998-11-25 21:41:02 +03:00
|
|
|
|
if (((nsnull == v1) && (nsnull != v2)) ||
|
|
|
|
|
((nsnull != v1) && (nsnull == v2))) {
|
1999-04-03 22:58:04 +04:00
|
|
|
|
ok = PR_FALSE;
|
1998-11-25 21:41:02 +03:00
|
|
|
|
LogVerifyMessage(k1, k2, "child views are not matched\n");
|
|
|
|
|
}
|
|
|
|
|
else if (nsnull != v1) {
|
2003-06-30 14:46:59 +04:00
|
|
|
|
if (v1->GetBounds() != v2->GetBounds()) {
|
|
|
|
|
LogVerifyMessage(k1, k2, "(view rects)", v1->GetBounds(), v2->GetBounds());
|
1998-11-25 21:41:02 +03:00
|
|
|
|
}
|
1998-07-13 23:49:42 +04:00
|
|
|
|
|
2003-06-30 14:46:59 +04:00
|
|
|
|
nsIWidget* w1 = v1->GetWidget();
|
|
|
|
|
nsIWidget* w2 = v2->GetWidget();
|
1998-11-25 21:41:02 +03:00
|
|
|
|
if (((nsnull == w1) && (nsnull != w2)) ||
|
|
|
|
|
((nsnull != w1) && (nsnull == w2))) {
|
1999-04-03 22:58:04 +04:00
|
|
|
|
ok = PR_FALSE;
|
1998-11-25 21:41:02 +03:00
|
|
|
|
LogVerifyMessage(k1, k2, "child widgets are not matched\n");
|
|
|
|
|
}
|
|
|
|
|
else if (nsnull != w1) {
|
|
|
|
|
w1->GetBounds(r1);
|
|
|
|
|
w2->GetBounds(r2);
|
|
|
|
|
if (r1 != r2) {
|
|
|
|
|
LogVerifyMessage(k1, k2, "(widget rects)", r1, r2);
|
|
|
|
|
}
|
1998-07-13 23:49:42 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
1999-09-10 22:49:23 +04:00
|
|
|
|
if (!ok && (0 == (VERIFY_REFLOW_ALL & gVerifyReflowFlags))) {
|
1998-11-25 21:41:02 +03:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2000-03-23 02:19:10 +03:00
|
|
|
|
// verify that neither frame has a space manager,
|
|
|
|
|
// or they both do and the space managers are equivalent
|
2004-08-24 22:50:29 +04:00
|
|
|
|
nsSpaceManager *sm1 = NS_STATIC_CAST(nsSpaceManager*,
|
|
|
|
|
k1->GetProperty(nsLayoutAtoms::spaceManagerProperty));
|
2004-02-24 00:29:06 +03:00
|
|
|
|
|
2000-03-23 02:19:10 +03:00
|
|
|
|
// look at the test frame
|
2004-08-24 22:50:29 +04:00
|
|
|
|
nsSpaceManager *sm2 = NS_STATIC_CAST(nsSpaceManager*,
|
|
|
|
|
k2->GetProperty(nsLayoutAtoms::spaceManagerProperty));
|
2004-02-24 00:29:06 +03:00
|
|
|
|
|
2000-03-23 02:19:10 +03:00
|
|
|
|
// now compare the space managers
|
|
|
|
|
if (((nsnull == sm1) && (nsnull != sm2)) ||
|
|
|
|
|
((nsnull != sm1) && (nsnull == sm2))) { // one is null, and the other is not
|
|
|
|
|
ok = PR_FALSE;
|
|
|
|
|
LogVerifyMessage(k1, k2, "space managers are not matched\n");
|
|
|
|
|
}
|
|
|
|
|
else if (sm1 && sm2) { // both are not null, compare them
|
|
|
|
|
// first, compare yMost
|
|
|
|
|
nscoord yMost1, yMost2;
|
|
|
|
|
nsresult smresult = sm1->YMost(yMost1);
|
|
|
|
|
if (NS_ERROR_ABORT != smresult)
|
|
|
|
|
{
|
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(smresult), "bad result");
|
|
|
|
|
smresult = sm2->YMost(yMost2);
|
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(smresult), "bad result");
|
|
|
|
|
if (yMost1 != yMost2) {
|
|
|
|
|
LogVerifyMessage(k1, k2, "yMost of space managers differs\n");
|
|
|
|
|
}
|
|
|
|
|
// now compare bands by sampling
|
|
|
|
|
PRInt32 yIncrement = yMost1/100;
|
|
|
|
|
if (0==yIncrement) {
|
|
|
|
|
yIncrement = 1; // guarantee we make progress in the loop below
|
|
|
|
|
}
|
|
|
|
|
nscoord yOffset = 0;
|
|
|
|
|
for ( ; ok && yOffset < yMost1; yOffset += yIncrement)
|
|
|
|
|
{
|
|
|
|
|
nscoord small=5, large=100;
|
|
|
|
|
nsBandData band1, band2;
|
|
|
|
|
nsBandTrapezoid trap1[20], trap2[20];
|
|
|
|
|
band1.mSize = band2.mSize = 20;
|
|
|
|
|
band1.mTrapezoids = trap1;
|
|
|
|
|
band2.mTrapezoids = trap2;
|
|
|
|
|
sm1->GetBandData(yOffset, nsSize(small,small), band1);
|
|
|
|
|
sm2->GetBandData(yOffset, nsSize(small,small), band2);
|
|
|
|
|
if (band1.mCount != band2.mCount)
|
|
|
|
|
{ // count mismatch, stop comparing
|
|
|
|
|
LogVerifyMessage(k1, k2, "band.mCount of space managers differs\n");
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("count1= %d, count2=%d, yOffset = %d, size=%d\n",
|
|
|
|
|
band1.mCount, band2.mCount, yOffset, small);
|
2000-03-23 02:19:10 +03:00
|
|
|
|
ok = PR_FALSE;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else // band counts match, compare individual traps
|
|
|
|
|
{
|
|
|
|
|
PRInt32 trapIndex=0;
|
|
|
|
|
for ( ;trapIndex<band1.mCount; trapIndex++)
|
|
|
|
|
{
|
|
|
|
|
PRBool match = (trap1[trapIndex].EqualGeometry(trap2[trapIndex])) &&
|
|
|
|
|
trap1[trapIndex].mState == trap2[trapIndex].mState;
|
|
|
|
|
if (!match)
|
|
|
|
|
{
|
|
|
|
|
LogVerifyMessage(k1, k2, "band.mTrapezoids of space managers differs\n");
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf ("index %d\n", trapIndex);
|
2000-03-23 02:19:10 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// test the larger maxSize
|
|
|
|
|
sm1->GetBandData(yOffset, nsSize(large,large), band1);
|
|
|
|
|
sm2->GetBandData(yOffset, nsSize(large,large), band2);
|
|
|
|
|
if (band1.mCount != band2.mCount)
|
|
|
|
|
{ // count mismatch, stop comparing
|
|
|
|
|
LogVerifyMessage(k1, k2, "band.mCount of space managers differs\n");
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("count1= %d, count2=%d, yOffset = %d, size=%d\n",
|
2000-03-23 02:19:10 +03:00
|
|
|
|
band1.mCount, band2.mCount, yOffset, small);
|
|
|
|
|
ok = PR_FALSE;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else // band counts match, compare individual traps
|
|
|
|
|
{
|
|
|
|
|
PRInt32 trapIndex=0;
|
|
|
|
|
for ( ; trapIndex<band1.mCount; trapIndex++)
|
|
|
|
|
{
|
|
|
|
|
PRBool match = (trap1[trapIndex].EqualGeometry(trap2[trapIndex])) &&
|
|
|
|
|
trap1[trapIndex].mState == trap2[trapIndex].mState;
|
|
|
|
|
if (!match)
|
|
|
|
|
{
|
|
|
|
|
LogVerifyMessage(k1, k2, "band.mTrapezoids of space managers differs\n");
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf ("index %d\n", trapIndex);
|
2000-03-23 02:19:10 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1998-11-25 21:41:02 +03:00
|
|
|
|
// Compare the sub-trees too
|
2000-03-17 04:50:54 +03:00
|
|
|
|
if (!CompareTrees(aFirstPresContext, k1, aSecondPresContext, k2)) {
|
1999-09-10 22:49:23 +04:00
|
|
|
|
ok = PR_FALSE;
|
|
|
|
|
if (0 == (VERIFY_REFLOW_ALL & gVerifyReflowFlags)) {
|
1999-04-03 22:58:04 +04:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
1998-11-25 21:41:02 +03:00
|
|
|
|
|
|
|
|
|
// Advance to next sibling
|
2003-06-30 14:46:59 +04:00
|
|
|
|
k1 = k1->GetNextSibling();
|
|
|
|
|
k2 = k2->GetNextSibling();
|
1998-07-13 23:49:42 +04:00
|
|
|
|
}
|
|
|
|
|
else {
|
1998-11-25 21:41:02 +03:00
|
|
|
|
break;
|
1998-07-13 23:49:42 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
1999-09-10 22:49:23 +04:00
|
|
|
|
if (!ok && (0 == (VERIFY_REFLOW_ALL & gVerifyReflowFlags))) {
|
1998-11-25 21:41:02 +03:00
|
|
|
|
break;
|
1998-07-13 23:49:42 +04:00
|
|
|
|
}
|
1998-11-25 21:41:02 +03:00
|
|
|
|
|
2004-01-09 17:20:53 +03:00
|
|
|
|
nsIAtom* listName1 = aFirstFrame->GetAdditionalChildListName(listIndex);
|
|
|
|
|
nsIAtom* listName2 = aSecondFrame->GetAdditionalChildListName(listIndex);
|
1998-11-25 21:41:02 +03:00
|
|
|
|
listIndex++;
|
|
|
|
|
if (listName1 != listName2) {
|
1999-09-10 22:49:23 +04:00
|
|
|
|
if (0 == (VERIFY_REFLOW_ALL & gVerifyReflowFlags)) {
|
|
|
|
|
ok = PR_FALSE;
|
|
|
|
|
}
|
1998-11-25 21:41:02 +03:00
|
|
|
|
LogVerifyMessage(k1, k2, "child list names are not matched: ");
|
|
|
|
|
nsAutoString tmp;
|
|
|
|
|
if (nsnull != listName1) {
|
|
|
|
|
listName1->ToString(tmp);
|
2006-02-03 17:18:39 +03:00
|
|
|
|
fputs(NS_LossyConvertUTF16toASCII(tmp).get(), stdout);
|
1998-11-25 21:41:02 +03:00
|
|
|
|
}
|
|
|
|
|
else
|
2000-10-29 02:17:53 +04:00
|
|
|
|
fputs("(null)", stdout);
|
|
|
|
|
printf(" != ");
|
1998-11-25 21:41:02 +03:00
|
|
|
|
if (nsnull != listName2) {
|
|
|
|
|
listName2->ToString(tmp);
|
2006-02-03 17:18:39 +03:00
|
|
|
|
fputs(NS_LossyConvertUTF16toASCII(tmp).get(), stdout);
|
1998-11-25 21:41:02 +03:00
|
|
|
|
}
|
|
|
|
|
else
|
2000-10-29 02:17:53 +04:00
|
|
|
|
fputs("(null)", stdout);
|
|
|
|
|
printf("\n");
|
1998-11-25 21:41:02 +03:00
|
|
|
|
break;
|
1998-07-13 23:49:42 +04:00
|
|
|
|
}
|
1998-11-25 21:41:02 +03:00
|
|
|
|
listName = listName1;
|
1999-04-03 22:58:04 +04:00
|
|
|
|
} while (ok && (listName != nsnull));
|
|
|
|
|
|
|
|
|
|
return ok;
|
|
|
|
|
}
|
1999-11-02 01:12:45 +03:00
|
|
|
|
#endif
|
1999-04-03 22:58:04 +04:00
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
static nsIFrame*
|
|
|
|
|
FindTopFrame(nsIFrame* aRoot)
|
|
|
|
|
{
|
2003-06-30 14:46:59 +04:00
|
|
|
|
if (aRoot) {
|
|
|
|
|
nsIContent* content = aRoot->GetContent();
|
|
|
|
|
if (content) {
|
1999-04-03 22:58:04 +04:00
|
|
|
|
nsIAtom* tag;
|
|
|
|
|
content->GetTag(tag);
|
|
|
|
|
if (nsnull != tag) {
|
|
|
|
|
NS_RELEASE(tag);
|
|
|
|
|
return aRoot;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Try one of the children
|
2004-01-09 17:20:53 +03:00
|
|
|
|
nsIFrame* kid = aRoot->GetFirstChild(nsnull);
|
1999-04-03 22:58:04 +04:00
|
|
|
|
while (nsnull != kid) {
|
|
|
|
|
nsIFrame* result = FindTopFrame(kid);
|
|
|
|
|
if (nsnull != result) {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2003-06-30 14:46:59 +04:00
|
|
|
|
kid = kid->GetNextSibling();
|
1999-04-03 22:58:04 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nsnull;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
1998-07-13 23:49:42 +04:00
|
|
|
|
|
1999-11-02 01:12:45 +03:00
|
|
|
|
#ifdef DEBUG
|
2004-01-08 01:30:53 +03:00
|
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
|
PresShell::CloneStyleSet(nsStyleSet* aSet, nsStyleSet** aResult)
|
|
|
|
|
{
|
|
|
|
|
nsStyleSet *clone = new nsStyleSet();
|
|
|
|
|
if (!clone) {
|
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PRInt32 i, n = aSet->SheetCount(nsStyleSet::eOverrideSheet);
|
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
|
nsIStyleSheet* ss = aSet->StyleSheetAt(nsStyleSet::eOverrideSheet, i);
|
|
|
|
|
if (ss)
|
|
|
|
|
clone->AppendStyleSheet(nsStyleSet::eOverrideSheet, ss);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
n = aSet->SheetCount(nsStyleSet::eDocSheet);
|
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
|
nsIStyleSheet* ss = aSet->StyleSheetAt(nsStyleSet::eDocSheet, i);
|
|
|
|
|
if (ss)
|
|
|
|
|
clone->AddDocStyleSheet(ss, mDocument);
|
|
|
|
|
}
|
|
|
|
|
n = aSet->SheetCount(nsStyleSet::eUserSheet);
|
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
|
nsIStyleSheet* ss = aSet->StyleSheetAt(nsStyleSet::eUserSheet, i);
|
|
|
|
|
if (ss)
|
|
|
|
|
clone->AppendStyleSheet(nsStyleSet::eUserSheet, ss);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
n = aSet->SheetCount(nsStyleSet::eAgentSheet);
|
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
|
nsIStyleSheet* ss = aSet->StyleSheetAt(nsStyleSet::eAgentSheet, i);
|
|
|
|
|
if (ss)
|
|
|
|
|
clone->AppendStyleSheet(nsStyleSet::eAgentSheet, ss);
|
|
|
|
|
}
|
|
|
|
|
*aResult = clone;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
1998-07-13 23:49:42 +04:00
|
|
|
|
// After an incremental reflow, we verify the correctness by doing a
|
|
|
|
|
// full reflow into a fresh frame tree.
|
1999-09-10 22:49:23 +04:00
|
|
|
|
PRBool
|
1998-07-13 23:49:42 +04:00
|
|
|
|
PresShell::VerifyIncrementalReflow()
|
|
|
|
|
{
|
2000-04-17 18:40:46 +04:00
|
|
|
|
if (VERIFY_REFLOW_NOISY & gVerifyReflowFlags) {
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("Building Verification Tree...\n");
|
2000-04-17 18:40:46 +04:00
|
|
|
|
}
|
1998-07-13 23:49:42 +04:00
|
|
|
|
// All the stuff we are creating that needs releasing
|
2004-08-01 03:15:21 +04:00
|
|
|
|
nsPresContext* cx;
|
1998-07-13 23:49:42 +04:00
|
|
|
|
nsIViewManager* vm;
|
|
|
|
|
nsIPresShell* sh;
|
|
|
|
|
|
|
|
|
|
// Create a presentation context to view the new frame tree
|
2006-05-19 14:26:44 +04:00
|
|
|
|
NS_IF_ADDREF(cx = new nsPresContext(mDocument,
|
|
|
|
|
mPresContext->IsPaginated() ?
|
2004-08-01 03:15:21 +04:00
|
|
|
|
nsPresContext::eContext_PrintPreview :
|
|
|
|
|
nsPresContext::eContext_Galley));
|
2004-07-29 23:41:39 +04:00
|
|
|
|
|
|
|
|
|
if (!cx)
|
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2000-04-17 11:13:57 +04:00
|
|
|
|
|
2004-02-01 13:09:07 +03:00
|
|
|
|
nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
|
|
|
|
|
if (container) {
|
1999-04-03 22:58:04 +04:00
|
|
|
|
cx->SetContainer(container);
|
2004-02-01 13:09:07 +03:00
|
|
|
|
nsCOMPtr<nsILinkHandler> lh = do_QueryInterface(container);
|
|
|
|
|
if (lh) {
|
1999-04-04 01:54:32 +04:00
|
|
|
|
cx->SetLinkHandler(lh);
|
|
|
|
|
}
|
1999-04-03 22:58:04 +04:00
|
|
|
|
}
|
2000-04-17 11:13:57 +04:00
|
|
|
|
|
2004-02-03 01:17:21 +03:00
|
|
|
|
nsIDeviceContext *dc = mPresContext->DeviceContext();
|
2004-07-29 23:41:39 +04:00
|
|
|
|
nsresult rv = cx->Init(dc);
|
2004-01-21 12:35:59 +03:00
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
1998-07-13 23:49:42 +04:00
|
|
|
|
|
2004-05-17 20:29:13 +04:00
|
|
|
|
// Get our scrolling preference
|
|
|
|
|
nsIView* rootView;
|
|
|
|
|
mViewManager->GetRootView(rootView);
|
|
|
|
|
void* nativeParentWidget = rootView->GetWidget()->GetNativeData(NS_NATIVE_WIDGET);
|
1998-07-13 23:49:42 +04:00
|
|
|
|
|
|
|
|
|
// Create a new view manager.
|
2004-11-01 21:50:36 +03:00
|
|
|
|
rv = CallCreateInstance(kViewManagerCID, &vm);
|
2003-03-12 06:22:11 +03:00
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED (rv), "failed to create view manager");
|
2004-05-17 20:29:13 +04:00
|
|
|
|
rv = vm->Init(dc);
|
2003-03-12 06:22:11 +03:00
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED (rv), "failed to init view manager");
|
1998-08-28 06:54:06 +04:00
|
|
|
|
|
1998-07-13 23:49:42 +04:00
|
|
|
|
// Create a child window of the parent that is our "root view/window"
|
|
|
|
|
// Create a view
|
2004-02-01 13:09:07 +03:00
|
|
|
|
nsRect tbounds = mPresContext->GetVisibleArea();
|
2004-11-04 18:06:50 +03:00
|
|
|
|
nsIView* view = vm->CreateView(tbounds, nsnull);
|
|
|
|
|
NS_ASSERTION(view, "failed to create view");
|
|
|
|
|
if (!view)
|
|
|
|
|
return PR_FALSE;
|
1998-11-04 07:14:10 +03:00
|
|
|
|
|
|
|
|
|
//now create the widget for the view
|
2004-05-17 20:29:13 +04:00
|
|
|
|
rv = view->CreateWidget(kWidgetCID, nsnull, nativeParentWidget, PR_TRUE);
|
2003-03-12 06:22:11 +03:00
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to create scroll view widget");
|
1998-11-04 07:14:10 +03:00
|
|
|
|
|
2004-05-17 20:29:13 +04:00
|
|
|
|
// Setup hierarchical relationship in view manager
|
|
|
|
|
vm->SetRootView(view);
|
|
|
|
|
|
1998-07-13 23:49:42 +04:00
|
|
|
|
// Make the new presentation context the same size as our
|
|
|
|
|
// presentation context.
|
2004-02-01 13:09:07 +03:00
|
|
|
|
nsRect r = mPresContext->GetVisibleArea();
|
1998-07-13 23:49:42 +04:00
|
|
|
|
cx->SetVisibleArea(r);
|
1999-04-03 22:58:04 +04:00
|
|
|
|
|
1998-11-25 21:41:02 +03:00
|
|
|
|
// Create a new presentation shell to view the document. Use the
|
|
|
|
|
// exact same style information that this document has.
|
2004-01-08 22:23:12 +03:00
|
|
|
|
nsAutoPtr<nsStyleSet> newSet;
|
2004-01-09 00:10:33 +03:00
|
|
|
|
rv = CloneStyleSet(mStyleSet, getter_Transfers(newSet));
|
1999-04-03 22:58:04 +04:00
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to clone style set");
|
|
|
|
|
rv = mDocument->CreateShell(cx, vm, newSet, &sh);
|
2000-03-17 04:50:54 +03:00
|
|
|
|
sh->SetVerifyReflowEnable(PR_FALSE); // turn off verify reflow while we're reflowing the test frame tree
|
2003-03-12 06:22:11 +03:00
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED (rv), "failed to create presentation shell");
|
1999-04-03 22:58:04 +04:00
|
|
|
|
vm->SetViewObserver((nsIViewObserver *)((PresShell*)sh));
|
2006-05-15 21:51:35 +04:00
|
|
|
|
rv = sh->InitialReflow(r.width, r.height);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2000-03-17 04:50:54 +03:00
|
|
|
|
sh->SetVerifyReflowEnable(PR_TRUE); // turn on verify reflow again now that we're done reflowing the test frame tree
|
2000-04-17 18:40:46 +04:00
|
|
|
|
if (VERIFY_REFLOW_NOISY & gVerifyReflowFlags) {
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("Verification Tree built, comparing...\n");
|
2000-04-17 18:40:46 +04:00
|
|
|
|
}
|
1998-07-13 23:49:42 +04:00
|
|
|
|
|
|
|
|
|
// Now that the document has been reflowed, use its frame tree to
|
|
|
|
|
// compare against our frame tree.
|
2004-03-06 07:46:11 +03:00
|
|
|
|
nsIFrame* root1 = FrameManager()->GetRootFrame();
|
2004-09-02 07:08:51 +04:00
|
|
|
|
nsIFrame* root2 = sh->FrameManager()->GetRootFrame();
|
2000-03-17 04:50:54 +03:00
|
|
|
|
PRBool ok = CompareTrees(mPresContext, root1, cx, root2);
|
1999-09-10 22:49:23 +04:00
|
|
|
|
if (!ok && (VERIFY_REFLOW_NOISY & gVerifyReflowFlags)) {
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("Verify reflow failed, primary tree:\n");
|
1999-11-02 01:12:45 +03:00
|
|
|
|
nsIFrameDebug* frameDebug;
|
|
|
|
|
|
2000-01-04 23:24:09 +03:00
|
|
|
|
if (NS_SUCCEEDED(root1->QueryInterface(NS_GET_IID(nsIFrameDebug),
|
|
|
|
|
(void**)&frameDebug))) {
|
2005-09-07 01:34:50 +04:00
|
|
|
|
frameDebug->List(stdout, 0);
|
1999-11-02 01:12:45 +03:00
|
|
|
|
}
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("Verification tree:\n");
|
2000-01-04 23:24:09 +03:00
|
|
|
|
if (NS_SUCCEEDED(root2->QueryInterface(NS_GET_IID(nsIFrameDebug),
|
|
|
|
|
(void**)&frameDebug))) {
|
2005-09-07 01:34:50 +04:00
|
|
|
|
frameDebug->List(stdout, 0);
|
1999-11-02 01:12:45 +03:00
|
|
|
|
}
|
1999-04-03 22:58:04 +04:00
|
|
|
|
}
|
1998-07-13 23:49:42 +04:00
|
|
|
|
|
1999-04-03 22:58:04 +04:00
|
|
|
|
cx->SetContainer(nsnull);
|
1998-07-13 23:49:42 +04:00
|
|
|
|
NS_RELEASE(cx);
|
1999-04-03 22:58:04 +04:00
|
|
|
|
sh->EndObservingDocument();
|
1998-07-13 23:49:42 +04:00
|
|
|
|
NS_RELEASE(sh);
|
1999-04-03 22:58:04 +04:00
|
|
|
|
NS_RELEASE(vm);
|
2000-04-17 18:40:46 +04:00
|
|
|
|
if (VERIFY_REFLOW_NOISY & gVerifyReflowFlags) {
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("Finished Verifying Reflow...\n");
|
2000-04-17 18:40:46 +04:00
|
|
|
|
}
|
1999-09-10 22:49:23 +04:00
|
|
|
|
|
|
|
|
|
return ok;
|
1998-07-13 23:49:42 +04:00
|
|
|
|
}
|
2004-01-08 01:30:53 +03:00
|
|
|
|
|
|
|
|
|
// Layout debugging hooks
|
|
|
|
|
void
|
|
|
|
|
PresShell::ListStyleContexts(nsIFrame *aRootFrame, FILE *out, PRInt32 aIndent)
|
|
|
|
|
{
|
|
|
|
|
nsStyleContext *sc = aRootFrame->GetStyleContext();
|
|
|
|
|
if (sc)
|
|
|
|
|
sc->List(out, aIndent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PresShell::ListStyleSheets(FILE *out, PRInt32 aIndent)
|
|
|
|
|
{
|
|
|
|
|
PRInt32 sheetCount = mStyleSet->SheetCount(nsStyleSet::eDocSheet);
|
|
|
|
|
for (PRInt32 i = 0; i < sheetCount; ++i) {
|
|
|
|
|
mStyleSet->StyleSheetAt(nsStyleSet::eDocSheet, i)->List(out, aIndent);
|
|
|
|
|
fputs("\n", out);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-11-06 21:01:17 +03:00
|
|
|
|
void
|
|
|
|
|
PresShell::VerifyStyleTree()
|
|
|
|
|
{
|
|
|
|
|
VERIFY_STYLE_TREE;
|
|
|
|
|
}
|
1998-07-13 23:49:42 +04:00
|
|
|
|
#endif
|
1999-10-15 08:29:30 +04:00
|
|
|
|
|
|
|
|
|
// PresShellViewEventListener
|
|
|
|
|
|
|
|
|
|
NS_IMPL_ISUPPORTS2(PresShellViewEventListener, nsIScrollPositionListener, nsICompositeListener)
|
|
|
|
|
|
|
|
|
|
PresShellViewEventListener::PresShellViewEventListener()
|
|
|
|
|
{
|
|
|
|
|
mPresShell = 0;
|
|
|
|
|
mWasVisible = PR_FALSE;
|
|
|
|
|
mCallCount = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PresShellViewEventListener::~PresShellViewEventListener()
|
|
|
|
|
{
|
|
|
|
|
mPresShell = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
|
PresShellViewEventListener::SetPresShell(nsIPresShell *aPresShell)
|
|
|
|
|
{
|
|
|
|
|
mPresShell = aPresShell;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
|
PresShellViewEventListener::HideCaret()
|
|
|
|
|
{
|
|
|
|
|
nsresult result = NS_OK;
|
|
|
|
|
|
|
|
|
|
if (mPresShell && 0 == mCallCount)
|
|
|
|
|
{
|
2000-04-27 11:37:12 +04:00
|
|
|
|
nsCOMPtr<nsISelectionController> selCon = do_QueryInterface(mPresShell);
|
|
|
|
|
if (selCon)
|
|
|
|
|
{
|
|
|
|
|
result = selCon->GetCaretEnabled(&mWasVisible);
|
1999-10-15 08:29:30 +04:00
|
|
|
|
|
2000-04-27 11:37:12 +04:00
|
|
|
|
if (NS_SUCCEEDED(result) && mWasVisible)
|
|
|
|
|
result = selCon->SetCaretEnabled(PR_FALSE);
|
|
|
|
|
}
|
1999-10-15 08:29:30 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
++mCallCount;
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
|
PresShellViewEventListener::RestoreCaretVisibility()
|
|
|
|
|
{
|
|
|
|
|
nsresult result = NS_OK;
|
|
|
|
|
|
|
|
|
|
--mCallCount;
|
|
|
|
|
|
|
|
|
|
if (mPresShell && 0 == mCallCount && mWasVisible)
|
2000-04-27 11:37:12 +04:00
|
|
|
|
{
|
|
|
|
|
nsCOMPtr<nsISelectionController> selCon = do_QueryInterface(mPresShell);
|
|
|
|
|
if (selCon)
|
|
|
|
|
result = selCon->SetCaretEnabled(PR_TRUE);
|
|
|
|
|
}
|
1999-10-15 08:29:30 +04:00
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShellViewEventListener::ScrollPositionWillChange(nsIScrollableView *aView, nscoord aX, nscoord aY)
|
|
|
|
|
{
|
|
|
|
|
return HideCaret();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShellViewEventListener::ScrollPositionDidChange(nsIScrollableView *aView, nscoord aX, nscoord aY)
|
|
|
|
|
{
|
|
|
|
|
return RestoreCaretVisibility();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShellViewEventListener::WillRefreshRegion(nsIViewManager *aViewManager,
|
|
|
|
|
nsIView *aView,
|
|
|
|
|
nsIRenderingContext *aContext,
|
|
|
|
|
nsIRegion *aRegion,
|
|
|
|
|
PRUint32 aUpdateFlags)
|
|
|
|
|
{
|
2006-04-18 03:16:46 +04:00
|
|
|
|
return NS_OK;
|
1999-10-15 08:29:30 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShellViewEventListener::DidRefreshRegion(nsIViewManager *aViewManager,
|
|
|
|
|
nsIView *aView,
|
|
|
|
|
nsIRenderingContext *aContext,
|
|
|
|
|
nsIRegion *aRegion,
|
|
|
|
|
PRUint32 aUpdateFlags)
|
|
|
|
|
{
|
2003-01-17 12:33:52 +03:00
|
|
|
|
nsCSSRendering::DidPaint();
|
|
|
|
|
|
2006-04-18 03:16:46 +04:00
|
|
|
|
return NS_OK;
|
1999-10-15 08:29:30 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShellViewEventListener::WillRefreshRect(nsIViewManager *aViewManager,
|
|
|
|
|
nsIView *aView,
|
|
|
|
|
nsIRenderingContext *aContext,
|
|
|
|
|
const nsRect *aRect,
|
|
|
|
|
PRUint32 aUpdateFlags)
|
|
|
|
|
{
|
2006-04-18 03:16:46 +04:00
|
|
|
|
return NS_OK;
|
1999-10-15 08:29:30 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShellViewEventListener::DidRefreshRect(nsIViewManager *aViewManager,
|
|
|
|
|
nsIView *aView,
|
|
|
|
|
nsIRenderingContext *aContext,
|
|
|
|
|
const nsRect *aRect,
|
|
|
|
|
PRUint32 aUpdateFlags)
|
|
|
|
|
{
|
2003-01-17 12:33:52 +03:00
|
|
|
|
nsCSSRendering::DidPaint();
|
|
|
|
|
|
2006-04-18 03:16:46 +04:00
|
|
|
|
return NS_OK;
|
1999-10-15 08:29:30 +04:00
|
|
|
|
}
|
2000-02-11 04:21:05 +03:00
|
|
|
|
|
2000-04-21 18:59:47 +04:00
|
|
|
|
|
2001-03-13 04:47:22 +03:00
|
|
|
|
//=============================================================
|
|
|
|
|
//=============================================================
|
|
|
|
|
//-- Debug Reflow Counts
|
|
|
|
|
//=============================================================
|
|
|
|
|
//=============================================================
|
2000-04-21 18:59:47 +04:00
|
|
|
|
#ifdef MOZ_REFLOW_PERF
|
2000-04-29 03:32:04 +04:00
|
|
|
|
//-------------------------------------------------------------
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::DumpReflows()
|
|
|
|
|
{
|
|
|
|
|
if (mReflowCountMgr) {
|
2002-03-06 10:48:55 +03:00
|
|
|
|
nsCAutoString uriStr;
|
2000-04-29 03:32:04 +04:00
|
|
|
|
if (mDocument) {
|
2004-01-10 02:54:21 +03:00
|
|
|
|
nsIURI *uri = mDocument->GetDocumentURI();
|
2000-04-29 03:32:04 +04:00
|
|
|
|
if (uri) {
|
2002-03-06 10:48:55 +03:00
|
|
|
|
uri->GetPath(uriStr);
|
2000-04-29 03:32:04 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
2002-03-06 10:48:55 +03:00
|
|
|
|
mReflowCountMgr->DisplayTotals(uriStr.get());
|
|
|
|
|
mReflowCountMgr->DisplayHTMLTotals(uriStr.get());
|
2000-04-29 03:32:04 +04:00
|
|
|
|
mReflowCountMgr->DisplayDiffsInTotals("Differences");
|
|
|
|
|
}
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-21 18:59:47 +04:00
|
|
|
|
//-------------------------------------------------------------
|
|
|
|
|
NS_IMETHODIMP
|
2001-02-22 16:58:17 +03:00
|
|
|
|
PresShell::CountReflows(const char * aName, PRUint32 aType, nsIFrame * aFrame)
|
2000-04-21 18:59:47 +04:00
|
|
|
|
{
|
|
|
|
|
if (mReflowCountMgr) {
|
2001-02-22 16:58:17 +03:00
|
|
|
|
mReflowCountMgr->Add(aName, (nsReflowReason)aType, aFrame);
|
2000-04-21 18:59:47 +04:00
|
|
|
|
}
|
2001-03-13 09:38:59 +03:00
|
|
|
|
|
2000-04-21 18:59:47 +04:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2001-03-13 04:47:22 +03:00
|
|
|
|
//-------------------------------------------------------------
|
|
|
|
|
NS_IMETHODIMP
|
2004-08-01 03:15:21 +04:00
|
|
|
|
PresShell::PaintCount(const char * aName, nsIRenderingContext* aRenderingContext, nsPresContext* aPresContext, nsIFrame * aFrame, PRUint32 aColor)
|
2001-03-13 04:47:22 +03:00
|
|
|
|
{
|
|
|
|
|
if (mReflowCountMgr) {
|
|
|
|
|
mReflowCountMgr->PaintCount(aName, aRenderingContext, aPresContext, aFrame, aColor);
|
|
|
|
|
}
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
PresShell::SetPaintFrameCount(PRBool aPaintFrameCounts)
|
|
|
|
|
{
|
|
|
|
|
if (mReflowCountMgr) {
|
|
|
|
|
mReflowCountMgr->SetPaintFrameCounts(aPaintFrameCounts);
|
|
|
|
|
}
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-21 18:59:47 +04:00
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
//-- Reflow Counter Classes Impls
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
ReflowCounter::ReflowCounter(ReflowCountMgr * aMgr) :
|
|
|
|
|
mMgr(aMgr)
|
|
|
|
|
{
|
|
|
|
|
ClearTotals();
|
2000-04-29 03:32:04 +04:00
|
|
|
|
SetTotalsCache();
|
2000-04-21 18:59:47 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
ReflowCounter::~ReflowCounter()
|
|
|
|
|
{
|
2001-03-13 04:47:22 +03:00
|
|
|
|
|
2000-04-21 18:59:47 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
void ReflowCounter::ClearTotals()
|
|
|
|
|
{
|
|
|
|
|
for (PRUint32 i=0;i<NUM_REFLOW_TYPES;i++) {
|
|
|
|
|
mTotals[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-29 03:32:04 +04:00
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
void ReflowCounter::SetTotalsCache()
|
|
|
|
|
{
|
|
|
|
|
for (PRUint32 i=0;i<NUM_REFLOW_TYPES;i++) {
|
|
|
|
|
mCacheTotals[i] = mTotals[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
void ReflowCounter::CalcDiffInTotals()
|
|
|
|
|
{
|
|
|
|
|
for (PRUint32 i=0;i<NUM_REFLOW_TYPES;i++) {
|
|
|
|
|
mCacheTotals[i] = mTotals[i] - mCacheTotals[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-21 18:59:47 +04:00
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
void ReflowCounter::DisplayTotals(const char * aStr)
|
|
|
|
|
{
|
2000-04-29 03:32:04 +04:00
|
|
|
|
DisplayTotals(mTotals, aStr?aStr:"Totals");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
void ReflowCounter::DisplayDiffTotals(const char * aStr)
|
|
|
|
|
{
|
|
|
|
|
DisplayTotals(mCacheTotals, aStr?aStr:"Diff Totals");
|
2000-04-21 18:59:47 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
void ReflowCounter::DisplayHTMLTotals(const char * aStr)
|
|
|
|
|
{
|
|
|
|
|
DisplayHTMLTotals(mTotals, aStr?aStr:"Totals");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
void ReflowCounter::DisplayTotals(PRUint32 * aArray, const char * aTitle)
|
|
|
|
|
{
|
2000-04-29 03:32:04 +04:00
|
|
|
|
// figure total
|
|
|
|
|
PRUint32 total = 0;
|
|
|
|
|
PRUint32 i;
|
|
|
|
|
for (i=0;i<NUM_REFLOW_TYPES;i++) {
|
|
|
|
|
total += aArray[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (total == 0) {
|
2000-04-21 18:59:47 +04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
ReflowCounter * gTots = (ReflowCounter *)mMgr->LookUp(kGrandTotalsStr);
|
|
|
|
|
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("%25s\t", aTitle);
|
2000-04-21 18:59:47 +04:00
|
|
|
|
for (i=0;i<NUM_REFLOW_TYPES;i++) {
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("%d\t", aArray[i]);
|
2000-04-21 18:59:47 +04:00
|
|
|
|
if (gTots != this && aArray[i] > 0) {
|
|
|
|
|
gTots->Add((nsReflowReason)i, aArray[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("%d\n", total);
|
2000-04-21 18:59:47 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
void ReflowCounter::DisplayHTMLTotals(PRUint32 * aArray, const char * aTitle)
|
|
|
|
|
{
|
2000-04-29 03:32:04 +04:00
|
|
|
|
// figure total
|
|
|
|
|
PRUint32 total = 0;
|
|
|
|
|
PRUint32 i;
|
|
|
|
|
for (i=0;i<NUM_REFLOW_TYPES;i++) {
|
|
|
|
|
total += aArray[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (total == 0) {
|
2000-04-21 18:59:47 +04:00
|
|
|
|
return;
|
|
|
|
|
}
|
2000-04-29 03:32:04 +04:00
|
|
|
|
|
2000-04-21 18:59:47 +04:00
|
|
|
|
ReflowCounter * gTots = (ReflowCounter *)mMgr->LookUp(kGrandTotalsStr);
|
|
|
|
|
FILE * fd = mMgr->GetOutFile();
|
|
|
|
|
if (!fd) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fprintf(fd, "<tr><td><center>%s</center></td>", aTitle);
|
|
|
|
|
for (i=0;i<NUM_REFLOW_TYPES;i++) {
|
|
|
|
|
fprintf(fd, "<td><center>");
|
|
|
|
|
if (aArray[i]) {
|
|
|
|
|
fprintf(fd, "%d", aArray[i]);
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(fd, " ");
|
|
|
|
|
}
|
|
|
|
|
fprintf(fd, "</center></td>");
|
|
|
|
|
if (gTots != this && aArray[i] > 0) {
|
|
|
|
|
gTots->Add((nsReflowReason)i, aArray[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
2000-04-29 03:32:04 +04:00
|
|
|
|
fprintf(fd, "<td><center>%d</center></td></tr>\n", total);
|
2000-04-21 18:59:47 +04:00
|
|
|
|
}
|
|
|
|
|
|
2001-03-13 04:47:22 +03:00
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
//-- ReflowCountMgr
|
2000-04-21 18:59:47 +04:00
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
ReflowCountMgr::ReflowCountMgr()
|
|
|
|
|
{
|
|
|
|
|
mCounts = PL_NewHashTable(10, PL_HashString, PL_CompareStrings,
|
|
|
|
|
PL_CompareValues, nsnull, nsnull);
|
2001-02-22 16:58:17 +03:00
|
|
|
|
mIndiFrameCounts = PL_NewHashTable(10, PL_HashString, PL_CompareStrings,
|
|
|
|
|
PL_CompareValues, nsnull, nsnull);
|
2001-03-13 04:47:22 +03:00
|
|
|
|
mCycledOnce = PR_FALSE;
|
|
|
|
|
mDumpFrameCounts = PR_FALSE;
|
|
|
|
|
mDumpFrameByFrameCounts = PR_FALSE;
|
|
|
|
|
mPaintFrameByFrameCounts = PR_FALSE;
|
2000-04-21 18:59:47 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
ReflowCountMgr::~ReflowCountMgr()
|
|
|
|
|
{
|
|
|
|
|
CleanUp();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
ReflowCounter * ReflowCountMgr::LookUp(const char * aName)
|
|
|
|
|
{
|
|
|
|
|
if (nsnull != mCounts) {
|
|
|
|
|
ReflowCounter * counter = (ReflowCounter *)PL_HashTableLookup(mCounts, aName);
|
|
|
|
|
return counter;
|
|
|
|
|
}
|
|
|
|
|
return nsnull;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
2001-02-22 16:58:17 +03:00
|
|
|
|
void ReflowCountMgr::Add(const char * aName, nsReflowReason aType, nsIFrame * aFrame)
|
2000-04-21 18:59:47 +04:00
|
|
|
|
{
|
2001-02-22 16:58:17 +03:00
|
|
|
|
NS_ASSERTION(aName != nsnull, "Name shouldn't be null!");
|
|
|
|
|
|
2001-03-13 04:47:22 +03:00
|
|
|
|
if (mDumpFrameCounts && nsnull != mCounts) {
|
2000-04-21 18:59:47 +04:00
|
|
|
|
ReflowCounter * counter = (ReflowCounter *)PL_HashTableLookup(mCounts, aName);
|
|
|
|
|
if (counter == nsnull) {
|
|
|
|
|
counter = new ReflowCounter(this);
|
|
|
|
|
NS_ASSERTION(counter != nsnull, "null ptr");
|
|
|
|
|
char * name = nsCRT::strdup(aName);
|
|
|
|
|
NS_ASSERTION(name != nsnull, "null ptr");
|
|
|
|
|
PL_HashTableAdd(mCounts, name, counter);
|
|
|
|
|
}
|
|
|
|
|
counter->Add(aType);
|
|
|
|
|
}
|
2001-02-22 16:58:17 +03:00
|
|
|
|
|
2001-03-13 04:47:22 +03:00
|
|
|
|
if ((mDumpFrameByFrameCounts || mPaintFrameByFrameCounts) &&
|
|
|
|
|
nsnull != mIndiFrameCounts &&
|
|
|
|
|
aFrame != nsnull) {
|
2001-02-22 16:58:17 +03:00
|
|
|
|
char * key = new char[16];
|
2002-08-24 18:41:28 +04:00
|
|
|
|
sprintf(key, "%p", (void*)aFrame);
|
2001-02-22 16:58:17 +03:00
|
|
|
|
IndiReflowCounter * counter = (IndiReflowCounter *)PL_HashTableLookup(mIndiFrameCounts, key);
|
|
|
|
|
if (counter == nsnull) {
|
|
|
|
|
counter = new IndiReflowCounter(this);
|
|
|
|
|
NS_ASSERTION(counter != nsnull, "null ptr");
|
|
|
|
|
counter->mFrame = aFrame;
|
2004-07-25 16:18:04 +04:00
|
|
|
|
counter->mName.AssignASCII(aName);
|
2001-02-22 16:58:17 +03:00
|
|
|
|
PL_HashTableAdd(mIndiFrameCounts, key, counter);
|
|
|
|
|
}
|
|
|
|
|
// this eliminates extra counts from super classes
|
2004-07-22 00:18:39 +04:00
|
|
|
|
if (counter != nsnull && counter->mName.EqualsASCII(aName)) {
|
2001-02-22 16:58:17 +03:00
|
|
|
|
counter->mCount++;
|
|
|
|
|
counter->mCounter.Add(aType, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
2000-04-21 18:59:47 +04:00
|
|
|
|
}
|
|
|
|
|
|
2001-03-13 04:47:22 +03:00
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
void ReflowCountMgr::PaintCount(const char * aName,
|
|
|
|
|
nsIRenderingContext* aRenderingContext,
|
2004-08-01 03:15:21 +04:00
|
|
|
|
nsPresContext* aPresContext,
|
2001-03-13 04:47:22 +03:00
|
|
|
|
nsIFrame* aFrame,
|
|
|
|
|
PRUint32 aColor)
|
|
|
|
|
{
|
|
|
|
|
if (mPaintFrameByFrameCounts &&
|
|
|
|
|
nsnull != mIndiFrameCounts &&
|
|
|
|
|
aFrame != nsnull) {
|
|
|
|
|
char * key = new char[16];
|
2002-08-24 18:41:28 +04:00
|
|
|
|
sprintf(key, "%p", (void*)aFrame);
|
2001-03-13 04:47:22 +03:00
|
|
|
|
IndiReflowCounter * counter = (IndiReflowCounter *)PL_HashTableLookup(mIndiFrameCounts, key);
|
2004-07-22 00:18:39 +04:00
|
|
|
|
if (counter != nsnull && counter->mName.EqualsASCII(aName)) {
|
2001-03-13 04:47:22 +03:00
|
|
|
|
aRenderingContext->PushState();
|
|
|
|
|
nsFont font("Times", NS_FONT_STYLE_NORMAL,NS_FONT_VARIANT_NORMAL,
|
2003-03-12 06:22:11 +03:00
|
|
|
|
NS_FONT_WEIGHT_NORMAL,0,NSIntPointsToTwips(8));
|
2001-03-13 04:47:22 +03:00
|
|
|
|
|
2004-07-29 23:41:39 +04:00
|
|
|
|
nsCOMPtr<nsIFontMetrics> fm = aPresContext->GetMetricsFor(font);
|
2001-03-13 04:47:22 +03:00
|
|
|
|
aRenderingContext->SetFont(fm);
|
|
|
|
|
char buf[16];
|
|
|
|
|
sprintf(buf, "%d", counter->mCount);
|
2001-10-31 01:58:00 +03:00
|
|
|
|
nscoord x = 0, y;
|
2001-03-13 04:47:22 +03:00
|
|
|
|
nscoord width, height;
|
|
|
|
|
aRenderingContext->GetWidth((char*)buf, width);
|
|
|
|
|
fm->GetHeight(height);
|
2001-10-31 01:58:00 +03:00
|
|
|
|
fm->GetMaxAscent(y);
|
2001-03-13 04:47:22 +03:00
|
|
|
|
|
|
|
|
|
PRUint32 color;
|
|
|
|
|
PRUint32 color2;
|
|
|
|
|
if (aColor != 0) {
|
|
|
|
|
color = aColor;
|
|
|
|
|
color2 = NS_RGB(0,0,0);
|
|
|
|
|
} else {
|
2003-05-30 23:47:39 +04:00
|
|
|
|
PRUint8 rc = 0, gc = 0, bc = 0;
|
2001-03-13 04:47:22 +03:00
|
|
|
|
if (counter->mCount < 5) {
|
|
|
|
|
rc = 255;
|
|
|
|
|
gc = 255;
|
|
|
|
|
} else if ( counter->mCount < 11) {
|
|
|
|
|
gc = 255;
|
|
|
|
|
} else {
|
|
|
|
|
rc = 255;
|
|
|
|
|
}
|
|
|
|
|
color = NS_RGB(rc,gc,bc);
|
|
|
|
|
color2 = NS_RGB(rc/2,gc/2,bc/2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsRect rect(0,0, width+15, height+15);
|
|
|
|
|
aRenderingContext->SetColor(NS_RGB(0,0,0));
|
|
|
|
|
aRenderingContext->FillRect(rect);
|
|
|
|
|
aRenderingContext->SetColor(color2);
|
2001-10-31 01:58:00 +03:00
|
|
|
|
aRenderingContext->DrawString(buf, strlen(buf), x+15,y+15);
|
2001-03-13 04:47:22 +03:00
|
|
|
|
aRenderingContext->SetColor(color);
|
2001-10-31 01:58:00 +03:00
|
|
|
|
aRenderingContext->DrawString(buf, strlen(buf), x,y);
|
2001-03-13 04:47:22 +03:00
|
|
|
|
|
2004-04-18 17:13:35 +04:00
|
|
|
|
aRenderingContext->PopState();
|
2001-03-13 04:47:22 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-21 18:59:47 +04:00
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
PRIntn ReflowCountMgr::RemoveItems(PLHashEntry *he, PRIntn i, void *arg)
|
|
|
|
|
{
|
|
|
|
|
char *str = (char *)he->key;
|
|
|
|
|
ReflowCounter * counter = (ReflowCounter *)he->value;
|
|
|
|
|
delete counter;
|
|
|
|
|
delete [] str;
|
|
|
|
|
|
|
|
|
|
return HT_ENUMERATE_REMOVE;
|
|
|
|
|
}
|
|
|
|
|
|
2001-02-22 16:58:17 +03:00
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
PRIntn ReflowCountMgr::RemoveIndiItems(PLHashEntry *he, PRIntn i, void *arg)
|
|
|
|
|
{
|
|
|
|
|
char *str = (char *)he->key;
|
|
|
|
|
IndiReflowCounter * counter = (IndiReflowCounter *)he->value;
|
|
|
|
|
delete counter;
|
|
|
|
|
delete [] str;
|
|
|
|
|
|
|
|
|
|
return HT_ENUMERATE_REMOVE;
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-21 18:59:47 +04:00
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
void ReflowCountMgr::CleanUp()
|
|
|
|
|
{
|
|
|
|
|
if (nsnull != mCounts) {
|
|
|
|
|
PL_HashTableEnumerateEntries(mCounts, RemoveItems, nsnull);
|
|
|
|
|
PL_HashTableDestroy(mCounts);
|
|
|
|
|
mCounts = nsnull;
|
2001-03-13 04:47:22 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nsnull != mIndiFrameCounts) {
|
|
|
|
|
PL_HashTableEnumerateEntries(mIndiFrameCounts, RemoveIndiItems, nsnull);
|
|
|
|
|
PL_HashTableDestroy(mIndiFrameCounts);
|
|
|
|
|
mIndiFrameCounts = nsnull;
|
2000-04-21 18:59:47 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
PRIntn ReflowCountMgr::DoSingleTotal(PLHashEntry *he, PRIntn i, void *arg)
|
|
|
|
|
{
|
|
|
|
|
char *str = (char *)he->key;
|
|
|
|
|
ReflowCounter * counter = (ReflowCounter *)he->value;
|
|
|
|
|
|
|
|
|
|
counter->DisplayTotals(str);
|
|
|
|
|
|
|
|
|
|
return HT_ENUMERATE_NEXT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
void ReflowCountMgr::DoGrandTotals()
|
|
|
|
|
{
|
|
|
|
|
if (nsnull != mCounts) {
|
|
|
|
|
ReflowCounter * gTots = (ReflowCounter *)PL_HashTableLookup(mCounts, kGrandTotalsStr);
|
|
|
|
|
if (gTots == nsnull) {
|
|
|
|
|
gTots = new ReflowCounter(this);
|
|
|
|
|
PL_HashTableAdd(mCounts, nsCRT::strdup(kGrandTotalsStr), gTots);
|
|
|
|
|
} else {
|
|
|
|
|
gTots->ClearTotals();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char * title[] = {"Init", "Incrm", "Resze", "Style", "Dirty", "Total"};
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("\t\t\t");
|
2000-04-21 18:59:47 +04:00
|
|
|
|
PRUint32 i;
|
|
|
|
|
for (i=0;i<NUM_REFLOW_TYPES+1;i++) {
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("\t%s", title[i]);
|
2000-04-21 18:59:47 +04:00
|
|
|
|
}
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("\n");
|
2000-04-21 18:59:47 +04:00
|
|
|
|
for (i=0;i<78;i++) {
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("-");
|
2000-04-21 18:59:47 +04:00
|
|
|
|
}
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("\n");
|
2000-04-21 18:59:47 +04:00
|
|
|
|
PL_HashTableEnumerateEntries(mCounts, DoSingleTotal, this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-08-01 03:15:21 +04:00
|
|
|
|
static void RecurseIndiTotals(nsPresContext* aPresContext,
|
2001-02-22 16:58:17 +03:00
|
|
|
|
PLHashTable * aHT,
|
|
|
|
|
nsIFrame * aParentFrame,
|
|
|
|
|
PRInt32 aLevel)
|
|
|
|
|
{
|
|
|
|
|
if (aParentFrame == nsnull) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char key[16];
|
2002-08-24 18:41:28 +04:00
|
|
|
|
sprintf(key, "%p", (void*)aParentFrame);
|
2001-02-22 16:58:17 +03:00
|
|
|
|
IndiReflowCounter * counter = (IndiReflowCounter *)PL_HashTableLookup(aHT, key);
|
|
|
|
|
if (counter) {
|
|
|
|
|
counter->mHasBeenOutput = PR_TRUE;
|
2001-09-29 12:28:41 +04:00
|
|
|
|
char * name = ToNewCString(counter->mName);
|
2001-02-22 16:58:17 +03:00
|
|
|
|
for (PRInt32 i=0;i<aLevel;i++) printf(" ");
|
2002-08-24 18:41:28 +04:00
|
|
|
|
printf("%s - %p [%d][", name, (void*)aParentFrame, counter->mCount);
|
2001-02-22 16:58:17 +03:00
|
|
|
|
for (PRInt32 inx=0;inx<5;inx++) {
|
|
|
|
|
if (inx != 0) printf(",");
|
|
|
|
|
printf("%d", counter->mCounter.GetTotalByType(nsReflowReason(inx)));
|
|
|
|
|
}
|
|
|
|
|
printf("]\n");
|
|
|
|
|
nsMemory::Free(name);
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-09 17:20:53 +03:00
|
|
|
|
nsIFrame* child = aParentFrame->GetFirstChild(nsnull);
|
2001-02-22 16:58:17 +03:00
|
|
|
|
while (child) {
|
|
|
|
|
RecurseIndiTotals(aPresContext, aHT, child, aLevel+1);
|
2003-06-30 14:46:59 +04:00
|
|
|
|
child = child->GetNextSibling();
|
2001-02-22 16:58:17 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
PRIntn ReflowCountMgr::DoSingleIndi(PLHashEntry *he, PRIntn i, void *arg)
|
|
|
|
|
{
|
|
|
|
|
IndiReflowCounter * counter = (IndiReflowCounter *)he->value;
|
|
|
|
|
if (counter && !counter->mHasBeenOutput) {
|
2001-09-29 12:28:41 +04:00
|
|
|
|
char * name = ToNewCString(counter->mName);
|
2002-08-24 18:41:28 +04:00
|
|
|
|
printf("%s - %p [%d][", name, (void*)counter->mFrame, counter->mCount);
|
2001-02-22 16:58:17 +03:00
|
|
|
|
for (PRInt32 inx=0;inx<5;inx++) {
|
|
|
|
|
if (inx != 0) printf(",");
|
|
|
|
|
printf("%d", counter->mCounter.GetTotalByType(nsReflowReason(inx)));
|
|
|
|
|
}
|
|
|
|
|
printf("]\n");
|
|
|
|
|
nsMemory::Free(name);
|
|
|
|
|
}
|
|
|
|
|
return HT_ENUMERATE_NEXT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
void ReflowCountMgr::DoIndiTotalsTree()
|
|
|
|
|
{
|
|
|
|
|
if (nsnull != mCounts) {
|
|
|
|
|
printf("\n------------------------------------------------\n");
|
|
|
|
|
printf("-- Individual Frame Counts\n");
|
|
|
|
|
printf("------------------------------------------------\n");
|
|
|
|
|
|
|
|
|
|
if (mPresShell) {
|
2004-09-02 07:08:51 +04:00
|
|
|
|
nsIFrame * rootFrame = mPresShell->FrameManager()->GetRootFrame();
|
2001-02-22 16:58:17 +03:00
|
|
|
|
RecurseIndiTotals(mPresContext, mIndiFrameCounts, rootFrame, 0);
|
|
|
|
|
printf("------------------------------------------------\n");
|
|
|
|
|
printf("-- Individual Counts of Frames not in Root Tree\n");
|
|
|
|
|
printf("------------------------------------------------\n");
|
|
|
|
|
PL_HashTableEnumerateEntries(mIndiFrameCounts, DoSingleIndi, this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-21 18:59:47 +04:00
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
PRIntn ReflowCountMgr::DoSingleHTMLTotal(PLHashEntry *he, PRIntn i, void *arg)
|
|
|
|
|
{
|
|
|
|
|
char *str = (char *)he->key;
|
|
|
|
|
ReflowCounter * counter = (ReflowCounter *)he->value;
|
|
|
|
|
|
|
|
|
|
counter->DisplayHTMLTotals(str);
|
|
|
|
|
|
|
|
|
|
return HT_ENUMERATE_NEXT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
void ReflowCountMgr::DoGrandHTMLTotals()
|
|
|
|
|
{
|
|
|
|
|
if (nsnull != mCounts) {
|
|
|
|
|
ReflowCounter * gTots = (ReflowCounter *)PL_HashTableLookup(mCounts, kGrandTotalsStr);
|
|
|
|
|
if (gTots == nsnull) {
|
|
|
|
|
gTots = new ReflowCounter(this);
|
|
|
|
|
PL_HashTableAdd(mCounts, nsCRT::strdup(kGrandTotalsStr), gTots);
|
|
|
|
|
} else {
|
|
|
|
|
gTots->ClearTotals();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char * title[] = {"Class", "Init", "Incrm", "Resze", "Style", "Dirty", "Total"};
|
|
|
|
|
fprintf(mFD, "<tr>");
|
|
|
|
|
PRUint32 i;
|
|
|
|
|
for (i=0;i<NUM_REFLOW_TYPES+2;i++) {
|
|
|
|
|
fprintf(mFD, "<td><center><b>%s<b></center></td>", title[i]);
|
|
|
|
|
}
|
|
|
|
|
fprintf(mFD, "</tr>\n");
|
|
|
|
|
PL_HashTableEnumerateEntries(mCounts, DoSingleHTMLTotal, this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------
|
|
|
|
|
void ReflowCountMgr::DisplayTotals(const char * aStr)
|
|
|
|
|
{
|
2001-07-18 08:29:14 +04:00
|
|
|
|
#ifdef DEBUG_rods
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("%s\n", aStr?aStr:"No name");
|
2001-07-18 08:29:14 +04:00
|
|
|
|
#endif
|
2001-03-13 04:47:22 +03:00
|
|
|
|
if (mDumpFrameCounts) {
|
|
|
|
|
DoGrandTotals();
|
|
|
|
|
}
|
|
|
|
|
if (mDumpFrameByFrameCounts) {
|
|
|
|
|
DoIndiTotalsTree();
|
|
|
|
|
}
|
2000-04-21 18:59:47 +04:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
//------------------------------------
|
|
|
|
|
void ReflowCountMgr::DisplayHTMLTotals(const char * aStr)
|
|
|
|
|
{
|
2000-04-29 03:32:04 +04:00
|
|
|
|
#ifdef WIN32x // XXX NOT XP!
|
2000-04-21 18:59:47 +04:00
|
|
|
|
char name[1024];
|
|
|
|
|
|
|
|
|
|
char * sptr = strrchr(aStr, '/');
|
|
|
|
|
if (sptr) {
|
|
|
|
|
sptr++;
|
|
|
|
|
strcpy(name, sptr);
|
|
|
|
|
char * eptr = strrchr(name, '.');
|
|
|
|
|
if (eptr) {
|
|
|
|
|
*eptr = 0;
|
|
|
|
|
}
|
|
|
|
|
strcat(name, "_stats.html");
|
|
|
|
|
}
|
|
|
|
|
mFD = fopen(name, "w");
|
|
|
|
|
if (mFD) {
|
|
|
|
|
fprintf(mFD, "<html><head><title>Reflow Stats</title></head><body>\n");
|
|
|
|
|
const char * title = aStr?aStr:"No name";
|
|
|
|
|
fprintf(mFD, "<center><b>%s</b><br><table border=1 style=\"background-color:#e0e0e0\">", title);
|
|
|
|
|
DoGrandHTMLTotals();
|
|
|
|
|
fprintf(mFD, "</center></table>\n");
|
|
|
|
|
fprintf(mFD, "</body></html>\n");
|
|
|
|
|
fclose(mFD);
|
|
|
|
|
mFD = nsnull;
|
|
|
|
|
}
|
|
|
|
|
#endif // not XP!
|
|
|
|
|
}
|
2000-04-29 03:32:04 +04:00
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
PRIntn ReflowCountMgr::DoClearTotals(PLHashEntry *he, PRIntn i, void *arg)
|
|
|
|
|
{
|
|
|
|
|
ReflowCounter * counter = (ReflowCounter *)he->value;
|
|
|
|
|
counter->ClearTotals();
|
|
|
|
|
|
|
|
|
|
return HT_ENUMERATE_NEXT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
void ReflowCountMgr::ClearTotals()
|
|
|
|
|
{
|
|
|
|
|
PL_HashTableEnumerateEntries(mCounts, DoClearTotals, this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
void ReflowCountMgr::ClearGrandTotals()
|
|
|
|
|
{
|
|
|
|
|
if (nsnull != mCounts) {
|
|
|
|
|
ReflowCounter * gTots = (ReflowCounter *)PL_HashTableLookup(mCounts, kGrandTotalsStr);
|
|
|
|
|
if (gTots == nsnull) {
|
|
|
|
|
gTots = new ReflowCounter(this);
|
|
|
|
|
PL_HashTableAdd(mCounts, nsCRT::strdup(kGrandTotalsStr), gTots);
|
|
|
|
|
} else {
|
|
|
|
|
gTots->ClearTotals();
|
|
|
|
|
gTots->SetTotalsCache();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
PRIntn ReflowCountMgr::DoDisplayDiffTotals(PLHashEntry *he, PRIntn i, void *arg)
|
|
|
|
|
{
|
2001-08-15 05:33:22 +04:00
|
|
|
|
PRBool cycledOnce = (arg != 0);
|
2000-04-29 03:32:04 +04:00
|
|
|
|
|
|
|
|
|
char *str = (char *)he->key;
|
|
|
|
|
ReflowCounter * counter = (ReflowCounter *)he->value;
|
|
|
|
|
|
|
|
|
|
if (cycledOnce) {
|
|
|
|
|
counter->CalcDiffInTotals();
|
|
|
|
|
counter->DisplayDiffTotals(str);
|
|
|
|
|
}
|
|
|
|
|
counter->SetTotalsCache();
|
|
|
|
|
|
|
|
|
|
return HT_ENUMERATE_NEXT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
void ReflowCountMgr::DisplayDiffsInTotals(const char * aStr)
|
|
|
|
|
{
|
|
|
|
|
if (mCycledOnce) {
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("Differences\n");
|
2000-04-29 03:32:04 +04:00
|
|
|
|
for (PRInt32 i=0;i<78;i++) {
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("-");
|
2000-04-29 03:32:04 +04:00
|
|
|
|
}
|
2000-10-29 02:17:53 +04:00
|
|
|
|
printf("\n");
|
2000-04-29 03:32:04 +04:00
|
|
|
|
ClearGrandTotals();
|
|
|
|
|
}
|
|
|
|
|
PL_HashTableEnumerateEntries(mCounts, DoDisplayDiffTotals, (void *)mCycledOnce);
|
|
|
|
|
|
|
|
|
|
mCycledOnce = PR_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-21 18:59:47 +04:00
|
|
|
|
#endif // MOZ_REFLOW_PERF
|
2000-10-11 12:33:01 +04:00
|
|
|
|
|
|
|
|
|
// make a color string like #RRGGBB
|
|
|
|
|
void ColorToString(nscolor aColor, nsAutoString &aString)
|
|
|
|
|
{
|
2004-01-18 17:44:43 +03:00
|
|
|
|
char buf[8];
|
2000-10-11 12:33:01 +04:00
|
|
|
|
|
2004-01-18 17:44:43 +03:00
|
|
|
|
PR_snprintf(buf, sizeof(buf), "#%02x%02x%02x",
|
|
|
|
|
NS_GET_R(aColor), NS_GET_G(aColor), NS_GET_B(aColor));
|
|
|
|
|
CopyASCIItoUTF16(buf, aString);
|
2000-10-11 12:33:01 +04:00
|
|
|
|
}
|