summaryrefslogtreecommitdiffstats
path: root/accessible/base/AccessibleOrProxy.h
blob: 415ce7273d3ca4aaa7e785a7de31a61c7ea66c56 (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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/* -*- 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/. */

#ifndef mozilla_a11y_AccessibleOrProxy_h
#define mozilla_a11y_AccessibleOrProxy_h

#include "mozilla/a11y/Accessible.h"
#include "mozilla/a11y/ProxyAccessible.h"
#include "mozilla/a11y/Role.h"

#include <stdint.h>

namespace mozilla {
namespace a11y {

/**
 * This class stores an Accessible* or a ProxyAccessible* in a safe manner
 * with size sizeof(void*).
 */
class AccessibleOrProxy {
 public:
  MOZ_IMPLICIT AccessibleOrProxy(Accessible* aAcc)
      : mBits(reinterpret_cast<uintptr_t>(aAcc)) {}
  MOZ_IMPLICIT AccessibleOrProxy(ProxyAccessible* aProxy)
      : mBits(aProxy ? (reinterpret_cast<uintptr_t>(aProxy) | IS_PROXY) : 0) {}
  MOZ_IMPLICIT AccessibleOrProxy(decltype(nullptr)) : mBits(0) {}
  MOZ_IMPLICIT AccessibleOrProxy() : mBits(0) {}

  bool IsProxy() const { return mBits & IS_PROXY; }
  ProxyAccessible* AsProxy() const {
    if (IsProxy()) {
      return reinterpret_cast<ProxyAccessible*>(mBits & ~IS_PROXY);
    }

    return nullptr;
  }

  bool IsAccessible() const { return !IsProxy(); }
  Accessible* AsAccessible() const {
    if (IsAccessible()) {
      return reinterpret_cast<Accessible*>(mBits);
    }

    return nullptr;
  }

  bool IsNull() const { return mBits == 0; }

  uint32_t ChildCount() const {
    if (IsProxy()) {
      return AsProxy()->ChildrenCount();
    }

    if (RemoteChildDoc()) {
      return 1;
    }

    return AsAccessible()->ChildCount();
  }

  /**
   * Return true if the object has children, false otherwise
   */
  bool HasChildren() const { return ChildCount() > 0; }

  /**
   * Return the child object either an accessible or a proxied accessible at
   * the given index.
   */
  AccessibleOrProxy ChildAt(uint32_t aIdx) const {
    if (IsProxy()) {
      return AsProxy()->ChildAt(aIdx);
    }

    ProxyAccessible* childDoc = RemoteChildDoc();
    if (childDoc && aIdx == 0) {
      return childDoc;
    }

    return AsAccessible()->GetChildAt(aIdx);
  }

  /**
   * Return the first child object.
   */
  AccessibleOrProxy FirstChild() {
    if (IsProxy()) {
      return AsProxy()->FirstChild();
    }

    ProxyAccessible* childDoc = RemoteChildDoc();
    if (childDoc) {
      return childDoc;
    }

    return AsAccessible()->FirstChild();
  }

  /**
   * Return the last child object.
   */
  AccessibleOrProxy LastChild() {
    if (IsProxy()) {
      return AsProxy()->LastChild();
    }

    ProxyAccessible* childDoc = RemoteChildDoc();
    if (childDoc) {
      return childDoc;
    }

    return AsAccessible()->LastChild();
  }

  /**
   * Return the next sibling object.
   */
  AccessibleOrProxy NextSibling() {
    if (IsProxy()) {
      return AsProxy()->NextSibling();
    }

    return AsAccessible()->NextSibling();
  }

  /**
   * Return the prev sibling object.
   */
  AccessibleOrProxy PrevSibling() {
    if (IsProxy()) {
      return AsProxy()->PrevSibling();
    }

    return AsAccessible()->PrevSibling();
  }

  role Role() const {
    if (IsProxy()) {
      return AsProxy()->Role();
    }

    return AsAccessible()->Role();
  }

  int32_t IndexInParent() const;

  AccessibleOrProxy Parent() const;

  AccessibleOrProxy ChildAtPoint(int32_t aX, int32_t aY,
                                 Accessible::EWhichChildAtPoint aWhichChild);

  bool operator!=(const AccessibleOrProxy& aOther) const {
    return mBits != aOther.mBits;
  }

  bool operator==(const AccessibleOrProxy& aOther) const {
    return mBits == aOther.mBits;
  }

  // XXX these are implementation details that ideally would not be exposed.
  uintptr_t Bits() const { return mBits; }
  void SetBits(uintptr_t aBits) { mBits = aBits; }

 private:
  /**
   * If this is an OuterDocAccessible, return the remote child document.
   */
  ProxyAccessible* RemoteChildDoc() const;

  uintptr_t mBits;
  static const uintptr_t IS_PROXY = 0x1;
};

}  // namespace a11y
}  // namespace mozilla

#endif