void SelectionManager::ProcessTextSelChangeEvent(AccEvent* aEvent) { // Fire selection change event if it's not pure caret-move selection change, // i.e. the accessible has or had not collapsed selection. AccTextSelChangeEvent* event = downcast_accEvent(aEvent); if (!event->IsCaretMoveOnly()) nsEventShell::FireEvent(aEvent); // Fire caret move event if there's a caret in the selection. nsINode* caretCntrNode = nsCoreUtils::GetDOMNodeFromDOMPoint( event->mSel->GetFocusNode(), event->mSel->FocusOffset()); if (!caretCntrNode) return; HyperTextAccessible* caretCntr = nsAccUtils::GetTextContainer(caretCntrNode); NS_ASSERTION( caretCntr, "No text container for focus while there's one for common ancestor?!"); if (!caretCntr) return; Selection* selection = caretCntr->DOMSelection(); // XXX Sometimes we can't get a selection for caretCntr, in that case assume // event->mSel is correct. if (!selection) selection = event->mSel; mCaretOffset = caretCntr->DOMPointToOffset(selection->GetFocusNode(), selection->FocusOffset()); mAccWithCaret = caretCntr; if (mCaretOffset != -1) { RefPtr<AccCaretMoveEvent> caretMoveEvent = new AccCaretMoveEvent(caretCntr, mCaretOffset, aEvent->FromUserInput()); nsEventShell::FireEvent(caretMoveEvent); } }
void AccessibleCaretManager::UpdateCaretsForCursorMode() { AC_LOG("%s, selection: %p", __FUNCTION__, GetSelection()); nsRefPtr<nsCaret> caret = mPresShell->GetCaret(); if (!caret || !caret->IsVisible()) { HideCarets(); return; } nsRefPtr<nsFrameSelection> fs = GetFrameSelection(); Selection* selection = GetSelection(); if (!fs || !selection) { HideCarets(); return; } nsINode* focusNode = selection->GetFocusNode(); nsIContent* focusContent = focusNode->AsContent(); uint32_t focusOffset = selection->FocusOffset(); nsIFrame* frame = nullptr; int32_t offset = 0; nsresult rv = nsCaret::GetCaretFrameForNodeOffset( fs, focusContent, focusOffset, fs->GetHint(), fs->GetCaretBidiLevel(), &frame, &offset); if (NS_FAILED(rv) || !frame) { HideCarets(); return; } Element* editingHost = frame->GetContent()->GetEditingHost(); if (!editingHost) { HideCarets(); return; } // No need to consider whether the caret's position is out of scrollport. // According to the spec, we need to explicitly hide it after the scrolling is // ended. bool oldSecondCaretVisible = mSecondCaret->IsLogicallyVisible(); PositionChangedResult caretResult = mFirstCaret->SetPosition(frame, offset); mFirstCaret->SetSelectionBarEnabled(false); if (nsContentUtils::HasNonEmptyTextContent( editingHost, nsContentUtils::eRecurseIntoChildren)) { mFirstCaret->SetAppearance(Appearance::Normal); } else { mFirstCaret->SetAppearance(Appearance::NormalNotShown); } LaunchCaretTimeoutTimer(); mSecondCaret->SetAppearance(Appearance::None); if ((caretResult == PositionChangedResult::Changed || oldSecondCaretVisible) && !mActiveCaret) { DispatchCaretStateChangedEvent(CaretChangedReason::Updateposition); } }