summaryrefslogtreecommitdiffstats
path: root/accessible/base/AccessibleOrProxy.cpp
blob: 3826e6968c6210b6874931ef1df12f2045fd70be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "AccessibleOrProxy.h"
#include "mozilla/a11y/DocAccessibleParent.h"
#include "mozilla/a11y/OuterDocAccessible.h"

namespace mozilla {
namespace a11y {

int32_t AccessibleOrProxy::IndexInParent() const {
  if (IsAccessible()) {
    return AsAccessible()->IndexInParent();
  }

  ProxyAccessible* proxy = AsProxy();
  if (!proxy) {
    return -1;
  }

  if (proxy->Parent()) {
    return proxy->IndexInParent();
  }

  if (proxy->OuterDocOfRemoteBrowser()) {
    return 0;
  }

  MOZ_ASSERT_UNREACHABLE("Proxy should have parent or outer doc.");
  return -1;
}

AccessibleOrProxy AccessibleOrProxy::Parent() const {
  if (IsAccessible()) {
    return AsAccessible()->Parent();
  }

  ProxyAccessible* proxy = AsProxy();
  if (!proxy) {
    return nullptr;
  }

  if (ProxyAccessible* parent = proxy->Parent()) {
    return parent;
  }

  // Otherwise this should be the proxy for the tab's top level document.
  return proxy->OuterDocOfRemoteBrowser();
}

AccessibleOrProxy AccessibleOrProxy::ChildAtPoint(
    int32_t aX, int32_t aY, Accessible::EWhichChildAtPoint aWhichChild) {
  if (IsProxy()) {
    return AsProxy()->ChildAtPoint(aX, aY, aWhichChild);
  }
  ProxyAccessible* childDoc = RemoteChildDoc();
  if (childDoc) {
    // This is an OuterDocAccessible.
    nsIntRect docRect = AsAccessible()->Bounds();
    if (!docRect.Contains(aX, aY)) {
      return nullptr;
    }
    if (aWhichChild == Accessible::eDirectChild) {
      return childDoc;
    }
    return childDoc->ChildAtPoint(aX, aY, aWhichChild);
  }
  AccessibleOrProxy target = AsAccessible()->ChildAtPoint(aX, aY, aWhichChild);
  if (target.IsNull() || aWhichChild == Accessible::eDirectChild) {
    return target;
  }
  childDoc = target.RemoteChildDoc();
  if (childDoc) {
    // Accessible::ChildAtPoint stopped at an OuterDocAccessible, since it
    // can't traverse into ProxyAccessibles. Continue the search from childDoc.
    return childDoc->ChildAtPoint(aX, aY, aWhichChild);
  }
  return target;
}

ProxyAccessible* AccessibleOrProxy::RemoteChildDoc() const {
  MOZ_ASSERT(!IsNull());
  if (IsProxy()) {
    return nullptr;
  }
  OuterDocAccessible* outerDoc = AsAccessible()->AsOuterDoc();
  if (!outerDoc) {
    return nullptr;
  }
  return outerDoc->RemoteChildDoc();
}

}  // namespace a11y
}  // namespace mozilla