void SelectionManager::NormalSelectionChanged(nsISelection* aSelection) { mLastUsedSelection = do_GetWeakReference(aSelection); int32_t rangeCount = 0; aSelection->GetRangeCount(&rangeCount); if (rangeCount == 0) { mLastTextAccessible = nullptr; return; // No selection } HyperTextAccessible* textAcc = nsAccUtils::GetTextAccessibleFromSelection(aSelection); if (!textAcc) return; int32_t caretOffset = -1; nsresult rv = textAcc->GetCaretOffset(&caretOffset); if (NS_FAILED(rv)) return; if (textAcc == mLastTextAccessible && caretOffset == mLastCaretOffset) { int32_t selectionCount = 0; textAcc->GetSelectionCount(&selectionCount); // Don't swallow similar events when selecting text if (!selectionCount) return; // Swallow duplicate caret event } mLastCaretOffset = caretOffset; mLastTextAccessible = textAcc; nsRefPtr<AccEvent> event = new AccCaretMoveEvent(mLastTextAccessible); mLastTextAccessible->Document()->FireDelayedEvent(event); }
void SelectionManager::ProcessTextSelChangeEvent(AccEvent* aEvent) { AccTextSelChangeEvent* event = downcast_accEvent(aEvent); Selection* sel = static_cast<Selection*>(event->mSel.get()); // Fire selection change event if it's not pure caret-move selection change. if (sel->GetRangeCount() != 1 || !sel->IsCollapsed()) nsEventShell::FireEvent(aEvent); // Fire caret move event if there's a caret in the selection. nsINode* caretCntrNode = nsCoreUtils::GetDOMNodeFromDOMPoint(sel->GetFocusNode(), sel->GetFocusOffset()); 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; int32_t caretOffset = -1; if (NS_SUCCEEDED(caretCntr->GetCaretOffset(&caretOffset)) && caretOffset != -1) { nsRefPtr<AccCaretMoveEvent> caretMoveEvent = new AccCaretMoveEvent(caretCntr, caretOffset, aEvent->FromUserInput()); nsEventShell::FireEvent(caretMoveEvent); } }
static gint getCaretOffsetCB(AtkText *aText) { AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText)); if (!accWrap) return 0; HyperTextAccessible* text = accWrap->AsHyperText(); if (!text || !text->IsTextRole()) return 0; int32_t offset; nsresult rv = text->GetCaretOffset(&offset); return (NS_FAILED(rv)) ? 0 : static_cast<gint>(offset); }
void EventQueue::ProcessEventQueue() { // Process only currently queued events. nsTArray<nsRefPtr<AccEvent> > events; events.SwapElements(mEvents); uint32_t eventCount = events.Length(); #ifdef A11Y_LOG if (eventCount > 0 && logging::IsEnabled(logging::eEvents)) { logging::MsgBegin("EVENTS", "events processing"); logging::Address("document", mDocument); logging::MsgEnd(); } #endif for (uint32_t idx = 0; idx < eventCount; idx++) { AccEvent* event = events[idx]; if (event->mEventRule != AccEvent::eDoNotEmit) { Accessible* target = event->GetAccessible(); if (!target || target->IsDefunct()) continue; // Dispatch the focus event if target is still focused. if (event->mEventType == nsIAccessibleEvent::EVENT_FOCUS) { FocusMgr()->ProcessFocusEvent(event); continue; } // Dispatch caret moved and text selection change events. if (event->mEventType == nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED) { AccCaretMoveEvent* caretMoveEvent = downcast_accEvent(event); HyperTextAccessible* hyperText = target->AsHyperText(); if (hyperText && NS_SUCCEEDED(hyperText->GetCaretOffset(&caretMoveEvent->mCaretOffset))) { nsEventShell::FireEvent(caretMoveEvent); // There's a selection so fire selection change as well. int32_t selectionCount; hyperText->GetSelectionCount(&selectionCount); if (selectionCount) nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED, hyperText); } continue; } // Fire selected state change events in support to selection events. if (event->mEventType == nsIAccessibleEvent::EVENT_SELECTION_ADD) { nsEventShell::FireEvent(event->mAccessible, states::SELECTED, true, event->mIsFromUserInput); } else if (event->mEventType == nsIAccessibleEvent::EVENT_SELECTION_REMOVE) { nsEventShell::FireEvent(event->mAccessible, states::SELECTED, false, event->mIsFromUserInput); } else if (event->mEventType == nsIAccessibleEvent::EVENT_SELECTION) { AccSelChangeEvent* selChangeEvent = downcast_accEvent(event); nsEventShell::FireEvent(event->mAccessible, states::SELECTED, (selChangeEvent->mSelChangeType == AccSelChangeEvent::eSelectionAdd), event->mIsFromUserInput); if (selChangeEvent->mPackedEvent) { nsEventShell::FireEvent(selChangeEvent->mPackedEvent->mAccessible, states::SELECTED, (selChangeEvent->mPackedEvent->mSelChangeType == AccSelChangeEvent::eSelectionAdd), selChangeEvent->mPackedEvent->mIsFromUserInput); } } nsEventShell::FireEvent(event); // Fire text change events. AccMutationEvent* mutationEvent = downcast_accEvent(event); if (mutationEvent) { if (mutationEvent->mTextChangeEvent) nsEventShell::FireEvent(mutationEvent->mTextChangeEvent); } } if (event->mEventType == nsIAccessibleEvent::EVENT_HIDE) mDocument->ShutdownChildrenInSubtree(event->mAccessible); if (!mDocument) return; } }