| 1 | // Copyright (C) 2022 The Qt Company Ltd. |
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
| 3 | |
| 4 | #ifndef QACCESSIBLE_BASE_H |
| 5 | #define QACCESSIBLE_BASE_H |
| 6 | |
| 7 | #include <QtGui/qtguiglobal.h> |
| 8 | #if QT_CONFIG(accessibility) |
| 9 | |
| 10 | #if 0 |
| 11 | // QAccessible class is handled in qaccessible.h |
| 12 | #pragma qt_sync_stop_processing |
| 13 | #endif |
| 14 | |
| 15 | #include <QtCore/qobjectdefs.h> |
| 16 | |
| 17 | #include <cstring> // memset, memcmp |
| 18 | |
| 19 | QT_BEGIN_NAMESPACE |
| 20 | |
| 21 | class QAccessibleInterface; |
| 22 | class QAccessibleEvent; |
| 23 | class QTextCursor; |
| 24 | |
| 25 | class Q_GUI_EXPORT QAccessible |
| 26 | { |
| 27 | Q_GADGET |
| 28 | public: |
| 29 | |
| 30 | enum Event { |
| 31 | SoundPlayed = 0x0001, |
| 32 | Alert = 0x0002, |
| 33 | ForegroundChanged = 0x0003, |
| 34 | = 0x0004, |
| 35 | = 0x0005, |
| 36 | = 0x0006, |
| 37 | = 0x0007, |
| 38 | ContextHelpStart = 0x000C, |
| 39 | ContextHelpEnd = 0x000D, |
| 40 | DragDropStart = 0x000E, |
| 41 | DragDropEnd = 0x000F, |
| 42 | DialogStart = 0x0010, |
| 43 | DialogEnd = 0x0011, |
| 44 | ScrollingStart = 0x0012, |
| 45 | ScrollingEnd = 0x0013, |
| 46 | |
| 47 | MenuCommand = 0x0018, |
| 48 | |
| 49 | // Values from IAccessible2 |
| 50 | ActionChanged = 0x0101, |
| 51 | ActiveDescendantChanged = 0x0102, |
| 52 | AttributeChanged = 0x0103, |
| 53 | DocumentContentChanged = 0x0104, |
| 54 | DocumentLoadComplete = 0x0105, |
| 55 | DocumentLoadStopped = 0x0106, |
| 56 | DocumentReload = 0x0107, |
| 57 | HyperlinkEndIndexChanged = 0x0108, |
| 58 | HyperlinkNumberOfAnchorsChanged = 0x0109, |
| 59 | HyperlinkSelectedLinkChanged = 0x010A, |
| 60 | HypertextLinkActivated = 0x010B, |
| 61 | HypertextLinkSelected = 0x010C, |
| 62 | HyperlinkStartIndexChanged = 0x010D, |
| 63 | HypertextChanged = 0x010E, |
| 64 | HypertextNLinksChanged = 0x010F, |
| 65 | ObjectAttributeChanged = 0x0110, |
| 66 | PageChanged = 0x0111, |
| 67 | SectionChanged = 0x0112, |
| 68 | TableCaptionChanged = 0x0113, |
| 69 | TableColumnDescriptionChanged = 0x0114, |
| 70 | TableColumnHeaderChanged = 0x0115, |
| 71 | TableModelChanged = 0x0116, |
| 72 | TableRowDescriptionChanged = 0x0117, |
| 73 | = 0x0118, |
| 74 | TableSummaryChanged = 0x0119, |
| 75 | TextAttributeChanged = 0x011A, |
| 76 | TextCaretMoved = 0x011B, |
| 77 | // TextChanged = 0x011C, is deprecated in IA2, use TextUpdated |
| 78 | TextColumnChanged = 0x011D, |
| 79 | TextInserted = 0x011E, |
| 80 | TextRemoved = 0x011F, |
| 81 | TextUpdated = 0x0120, |
| 82 | TextSelectionChanged = 0x0121, |
| 83 | VisibleDataChanged = 0x0122, |
| 84 | |
| 85 | ObjectCreated = 0x8000, |
| 86 | ObjectDestroyed = 0x8001, |
| 87 | ObjectShow = 0x8002, |
| 88 | ObjectHide = 0x8003, |
| 89 | ObjectReorder = 0x8004, |
| 90 | Focus = 0x8005, |
| 91 | Selection = 0x8006, |
| 92 | SelectionAdd = 0x8007, |
| 93 | SelectionRemove = 0x8008, |
| 94 | SelectionWithin = 0x8009, |
| 95 | StateChanged = 0x800A, |
| 96 | LocationChanged = 0x800B, |
| 97 | NameChanged = 0x800C, |
| 98 | DescriptionChanged = 0x800D, |
| 99 | ValueChanged = 0x800E, |
| 100 | ParentChanged = 0x800F, |
| 101 | HelpChanged = 0x80A0, |
| 102 | DefaultActionChanged = 0x80B0, |
| 103 | AcceleratorChanged = 0x80C0, |
| 104 | Announcement = 0x80D0, |
| 105 | IdentifierChanged = 0x80E0, |
| 106 | |
| 107 | // was declared after AcceleratorChanged, without explicit value |
| 108 | InvalidEvent = AcceleratorChanged + 1, |
| 109 | }; |
| 110 | Q_ENUM(Event) |
| 111 | |
| 112 | // 64 bit enums seem hard on some platforms (windows...) |
| 113 | // which makes using a bit field a sensible alternative |
| 114 | struct State { |
| 115 | // http://msdn.microsoft.com/en-us/library/ms697270.aspx |
| 116 | quint64 disabled : 1; // used to be Unavailable |
| 117 | quint64 selected : 1; |
| 118 | quint64 focusable : 1; |
| 119 | quint64 focused : 1; |
| 120 | quint64 pressed : 1; |
| 121 | quint64 checkable : 1; |
| 122 | quint64 checked : 1; |
| 123 | quint64 checkStateMixed : 1; // used to be Mixed |
| 124 | quint64 readOnly : 1; |
| 125 | quint64 hotTracked : 1; |
| 126 | quint64 defaultButton : 1; |
| 127 | quint64 expanded : 1; |
| 128 | quint64 collapsed : 1; |
| 129 | quint64 busy : 1; |
| 130 | quint64 expandable : 1; |
| 131 | quint64 marqueed : 1; |
| 132 | quint64 animated : 1; |
| 133 | quint64 invisible : 1; |
| 134 | quint64 offscreen : 1; |
| 135 | quint64 sizeable : 1; |
| 136 | quint64 movable : 1; |
| 137 | quint64 selfVoicing : 1; |
| 138 | quint64 selectable : 1; |
| 139 | quint64 linked : 1; |
| 140 | quint64 traversed : 1; |
| 141 | quint64 multiSelectable : 1; |
| 142 | quint64 extSelectable : 1; |
| 143 | quint64 passwordEdit : 1; // used to be Protected |
| 144 | quint64 : 1; |
| 145 | quint64 modal : 1; |
| 146 | |
| 147 | // IA2 - we chose to not add some IA2 states for now |
| 148 | // Below the ones that seem helpful |
| 149 | quint64 active : 1; |
| 150 | quint64 invalid : 1; // = defunct |
| 151 | quint64 editable : 1; |
| 152 | quint64 multiLine : 1; |
| 153 | quint64 selectableText : 1; |
| 154 | quint64 supportsAutoCompletion : 1; |
| 155 | |
| 156 | quint64 searchEdit : 1; |
| 157 | |
| 158 | // quint64 horizontal : 1; |
| 159 | // quint64 vertical : 1; |
| 160 | // quint64 invalidEntry : 1; |
| 161 | // quint64 managesDescendants : 1; |
| 162 | // quint64 singleLine : 1; // we have multi line, this is redundant. |
| 163 | // quint64 stale : 1; |
| 164 | // quint64 transient : 1; |
| 165 | // quint64 pinned : 1; |
| 166 | |
| 167 | // Apple - see http://mattgemmell.com/2010/12/19/accessibility-for-iphone-and-ipad-apps/ |
| 168 | // quint64 playsSound : 1; |
| 169 | // quint64 summaryElement : 1; |
| 170 | // quint64 updatesFrequently : 1; |
| 171 | // quint64 adjustable : 1; |
| 172 | // more and not included here: http://developer.apple.com/library/mac/#documentation/UserExperience/Reference/Accessibility_RoleAttribute_Ref/Attributes.html |
| 173 | |
| 174 | // MSAA |
| 175 | // quint64 alertLow : 1; |
| 176 | // quint64 alertMedium : 1; |
| 177 | // quint64 alertHigh : 1; |
| 178 | |
| 179 | State() { |
| 180 | std::memset(s: this, c: 0, n: sizeof(State)); |
| 181 | } |
| 182 | friend inline bool operator==(const QAccessible::State &first, const QAccessible::State &second) |
| 183 | { |
| 184 | return std::memcmp(s1: &first, s2: &second, n: sizeof(QAccessible::State)) == 0; |
| 185 | } |
| 186 | }; |
| 187 | |
| 188 | |
| 189 | |
| 190 | |
| 191 | |
| 192 | enum Role { |
| 193 | NoRole = 0x00000000, |
| 194 | TitleBar = 0x00000001, |
| 195 | = 0x00000002, |
| 196 | ScrollBar = 0x00000003, |
| 197 | Grip = 0x00000004, |
| 198 | Sound = 0x00000005, |
| 199 | Cursor = 0x00000006, |
| 200 | Caret = 0x00000007, |
| 201 | AlertMessage = 0x00000008, |
| 202 | Window = 0x00000009, |
| 203 | Client = 0x0000000A, |
| 204 | = 0x0000000B, |
| 205 | = 0x0000000C, |
| 206 | ToolTip = 0x0000000D, |
| 207 | Application = 0x0000000E, |
| 208 | Document = 0x0000000F, |
| 209 | Pane = 0x00000010, |
| 210 | Chart = 0x00000011, |
| 211 | Dialog = 0x00000012, |
| 212 | Border = 0x00000013, |
| 213 | Grouping = 0x00000014, |
| 214 | Separator = 0x00000015, |
| 215 | ToolBar = 0x00000016, |
| 216 | StatusBar = 0x00000017, |
| 217 | Table = 0x00000018, |
| 218 | ColumnHeader = 0x00000019, |
| 219 | = 0x0000001A, |
| 220 | Column = 0x0000001B, |
| 221 | Row = 0x0000001C, |
| 222 | Cell = 0x0000001D, |
| 223 | Link = 0x0000001E, |
| 224 | HelpBalloon = 0x0000001F, |
| 225 | Assistant = 0x00000020, |
| 226 | List = 0x00000021, |
| 227 | ListItem = 0x00000022, |
| 228 | Tree = 0x00000023, |
| 229 | TreeItem = 0x00000024, |
| 230 | PageTab = 0x00000025, |
| 231 | PropertyPage = 0x00000026, |
| 232 | Indicator = 0x00000027, |
| 233 | Graphic = 0x00000028, |
| 234 | StaticText = 0x00000029, |
| 235 | EditableText = 0x0000002A, // Editable, selectable, etc. |
| 236 | Button = 0x0000002B, |
| 237 | #ifndef Q_QDOC |
| 238 | PushButton = Button, // deprecated |
| 239 | #endif |
| 240 | CheckBox = 0x0000002C, |
| 241 | RadioButton = 0x0000002D, |
| 242 | ComboBox = 0x0000002E, |
| 243 | // DropList = 0x0000002F, |
| 244 | ProgressBar = 0x00000030, |
| 245 | Dial = 0x00000031, |
| 246 | HotkeyField = 0x00000032, |
| 247 | Slider = 0x00000033, |
| 248 | SpinBox = 0x00000034, |
| 249 | Canvas = 0x00000035, // MSAA: ROLE_SYSTEM_DIAGRAM - The object represents a graphical image that is used to diagram data. |
| 250 | Animation = 0x00000036, |
| 251 | Equation = 0x00000037, |
| 252 | ButtonDropDown = 0x00000038, // The object represents a button that expands a grid. |
| 253 | = 0x00000039, |
| 254 | ButtonDropGrid = 0x0000003A, |
| 255 | Whitespace = 0x0000003B, // The object represents blank space between other objects. |
| 256 | PageTabList = 0x0000003C, |
| 257 | Clock = 0x0000003D, |
| 258 | Splitter = 0x0000003E, |
| 259 | // Reserved space in case MSAA roles needs to be added |
| 260 | |
| 261 | // Additional Qt roles where enum value does not map directly to MSAA: |
| 262 | LayeredPane = 0x00000080, |
| 263 | Terminal = 0x00000081, |
| 264 | Desktop = 0x00000082, |
| 265 | Paragraph = 0x00000083, |
| 266 | WebDocument = 0x00000084, |
| 267 | Section = 0x00000085, |
| 268 | Notification = 0x00000086, |
| 269 | |
| 270 | // IAccessible2 roles |
| 271 | // IA2_ROLE_CANVAS = 0x401, // An object that can be drawn into and to manage events from the objects drawn into it |
| 272 | // IA2_ROLE_CAPTION = 0x402, |
| 273 | // IA2_ROLE_CHECK_MENU_ITEM = 0x403, |
| 274 | ColorChooser = 0x404, |
| 275 | // IA2_ROLE_DATE_EDITOR = 0x405, |
| 276 | // IA2_ROLE_DESKTOP_ICON = 0x406, |
| 277 | // IA2_ROLE_DESKTOP_PANE = 0x407, |
| 278 | // IA2_ROLE_DIRECTORY_PANE = 0x408, |
| 279 | // IA2_ROLE_EDITBAR = 0x409, |
| 280 | // IA2_ROLE_EMBEDDED_OBJECT = 0x40A, |
| 281 | // IA2_ROLE_ENDNOTE = 0x40B, |
| 282 | // IA2_ROLE_FILE_CHOOSER = 0x40C, |
| 283 | // IA2_ROLE_FONT_CHOOSER = 0x40D, |
| 284 | = 0x40E, |
| 285 | // IA2_ROLE_FOOTNOTE = 0x40F, |
| 286 | Form = 0x410, |
| 287 | // some platforms (windows and at-spi) use Frame for regular windows |
| 288 | // because window was taken for tool/dock windows by MSAA |
| 289 | // Frame = 0x411, |
| 290 | // IA2_ROLE_GLASS_PANE = 0x412, |
| 291 | // IA2_ROLE_HEADER = 0x413, |
| 292 | Heading = 0x414, |
| 293 | // IA2_ROLE_ICON = 0x415, |
| 294 | // IA2_ROLE_IMAGE_MAP = 0x416, |
| 295 | // IA2_ROLE_INPUT_METHOD_WINDOW = 0x417, |
| 296 | // IA2_ROLE_INTERNAL_FRAME = 0x418, |
| 297 | // IA2_ROLE_LABEL = 0x419, |
| 298 | // IA2_ROLE_LAYERED_PANE = 0x41A, |
| 299 | Note = 0x41B, |
| 300 | // IA2_ROLE_OPTION_PANE = 0x41C, |
| 301 | // IA2_ROLE_PAGE = 0x41D, |
| 302 | // IA2_ROLE_PARAGRAPH = 0x42E, |
| 303 | // IA2_ROLE_RADIO_MENU_ITEM = 0x41F, |
| 304 | // IA2_ROLE_REDUNDANT_OBJECT = 0x420, |
| 305 | // IA2_ROLE_ROOT_PANE = 0x421, |
| 306 | // IA2_ROLE_RULER = 0x422, |
| 307 | // IA2_ROLE_SCROLL_PANE = 0x423, |
| 308 | // IA2_ROLE_SECTION = 0x424, |
| 309 | // IA2_ROLE_SHAPE = 0x425, |
| 310 | // IA2_ROLE_SPLIT_PANE = 0x426, |
| 311 | // IA2_ROLE_TEAR_OFF_MENU = 0x427, |
| 312 | // IA2_ROLE_TERMINAL = 0x428, |
| 313 | // IA2_ROLE_TEXT_FRAME = 0x429, |
| 314 | // IA2_ROLE_TOGGLE_BUTTON = 0x42A, |
| 315 | // IA2_ROLE_VIEW_PORT = 0x42B, |
| 316 | ComplementaryContent = 0x42C, |
| 317 | |
| 318 | UserRole = 0x0000ffff |
| 319 | }; |
| 320 | Q_ENUM(Role) |
| 321 | |
| 322 | enum Text { |
| 323 | Name = 0, |
| 324 | Description, |
| 325 | Value, |
| 326 | Help, |
| 327 | Accelerator, |
| 328 | DebugDescription, |
| 329 | Identifier, |
| 330 | UserText = 0x0000ffff |
| 331 | }; |
| 332 | |
| 333 | enum RelationFlag { |
| 334 | Label = 0x00000001, |
| 335 | Labelled = 0x00000002, |
| 336 | Controller = 0x00000004, |
| 337 | Controlled = 0x00000008, |
| 338 | DescriptionFor = 0x00000010, |
| 339 | Described = 0x00000020, |
| 340 | FlowsFrom = 0x00000040, |
| 341 | FlowsTo = 0x00000080, |
| 342 | AllRelations = 0xffffffff |
| 343 | }; |
| 344 | Q_DECLARE_FLAGS(Relation, RelationFlag) |
| 345 | |
| 346 | enum InterfaceType |
| 347 | { |
| 348 | TextInterface, |
| 349 | EditableTextInterface, |
| 350 | ValueInterface, |
| 351 | ActionInterface, |
| 352 | ImageInterface, |
| 353 | TableInterface, |
| 354 | TableCellInterface, |
| 355 | HyperlinkInterface, |
| 356 | SelectionInterface, |
| 357 | AttributesInterface, |
| 358 | }; |
| 359 | |
| 360 | enum TextBoundaryType { |
| 361 | CharBoundary, |
| 362 | WordBoundary, |
| 363 | SentenceBoundary, |
| 364 | ParagraphBoundary, |
| 365 | LineBoundary, |
| 366 | NoBoundary |
| 367 | }; |
| 368 | |
| 369 | enum class Attribute { |
| 370 | Custom, |
| 371 | Level, |
| 372 | }; |
| 373 | Q_ENUM(Attribute) |
| 374 | |
| 375 | enum class AnnouncementPoliteness { |
| 376 | Polite, |
| 377 | Assertive, |
| 378 | }; |
| 379 | Q_ENUM(AnnouncementPoliteness) |
| 380 | |
| 381 | typedef QAccessibleInterface*(*InterfaceFactory)(const QString &key, QObject*); |
| 382 | typedef void(*UpdateHandler)(QAccessibleEvent *event); |
| 383 | typedef void(*RootObjectHandler)(QObject*); |
| 384 | |
| 385 | typedef unsigned Id; |
| 386 | |
| 387 | static void installFactory(InterfaceFactory); |
| 388 | static void removeFactory(InterfaceFactory); |
| 389 | static UpdateHandler installUpdateHandler(UpdateHandler); |
| 390 | static RootObjectHandler installRootObjectHandler(RootObjectHandler); |
| 391 | |
| 392 | class Q_GUI_EXPORT ActivationObserver |
| 393 | { |
| 394 | public: |
| 395 | virtual ~ActivationObserver(); |
| 396 | virtual void accessibilityActiveChanged(bool active) = 0; |
| 397 | }; |
| 398 | static void installActivationObserver(ActivationObserver *); |
| 399 | static void removeActivationObserver(ActivationObserver *); |
| 400 | |
| 401 | static QAccessibleInterface *queryAccessibleInterface(QObject *); |
| 402 | static Id uniqueId(QAccessibleInterface *iface); |
| 403 | static QAccessibleInterface *accessibleInterface(Id uniqueId); |
| 404 | static Id registerAccessibleInterface(QAccessibleInterface *iface); |
| 405 | static void deleteAccessibleInterface(Id uniqueId); |
| 406 | |
| 407 | static void updateAccessibility(QAccessibleEvent *event); |
| 408 | |
| 409 | static bool isActive(); |
| 410 | static void setActive(bool active); |
| 411 | static void setRootObject(QObject *object); |
| 412 | |
| 413 | static void cleanup(); |
| 414 | |
| 415 | static QPair< int, int > qAccessibleTextBoundaryHelper(const QTextCursor &cursor, TextBoundaryType boundaryType); |
| 416 | |
| 417 | private: |
| 418 | static UpdateHandler updateHandler; |
| 419 | static RootObjectHandler rootObjectHandler; |
| 420 | |
| 421 | QAccessible() {} |
| 422 | |
| 423 | friend class QAccessibleCache; |
| 424 | }; |
| 425 | |
| 426 | Q_DECLARE_OPERATORS_FOR_FLAGS(QAccessible::Relation) |
| 427 | |
| 428 | QT_END_NAMESPACE |
| 429 | |
| 430 | #endif // QT_CONFIG(accessibility) |
| 431 | #endif // QACCESSIBLE_BASE_H |
| 432 | |