void SelectionManager::ProcessSelectionChanged(nsISelection* aSelection) { Selection* selection = static_cast<Selection*>(aSelection); const nsRange* range = selection->GetAnchorFocusRange(); nsINode* cntrNode = nullptr; if (range) cntrNode = range->GetCommonAncestor(); if (!cntrNode) { cntrNode = selection->GetFrameSelection()->GetAncestorLimiter(); if (!cntrNode) { cntrNode = selection->GetPresShell()->GetDocument(); NS_ASSERTION(selection->GetPresShell()->ConstFrameSelection() == selection->GetFrameSelection(), "Wrong selection container was used!"); } } HyperTextAccessible* text = nsAccUtils::GetTextContainer(cntrNode); if (!text) { NS_NOTREACHED("We must reach document accessible implementing text interface!"); return; } if (selection->GetType() == nsISelectionController::SELECTION_NORMAL) { nsRefPtr<AccEvent> event = new AccTextSelChangeEvent(text, aSelection); text->Document()->FireDelayedEvent(event); } else if (selection->GetType() == nsISelectionController::SELECTION_SPELLCHECK) { // XXX: fire an event for container accessible of the focus/anchor range // of the spelcheck selection. text->Document()->FireDelayedEvent(nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED, text); } }
void SelectionManager::ProcessSelectionChanged(SelData* aSelData) { Selection* selection = aSelData->mSel; if (!selection->GetPresShell()) return; const nsRange* range = selection->GetAnchorFocusRange(); nsINode* cntrNode = nullptr; if (range) cntrNode = range->GetCommonAncestor(); if (!cntrNode) { cntrNode = selection->GetFrameSelection()->GetAncestorLimiter(); if (!cntrNode) { cntrNode = selection->GetPresShell()->GetDocument(); NS_ASSERTION(aSelData->mSel->GetPresShell()->ConstFrameSelection() == selection->GetFrameSelection(), "Wrong selection container was used!"); } } HyperTextAccessible* text = nsAccUtils::GetTextContainer(cntrNode); if (!text) { // FIXME bug 1126649 NS_ERROR("We must reach document accessible implementing text interface!"); return; } if (selection->GetType() == SelectionType::eNormal) { RefPtr<AccEvent> event = new AccTextSelChangeEvent(text, selection, aSelData->mReason); text->Document()->FireDelayedEvent(event); } else if (selection->GetType() == SelectionType::eSpellCheck) { // XXX: fire an event for container accessible of the focus/anchor range // of the spelcheck selection. text->Document()->FireDelayedEvent( nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED, text); } }
void AccessibleCaretManager::DispatchCaretStateChangedEvent(CaretChangedReason aReason) const { // Holding PresShell to prevent AccessibleCaretManager to be destroyed. nsCOMPtr<nsIPresShell> presShell = mPresShell; FlushLayout(); if (presShell->IsDestroying()) { return; } Selection* sel = GetSelection(); if (!sel) { return; } nsIDocument* doc = mPresShell->GetDocument(); MOZ_ASSERT(doc); CaretStateChangedEventInit init; init.mBubbles = true; const nsRange* range = sel->GetAnchorFocusRange(); nsINode* commonAncestorNode = nullptr; if (range) { commonAncestorNode = range->GetCommonAncestor(); } if (!commonAncestorNode) { commonAncestorNode = sel->GetFrameSelection()->GetAncestorLimiter(); } RefPtr<DOMRect> domRect = new DOMRect(ToSupports(doc)); nsRect rect = nsLayoutUtils::GetSelectionBoundingRect(sel); nsIFrame* commonAncestorFrame = nullptr; nsIFrame* rootFrame = mPresShell->GetRootFrame(); if (commonAncestorNode && commonAncestorNode->IsContent()) { commonAncestorFrame = commonAncestorNode->AsContent()->GetPrimaryFrame(); } if (commonAncestorFrame && rootFrame) { nsLayoutUtils::TransformRect(rootFrame, commonAncestorFrame, rect); nsRect clampedRect = nsLayoutUtils::ClampRectToScrollFrames(commonAncestorFrame, rect); nsLayoutUtils::TransformRect(commonAncestorFrame, rootFrame, clampedRect); domRect->SetLayoutRect(clampedRect); init.mSelectionVisible = !clampedRect.IsEmpty(); } else { domRect->SetLayoutRect(rect); init.mSelectionVisible = true; } // Send isEditable info w/ event detail. This info can help determine // whether to show cut command on selection dialog or not. init.mSelectionEditable = commonAncestorFrame && GetEditingHostForFrame(commonAncestorFrame); init.mBoundingClientRect = domRect; init.mReason = aReason; init.mCollapsed = sel->IsCollapsed(); init.mCaretVisible = mFirstCaret->IsLogicallyVisible() || mSecondCaret->IsLogicallyVisible(); init.mCaretVisuallyVisible = mFirstCaret->IsVisuallyVisible() || mSecondCaret->IsVisuallyVisible(); sel->Stringify(init.mSelectedTextContent); RefPtr<CaretStateChangedEvent> event = CaretStateChangedEvent::Constructor(doc, NS_LITERAL_STRING("mozcaretstatechanged"), init); event->SetTrusted(true); event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true; AC_LOG("%s: reason %d, collapsed %d, caretVisible %d", __FUNCTION__, init.mReason, init.mCollapsed, init.mCaretVisible); (new AsyncEventDispatcher(doc, event))->RunDOMEventWhenSafe(); }
void AccessibleCaretManager::DispatchCaretStateChangedEvent(CaretChangedReason aReason) const { // Holding PresShell to prevent AccessibleCaretManager to be destroyed. nsCOMPtr<nsIPresShell> presShell = mPresShell; // XXX: Do we need to flush layout? presShell->FlushPendingNotifications(Flush_Layout); if (presShell->IsDestroying()) { return; } Selection* sel = GetSelection(); if (!sel) { return; } nsIDocument* doc = mPresShell->GetDocument(); MOZ_ASSERT(doc); CaretStateChangedEventInit init; init.mBubbles = true; const nsRange* range = sel->GetAnchorFocusRange(); nsINode* commonAncestorNode = nullptr; if (range) { commonAncestorNode = range->GetCommonAncestor(); } if (!commonAncestorNode) { commonAncestorNode = sel->GetFrameSelection()->GetAncestorLimiter(); } nsRefPtr<DOMRect> domRect = new DOMRect(ToSupports(doc)); nsRect rect = nsContentUtils::GetSelectionBoundingRect(sel); nsIFrame* commonAncestorFrame = nullptr; nsIFrame* rootFrame = mPresShell->GetRootFrame(); if (commonAncestorNode && commonAncestorNode->IsContent()) { commonAncestorFrame = commonAncestorNode->AsContent()->GetPrimaryFrame(); } if (commonAncestorFrame && rootFrame) { nsLayoutUtils::TransformRect(rootFrame, commonAncestorFrame, rect); nsRect clampedRect = nsLayoutUtils::ClampRectToScrollFrames(commonAncestorFrame, rect); nsLayoutUtils::TransformRect(commonAncestorFrame, rootFrame, clampedRect); domRect->SetLayoutRect(clampedRect); init.mSelectionVisible = !clampedRect.IsEmpty(); } else { domRect->SetLayoutRect(rect); init.mSelectionVisible = true; } init.mBoundingClientRect = domRect; init.mReason = aReason; init.mCollapsed = sel->IsCollapsed(); init.mCaretVisible = mFirstCaret->IsLogicallyVisible() || mSecondCaret->IsLogicallyVisible(); nsRefPtr<CaretStateChangedEvent> event = CaretStateChangedEvent::Constructor(doc, NS_LITERAL_STRING("mozcaretstatechanged"), init); event->SetTrusted(true); event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true; (new AsyncEventDispatcher(doc, event))->RunDOMEventWhenSafe(); }