Bug 1026164, improve focus handling in shadow dom, r=wchen

--HG--
extra : rebase_source : 026b9ee49cdce82a703700593d7a1f0e5d27969f
This commit is contained in:
Olli Pettay 2014-08-06 02:23:02 +03:00
parent f1211000f6
commit 70bc61a2af
15 changed files with 73 additions and 61 deletions

View File

@ -308,7 +308,7 @@ Element::LockedStyleStates() const
void
Element::NotifyStyleStateChange(EventStates aStates)
{
nsIDocument* doc = GetCurrentDoc();
nsIDocument* doc = GetComposedDoc();
if (doc) {
nsIPresShell *presShell = doc->GetShell();
if (presShell) {

View File

@ -1085,9 +1085,9 @@ nsGenericHTMLElement::GetAttributeMappingFunction() const
nsIFormControlFrame*
nsGenericHTMLElement::GetFormControlFrame(bool aFlushFrames)
{
if (aFlushFrames && IsInDoc()) {
if (aFlushFrames && IsInComposedDoc()) {
// Cause a flush of the frames, so we get up-to-date frame information
GetCurrentDoc()->FlushPendingNotifications(Flush_Frames);
GetComposedDoc()->FlushPendingNotifications(Flush_Frames);
}
nsIFrame* frame = GetPrimaryFrame();
if (frame) {
@ -2345,8 +2345,8 @@ nsGenericHTMLFormElement::IntrinsicState() const
nsGenericHTMLFormElement::FocusTristate
nsGenericHTMLFormElement::FocusState()
{
// We can't be focused if we aren't in a document
nsIDocument* doc = GetCurrentDoc();
// We can't be focused if we aren't in a (composed) document
nsIDocument* doc = GetComposedDoc();
if (!doc)
return eUnfocusable;
@ -2592,7 +2592,7 @@ nsGenericHTMLElement::Blur(mozilla::ErrorResult& aError)
return;
}
nsIDocument* doc = GetCurrentDoc();
nsIDocument* doc = GetComposedDoc();
if (!doc) {
return;
}
@ -2620,7 +2620,7 @@ nsGenericHTMLElement::Click()
return;
// Strong in case the event kills it
nsCOMPtr<nsIDocument> doc = GetCurrentDoc();
nsCOMPtr<nsIDocument> doc = GetComposedDoc();
nsCOMPtr<nsIPresShell> shell;
nsRefPtr<nsPresContext> context;
@ -2650,7 +2650,7 @@ nsGenericHTMLElement::IsHTMLFocusable(bool aWithMouse,
bool *aIsFocusable,
int32_t *aTabIndex)
{
nsIDocument *doc = GetCurrentDoc();
nsIDocument* doc = GetComposedDoc();
if (!doc || doc->HasFlag(NODE_IS_EDITABLE)) {
// In designMode documents we only allow focusing the document.
if (aTabIndex) {

View File

@ -769,7 +769,7 @@ nsTextInputListener::NotifySelectionChanged(nsIDOMDocument* aDoc, nsISelection*
nsIContent* content = mFrame->GetContent();
if (content)
{
nsCOMPtr<nsIDocument> doc = content->GetDocument();
nsCOMPtr<nsIDocument> doc = content->GetComposedDoc();
if (doc)
{
nsCOMPtr<nsIPresShell> presShell = doc->GetShell();
@ -955,7 +955,7 @@ nsTextInputListener::UpdateTextInputCommands(const nsAString& commandsToUpdate,
nsIContent* content = mFrame->GetContent();
NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
nsCOMPtr<nsIDocument> doc = content->GetDocument();
nsCOMPtr<nsIDocument> doc = content->GetComposedDoc();
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
nsPIDOMWindow *domWindow = doc->GetWindow();

View File

@ -243,7 +243,7 @@ nsFocusManager::Observe(nsISupports *aSubject,
static nsPIDOMWindow*
GetContentWindow(nsIContent* aContent)
{
nsIDocument* doc = aContent->GetCurrentDoc();
nsIDocument* doc = aContent->GetComposedDoc();
if (doc) {
nsIDocument* subdoc = doc->GetSubDocumentFor(aContent);
if (subdoc)
@ -257,7 +257,7 @@ GetContentWindow(nsIContent* aContent)
static nsPIDOMWindow*
GetCurrentWindow(nsIContent* aContent)
{
nsIDocument *doc = aContent->GetCurrentDoc();
nsIDocument* doc = aContent->GetComposedDoc();
return doc ? doc->GetWindow() : nullptr;
}
@ -304,7 +304,7 @@ nsFocusManager::GetRedirectedFocus(nsIContent* aContent)
menulist->GetInputField(getter_AddRefs(inputField));
}
else if (aContent->Tag() == nsGkAtoms::scale) {
nsCOMPtr<nsIDocument> doc = aContent->GetCurrentDoc();
nsCOMPtr<nsIDocument> doc = aContent->GetComposedDoc();
if (!doc)
return nullptr;
@ -919,7 +919,7 @@ nsFocusManager::WindowHidden(nsIDOMWindow* aWindow)
nsCOMPtr<nsIDocShell> focusedDocShell = mFocusedWindow->GetDocShell();
nsCOMPtr<nsIPresShell> presShell = focusedDocShell->GetPresShell();
if (oldFocusedContent && oldFocusedContent->IsInDoc()) {
if (oldFocusedContent && oldFocusedContent->IsInComposedDoc()) {
NotifyFocusStateChange(oldFocusedContent,
mFocusedWindow->ShouldShowFocusRing(),
false);
@ -927,7 +927,7 @@ nsFocusManager::WindowHidden(nsIDOMWindow* aWindow)
if (presShell) {
SendFocusOrBlurEvent(NS_BLUR_CONTENT, presShell,
oldFocusedContent->GetCurrentDoc(),
oldFocusedContent->GetComposedDoc(),
oldFocusedContent, 1, false);
}
}
@ -1403,7 +1403,7 @@ bool
nsFocusManager::IsNonFocusableRoot(nsIContent* aContent)
{
NS_PRECONDITION(aContent, "aContent must not be NULL");
NS_PRECONDITION(aContent->IsInDoc(), "aContent must be in a document");
NS_PRECONDITION(aContent->IsInComposedDoc(), "aContent must be in a document");
// If aContent is in designMode, the root element is not focusable.
// NOTE: in designMode, most elements are not focusable, just the document is
@ -1411,7 +1411,7 @@ nsFocusManager::IsNonFocusableRoot(nsIContent* aContent)
// Also, if aContent is not editable but it isn't in designMode, it's not
// focusable.
// And in userfocusignored context nothing is focusable.
nsIDocument* doc = aContent->GetCurrentDoc();
nsIDocument* doc = aContent->GetComposedDoc();
NS_ASSERTION(doc, "aContent must have current document");
return aContent == doc->GetRootElement() &&
(doc->HasFlag(NODE_IS_EDITABLE) || !aContent->IsEditable() ||
@ -1430,7 +1430,7 @@ nsFocusManager::CheckIfFocusable(nsIContent* aContent, uint32_t aFlags)
if (redirectedFocus)
return CheckIfFocusable(redirectedFocus, aFlags);
nsCOMPtr<nsIDocument> doc = aContent->GetCurrentDoc();
nsCOMPtr<nsIDocument> doc = aContent->GetComposedDoc();
// can't focus elements that are not in documents
if (!doc) {
LOGCONTENT("Cannot focus %s because content not in document", aContent)
@ -1496,7 +1496,7 @@ nsFocusManager::Blur(nsPIDOMWindow* aWindowToClear,
// hold a reference to the focused content, which may be null
nsCOMPtr<nsIContent> content = mFocusedContent;
if (content) {
if (!content->IsInDoc()) {
if (!content->IsInComposedDoc()) {
mFocusedContent = nullptr;
return true;
}
@ -1547,7 +1547,7 @@ nsFocusManager::Blur(nsPIDOMWindow* aWindowToClear,
// Don't fire blur event on the root content which isn't editable.
bool sendBlurEvent =
content && content->IsInDoc() && !IsNonFocusableRoot(content);
content && content->IsInComposedDoc() && !IsNonFocusableRoot(content);
if (content) {
if (sendBlurEvent) {
NotifyFocusStateChange(content, shouldShowFocusRing, false);
@ -1589,7 +1589,7 @@ nsFocusManager::Blur(nsPIDOMWindow* aWindowToClear,
window->UpdateCommands(NS_LITERAL_STRING("focus"), nullptr, 0);
SendFocusOrBlurEvent(NS_BLUR_CONTENT, presShell,
content->GetCurrentDoc(), content, 1, false);
content->GetComposedDoc(), content, 1, false);
}
// if we are leaving the document or the window was lowered, make the caret
@ -1777,7 +1777,7 @@ nsFocusManager::Focus(nsPIDOMWindow* aWindow,
aWindow->SetFocusedNode(aContent, focusMethod);
bool sendFocusEvent =
aContent && aContent->IsInDoc() && !IsNonFocusableRoot(aContent);
aContent && aContent->IsInComposedDoc() && !IsNonFocusableRoot(aContent);
nsPresContext* presContext = presShell->GetPresContext();
if (sendFocusEvent) {
// if the focused element changed, scroll it into view
@ -1789,7 +1789,7 @@ nsFocusManager::Focus(nsPIDOMWindow* aWindow,
// if this is an object/plug-in/remote browser, focus its widget. Note that we might
// no longer be in the same document, due to the events we fired above when
// aIsNewDocument.
if (presShell->GetDocument() == aContent->GetDocument()) {
if (presShell->GetDocument() == aContent->GetComposedDoc()) {
if (aAdjustWidgets && objectFrameWidget && !sTestMode)
objectFrameWidget->SetFocus(false);
@ -1810,7 +1810,7 @@ nsFocusManager::Focus(nsPIDOMWindow* aWindow,
aWindow->UpdateCommands(NS_LITERAL_STRING("focus"), nullptr, 0);
SendFocusOrBlurEvent(NS_FOCUS_CONTENT, presShell,
aContent->GetCurrentDoc(),
aContent->GetComposedDoc(),
aContent, aFlags & FOCUSMETHOD_MASK,
aWindowRaised, isRefocus);
} else {
@ -2152,7 +2152,7 @@ nsFocusManager::SetCaretVisible(nsIPresShell* aPresShell,
nsRefPtr<nsFrameSelection> frameSelection;
if (aContent) {
NS_ASSERTION(aContent->GetDocument() == aPresShell->GetDocument(),
NS_ASSERTION(aContent->GetComposedDoc() == aPresShell->GetDocument(),
"Wrong document?");
nsIFrame *focusFrame = aContent->GetPrimaryFrame();
if (focusFrame)
@ -2355,7 +2355,7 @@ nsFocusManager::DetermineElementToMoveFocus(nsPIDOMWindow* aWindow,
nsCOMPtr<nsIDocument> doc;
if (startContent)
doc = startContent->GetCurrentDoc();
doc = startContent->GetComposedDoc();
else
doc = aWindow->GetExtantDoc();
if (!doc)
@ -2447,7 +2447,7 @@ nsFocusManager::DetermineElementToMoveFocus(nsPIDOMWindow* aWindow,
if (startContent == rootContent) {
doNavigation = false;
} else {
nsIDocument* doc = startContent->GetCurrentDoc();
nsIDocument* doc = startContent->GetComposedDoc();
if (startContent ==
nsLayoutUtils::GetEditableRootContentByContentEditable(doc)) {
doNavigation = false;
@ -2769,7 +2769,7 @@ nsFocusManager::GetNextTabbableContent(nsIPresShell* aPresShell,
// found a node with a matching tab index. Check if it is a child
// frame. If so, navigate into the child frame instead.
nsIDocument* doc = currentContent->GetCurrentDoc();
nsIDocument* doc = currentContent->GetComposedDoc();
NS_ASSERTION(doc, "content not in document");
nsIDocument* subdoc = doc->GetSubDocumentFor(currentContent);
if (subdoc) {
@ -2862,7 +2862,8 @@ nsFocusManager::GetNextTabbableContent(nsIPresShell* aPresShell,
nsCOMPtr<nsPIDOMWindow> window = GetCurrentWindow(aRootContent);
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
NS_IF_ADDREF(*aResultContent =
GetRootForFocus(window, aRootContent->GetCurrentDoc(), false, true));
GetRootForFocus(window, aRootContent->GetComposedDoc(),
false, true));
}
break;
}
@ -2884,7 +2885,7 @@ nsFocusManager::GetNextTabbableMapArea(bool aForward,
nsAutoString useMap;
aImageContent->GetAttr(kNameSpaceID_None, nsGkAtoms::usemap, useMap);
nsCOMPtr<nsIDocument> doc = aImageContent->GetDocument();
nsCOMPtr<nsIDocument> doc = aImageContent->GetComposedDoc();
if (doc) {
nsCOMPtr<nsIContent> mapContent = doc->FindImageMap(useMap);
if (!mapContent)
@ -3134,7 +3135,7 @@ nsFocusManager::GetNextTabbablePanel(nsIDocument* aDocument, nsIFrame* aCurrentP
// Skip over non-panels
if (popupFrame->GetContent()->Tag() != nsGkAtoms::panel ||
(aDocument && popupFrame->GetContent()->GetCurrentDoc() != aDocument)) {
(aDocument && popupFrame->GetContent()->GetComposedDoc() != aDocument)) {
continue;
}
@ -3166,7 +3167,7 @@ nsFocusManager::GetNextTabbableDocument(nsIContent* aStartContent, bool aForward
nsCOMPtr<nsIDocShell> startDocShell;
if (aStartContent) {
doc = aStartContent->GetCurrentDoc();
doc = aStartContent->GetComposedDoc();
if (doc) {
startDocShell = doc->GetWindow()->GetDocShell();
}

View File

@ -9901,7 +9901,7 @@ nsGlobalWindow::SetFocusedNode(nsIContent* aNode,
{
FORWARD_TO_INNER_VOID(SetFocusedNode, (aNode, aFocusMethod, aNeedsFocus));
if (aNode && aNode->GetCurrentDoc() != mDoc) {
if (aNode && aNode->GetComposedDoc() != mDoc) {
NS_WARNING("Trying to set focus to a node from a wrong document");
return;
}

View File

@ -365,7 +365,7 @@ EventTargetChainItemForChromeTarget(nsTArray<EventTargetChainItem>& aChain,
nsINode* aNode,
EventTargetChainItem* aChild = nullptr)
{
if (!aNode->IsInDoc()) {
if (!aNode->IsInComposedDoc()) {
return nullptr;
}
nsPIDOMWindow* win = aNode->OwnerDoc()->GetInnerWindow();

View File

@ -296,7 +296,7 @@ IMEContentObserver::IsManaging(nsPresContext* aPresContext,
if (!mSelection || !mRootContent || !mEditableNode) {
return false; // failed to initialize.
}
if (!mRootContent->IsInDoc()) {
if (!mRootContent->IsInComposedDoc()) {
return false; // the focused editor has already been reframed.
}
return mEditableNode == IMEStateManager::GetRootEditableNode(aPresContext,

View File

@ -6426,7 +6426,8 @@ nsCSSFrameConstructor::MaybeConstructLazily(Operation aOperation,
if (aOperation == CONTENTINSERT) {
if (aChild->IsRootOfAnonymousSubtree() ||
aChild->HasFlag(NODE_IS_IN_SHADOW_TREE) ||
(aChild->HasFlag(NODE_IS_IN_SHADOW_TREE) &&
!aChild->IsInNativeAnonymousSubtree()) ||
aChild->IsEditable() || aChild->IsXUL()) {
return false;
}
@ -6739,10 +6740,13 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
}
#endif // MOZ_XUL
if (aContainer && aContainer->HasFlag(NODE_IS_IN_SHADOW_TREE)) {
if (aContainer && aContainer->HasFlag(NODE_IS_IN_SHADOW_TREE) &&
!aContainer->IsInNativeAnonymousSubtree() &&
!aFirstNewContent->IsInNativeAnonymousSubtree()) {
// Recreate frames if content is appended into a ShadowRoot
// because children of ShadowRoot are rendered in place of children
// of the host.
//XXXsmaug This is super unefficient!
nsIContent* bindingParent = aContainer->GetBindingParent();
LAYOUT_PHASE_TEMP_EXIT();
nsresult rv = RecreateFramesForContent(bindingParent, false);
@ -7173,10 +7177,14 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer,
return NS_OK;
}
if (aContainer->HasFlag(NODE_IS_IN_SHADOW_TREE)) {
if (aContainer->HasFlag(NODE_IS_IN_SHADOW_TREE) &&
!aContainer->IsInNativeAnonymousSubtree() &&
(!aStartChild || !aStartChild->IsInNativeAnonymousSubtree()) &&
(!aEndChild || !aEndChild->IsInNativeAnonymousSubtree())) {
// Recreate frames if content is inserted into a ShadowRoot
// because children of ShadowRoot are rendered in place of
// the children of the host.
//XXXsmaug This is super unefficient!
nsIContent* bindingParent = aContainer->GetBindingParent();
LAYOUT_PHASE_TEMP_EXIT();
nsresult rv = RecreateFramesForContent(bindingParent, false);
@ -7665,10 +7673,13 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
}
}
if (aContainer && aContainer->HasFlag(NODE_IS_IN_SHADOW_TREE)) {
if (aContainer && aContainer->HasFlag(NODE_IS_IN_SHADOW_TREE) &&
!aContainer->IsInNativeAnonymousSubtree() &&
!aChild->IsInNativeAnonymousSubtree()) {
// Recreate frames if content is removed from a ShadowRoot
// because it may contain an insertion point which can change
// how the host is rendered.
//XXXsmaug This is super unefficient!
nsIContent* bindingParent = aContainer->GetBindingParent();
*aDidReconstruct = true;
LAYOUT_PHASE_TEMP_EXIT();

View File

@ -676,8 +676,8 @@ nsCaret::GetCaretFrameForNodeOffset(nsIContent* aContentNode,
if (!presShell)
return NS_ERROR_FAILURE;
if (!aContentNode || !aContentNode->IsInDoc() ||
presShell->GetDocument() != aContentNode->GetCurrentDoc())
if (!aContentNode || !aContentNode->IsInComposedDoc() ||
presShell->GetDocument() != aContentNode->GetComposedDoc())
return NS_ERROR_FAILURE;
nsRefPtr<nsFrameSelection> frameSelection = GetFrameSelection();
@ -1018,8 +1018,8 @@ void nsCaret::DrawCaret(bool aInvalidate)
mDrawn = false;
return;
}
if (!mLastContent->IsInDoc() ||
presShell->GetDocument() != mLastContent->GetCurrentDoc())
if (!mLastContent->IsInComposedDoc() ||
presShell->GetDocument() != mLastContent->GetComposedDoc())
{
mLastContent = nullptr;
mDrawn = false;

View File

@ -6253,7 +6253,7 @@ nsLayoutUtils::PostRestyleEvent(Element* aElement,
nsRestyleHint aRestyleHint,
nsChangeHint aMinChangeHint)
{
nsIDocument* doc = aElement->GetCurrentDoc();
nsIDocument* doc = aElement->GetComposedDoc();
if (doc) {
nsCOMPtr<nsIPresShell> presShell = doc->GetShell();
if (presShell) {

View File

@ -2721,7 +2721,7 @@ nsPresContext::GetPrimaryFrameFor(nsIContent* aContent)
{
NS_PRECONDITION(aContent, "Don't do that");
if (GetPresShell() &&
GetPresShell()->GetDocument() == aContent->GetCurrentDoc()) {
GetPresShell()->GetDocument() == aContent->GetComposedDoc()) {
return aContent->GetPrimaryFrame();
}
return nullptr;

View File

@ -3530,8 +3530,8 @@ PresShell::ScrollContentIntoView(nsIContent* aContent,
uint32_t aFlags)
{
NS_ENSURE_TRUE(aContent, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsIDocument> currentDoc = aContent->GetCurrentDoc();
NS_ENSURE_STATE(currentDoc);
nsCOMPtr<nsIDocument> composedDoc = aContent->GetComposedDoc();
NS_ENSURE_STATE(composedDoc);
NS_ASSERTION(mDidInitialize, "should have done initial reflow by now");
@ -3549,8 +3549,8 @@ PresShell::ScrollContentIntoView(nsIContent* aContent,
}
// Flush layout and attempt to scroll in the process.
currentDoc->SetNeedLayoutFlush();
currentDoc->FlushPendingNotifications(Flush_InterruptibleLayout);
composedDoc->SetNeedLayoutFlush();
composedDoc->FlushPendingNotifications(Flush_InterruptibleLayout);
// If mContentToScrollTo is non-null, that means we interrupted the reflow
// (or suppressed it altogether because we're suppressing interruptible
@ -4724,7 +4724,7 @@ PresShell::StyleRuleRemoved(nsIDocument *aDocument,
nsIFrame*
PresShell::GetRealPrimaryFrameFor(nsIContent* aContent) const
{
if (aContent->GetDocument() != GetDocument()) {
if (aContent->GetComposedDoc() != GetDocument()) {
return nullptr;
}
nsIFrame *primaryFrame = aContent->GetPrimaryFrame();
@ -6467,7 +6467,7 @@ bool PresShell::InZombieDocument(nsIContent *aContent)
// 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.
nsIDocument *doc = aContent->GetDocument();
nsIDocument* doc = aContent->GetComposedDoc();
return !doc || !doc->GetWindow();
}
@ -7354,8 +7354,8 @@ PresShell::HandleEvent(nsIFrame* aFrame,
// content area from grabbing the focus from chrome in-between key
// events.
if (eventTarget &&
nsContentUtils::IsChromeDoc(gKeyDownTarget->GetCurrentDoc()) !=
nsContentUtils::IsChromeDoc(eventTarget->GetCurrentDoc())) {
nsContentUtils::IsChromeDoc(gKeyDownTarget->GetComposedDoc()) !=
nsContentUtils::IsChromeDoc(eventTarget->GetComposedDoc())) {
eventTarget = gKeyDownTarget;
}

View File

@ -244,7 +244,7 @@ nsTextControlFrame::EnsureEditorInitialized()
if (mEditorHasBeenInitialized)
return NS_OK;
nsIDocument* doc = mContent->GetCurrentDoc();
nsIDocument* doc = mContent->GetComposedDoc();
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
nsWeakFrame weakFrame(this);

View File

@ -3277,8 +3277,8 @@ CompareToRangeStart(nsINode* aCompareNode, int32_t aCompareOffset,
NS_ENSURE_STATE(aCompareNode && start);
// If the nodes that we're comparing are not in the same document,
// assume that aCompareNode will fall at the end of the ranges.
if (aCompareNode->GetCurrentDoc() != start->GetCurrentDoc() ||
!start->GetCurrentDoc()) {
if (aCompareNode->GetComposedDoc() != start->GetComposedDoc() ||
!start->GetComposedDoc()) {
*aCmp = 1;
} else {
*aCmp = nsContentUtils::ComparePoints(aCompareNode, aCompareOffset,
@ -3295,8 +3295,8 @@ CompareToRangeEnd(nsINode* aCompareNode, int32_t aCompareOffset,
NS_ENSURE_STATE(aCompareNode && end);
// If the nodes that we're comparing are not in the same document,
// assume that aCompareNode will fall at the end of the ranges.
if (aCompareNode->GetCurrentDoc() != end->GetCurrentDoc() ||
!end->GetCurrentDoc()) {
if (aCompareNode->GetComposedDoc() != end->GetComposedDoc() ||
!end->GetComposedDoc()) {
*aCmp = 1;
} else {
*aCmp = nsContentUtils::ComparePoints(aCompareNode, aCompareOffset,

View File

@ -526,11 +526,11 @@ nsComputedDOMStyle::GetAdjustedValuesForBoxSizing()
nsIPresShell*
nsComputedDOMStyle::GetPresShellForContent(nsIContent* aContent)
{
nsIDocument* currentDoc = aContent->GetCurrentDoc();
if (!currentDoc)
nsIDocument* composedDoc = aContent->GetComposedDoc();
if (!composedDoc)
return nullptr;
return currentDoc->GetShell();
return composedDoc->GetShell();
}
// nsDOMCSSDeclaration abstract methods which should never be called