From db0739bf3ce3df4fd7ae6efb1fde8b6093c6f480 Mon Sep 17 00:00:00 2001 From: "enndeakin%sympatico.ca" Date: Thu, 21 Feb 2008 17:40:13 +0000 Subject: [PATCH] Bug 405719, regression where menus cannot be generated with templates without extra tags, also improve construction by not setting the open attribute too early and instead call the builder directly before opening a menu, r=smaug,sr=neil,a=beltzner git-svn-id: svn://10.0.0.236/trunk@246202 18797224-902f-48f8-a5cc-f745e15eee43 --- .../content/xul/content/src/nsXULElement.cpp | 2 +- .../xul/document/src/nsXULDocument.cpp | 2 +- .../public/nsIXULTemplateBuilder.idl | 15 ++++--- .../xul/templates/src/nsXULContentBuilder.cpp | 42 ++++++++++++++----- .../templates/src/nsXULTemplateBuilder.cpp | 2 +- mozilla/layout/xul/base/src/Makefile.in | 1 + .../layout/xul/base/src/nsXULPopupManager.cpp | 26 +++++++++--- mozilla/toolkit/content/xul.css | 2 +- 8 files changed, 65 insertions(+), 27 deletions(-) diff --git a/mozilla/content/xul/content/src/nsXULElement.cpp b/mozilla/content/xul/content/src/nsXULElement.cpp index 1d3960ab4bc..4b3ddb7ba48 100644 --- a/mozilla/content/xul/content/src/nsXULElement.cpp +++ b/mozilla/content/xul/content/src/nsXULElement.cpp @@ -1646,7 +1646,7 @@ nsXULElement::EnsureContentsGenerated(void) const return NS_OK; } - return builder->CreateContents(unconstThis); + return builder->CreateContents(unconstThis, PR_FALSE); } } diff --git a/mozilla/content/xul/document/src/nsXULDocument.cpp b/mozilla/content/xul/document/src/nsXULDocument.cpp index dc0d3bed5f4..279f53ee57e 100644 --- a/mozilla/content/xul/document/src/nsXULDocument.cpp +++ b/mozilla/content/xul/document/src/nsXULDocument.cpp @@ -3659,7 +3659,7 @@ nsXULDocument::CreateTemplateBuilder(nsIContent* aElement) } else { // Force construction of immediate template sub-content _now_. - builder->CreateContents(aElement); + builder->CreateContents(aElement, PR_FALSE); } } diff --git a/mozilla/content/xul/templates/public/nsIXULTemplateBuilder.idl b/mozilla/content/xul/templates/public/nsIXULTemplateBuilder.idl index a9635d1f2ae..8e4773eb6f3 100644 --- a/mozilla/content/xul/templates/public/nsIXULTemplateBuilder.idl +++ b/mozilla/content/xul/templates/public/nsIXULTemplateBuilder.idl @@ -42,8 +42,6 @@ #include "domstubs.idl" #include "nsISupports.idl" -#include "nsIRDFCompositeDataSource.idl" -#include "nsIRDFResource.idl" interface nsIAtom; interface nsIContent; @@ -51,6 +49,8 @@ interface nsIXULBuilderListener; interface nsIXULTemplateResult; interface nsIXULTemplateRuleFilter; interface nsIXULTemplateQueryProcessor; +interface nsIRDFResource; +interface nsIRDFCompositeDataSource; /** * A template builder, given an input source of data, a template, and a @@ -158,7 +158,7 @@ interface nsIXULTemplateQueryProcessor; * * See http://wiki.mozilla.org/XUL:Templates_Plan for details about templates. */ -[scriptable, uuid(1762801E-1147-4197-BF0D-D749C903AF74)] +[scriptable, uuid(A583B676-5B02-4F9C-A0C9-CB850CB99818)] interface nsIXULTemplateBuilder : nsISupports { /** @@ -328,10 +328,13 @@ interface nsIXULTemplateBuilder : nsISupports [noscript] void init(in nsIContent aElement); /** - * Invoked lazily by a XUL element that needs its child content - * built. + * Invoked lazily by a XUL element that needs its child content built. + * If aForceCreation is true, then the contents of an element will be + * generated even if it is closed. If false, the element will only + * generate its contents if it is open. This behaviour is used with menus. */ - [noscript] void createContents(in nsIContent aElement); + [noscript] void createContents(in nsIContent aElement, + in boolean aForceCreation); /** * Add a listener to this template builder. The template builder diff --git a/mozilla/content/xul/templates/src/nsXULContentBuilder.cpp b/mozilla/content/xul/templates/src/nsXULContentBuilder.cpp index 32978bed279..15b4f52d351 100644 --- a/mozilla/content/xul/templates/src/nsXULContentBuilder.cpp +++ b/mozilla/content/xul/templates/src/nsXULContentBuilder.cpp @@ -128,7 +128,7 @@ class nsXULContentBuilder : public nsXULTemplateBuilder { public: // nsIXULTemplateBuilder interface - NS_IMETHOD CreateContents(nsIContent* aElement); + NS_IMETHOD CreateContents(nsIContent* aElement, PRBool aForceCreation); NS_IMETHOD HasGeneratedContent(nsIRDFResource* aResource, nsIAtom* aTag, @@ -261,11 +261,13 @@ protected: * was generated. * * @param aElement element to generate content inside + * @param aForceCreation true to force creation for closed items such as menus * @param aContainer container content was added inside * @param aNewIndexInContainer index with container in which content was added */ nsresult CreateTemplateAndContainerContents(nsIContent* aElement, + PRBool aForceCreation, nsIContent** aContainer, PRInt32* aNewIndexInContainer); @@ -275,6 +277,7 @@ protected: * * @param aElement element to generate content inside * @param aResult reference point for query + * @param aForceCreation true to force creation for closed items such as menus * @param aNotify true to notify of DOM changes * @param aContainer container content was added inside * @param aNewIndexInContainer index with container in which content was added @@ -282,6 +285,7 @@ protected: nsresult CreateContainerContents(nsIContent* aElement, nsIXULTemplateResult* aResult, + PRBool aForceCreation, PRBool aNotify, nsIContent** aContainer, PRInt32* aNewIndexInContainer); @@ -853,7 +857,7 @@ nsXULContentBuilder::BuildContentFromTemplate(nsIContent *aTemplateNode, if (NS_FAILED(rv)) return rv; if (isGenerationElement) { - rv = CreateContainerContents(realKid, aChild, PR_FALSE, + rv = CreateContainerContents(realKid, aChild, PR_FALSE, PR_FALSE, nsnull /* don't care */, nsnull /* don't care */); if (NS_FAILED(rv)) return rv; @@ -1099,6 +1103,7 @@ nsXULContentBuilder::RemoveMember(nsIContent* aContent) nsresult nsXULContentBuilder::CreateTemplateAndContainerContents(nsIContent* aElement, + PRBool aForceCreation, nsIContent** aContainer, PRInt32* aNewIndexInContainer) { @@ -1143,8 +1148,8 @@ nsXULContentBuilder::CreateTemplateAndContainerContents(nsIContent* aElement, } if (mRootResult) { - CreateContainerContents(aElement, mRootResult, PR_FALSE, - aContainer, aNewIndexInContainer); + CreateContainerContents(aElement, mRootResult, aForceCreation, + PR_FALSE, aContainer, aNewIndexInContainer); } } else if (!(mFlags & eDontRecurse)) { @@ -1159,8 +1164,8 @@ nsXULContentBuilder::CreateTemplateAndContainerContents(nsIContent* aElement, if (NS_FAILED(rv) || !mayProcessChildren) return rv; - CreateContainerContents(aElement, match->mResult, PR_FALSE, - aContainer, aNewIndexInContainer); + CreateContainerContents(aElement, match->mResult, aForceCreation, + PR_FALSE, aContainer, aNewIndexInContainer); } } @@ -1173,6 +1178,7 @@ nsXULContentBuilder::CreateTemplateAndContainerContents(nsIContent* aElement, nsresult nsXULContentBuilder::CreateContainerContents(nsIContent* aElement, nsIXULTemplateResult* aResult, + PRBool aForceCreation, PRBool aNotify, nsIContent** aContainer, PRInt32* aNewIndexInContainer) @@ -1210,7 +1216,7 @@ nsXULContentBuilder::CreateContainerContents(nsIContent* aElement, // The tree widget is special. If the item isn't open, then just // "pretend" that there aren't any contents here. We'll create // them when OpenContainer() gets called. - if (IsLazyWidgetItem(aElement) && !IsOpen(aElement)) + if (!aForceCreation && IsLazyWidgetItem(aElement) && !IsOpen(aElement)) return NS_OK; // See if the element's templates contents have been generated: @@ -1670,13 +1676,26 @@ nsXULContentBuilder::SetContainerAttrs(nsIContent *aElement, // NS_IMETHODIMP -nsXULContentBuilder::CreateContents(nsIContent* aElement) +nsXULContentBuilder::CreateContents(nsIContent* aElement, PRBool aForceCreation) { NS_PRECONDITION(aElement != nsnull, "null ptr"); if (! aElement) return NS_ERROR_NULL_POINTER; - return CreateTemplateAndContainerContents(aElement, nsnull /* don't care */, nsnull /* don't care */); + nsCOMPtr container; + PRInt32 newIndex; + nsresult rv = CreateTemplateAndContainerContents(aElement, aForceCreation, + getter_AddRefs(container), &newIndex); + NS_ENSURE_SUCCESS(rv, rv); + + // if forcing an element to be created, make sure to notify + if (aForceCreation && container) { + MOZ_AUTO_DOC_UPDATE(container->GetCurrentDoc(), UPDATE_CONTENT_MODEL, + PR_TRUE); + nsNodeUtils::ContentAppended(container, newIndex); + } + + return NS_OK; } NS_IMETHODIMP @@ -2017,7 +2036,8 @@ nsXULContentBuilder::OpenContainer(nsIContent* aElement) // notify layout where content got created. nsCOMPtr container; PRInt32 newIndex; - CreateContainerContents(aElement, result, PR_FALSE, getter_AddRefs(container), &newIndex); + CreateContainerContents(aElement, result, PR_FALSE, + PR_FALSE, getter_AddRefs(container), &newIndex); if (container && IsLazyWidgetItem(aElement)) { // The tree widget is special, and has to be spanked every @@ -2090,7 +2110,7 @@ nsXULContentBuilder::RebuildAll() // contents for the current element... nsCOMPtr container; PRInt32 newIndex; - CreateTemplateAndContainerContents(mRoot, getter_AddRefs(container), &newIndex); + CreateTemplateAndContainerContents(mRoot, PR_FALSE, getter_AddRefs(container), &newIndex); if (container) { MOZ_AUTO_DOC_UPDATE(container->GetCurrentDoc(), UPDATE_CONTENT_MODEL, diff --git a/mozilla/content/xul/templates/src/nsXULTemplateBuilder.cpp b/mozilla/content/xul/templates/src/nsXULTemplateBuilder.cpp index 28afe0132e9..6a8b3ef8773 100644 --- a/mozilla/content/xul/templates/src/nsXULTemplateBuilder.cpp +++ b/mozilla/content/xul/templates/src/nsXULTemplateBuilder.cpp @@ -457,7 +457,7 @@ nsXULTemplateBuilder::Init(nsIContent* aElement) } NS_IMETHODIMP -nsXULTemplateBuilder::CreateContents(nsIContent* aElement) +nsXULTemplateBuilder::CreateContents(nsIContent* aElement, PRBool aForceCreation) { return NS_OK; } diff --git a/mozilla/layout/xul/base/src/Makefile.in b/mozilla/layout/xul/base/src/Makefile.in index 2fe5e770752..4f1c6e900b0 100644 --- a/mozilla/layout/xul/base/src/Makefile.in +++ b/mozilla/layout/xul/base/src/Makefile.in @@ -64,6 +64,7 @@ REQUIRES = xpcom \ unicharutil \ xpconnect \ js \ + xultmpl \ $(NULL) ifdef MOZ_ENABLE_CANVAS diff --git a/mozilla/layout/xul/base/src/nsXULPopupManager.cpp b/mozilla/layout/xul/base/src/nsXULPopupManager.cpp index 4b6aae8bb14..216df6732e7 100644 --- a/mozilla/layout/xul/base/src/nsXULPopupManager.cpp +++ b/mozilla/layout/xul/base/src/nsXULPopupManager.cpp @@ -45,6 +45,8 @@ #include "nsIDOMDocument.h" #include "nsIDOMNSEvent.h" #include "nsIDOMNSUIEvent.h" +#include "nsIDOMXULElement.h" +#include "nsIXULTemplateBuilder.h" #include "nsIPrivateDOMEvent.h" #include "nsEventDispatcher.h" #include "nsEventStateManager.h" @@ -366,6 +368,24 @@ nsXULPopupManager::ShowMenu(nsIContent *aMenu, PRBool aSelectFirstItem, PRBool aAsynchronous) { + // generate any template content first. Otherwise, the menupopup may not + // have been created yet. + if (aMenu) { + nsIContent* element = aMenu; + do { + nsCOMPtr xulelem = do_QueryInterface(element); + if (xulelem) { + nsCOMPtr builder; + xulelem->GetBuilder(getter_AddRefs(builder)); + if (builder) { + builder->CreateContents(aMenu, PR_TRUE); + break; + } + } + element = element->GetParent(); + } while (element); + } + nsMenuFrame* menuFrame = GetMenuFrameForContent(aMenu); if (!menuFrame || !menuFrame->IsMenu()) return; @@ -914,12 +934,6 @@ nsXULPopupManager::FirePopupShowingEvent(nsIContent* aPopup, { nsCOMPtr presShell = aPresContext->PresShell(); - // set the open attribute on the menu first so that templates will generate - // their content before the popupshowing event fires. - if (aMenu) - aMenu->SetAttr(kNameSpaceID_None, nsGkAtoms::open, - NS_LITERAL_STRING("true"), PR_TRUE); - // XXXndeakin (bug 383930) // eventually, the popup events will be a different event type with // additional fields for the anchor node and position and so forth. This diff --git a/mozilla/toolkit/content/xul.css b/mozilla/toolkit/content/xul.css index 610c301a8e4..8e7c043d0b6 100644 --- a/mozilla/toolkit/content/xul.css +++ b/mozilla/toolkit/content/xul.css @@ -277,7 +277,7 @@ menu.menu-iconic { -moz-binding: url("chrome://global/content/bindings/menu.xml#menu-iconic"); } -menu:empty { +menubar > menu:empty { visibility: collapse; }