accessible/src/base/AccEvent.cpp

changeset 0
6474c204b198
     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 +  }

mercurial