1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/accessible/src/base/AccEvent.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,255 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "AccEvent.h" 1.11 + 1.12 +#include "nsAccUtils.h" 1.13 +#include "DocAccessible.h" 1.14 +#include "xpcAccEvents.h" 1.15 +#include "States.h" 1.16 + 1.17 +#include "mozilla/EventStateManager.h" 1.18 +#include "mozilla/dom/Selection.h" 1.19 + 1.20 +using namespace mozilla; 1.21 +using namespace mozilla::a11y; 1.22 + 1.23 +static_assert(static_cast<bool>(eNoUserInput) == false && 1.24 + static_cast<bool>(eFromUserInput) == true, 1.25 + "EIsFromUserInput cannot be casted to bool"); 1.26 + 1.27 +//////////////////////////////////////////////////////////////////////////////// 1.28 +// AccEvent 1.29 +//////////////////////////////////////////////////////////////////////////////// 1.30 + 1.31 +//////////////////////////////////////////////////////////////////////////////// 1.32 +// AccEvent constructors 1.33 + 1.34 +AccEvent::AccEvent(uint32_t aEventType, Accessible* aAccessible, 1.35 + EIsFromUserInput aIsFromUserInput, EEventRule aEventRule) : 1.36 + mEventType(aEventType), mEventRule(aEventRule), mAccessible(aAccessible) 1.37 +{ 1.38 + if (aIsFromUserInput == eAutoDetect) 1.39 + mIsFromUserInput = EventStateManager::IsHandlingUserInput(); 1.40 + else 1.41 + mIsFromUserInput = aIsFromUserInput == eFromUserInput ? true : false; 1.42 +} 1.43 + 1.44 +//////////////////////////////////////////////////////////////////////////////// 1.45 +// AccEvent cycle collection 1.46 + 1.47 +NS_IMPL_CYCLE_COLLECTION(AccEvent, mAccessible) 1.48 + 1.49 +NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AccEvent, AddRef) 1.50 +NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AccEvent, Release) 1.51 + 1.52 +//////////////////////////////////////////////////////////////////////////////// 1.53 +//////////////////////////////////////////////////////////////////////////////// 1.54 +// AccTextChangeEvent 1.55 +//////////////////////////////////////////////////////////////////////////////// 1.56 + 1.57 +// Note: we pass in eAllowDupes to the base class because we don't support text 1.58 +// events coalescence. We fire delayed text change events in DocAccessible but 1.59 +// we continue to base the event off the accessible object rather than just the 1.60 +// node. This means we won't try to create an accessible based on the node when 1.61 +// we are ready to fire the event and so we will no longer assert at that point 1.62 +// if the node was removed from the document. Either way, the AT won't work with 1.63 +// a defunct accessible so the behaviour should be equivalent. 1.64 +AccTextChangeEvent:: 1.65 + AccTextChangeEvent(Accessible* aAccessible, int32_t aStart, 1.66 + const nsAString& aModifiedText, bool aIsInserted, 1.67 + EIsFromUserInput aIsFromUserInput) 1.68 + : AccEvent(aIsInserted ? 1.69 + static_cast<uint32_t>(nsIAccessibleEvent::EVENT_TEXT_INSERTED) : 1.70 + static_cast<uint32_t>(nsIAccessibleEvent::EVENT_TEXT_REMOVED), 1.71 + aAccessible, aIsFromUserInput, eAllowDupes) 1.72 + , mStart(aStart) 1.73 + , mIsInserted(aIsInserted) 1.74 + , mModifiedText(aModifiedText) 1.75 +{ 1.76 + // XXX We should use IsFromUserInput here, but that isn't always correct 1.77 + // when the text change isn't related to content insertion or removal. 1.78 + mIsFromUserInput = mAccessible->State() & 1.79 + (states::FOCUSED | states::EDITABLE); 1.80 +} 1.81 + 1.82 + 1.83 +//////////////////////////////////////////////////////////////////////////////// 1.84 +// AccReorderEvent 1.85 +//////////////////////////////////////////////////////////////////////////////// 1.86 + 1.87 +uint32_t 1.88 +AccReorderEvent::IsShowHideEventTarget(const Accessible* aTarget) const 1.89 +{ 1.90 + uint32_t count = mDependentEvents.Length(); 1.91 + for (uint32_t index = count - 1; index < count; index--) { 1.92 + if (mDependentEvents[index]->mAccessible == aTarget) { 1.93 + uint32_t eventType = mDependentEvents[index]->mEventType; 1.94 + if (eventType == nsIAccessibleEvent::EVENT_SHOW || 1.95 + eventType == nsIAccessibleEvent::EVENT_HIDE) { 1.96 + return mDependentEvents[index]->mEventType; 1.97 + } 1.98 + } 1.99 + } 1.100 + 1.101 + return 0; 1.102 +} 1.103 + 1.104 +//////////////////////////////////////////////////////////////////////////////// 1.105 +// AccHideEvent 1.106 +//////////////////////////////////////////////////////////////////////////////// 1.107 + 1.108 +AccHideEvent:: 1.109 + AccHideEvent(Accessible* aTarget, nsINode* aTargetNode) : 1.110 + AccMutationEvent(::nsIAccessibleEvent::EVENT_HIDE, aTarget, aTargetNode) 1.111 +{ 1.112 + mNextSibling = mAccessible->NextSibling(); 1.113 + mPrevSibling = mAccessible->PrevSibling(); 1.114 +} 1.115 + 1.116 + 1.117 +//////////////////////////////////////////////////////////////////////////////// 1.118 +// AccShowEvent 1.119 +//////////////////////////////////////////////////////////////////////////////// 1.120 + 1.121 +AccShowEvent:: 1.122 + AccShowEvent(Accessible* aTarget, nsINode* aTargetNode) : 1.123 + AccMutationEvent(::nsIAccessibleEvent::EVENT_SHOW, aTarget, aTargetNode) 1.124 +{ 1.125 +} 1.126 + 1.127 + 1.128 +//////////////////////////////////////////////////////////////////////////////// 1.129 +// AccTextSelChangeEvent 1.130 +//////////////////////////////////////////////////////////////////////////////// 1.131 + 1.132 +AccTextSelChangeEvent::AccTextSelChangeEvent(HyperTextAccessible* aTarget, 1.133 + dom::Selection* aSelection, 1.134 + int32_t aReason) : 1.135 + AccEvent(nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED, aTarget, 1.136 + eAutoDetect, eCoalesceTextSelChange), 1.137 + mSel(aSelection), mReason(aReason) {} 1.138 + 1.139 +AccTextSelChangeEvent::~AccTextSelChangeEvent() { } 1.140 + 1.141 +bool 1.142 +AccTextSelChangeEvent::IsCaretMoveOnly() const 1.143 +{ 1.144 + return mSel->GetRangeCount() == 1 && mSel->IsCollapsed() && 1.145 + ((mReason & (nsISelectionListener::COLLAPSETOSTART_REASON | 1.146 + nsISelectionListener::COLLAPSETOEND_REASON)) == 0); 1.147 +} 1.148 + 1.149 +//////////////////////////////////////////////////////////////////////////////// 1.150 +// AccSelChangeEvent 1.151 +//////////////////////////////////////////////////////////////////////////////// 1.152 + 1.153 +AccSelChangeEvent:: 1.154 + AccSelChangeEvent(Accessible* aWidget, Accessible* aItem, 1.155 + SelChangeType aSelChangeType) : 1.156 + AccEvent(0, aItem, eAutoDetect, eCoalesceSelectionChange), 1.157 + mWidget(aWidget), mItem(aItem), mSelChangeType(aSelChangeType), 1.158 + mPreceedingCount(0), mPackedEvent(nullptr) 1.159 +{ 1.160 + if (aSelChangeType == eSelectionAdd) { 1.161 + if (mWidget->GetSelectedItem(1)) 1.162 + mEventType = nsIAccessibleEvent::EVENT_SELECTION_ADD; 1.163 + else 1.164 + mEventType = nsIAccessibleEvent::EVENT_SELECTION; 1.165 + } else { 1.166 + mEventType = nsIAccessibleEvent::EVENT_SELECTION_REMOVE; 1.167 + } 1.168 +} 1.169 + 1.170 + 1.171 +//////////////////////////////////////////////////////////////////////////////// 1.172 +// AccTableChangeEvent 1.173 +//////////////////////////////////////////////////////////////////////////////// 1.174 + 1.175 +AccTableChangeEvent:: 1.176 + AccTableChangeEvent(Accessible* aAccessible, uint32_t aEventType, 1.177 + int32_t aRowOrColIndex, int32_t aNumRowsOrCols) : 1.178 + AccEvent(aEventType, aAccessible), 1.179 + mRowOrColIndex(aRowOrColIndex), mNumRowsOrCols(aNumRowsOrCols) 1.180 +{ 1.181 +} 1.182 + 1.183 + 1.184 +//////////////////////////////////////////////////////////////////////////////// 1.185 +// AccVCChangeEvent 1.186 +//////////////////////////////////////////////////////////////////////////////// 1.187 + 1.188 +AccVCChangeEvent:: 1.189 + AccVCChangeEvent(Accessible* aAccessible, 1.190 + nsIAccessible* aOldAccessible, 1.191 + int32_t aOldStart, int32_t aOldEnd, 1.192 + int16_t aReason) : 1.193 + AccEvent(::nsIAccessibleEvent::EVENT_VIRTUALCURSOR_CHANGED, aAccessible), 1.194 + mOldAccessible(aOldAccessible), mOldStart(aOldStart), mOldEnd(aOldEnd), 1.195 + mReason(aReason) 1.196 +{ 1.197 +} 1.198 + 1.199 +already_AddRefed<nsIAccessibleEvent> 1.200 +a11y::MakeXPCEvent(AccEvent* aEvent) 1.201 +{ 1.202 + DocAccessible* doc = aEvent->GetDocAccessible(); 1.203 + Accessible* acc = aEvent->GetAccessible(); 1.204 + nsINode* node = acc->GetNode(); 1.205 + nsIDOMNode* domNode = node ? node->AsDOMNode() : nullptr; 1.206 + bool fromUser = aEvent->IsFromUserInput(); 1.207 + uint32_t type = aEvent->GetEventType(); 1.208 + uint32_t eventGroup = aEvent->GetEventGroups(); 1.209 + nsCOMPtr<nsIAccessibleEvent> xpEvent; 1.210 + 1.211 + if (eventGroup & (1 << AccEvent::eStateChangeEvent)) { 1.212 + AccStateChangeEvent* sc = downcast_accEvent(aEvent); 1.213 + bool extra = false; 1.214 + uint32_t state = nsAccUtils::To32States(sc->GetState(), &extra); 1.215 + xpEvent = new xpcAccStateChangeEvent(type, acc, doc, domNode, fromUser, 1.216 + state, extra, sc->IsStateEnabled()); 1.217 + return xpEvent.forget(); 1.218 + } 1.219 + 1.220 + if (eventGroup & (1 << AccEvent::eTextChangeEvent)) { 1.221 + AccTextChangeEvent* tc = downcast_accEvent(aEvent); 1.222 + nsString text; 1.223 + tc->GetModifiedText(text); 1.224 + xpEvent = new xpcAccTextChangeEvent(type, acc, doc, domNode, fromUser, 1.225 + tc->GetStartOffset(), tc->GetLength(), 1.226 + tc->IsTextInserted(), text); 1.227 + return xpEvent.forget(); 1.228 + } 1.229 + 1.230 + if (eventGroup & (1 << AccEvent::eHideEvent)) { 1.231 + AccHideEvent* hideEvent = downcast_accEvent(aEvent); 1.232 + xpEvent = new xpcAccHideEvent(type, acc, doc, domNode, fromUser, 1.233 + hideEvent->TargetParent(), 1.234 + hideEvent->TargetNextSibling(), 1.235 + hideEvent->TargetPrevSibling()); 1.236 + return xpEvent.forget(); 1.237 + } 1.238 + 1.239 + if (eventGroup & (1 << AccEvent::eCaretMoveEvent)) { 1.240 + AccCaretMoveEvent* cm = downcast_accEvent(aEvent); 1.241 + xpEvent = new xpcAccCaretMoveEvent(type, acc, doc, domNode, fromUser, 1.242 + cm->GetCaretOffset()); 1.243 + return xpEvent.forget(); 1.244 + } 1.245 + 1.246 + if (eventGroup & (1 << AccEvent::eVirtualCursorChangeEvent)) { 1.247 + AccVCChangeEvent* vcc = downcast_accEvent(aEvent); 1.248 + xpEvent = new xpcAccVirtualCursorChangeEvent(type, acc, doc, domNode, fromUser, 1.249 + vcc->OldAccessible(), 1.250 + vcc->OldStartOffset(), 1.251 + vcc->OldEndOffset(), 1.252 + vcc->Reason()); 1.253 + return xpEvent.forget(); 1.254 + } 1.255 + 1.256 + xpEvent = new xpcAccEvent(type, acc, doc, domNode, fromUser); 1.257 + return xpEvent.forget(); 1.258 + }