~ubuntu-branches/ubuntu/precise/qt4-x11/precise-proposed

« back to all changes in this revision

Viewing changes to .pc/kubuntu_97_a11y_qt_and_qml_backport.diff/src/gui/accessible/qaccessible_mac.mm

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell, Jonathan Riddell, Felix Geyer
  • Date: 2011-11-01 16:23:55 UTC
  • mfrom: (15.3.22 sid)
  • Revision ID: package-import@ubuntu.com-20111101162355-4dhsj6563ii8enl6
Tags: 4:4.7.4-1ubuntu1
[ Jonathan Riddell ]
* Merge from Debian Git packaging.  Remaining Ubuntu changes:
  - Do not package ibase/firebird package, remove from debian/rules and
    debian/control
  - libqt4-sql-ibase not recommend for libqt4-sql
  - build with -no-phonon
  - do not build libqt4-phonon, disable in debian/control
  - Build packages with lzma compression using the dh addon from pkg-kde-tools
  - Rules to remove po dir in clean
  - Add MessagesQt.sh
  - Rules to create Messages.sh link to MessagesQt.sh and rules to create po
    dir and exectue extract-messages.sh in common-install-prehook-impl
  - Make libqt4-dev depend on libx11-dev
  - Add and install Trolltech.conf in libqtcore4.install
  - Build QtWebkit and use it only for QtAssistant
    + Rule to put qt_webkit_version.pri in mkspecs/modules
    + Rule to remove libQtWebKit* after build
    + Exclude usr/bin/assistant-qt4 from dh_shlibdeps
  - Fix Lucid upgrades: libqt4-help breaks/replaces libqtcore4 (<< 4:4.7.0)
  - Change OpenGL backend from GL to GLES 2 for armel (Debian does this for
    armhf)
    + Build-depend and make libqt4-opengl-dev depend on libgles2-mesa-dev
      instead of libgl1-mesa-dev and libglu1-mesa-dev
    + Pass "-opengl es2" to configure
  - Pass extra_configure_opts += -arch armv6 on both armel and armhf and not
    just armhf
  - In debian/rules Move documentation building to override_dh_auto_install where
    dh_listpackages works as expected with dpkg-buildpackage. (LP: #857377)
  - debian/compat is 9 and build-depend on newer debhelper for multiarch
* debian/patches/blacklist-diginotar-certs.diff is now
  debian/patches/blacklist-diginotar-cert.diff to match Debian
* Add prefix to some patches to clarify they come from Ubuntu rather than Debian
 - kubuntu_97_a11y_qt_and_qml_backport.diff
 - kubuntu_98_fix_accessible_menu.diff
 - kubuntu_99_notify_qml_name_description_change.diff

[ Felix Geyer ]
* Use DEB_*_MAINT_APPEND instead of setting CXXFLAGS and LDFLAGS.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
 
4
** All rights reserved.
 
5
** Contact: Nokia Corporation (qt-info@nokia.com)
 
6
**
 
7
** This file is part of the QtGui module of the Qt Toolkit.
 
8
**
 
9
** $QT_BEGIN_LICENSE:LGPL$
 
10
** GNU Lesser General Public License Usage
 
11
** This file may be used under the terms of the GNU Lesser General Public
 
12
** License version 2.1 as published by the Free Software Foundation and
 
13
** appearing in the file LICENSE.LGPL included in the packaging of this
 
14
** file. Please review the following information to ensure the GNU Lesser
 
15
** General Public License version 2.1 requirements will be met:
 
16
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 
17
**
 
18
** In addition, as a special exception, Nokia gives you certain additional
 
19
** rights. These rights are described in the Nokia Qt LGPL Exception
 
20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
21
**
 
22
** GNU General Public License Usage
 
23
** Alternatively, this file may be used under the terms of the GNU General
 
24
** Public License version 3.0 as published by the Free Software Foundation
 
25
** and appearing in the file LICENSE.GPL included in the packaging of this
 
26
** file. Please review the following information to ensure the GNU General
 
27
** Public License version 3.0 requirements will be met:
 
28
** http://www.gnu.org/copyleft/gpl.html.
 
29
**
 
30
** Other Usage
 
31
** Alternatively, this file may be used in accordance with the terms and
 
32
** conditions contained in a signed written agreement between you and Nokia.
 
33
**
 
34
**
 
35
**
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
#include "qaccessible.h"
 
43
 
 
44
#ifndef QT_NO_ACCESSIBILITY
 
45
#include "qaccessible_mac_p.h"
 
46
#include "qhash.h"
 
47
#include "qset.h"
 
48
#include "qpointer.h"
 
49
#include "qapplication.h"
 
50
#include "qmainwindow.h"
 
51
#include "qtextdocument.h"
 
52
#include "qdebug.h"
 
53
#include "qabstractslider.h"
 
54
#include "qsplitter.h"
 
55
#include "qtabwidget.h"
 
56
#include "qlistview.h"
 
57
#include "qtableview.h"
 
58
#include "qdockwidget.h"
 
59
 
 
60
#include <private/qt_mac_p.h>
 
61
#include <private/qwidget_p.h>
 
62
#include <CoreFoundation/CoreFoundation.h>
 
63
 
 
64
QT_BEGIN_NAMESPACE
 
65
 
 
66
/*
 
67
    Set up platform defines. There is a one-to-one correspondence between the
 
68
    Carbon and Cocoa roles and attributes, but the prefix and type changes.
 
69
*/
 
70
#ifdef QT_MAC_USE_COCOA
 
71
typedef NSString * const QAXRoleType;
 
72
#define QAXApplicationRole NSAccessibilityApplicationRole
 
73
#define QAXButtonRole NSAccessibilityButtonRole
 
74
#define QAXCancelAction NSAccessibilityCancelAction
 
75
#define QAXCheckBoxRole NSAccessibilityCheckBoxRole
 
76
#define QAXChildrenAttribute NSAccessibilityChildrenAttribute
 
77
#define QAXCloseButtonAttribute NSAccessibilityCloseButtonAttribute
 
78
#define QAXCloseButtonAttribute NSAccessibilityCloseButtonAttribute
 
79
#define QAXColumnRole NSAccessibilityColumnRole
 
80
#define QAXConfirmAction NSAccessibilityConfirmAction
 
81
#define QAXContentsAttribute NSAccessibilityContentsAttribute
 
82
#define QAXDecrementAction NSAccessibilityDecrementAction
 
83
#define QAXDecrementArrowSubrole NSAccessibilityDecrementArrowSubrole
 
84
#define QAXDecrementPageSubrole NSAccessibilityDecrementPageSubrole
 
85
#define QAXDescriptionAttribute NSAccessibilityDescriptionAttribute
 
86
#define QAXEnabledAttribute NSAccessibilityEnabledAttribute
 
87
#define QAXExpandedAttribute NSAccessibilityExpandedAttribute
 
88
#define QAXFocusedAttribute NSAccessibilityFocusedAttribute
 
89
#define QAXFocusedUIElementChangedNotification NSAccessibilityFocusedUIElementChangedNotification
 
90
#define QAXFocusedWindowChangedNotification NSAccessibilityFocusedWindowChangedNotification
 
91
#define QAXGroupRole NSAccessibilityGroupRole
 
92
#define QAXGrowAreaAttribute NSAccessibilityGrowAreaAttribute
 
93
#define QAXGrowAreaRole NSAccessibilityGrowAreaRole
 
94
#define QAXHelpAttribute NSAccessibilityHelpAttribute
 
95
#define QAXHorizontalOrientationValue NSAccessibilityHorizontalOrientationValue
 
96
#define QAXHorizontalScrollBarAttribute NSAccessibilityHorizontalScrollBarAttribute
 
97
#define QAXIncrementAction NSAccessibilityIncrementAction
 
98
#define QAXIncrementArrowSubrole NSAccessibilityIncrementArrowSubrole
 
99
#define QAXIncrementPageSubrole NSAccessibilityIncrementPageSubrole
 
100
#define QAXIncrementorRole NSAccessibilityIncrementorRole
 
101
#define QAXLinkedUIElementsAttribute NSAccessibilityLinkedUIElementsAttribute
 
102
#define QAXListRole NSAccessibilityListRole
 
103
#define QAXMainAttribute NSAccessibilityMainAttribute
 
104
#define QAXMaxValueAttribute NSAccessibilityMaxValueAttribute
 
105
#define QAXMenuBarRole NSAccessibilityMenuBarRole
 
106
#define QAXMenuButtonRole NSAccessibilityMenuButtonRole
 
107
#define QAXMenuClosedNotification NSAccessibilityMenuClosedNotification
 
108
#define QAXMenuItemRole NSAccessibilityMenuItemRole
 
109
#define QAXMenuOpenedNotification NSAccessibilityMenuOpenedNotification
 
110
#define QAXMenuRole NSAccessibilityMenuRole
 
111
#define QAXMinValueAttribute NSAccessibilityMinValueAttribute
 
112
#define QAXMinimizeButtonAttribute NSAccessibilityMinimizeButtonAttribute
 
113
#define QAXMinimizedAttribute NSAccessibilityMinimizedAttribute
 
114
#define QAXNextContentsAttribute NSAccessibilityNextContentsAttribute
 
115
#define QAXOrientationAttribute NSAccessibilityOrientationAttribute
 
116
#define QAXParentAttribute NSAccessibilityParentAttribute
 
117
#define QAXPickAction NSAccessibilityPickAction
 
118
#define QAXPopUpButtonRole NSAccessibilityPopUpButtonRole
 
119
#define QAXPositionAttribute NSAccessibilityPositionAttribute
 
120
#define QAXPressAction NSAccessibilityPressAction
 
121
#define QAXPreviousContentsAttribute NSAccessibilityPreviousContentsAttribute
 
122
#define QAXProgressIndicatorRole NSAccessibilityProgressIndicatorRole
 
123
#define QAXRadioButtonRole NSAccessibilityRadioButtonRole
 
124
#define QAXRoleAttribute NSAccessibilityRoleAttribute
 
125
#define QAXRoleDescriptionAttribute NSAccessibilityRoleDescriptionAttribute
 
126
#define QAXRowRole NSAccessibilityRowRole
 
127
#define QAXRowsAttribute NSAccessibilityRowsAttribute
 
128
#define QAXScrollAreaRole NSAccessibilityScrollAreaRole
 
129
#define QAXScrollBarRole NSAccessibilityScrollBarRole
 
130
#define QAXSelectedAttribute NSAccessibilitySelectedAttribute
 
131
#define QAXSelectedChildrenAttribute NSAccessibilitySelectedChildrenAttribute
 
132
#define QAXSelectedRowsAttribute NSAccessibilitySelectedRowsAttribute
 
133
#define QAXSizeAttribute NSAccessibilitySizeAttribute
 
134
#define QAXSliderRole NSAccessibilitySliderRole
 
135
#define QAXSplitGroupRole NSAccessibilitySplitGroupRole
 
136
#define QAXSplitterRole NSAccessibilitySplitterRole
 
137
#define QAXSplittersAttribute NSAccessibilitySplittersAttribute
 
138
#define QAXStaticTextRole NSAccessibilityStaticTextRole
 
139
#define QAXSubroleAttribute NSAccessibilitySubroleAttribute
 
140
#define QAXSubroleAttribute NSAccessibilitySubroleAttribute
 
141
#define QAXTabGroupRole NSAccessibilityTabGroupRole
 
142
#define QAXTableRole NSAccessibilityTableRole
 
143
#define QAXTabsAttribute NSAccessibilityTabsAttribute
 
144
#define QAXTextFieldRole NSAccessibilityTextFieldRole
 
145
#define QAXTitleAttribute NSAccessibilityTitleAttribute
 
146
#define QAXTitleUIElementAttribute NSAccessibilityTitleUIElementAttribute
 
147
#define QAXToolbarButtonAttribute NSAccessibilityToolbarButtonAttribute
 
148
#define QAXToolbarRole NSAccessibilityToolbarRole
 
149
#define QAXTopLevelUIElementAttribute NSAccessibilityTopLevelUIElementAttribute
 
150
#define QAXUnknownRole NSAccessibilityUnknownRole
 
151
#define QAXValueAttribute NSAccessibilityValueAttribute
 
152
#define QAXValueChangedNotification NSAccessibilityValueChangedNotification
 
153
#define QAXValueIndicatorRole NSAccessibilityValueIndicatorRole
 
154
#define QAXVerticalOrientationValue NSAccessibilityVerticalOrientationValue
 
155
#define QAXVerticalScrollBarAttribute NSAccessibilityVerticalScrollBarAttribute
 
156
#define QAXVisibleRowsAttribute NSAccessibilityVisibleRowsAttribute
 
157
#define QAXWindowAttribute NSAccessibilityWindowAttribute
 
158
#define QAXWindowCreatedNotification NSAccessibilityWindowCreatedNotification
 
159
#define QAXWindowMovedNotification NSAccessibilityWindowMovedNotification
 
160
#define QAXWindowRole NSAccessibilityWindowRole
 
161
#define QAXZoomButtonAttribute NSAccessibilityZoomButtonAttribute
 
162
#else
 
163
typedef CFStringRef const QAXRoleType;
 
164
#define QAXApplicationRole kAXApplicationRole
 
165
#define QAXButtonRole kAXButtonRole
 
166
#define QAXCancelAction kAXCancelAction
 
167
#define QAXCheckBoxRole kAXCheckBoxRole
 
168
#define QAXChildrenAttribute kAXChildrenAttribute
 
169
#define QAXCloseButtonAttribute kAXCloseButtonAttribute
 
170
#define QAXColumnRole kAXColumnRole
 
171
#define QAXConfirmAction kAXConfirmAction
 
172
#define QAXContentsAttribute kAXContentsAttribute
 
173
#define QAXDecrementAction kAXDecrementAction
 
174
#define QAXDecrementArrowSubrole kAXDecrementArrowSubrole
 
175
#define QAXDecrementPageSubrole kAXDecrementPageSubrole
 
176
#define QAXDescriptionAttribute kAXDescriptionAttribute
 
177
#define QAXEnabledAttribute kAXEnabledAttribute
 
178
#define QAXExpandedAttribute kAXExpandedAttribute
 
179
#define QAXFocusedAttribute kAXFocusedAttribute
 
180
#define QAXFocusedUIElementChangedNotification kAXFocusedUIElementChangedNotification
 
181
#define QAXFocusedWindowChangedNotification kAXFocusedWindowChangedNotification
 
182
#define QAXGroupRole kAXGroupRole
 
183
#define QAXGrowAreaAttribute kAXGrowAreaAttribute
 
184
#define QAXGrowAreaRole kAXGrowAreaRole
 
185
#define QAXHelpAttribute kAXHelpAttribute
 
186
#define QAXHorizontalOrientationValue kAXHorizontalOrientationValue
 
187
#define QAXHorizontalScrollBarAttribute kAXHorizontalScrollBarAttribute
 
188
#define QAXIncrementAction kAXIncrementAction
 
189
#define QAXIncrementArrowSubrole kAXIncrementArrowSubrole
 
190
#define QAXIncrementPageSubrole kAXIncrementPageSubrole
 
191
#define QAXIncrementorRole kAXIncrementorRole
 
192
#define QAXLinkedUIElementsAttribute kAXLinkedUIElementsAttribute
 
193
#define QAXListRole kAXListRole
 
194
#define QAXMainAttribute kAXMainAttribute
 
195
#define QAXMaxValueAttribute kAXMaxValueAttribute
 
196
#define QAXMenuBarRole kAXMenuBarRole
 
197
#define QAXMenuButtonRole kAXMenuButtonRole
 
198
#define QAXMenuClosedNotification kAXMenuClosedNotification
 
199
#define QAXMenuItemRole kAXMenuItemRole
 
200
#define QAXMenuOpenedNotification kAXMenuOpenedNotification
 
201
#define QAXMenuRole kAXMenuRole
 
202
#define QAXMinValueAttribute kAXMinValueAttribute
 
203
#define QAXMinimizeButtonAttribute kAXMinimizeButtonAttribute
 
204
#define QAXMinimizedAttribute kAXMinimizedAttribute
 
205
#define QAXNextContentsAttribute kAXNextContentsAttribute
 
206
#define QAXOrientationAttribute kAXOrientationAttribute
 
207
#define QAXParentAttribute kAXParentAttribute
 
208
#define QAXPickAction kAXPickAction
 
209
#define QAXPopUpButtonRole kAXPopUpButtonRole
 
210
#define QAXPositionAttribute kAXPositionAttribute
 
211
#define QAXPressAction kAXPressAction
 
212
#define QAXPreviousContentsAttribute kAXPreviousContentsAttribute
 
213
#define QAXProgressIndicatorRole kAXProgressIndicatorRole
 
214
#define QAXRadioButtonRole kAXRadioButtonRole
 
215
#define QAXRoleAttribute kAXRoleAttribute
 
216
#define QAXRoleDescriptionAttribute kAXRoleDescriptionAttribute
 
217
#define QAXRowRole kAXRowRole
 
218
#define QAXRowsAttribute kAXRowsAttribute
 
219
#define QAXScrollAreaRole kAXScrollAreaRole
 
220
#define QAXScrollBarRole kAXScrollBarRole
 
221
#define QAXSelectedAttribute kAXSelectedAttribute
 
222
#define QAXSelectedChildrenAttribute kAXSelectedChildrenAttribute
 
223
#define QAXSelectedRowsAttribute kAXSelectedRowsAttribute
 
224
#define QAXSizeAttribute kAXSizeAttribute
 
225
#define QAXSliderRole kAXSliderRole
 
226
#define QAXSplitGroupRole kAXSplitGroupRole
 
227
#define QAXSplitterRole kAXSplitterRole
 
228
#define QAXSplittersAttribute kAXSplittersAttribute
 
229
#define QAXStaticTextRole kAXStaticTextRole
 
230
#define QAXSubroleAttribute kAXSubroleAttribute
 
231
#define QAXTabGroupRole kAXTabGroupRole
 
232
#define QAXTableRole kAXTableRole
 
233
#define QAXTabsAttribute kAXTabsAttribute
 
234
#define QAXTextFieldRole kAXTextFieldRole
 
235
#define QAXTitleAttribute kAXTitleAttribute
 
236
#define QAXTitleUIElementAttribute kAXTitleUIElementAttribute
 
237
#define QAXToolbarButtonAttribute kAXToolbarButtonAttribute
 
238
#define QAXToolbarRole kAXToolbarRole
 
239
#define QAXTopLevelUIElementAttribute kAXTopLevelUIElementAttribute
 
240
#define QAXUnknownRole kAXUnknownRole
 
241
#define QAXValueAttribute kAXValueAttribute
 
242
#define QAXValueChangedNotification kAXValueChangedNotification
 
243
#define QAXValueIndicatorRole kAXValueIndicatorRole
 
244
#define QAXVerticalOrientationValue kAXVerticalOrientationValue
 
245
#define QAXVerticalScrollBarAttribute kAXVerticalScrollBarAttribute
 
246
#define QAXVisibleRowsAttribute kAXVisibleRowsAttribute
 
247
#define QAXWindowAttribute kAXWindowAttribute
 
248
#define QAXWindowCreatedNotification kAXWindowCreatedNotification
 
249
#define QAXWindowMovedNotification kAXWindowMovedNotification
 
250
#define QAXWindowRole kAXWindowRole
 
251
#define QAXZoomButtonAttribute kAXZoomButtonAttribute
 
252
#endif
 
253
 
 
254
 
 
255
/*****************************************************************************
 
256
  Externals
 
257
 *****************************************************************************/
 
258
extern bool qt_mac_is_macsheet(const QWidget *w); //qwidget_mac.cpp
 
259
extern bool qt_mac_is_macdrawer(const QWidget *w); //qwidget_mac.cpp
 
260
 
 
261
/*****************************************************************************
 
262
  QAccessible Bindings
 
263
 *****************************************************************************/
 
264
//hardcoded bindings between control info and (known) QWidgets
 
265
struct QAccessibleTextBinding {
 
266
    int qt;
 
267
    QAXRoleType mac;
 
268
    bool settable;
 
269
} text_bindings[][10] = {
 
270
    { { QAccessible::MenuItem, QAXMenuItemRole, false },
 
271
      { -1, 0, false }
 
272
    },
 
273
    { { QAccessible::MenuBar, QAXMenuBarRole, false },
 
274
      { -1, 0, false }
 
275
    },
 
276
    { { QAccessible::ScrollBar, QAXScrollBarRole, false },
 
277
      { -1, 0, false }
 
278
    },
 
279
    { { QAccessible::Grip, QAXGrowAreaRole, false },
 
280
      { -1, 0, false }
 
281
    },
 
282
    { { QAccessible::Window, QAXWindowRole, false },
 
283
      { -1, 0, false }
 
284
    },
 
285
    { { QAccessible::Dialog, QAXWindowRole, false },
 
286
      { -1, 0, false }
 
287
    },
 
288
    { { QAccessible::AlertMessage, QAXWindowRole, false },
 
289
      { -1, 0, false }
 
290
    },
 
291
    { { QAccessible::ToolTip, QAXWindowRole, false },
 
292
      { -1, 0, false }
 
293
    },
 
294
    { { QAccessible::HelpBalloon, QAXWindowRole, false },
 
295
      { -1, 0, false }
 
296
    },
 
297
    { { QAccessible::PopupMenu, QAXMenuRole, false },
 
298
      { -1, 0, false }
 
299
    },
 
300
    { { QAccessible::Application, QAXApplicationRole, false },
 
301
      { -1, 0, false }
 
302
    },
 
303
    { { QAccessible::Pane, QAXGroupRole, false },
 
304
      { -1, 0, false }
 
305
    },
 
306
    { { QAccessible::Grouping, QAXGroupRole, false },
 
307
      { -1, 0, false }
 
308
    },
 
309
    { { QAccessible::Separator, QAXSplitterRole, false },
 
310
      { -1, 0, false }
 
311
    },
 
312
    { { QAccessible::ToolBar, QAXToolbarRole, false },
 
313
      { -1, 0, false }
 
314
    },
 
315
    { { QAccessible::PageTab, QAXRadioButtonRole, false },
 
316
      { -1, 0, false }
 
317
    },
 
318
    { { QAccessible::ButtonMenu, QAXMenuButtonRole, false },
 
319
      { -1, 0, false }
 
320
    },
 
321
    { { QAccessible::ButtonDropDown, QAXPopUpButtonRole, false },
 
322
      { -1, 0, false }
 
323
    },
 
324
    { { QAccessible::SpinBox, QAXIncrementorRole, false },
 
325
      { -1, 0, false }
 
326
    },
 
327
    { { QAccessible::Slider, QAXSliderRole, false },
 
328
      { -1, 0, false }
 
329
    },
 
330
    { { QAccessible::ProgressBar, QAXProgressIndicatorRole, false },
 
331
      { -1, 0, false }
 
332
    },
 
333
    { { QAccessible::ComboBox, QAXPopUpButtonRole, false },
 
334
      { -1, 0, false }
 
335
    },
 
336
    { { QAccessible::RadioButton, QAXRadioButtonRole, false },
 
337
      { -1, 0, false }
 
338
    },
 
339
    { { QAccessible::CheckBox, QAXCheckBoxRole, false },
 
340
      { -1, 0, false }
 
341
    },
 
342
    { { QAccessible::StaticText, QAXStaticTextRole, false },
 
343
      { QAccessible::Name, QAXValueAttribute, false },
 
344
      { -1, 0, false }
 
345
    },
 
346
    { { QAccessible::Table, QAXTableRole, false },
 
347
      { -1, 0, false }
 
348
    },
 
349
    { { QAccessible::StatusBar, QAXStaticTextRole, false },
 
350
      { -1, 0, false }
 
351
    },
 
352
    { { QAccessible::Column, QAXColumnRole, false },
 
353
      { -1, 0, false }
 
354
    },
 
355
    { { QAccessible::ColumnHeader, QAXColumnRole, false },
 
356
      { -1, 0, false }
 
357
    },
 
358
    { { QAccessible::Row, QAXRowRole, false },
 
359
      { -1, 0, false }
 
360
    },
 
361
    { { QAccessible::RowHeader, QAXRowRole, false },
 
362
      { -1, 0, false }
 
363
    },
 
364
    { { QAccessible::Cell, QAXTextFieldRole, false },
 
365
      { -1, 0, false }
 
366
    },
 
367
    { { QAccessible::PushButton, QAXButtonRole, false },
 
368
      { -1, 0, false }
 
369
    },
 
370
    { { QAccessible::EditableText, QAXTextFieldRole, true },
 
371
      { -1, 0, false }
 
372
    },
 
373
    { { QAccessible::Link, QAXTextFieldRole, false },
 
374
      { -1, 0, false }
 
375
    },
 
376
    { { QAccessible::Indicator, QAXValueIndicatorRole, false },
 
377
      { -1, 0, false }
 
378
    },
 
379
    { { QAccessible::Splitter, QAXSplitGroupRole, false },
 
380
      { -1, 0, false }
 
381
    },
 
382
    { { QAccessible::List, QAXListRole, false },
 
383
      { -1, 0, false }
 
384
    },
 
385
    { { QAccessible::ListItem, QAXStaticTextRole, false },
 
386
      { -1, 0, false }
 
387
    },
 
388
    { { QAccessible::Cell, QAXStaticTextRole, false },
 
389
      { -1, 0, false }
 
390
    },
 
391
    { { -1, 0, false } }
 
392
};
 
393
 
 
394
class QAInterface;
 
395
static CFStringRef macRole(const QAInterface &interface);
 
396
 
 
397
QDebug operator<<(QDebug debug, const QAInterface &interface)
 
398
{
 
399
    if (interface.isValid() == false)
 
400
        debug << "invalid interface";
 
401
    else 
 
402
        debug << interface.object() << "id" << interface.id() << "role" << hex << interface.role();
 
403
    return debug;
 
404
}
 
405
 
 
406
// The root of the Qt accessible hiearchy.
 
407
static QObject *rootObject = 0;
 
408
 
 
409
 
 
410
bool QAInterface::operator==(const QAInterface &other) const
 
411
{
 
412
    if (isValid() == false || other.isValid() == false)
 
413
        return (isValid() && other.isValid());
 
414
    
 
415
    // walk up the parent chain, comparing child indexes, until we reach
 
416
    // an interface that has a QObject.
 
417
    QAInterface currentThis = *this;
 
418
    QAInterface currentOther = other;
 
419
    
 
420
    while (currentThis.object() == 0) {
 
421
        if (currentOther.object() != 0)
 
422
            return false;
 
423
 
 
424
        // fail if the child indexes in the two hirearchies don't match.
 
425
        if (currentThis.parent().indexOfChild(currentThis) !=
 
426
            currentOther.parent().indexOfChild(currentOther))
 
427
            return false;
 
428
 
 
429
        currentThis = currentThis.parent();
 
430
        currentOther = currentOther.parent();
 
431
    }
 
432
    
 
433
    return (currentThis.object() == currentOther.object() && currentThis.id() == currentOther.id());
 
434
}
 
435
 
 
436
bool QAInterface::operator!=(const QAInterface &other) const
 
437
{
 
438
    return !operator==(other);
 
439
}
 
440
 
 
441
uint qHash(const QAInterface &item)
 
442
{
 
443
    if (item.isValid())
 
444
        return qHash(item.object()) + qHash(item.id());
 
445
    else
 
446
        return qHash(item.cachedObject()) + qHash(item.id());
 
447
}
 
448
 
 
449
QAInterface QAInterface::navigate(RelationFlag relation, int entry) const
 
450
{
 
451
        if (!checkValid())
 
452
            return QAInterface();
 
453
 
 
454
    // On a QAccessibleInterface that handles its own children we can short-circut
 
455
    // the navigation if this QAInterface refers to one of the children:
 
456
    if (child != 0) {
 
457
        // The Ancestor interface will always be the same QAccessibleInterface with
 
458
        // a child value of 0.
 
459
        if (relation == QAccessible::Ancestor)
 
460
            return QAInterface(*this, 0);
 
461
 
 
462
        // The child hiearchy is only one level deep, so navigating to a child
 
463
        // of a child is not possible.
 
464
        if (relation == QAccessible::Child) {
 
465
            return QAInterface();
 
466
        }
 
467
    }
 
468
    QAccessibleInterface *child_iface = 0;
 
469
 
 
470
    const int status = base.interface->navigate(relation, entry, &child_iface);
 
471
 
 
472
    if (status == -1)
 
473
        return QAInterface(); // not found;
 
474
 
 
475
    // Check if target is a child of this interface.
 
476
    if (!child_iface) {
 
477
        return QAInterface(*this, status);
 
478
    } else {
 
479
        // Target is child_iface or a child of that (status decides).
 
480
        return QAInterface(child_iface, status);
 
481
    }
 
482
}
 
483
 
 
484
QAElement::QAElement()
 
485
:elementRef(0)
 
486
{}
 
487
 
 
488
QAElement::QAElement(AXUIElementRef elementRef)
 
489
:elementRef(elementRef)
 
490
{
 
491
    if (elementRef != 0) {
 
492
        CFRetain(elementRef);
 
493
        CFRetain(object());
 
494
    }
 
495
}
 
496
 
 
497
QAElement::QAElement(const QAElement &element)
 
498
:elementRef(element.elementRef)
 
499
{
 
500
    if (elementRef != 0) {
 
501
        CFRetain(elementRef);
 
502
        CFRetain(object());
 
503
    }
 
504
}
 
505
 
 
506
QAElement::QAElement(HIObjectRef object, int child)
 
507
{
 
508
#ifndef QT_MAC_USE_COCOA
 
509
    if (object == 0) {
 
510
        elementRef = 0; // Create invalid QAElement.
 
511
    } else {
 
512
        elementRef = AXUIElementCreateWithHIObjectAndIdentifier(object, child);
 
513
        CFRetain(object);
 
514
    }
 
515
#else
 
516
    Q_UNUSED(object);
 
517
    Q_UNUSED(child);
 
518
#endif
 
519
}
 
520
 
 
521
QAElement::~QAElement()
 
522
{
 
523
    if (elementRef != 0) {
 
524
        CFRelease(object());
 
525
        CFRelease(elementRef);
 
526
    }
 
527
}
 
528
 
 
529
void QAElement::operator=(const QAElement &other)
 
530
{
 
531
    if (*this == other)
 
532
        return;
 
533
 
 
534
    if (elementRef != 0) {
 
535
        CFRelease(object());
 
536
        CFRelease(elementRef);
 
537
    }
 
538
 
 
539
    elementRef = other.elementRef;
 
540
 
 
541
    if (elementRef != 0) {
 
542
        CFRetain(elementRef);
 
543
        CFRetain(object());
 
544
    }
 
545
}
 
546
 
 
547
bool QAElement::operator==(const QAElement &other) const
 
548
{
 
549
    if (elementRef == 0 || other.elementRef == 0)
 
550
        return (elementRef == other.elementRef);
 
551
 
 
552
    return CFEqual(elementRef, other.elementRef);
 
553
}
 
554
 
 
555
uint qHash(QAElement element)
 
556
{
 
557
    return qHash(element.object()) + qHash(element.id());
 
558
}
 
559
 
 
560
#ifndef QT_MAC_USE_COCOA
 
561
static QInterfaceFactory *createFactory(const QAInterface &interface);
 
562
#endif
 
563
Q_GLOBAL_STATIC(QAccessibleHierarchyManager, accessibleHierarchyManager);
 
564
 
 
565
/*
 
566
    Reomves all accessibility info accosiated with the sender object.
 
567
*/
 
568
void QAccessibleHierarchyManager::objectDestroyed(QObject *object)
 
569
{
 
570
    HIObjectRef hiObject = qobjectHiobjectHash.value(object);
 
571
    delete qobjectElementHash.value(object);
 
572
    qobjectElementHash.remove(object);
 
573
    hiobjectInterfaceHash.remove(hiObject);
 
574
}
 
575
 
 
576
/*
 
577
    Removes all stored items.
 
578
*/
 
579
void QAccessibleHierarchyManager::reset()
 
580
{
 
581
    qDeleteAll(qobjectElementHash);
 
582
    qobjectElementHash.clear();
 
583
    hiobjectInterfaceHash.clear();
 
584
    qobjectHiobjectHash.clear();
 
585
}
 
586
 
 
587
QAccessibleHierarchyManager *QAccessibleHierarchyManager::instance()
 
588
{
 
589
    return accessibleHierarchyManager();
 
590
}
 
591
 
 
592
#ifndef QT_MAC_USE_COCOA
 
593
static bool isItemView(const QAInterface &interface)
 
594
{
 
595
    QObject *object = interface.object();
 
596
    return (interface.role() == QAccessible::List || interface.role() == QAccessible::Table
 
597
            || (object && qobject_cast<QAbstractItemView *>(interface.object()))
 
598
            || (object && object->objectName() == QLatin1String("qt_scrollarea_viewport")
 
599
                && qobject_cast<QAbstractItemView *>(object->parent())));
 
600
}
 
601
#endif
 
602
 
 
603
static bool isTabWidget(const QAInterface &interface)
 
604
{
 
605
    if (QObject *object = interface.object())
 
606
        return (object->inherits("QTabWidget") && interface.id() == 0);
 
607
    return false;
 
608
}
 
609
 
 
610
static bool isStandaloneTabBar(const QAInterface &interface)
 
611
{
 
612
    QObject *object = interface.object();
 
613
    if (interface.role() == QAccessible::PageTabList && object)
 
614
        return (qobject_cast<QTabWidget *>(object->parent()) == 0);
 
615
 
 
616
    return false;
 
617
}
 
618
 
 
619
static bool isEmbeddedTabBar(const QAInterface &interface)
 
620
{
 
621
    QObject *object = interface.object();
 
622
    if (interface.role() == QAccessible::PageTabList && object)
 
623
        return (qobject_cast<QTabWidget *>(object->parent()));
 
624
 
 
625
    return false;
 
626
}
 
627
 
 
628
/*
 
629
    Decides if a QAInterface is interesting from an accessibility users point of view.
 
630
*/
 
631
bool isItInteresting(const QAInterface &interface)
 
632
{
 
633
    // Mac accessibility does not have an attribute that corresponds to the Invisible/Offscreen
 
634
    // state, so we disable the interface here.
 
635
    const QAccessible::State state = interface.state();
 
636
    if (state & QAccessible::Invisible ||
 
637
        state & QAccessible::Offscreen )
 
638
        return false;
 
639
 
 
640
    const QAccessible::Role role = interface.role();
 
641
 
 
642
    if (QObject * const object = interface.object()) {
 
643
        const QString className = QLatin1String(object->metaObject()->className());
 
644
 
 
645
        // VoiceOver focusing on tool tips can be confusing. The contents of the
 
646
        // tool tip is avalible through the description attribute anyway, so
 
647
        // we disable accessibility for tool tips.
 
648
        if (className == QLatin1String("QTipLabel"))
 
649
            return false;
 
650
 
 
651
        // Hide TabBars that has a QTabWidget parent (the tab widget handles the accessibility)
 
652
        if (isEmbeddedTabBar(interface))
 
653
            return false;
 
654
 
 
655
         // Hide docked dockwidgets. ### causes infinitie loop in the apple accessibility code.
 
656
     /*    if (QDockWidget *dockWidget = qobject_cast<QDockWidget *>(object)) {
 
657
            if (dockWidget->isFloating() == false)
 
658
                return false;        
 
659
         }
 
660
    */
 
661
    }
 
662
 
 
663
    // Client is a generic role returned by plain QWidgets or other
 
664
    // widgets that does not have separate QAccessible interface, such
 
665
    // as the TabWidget. Return false unless macRole gives the interface
 
666
    // a special role.
 
667
    if (role == QAccessible::Client && macRole(interface) == CFStringRef(QAXUnknownRole))
 
668
        return false;
 
669
 
 
670
    // Some roles are not interesting:
 
671
    if (role == QAccessible::Border ||    // QFrame
 
672
        role == QAccessible::Application || // We use the system-provided application element.
 
673
        role == QAccessible::MenuItem)      // The system also provides the menu items.
 
674
        return false;
 
675
 
 
676
    // It is probably better to access the toolbar buttons directly than having
 
677
    // to navigate through the toolbar.
 
678
    if (role == QAccessible::ToolBar)
 
679
        return false;
 
680
 
 
681
    return true;
 
682
}
 
683
 
 
684
QAElement QAccessibleHierarchyManager::registerInterface(QObject *object, int child)
 
685
{
 
686
#ifndef QT_MAC_USE_COCOA
 
687
    return registerInterface(QAInterface(QAccessible::queryAccessibleInterface(object), child));
 
688
#else
 
689
    Q_UNUSED(object);
 
690
    Q_UNUSED(child);
 
691
    return QAElement();
 
692
#endif
 
693
}
 
694
 
 
695
/*
 
696
    Creates a QAXUIelement that corresponds to the given QAInterface.
 
697
*/
 
698
QAElement QAccessibleHierarchyManager::registerInterface(const QAInterface &interface)
 
699
{
 
700
#ifndef QT_MAC_USE_COCOA
 
701
    if (interface.isValid() == false)
 
702
        return QAElement();
 
703
    QAInterface objectInterface = interface.objectInterface();
 
704
 
 
705
    QObject * qobject = objectInterface.object();
 
706
    HIObjectRef hiobject = objectInterface.hiObject();
 
707
    if (qobject == 0 || hiobject == 0)
 
708
        return QAElement();
 
709
 
 
710
    if (qobjectElementHash.contains(qobject) == false) {
 
711
        registerInterface(qobject, hiobject, createFactory(interface));
 
712
        HIObjectSetAccessibilityIgnored(hiobject, !isItInteresting(interface));
 
713
    }
 
714
 
 
715
    return QAElement(hiobject, interface.id());
 
716
#else
 
717
    Q_UNUSED(interface);
 
718
    return QAElement();
 
719
#endif
 
720
}
 
721
 
 
722
#ifndef QT_MAC_USE_COCOA
 
723
#include "qaccessible_mac_carbon.cpp"
 
724
#endif
 
725
 
 
726
void QAccessibleHierarchyManager::registerInterface(QObject * qobject, HIObjectRef hiobject, QInterfaceFactory *interfaceFactory)
 
727
{
 
728
#ifndef QT_MAC_USE_COCOA
 
729
    if (qobjectElementHash.contains(qobject) == false) {
 
730
        qobjectElementHash.insert(qobject, interfaceFactory);
 
731
        qobjectHiobjectHash.insert(qobject, hiobject);
 
732
        connect(qobject, SIGNAL(destroyed(QObject *)), SLOT(objectDestroyed(QObject *)));
 
733
    }
 
734
 
 
735
    if (hiobjectInterfaceHash.contains(hiobject) == false) {
 
736
        hiobjectInterfaceHash.insert(hiobject, interfaceFactory);
 
737
        installAcessibilityEventHandler(hiobject);
 
738
    }
 
739
#else
 
740
    Q_UNUSED(qobject);
 
741
    Q_UNUSED(hiobject);
 
742
    Q_UNUSED(interfaceFactory);
 
743
#endif
 
744
}
 
745
 
 
746
void QAccessibleHierarchyManager::registerChildren(const QAInterface &interface)
 
747
{
 
748
    QObject * const object = interface.object();
 
749
    if (object == 0)
 
750
        return;
 
751
 
 
752
    QInterfaceFactory *interfaceFactory = qobjectElementHash.value(object);
 
753
    
 
754
    if (interfaceFactory == 0)
 
755
        return;
 
756
 
 
757
    interfaceFactory->registerChildren();
 
758
}
 
759
 
 
760
QAInterface QAccessibleHierarchyManager::lookup(const AXUIElementRef &element)
 
761
{
 
762
     if (element == 0)
 
763
        return QAInterface();
 
764
#ifndef QT_MAC_USE_COCOA
 
765
    HIObjectRef hiObject = AXUIElementGetHIObject(element);
 
766
 
 
767
    QInterfaceFactory *factory = hiobjectInterfaceHash.value(hiObject);
 
768
    if (factory == 0) {
 
769
        return QAInterface();
 
770
    }
 
771
 
 
772
    UInt64 id;
 
773
    AXUIElementGetIdentifier(element, &id);
 
774
    return factory->interface(id);
 
775
#else
 
776
    return QAInterface();
 
777
#endif;
 
778
}
 
779
 
 
780
QAInterface QAccessibleHierarchyManager::lookup(const QAElement &element)
 
781
{
 
782
    return lookup(element.element());
 
783
}
 
784
 
 
785
QAElement QAccessibleHierarchyManager::lookup(const QAInterface &interface)
 
786
{
 
787
    if (interface.isValid() == false)
 
788
        return QAElement();
 
789
 
 
790
    QInterfaceFactory *factory = qobjectElementHash.value(interface.objectInterface().object());
 
791
    if (factory == 0)
 
792
        return QAElement();
 
793
 
 
794
    return factory->element(interface);
 
795
}
 
796
 
 
797
QAElement QAccessibleHierarchyManager::lookup(QObject * const object, int id)
 
798
{
 
799
    QInterfaceFactory *factory = qobjectElementHash.value(object);
 
800
    if (factory == 0)
 
801
        return QAElement();
 
802
 
 
803
    return factory->element(id);
 
804
}
 
805
 
 
806
/*
 
807
    Standard interface mapping, return the stored interface
 
808
    or HIObjectRef, and there is an one-to-one mapping between
 
809
    the identifier and child.
 
810
*/
 
811
class QStandardInterfaceFactory : public QInterfaceFactory
 
812
{
 
813
public:
 
814
    QStandardInterfaceFactory(const QAInterface &interface)
 
815
    : m_interface(interface), object(interface.hiObject())
 
816
    {
 
817
        CFRetain(object);
 
818
    }
 
819
    
 
820
    ~QStandardInterfaceFactory()
 
821
    {
 
822
         CFRelease(object);
 
823
    }
 
824
 
 
825
    
 
826
    QAInterface interface(UInt64 identifier)
 
827
    {
 
828
        const int child = identifier;
 
829
        return QAInterface(m_interface, child);
 
830
    }
 
831
 
 
832
    QAElement element(int id)
 
833
    {
 
834
        return QAElement(object, id);
 
835
    }
 
836
 
 
837
    QAElement element(const QAInterface &interface)
 
838
    {
 
839
        if (interface.object() == 0)
 
840
            return QAElement();
 
841
        return QAElement(object, interface.id());
 
842
    }
 
843
 
 
844
    void registerChildren()
 
845
    {
 
846
        const int childCount = m_interface.childCount();
 
847
        for (int i = 1; i <= childCount; ++i) {
 
848
            accessibleHierarchyManager()->registerInterface(m_interface.navigate(QAccessible::Child, i));
 
849
        }
 
850
    }
 
851
 
 
852
private:
 
853
    QAInterface m_interface;
 
854
    HIObjectRef object;
 
855
};
 
856
 
 
857
/*
 
858
    Interface mapping where that creates one HIObject for each interface child.
 
859
*/
 
860
class QMultipleHIObjectFactory : public QInterfaceFactory
 
861
{
 
862
public:
 
863
    QMultipleHIObjectFactory(const QAInterface &interface)
 
864
    : m_interface(interface)
 
865
    {  }
 
866
    
 
867
    ~QMultipleHIObjectFactory()
 
868
    {
 
869
        foreach (HIObjectRef object, objects) {
 
870
            CFRelease(object);
 
871
        }
 
872
    }
 
873
 
 
874
    QAInterface interface(UInt64 identifier)
 
875
    {
 
876
        const int child = identifier;
 
877
        return QAInterface(m_interface, child);
 
878
    }
 
879
 
 
880
    QAElement element(int child)
 
881
    {
 
882
        if (child == 0)
 
883
            return QAElement(m_interface.hiObject(), 0);
 
884
        
 
885
        if (child > objects.count())
 
886
            return QAElement();
 
887
 
 
888
        return QAElement(objects.at(child - 1), child);
 
889
    }
 
890
 
 
891
    void registerChildren()
 
892
    {
 
893
#ifndef QT_MAC_USE_COCOA
 
894
        const int childCount = m_interface.childCount();
 
895
        for (int i = 1; i <= childCount; ++i) {
 
896
            HIObjectRef hiobject;
 
897
            HIObjectCreate(kObjectQtAccessibility, 0, &hiobject);
 
898
            objects.append(hiobject);
 
899
              accessibleHierarchyManager()->registerInterface(m_interface.object(), hiobject, this);
 
900
            HIObjectSetAccessibilityIgnored(hiobject, !isItInteresting(m_interface.navigate(QAccessible::Child, i)));
 
901
        }
 
902
#endif
 
903
    }
 
904
 
 
905
private:
 
906
    QAInterface m_interface;
 
907
    QList<HIObjectRef> objects;
 
908
};
 
909
 
 
910
class QItemViewInterfaceFactory : public QInterfaceFactory
 
911
{
 
912
public:
 
913
    QItemViewInterfaceFactory(const QAInterface &interface)
 
914
    : m_interface(interface), object(interface.hiObject())
 
915
    {
 
916
        CFRetain(object);
 
917
        columnCount = 0;
 
918
        if (QTableView * tableView = qobject_cast<QTableView *>(interface.parent().object())) {
 
919
            if (tableView->model())
 
920
                columnCount = tableView->model()->columnCount();
 
921
            if (tableView->verticalHeader())
 
922
                ++columnCount;
 
923
        }
 
924
    }
 
925
    
 
926
    ~QItemViewInterfaceFactory()
 
927
    {
 
928
        CFRelease(object);
 
929
    }
 
930
 
 
931
    QAInterface interface(UInt64 identifier)
 
932
    {
 
933
        if (identifier == 0)
 
934
            return m_interface;
 
935
 
 
936
        if (m_interface.role() == QAccessible::List)
 
937
            return m_interface.childAt(identifier);
 
938
        
 
939
        if (m_interface.role() == QAccessible::Table) {
 
940
            const int index = identifier;
 
941
            if (index == 0)
 
942
                return m_interface; // return the item view interface.
 
943
           
 
944
            const int rowIndex = (index - 1) / (columnCount + 1);
 
945
            const int cellIndex = (index - 1)  % (columnCount + 1);
 
946
/*
 
947
            qDebug() << "index" << index;
 
948
            qDebug() << "rowIndex" << rowIndex;
 
949
            qDebug() << "cellIndex" << cellIndex;
 
950
*/
 
951
            const QAInterface rowInterface = m_interface.childAt(rowIndex + 1);
 
952
 
 
953
            if ((cellIndex) == 0) // Is it a row?
 
954
                return rowInterface;
 
955
            else {
 
956
                return rowInterface.childAt(cellIndex);
 
957
            }
 
958
        }
 
959
 
 
960
        return QAInterface();
 
961
    }
 
962
 
 
963
    QAElement element(int id)
 
964
    {
 
965
        if (id != 0) {
 
966
            return QAElement();
 
967
        }
 
968
        return QAElement(object, 0);
 
969
    }
 
970
 
 
971
    QAElement element(const QAInterface &interface)
 
972
    {
 
973
        if (interface.object() && interface.object() == m_interface.object()) {
 
974
            return QAElement(object, 0);
 
975
        } else if (m_interface.role() == QAccessible::List) {
 
976
            if (interface.parent().object() && interface.parent().object() == m_interface.object())
 
977
                return QAElement(object, m_interface.indexOfChild(interface));
 
978
        } else if (m_interface.role() == QAccessible::Table) {
 
979
            QAInterface currentInterface = interface;
 
980
            int index = 0;
 
981
 
 
982
            while (currentInterface.isValid() && currentInterface.object() == 0) {
 
983
                const QAInterface parentInterface = currentInterface.parent();
 
984
/*
 
985
                qDebug() << "current index" << index;
 
986
                qDebug() << "current interface" << interface;
 
987
 
 
988
                qDebug() << "parent interface" << parentInterface;
 
989
                qDebug() << "grandparent interface" << parentInterface.parent();
 
990
                qDebug() << "childCount" << interface.childCount();
 
991
                qDebug() << "index of child" << parentInterface.indexOfChild(currentInterface);
 
992
*/
 
993
                index += ((parentInterface.indexOfChild(currentInterface) - 1) * (currentInterface.childCount() + 1)) + 1;
 
994
                currentInterface = parentInterface;
 
995
//                qDebug() << "new current interface" << currentInterface;
 
996
            }
 
997
            if (currentInterface.object() == m_interface.object())
 
998
                return QAElement(object, index);
 
999
 
 
1000
 
 
1001
        }
 
1002
        return QAElement();
 
1003
    }
 
1004
 
 
1005
    void registerChildren()
 
1006
    {
 
1007
        // Item view child interfraces don't have their own qobjects, so there is nothing to register here.
 
1008
    }
 
1009
 
 
1010
private:
 
1011
    QAInterface m_interface;
 
1012
    HIObjectRef object;
 
1013
    int columnCount; // for table views;
 
1014
};
 
1015
 
 
1016
#ifndef QT_MAC_USE_COCOA
 
1017
static bool managesChildren(const QAInterface &interface)
 
1018
{
 
1019
    return (interface.childCount() > 0 && interface.childAt(1).id() > 0);
 
1020
}
 
1021
 
 
1022
static QInterfaceFactory *createFactory(const QAInterface &interface)
 
1023
{
 
1024
    if (isItemView(interface)) {
 
1025
        return new QItemViewInterfaceFactory(interface);
 
1026
    }  if (managesChildren(interface)) {
 
1027
        return new QMultipleHIObjectFactory(interface);
 
1028
    }
 
1029
 
 
1030
    return new QStandardInterfaceFactory(interface);
 
1031
}
 
1032
#endif
 
1033
 
 
1034
QList<QAElement> lookup(const QList<QAInterface> &interfaces)
 
1035
{
 
1036
    QList<QAElement> elements;
 
1037
    foreach (const QAInterface &interface, interfaces)
 
1038
        if (interface.isValid()) {
 
1039
            const QAElement element = accessibleHierarchyManager()->lookup(interface);
 
1040
            if (element.isValid())
 
1041
                elements.append(element);
 
1042
        }
 
1043
    return elements;
 
1044
}
 
1045
 
 
1046
// Debug output helpers:
 
1047
/*
 
1048
static QString nameForEventKind(UInt32 kind)
 
1049
{
 
1050
    switch(kind) {
 
1051
        case kEventAccessibleGetChildAtPoint:       return QString("GetChildAtPoint");      break;
 
1052
        case kEventAccessibleGetAllAttributeNames:  return QString("GetAllAttributeNames"); break;
 
1053
        case kEventAccessibleGetNamedAttribute:     return QString("GetNamedAttribute");    break;
 
1054
        case kEventAccessibleSetNamedAttribute:     return QString("SetNamedAttribute");    break;
 
1055
        case kEventAccessibleGetAllActionNames:     return QString("GetAllActionNames");    break;
 
1056
        case kEventAccessibleGetFocusedChild:       return QString("GetFocusedChild");      break;
 
1057
        default:
 
1058
            return QString("Unknown accessibility event type: %1").arg(kind);
 
1059
        break;
 
1060
    };
 
1061
}
 
1062
*/
 
1063
#ifndef QT_MAC_USE_COCOA
 
1064
static bool qt_mac_append_cf_uniq(CFMutableArrayRef array, CFTypeRef value)
 
1065
{
 
1066
    if (value == 0)
 
1067
        return false; 
 
1068
 
 
1069
    CFRange range;
 
1070
    range.location = 0;
 
1071
    range.length = CFArrayGetCount(array);
 
1072
    if(!CFArrayContainsValue(array, range, value)) {
 
1073
        CFArrayAppendValue(array, value);
 
1074
        return true;
 
1075
    }
 
1076
    return false;
 
1077
}
 
1078
 
 
1079
static OSStatus setAttributeValue(EventRef event, const QList<QAElement> &elements)
 
1080
{
 
1081
    CFMutableArrayRef array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks);
 
1082
    foreach (const QAElement &element, elements) {
 
1083
        if (element.isValid())
 
1084
            CFArrayAppendValue(array, element.element());
 
1085
    }
 
1086
 
 
1087
    const OSStatus err = SetEventParameter(event, kEventParamAccessibleAttributeValue, 
 
1088
                                           typeCFTypeRef, sizeof(array), &array);
 
1089
    CFRelease(array);
 
1090
    return err;
 
1091
}
 
1092
#endif //QT_MAC_USE_COCOA
 
1093
 
 
1094
/*
 
1095
    Gets the AccessibleObject parameter from an event.
 
1096
*/
 
1097
static inline AXUIElementRef getAccessibleObjectParameter(EventRef event)
 
1098
{
 
1099
    AXUIElementRef element;
 
1100
    GetEventParameter(event, kEventParamAccessibleObject, typeCFTypeRef, 0,
 
1101
                        sizeof(element), 0, &element);
 
1102
    return element;
 
1103
}
 
1104
 
 
1105
/*
 
1106
    The application event handler makes sure that all top-level qt windows are registered
 
1107
    before any accessibility events are handeled.
 
1108
*/
 
1109
#ifndef QT_MAC_USE_COCOA
 
1110
static OSStatus applicationEventHandler(EventHandlerCallRef next_ref, EventRef event, void *)
 
1111
{
 
1112
    QAInterface rootInterface(QAccessible::queryAccessibleInterface(rootObject ? rootObject : qApp), 0);
 
1113
    accessibleHierarchyManager()->registerChildren(rootInterface);
 
1114
 
 
1115
    return CallNextEventHandler(next_ref, event);
 
1116
}
 
1117
 
 
1118
/*
 
1119
    Returns the value for element by combining the QAccessibility::Checked and
 
1120
    QAccessibility::Mixed flags into an int value that the Mac accessibilty
 
1121
    system understands. This works for check boxes, radio buttons, and the like.
 
1122
    The return values are:
 
1123
    0: unchecked
 
1124
    1: checked
 
1125
    2: undecided
 
1126
*/
 
1127
static int buttonValue(QAInterface element)
 
1128
{
 
1129
    const QAccessible::State state = element.state();
 
1130
    if (state & QAccessible::Mixed)
 
1131
        return 2;
 
1132
    else if(state & QAccessible::Checked)
 
1133
        return 1;
 
1134
    else
 
1135
        return 0;
 
1136
}
 
1137
 
 
1138
static QString getValue(const QAInterface &interface)
 
1139
{
 
1140
    const QAccessible::Role role = interface.role();
 
1141
    if (role == QAccessible::RadioButton || role == QAccessible::CheckBox)
 
1142
        return QString::number(buttonValue(interface));
 
1143
    else
 
1144
        return interface.text(QAccessible::Value);
 
1145
}
 
1146
#endif //QT_MAC_USE_COCOA
 
1147
 
 
1148
/*
 
1149
    Translates a QAccessible::Role into a mac accessibility role.
 
1150
*/
 
1151
static CFStringRef macRole(const QAInterface &interface)
 
1152
{
 
1153
    const QAccessible::Role qtRole = interface.role();
 
1154
 
 
1155
//    qDebug() << "role for" << interface.object() << "interface role" << hex << qtRole;
 
1156
 
 
1157
    // Qt accessibility:  QAccessible::Splitter contains QAccessible::Grip.
 
1158
    // Mac accessibility: AXSplitGroup contains AXSplitter.
 
1159
    if (qtRole == QAccessible::Grip) {
 
1160
        const QAInterface parent = interface.parent();
 
1161
        if (parent.isValid() && parent.role() == QAccessible::Splitter)
 
1162
            return CFStringRef(QAXSplitterRole);
 
1163
    }
 
1164
 
 
1165
    // Tab widgets and standalone tab bars get the kAXTabGroupRole. Accessibility
 
1166
    // for tab bars emebedded in a tab widget is handled by the tab widget.
 
1167
    if (isTabWidget(interface) || isStandaloneTabBar(interface))
 
1168
        return kAXTabGroupRole;
 
1169
 
 
1170
    if (QObject *object = interface.object()) {
 
1171
        // ### The interface for an abstract scroll area returns the generic "Client"
 
1172
        // role, so we have to to an extra detect on the QObject here.
 
1173
        if (object->inherits("QAbstractScrollArea") && interface.id() == 0)
 
1174
            return CFStringRef(QAXScrollAreaRole);
 
1175
 
 
1176
        if (object->inherits("QDockWidget"))
 
1177
            return CFStringRef(QAXUnknownRole);
 
1178
    }
 
1179
 
 
1180
    int i = 0;
 
1181
    int testRole = text_bindings[i][0].qt;
 
1182
    while (testRole != -1) {
 
1183
        if (testRole == qtRole)
 
1184
            return CFStringRef(text_bindings[i][0].mac);
 
1185
        ++i;
 
1186
        testRole = text_bindings[i][0].qt;
 
1187
    }
 
1188
 
 
1189
//    qDebug() << "got unknown role!" << interface << interface.parent();
 
1190
 
 
1191
    return CFStringRef(QAXUnknownRole);
 
1192
}
 
1193
 
 
1194
/*
 
1195
    Translates a QAccessible::Role and an attribute name into a QAccessible::Text, taking into
 
1196
    account execptions listed in text_bindings.
 
1197
*/
 
1198
#ifndef QT_MAC_USE_COCOA
 
1199
static int textForRoleAndAttribute(QAccessible::Role role, CFStringRef attribute)
 
1200
{
 
1201
     // Search for exception, return it if found.
 
1202
    int testRole = text_bindings[0][0].qt;
 
1203
    int i = 0;
 
1204
    while (testRole != -1) {
 
1205
        if (testRole == role) {
 
1206
            int j = 1;
 
1207
            int qtRole = text_bindings[i][j].qt;
 
1208
            CFStringRef testAttribute = CFStringRef(text_bindings[i][j].mac);
 
1209
            while (qtRole != -1) {
 
1210
                if (CFStringCompare(attribute, testAttribute, 0) == kCFCompareEqualTo) {
 
1211
                    return (QAccessible::Text)qtRole;
 
1212
                }
 
1213
                ++j;
 
1214
                testAttribute = CFStringRef(text_bindings[i][j].mac); /// ### custom compare
 
1215
                qtRole = text_bindings[i][j].qt; /// ### custom compare
 
1216
            }
 
1217
            break;
 
1218
        }
 
1219
        ++i;
 
1220
        testRole = text_bindings[i][0].qt;
 
1221
    }
 
1222
 
 
1223
    // Return default mappping
 
1224
    if (CFStringCompare(attribute, CFStringRef(QAXTitleAttribute), 0) == kCFCompareEqualTo)
 
1225
        return QAccessible::Name;
 
1226
    else if (CFStringCompare(attribute, CFStringRef(QAXValueAttribute), 0) == kCFCompareEqualTo)
 
1227
        return QAccessible::Value;
 
1228
    else if (CFStringCompare(attribute, CFStringRef(QAXHelpAttribute), 0) == kCFCompareEqualTo)
 
1229
        return QAccessible::Help;
 
1230
    else if (CFStringCompare(attribute, CFStringRef(QAXDescriptionAttribute), 0) == kCFCompareEqualTo)
 
1231
        return QAccessible::Description;
 
1232
    else
 
1233
        return -1;
 
1234
}
 
1235
 
 
1236
/*
 
1237
    Returns the subrole string constant for the interface if it has one,
 
1238
    else returns an empty string.
 
1239
*/
 
1240
static QCFString subrole(const QAInterface &interface)
 
1241
{
 
1242
    const QAInterface parent = interface.parent();
 
1243
    if (parent.isValid() == false)
 
1244
        return QCFString();
 
1245
 
 
1246
    if (parent.role() == QAccessible::ScrollBar) {
 
1247
        QCFString subrole;
 
1248
        switch(interface.id()) {
 
1249
            case 1: subrole = CFStringRef(QAXDecrementArrowSubrole); break;
 
1250
            case 2: subrole = CFStringRef(QAXDecrementPageSubrole); break;
 
1251
            case 4: subrole = CFStringRef(QAXIncrementPageSubrole); break;
 
1252
            case 5: subrole = CFStringRef(QAXIncrementArrowSubrole); break;
 
1253
            default:
 
1254
            break;
 
1255
        }
 
1256
        return subrole;
 
1257
    }
 
1258
    return QCFString();
 
1259
}
 
1260
 
 
1261
// Gets the scroll bar orientation by asking the QAbstractSlider object directly.
 
1262
static Qt::Orientation scrollBarOrientation(const QAInterface &scrollBar)
 
1263
{
 
1264
    QObject *const object = scrollBar.object();
 
1265
    if (QAbstractSlider * const sliderObject = qobject_cast<QAbstractSlider * const>(object))
 
1266
        return sliderObject->orientation();
 
1267
 
 
1268
    return Qt::Vertical; // D'oh! The interface wasn't a scroll bar.
 
1269
}
 
1270
 
 
1271
static QAInterface scrollAreaGetScrollBarInterface(const QAInterface &scrollArea, Qt::Orientation orientation)
 
1272
{
 
1273
    if (macRole(scrollArea) != CFStringRef(CFStringRef(QAXScrollAreaRole)))
 
1274
        return QAInterface();
 
1275
 
 
1276
    // Child 1 is the contents widget, 2 and 3 are the scroll bar containers wich contains possible scroll bars.
 
1277
    for (int i = 2; i <= 3; ++i) {
 
1278
        QAInterface scrollBarContainer = scrollArea.childAt(i);
 
1279
        for (int i = 1; i <= scrollBarContainer.childCount(); ++i) {
 
1280
            QAInterface scrollBar = scrollBarContainer.childAt(i);
 
1281
            if (scrollBar.isValid() &&
 
1282
                scrollBar.role() == QAccessible::ScrollBar &&
 
1283
                scrollBarOrientation(scrollBar) == orientation)
 
1284
                return scrollBar;
 
1285
        }
 
1286
    }
 
1287
 
 
1288
    return QAInterface();
 
1289
}
 
1290
 
 
1291
static bool scrollAreaHasScrollBar(const QAInterface &scrollArea, Qt::Orientation orientation)
 
1292
{
 
1293
    return scrollAreaGetScrollBarInterface(scrollArea, orientation).isValid();
 
1294
}
 
1295
 
 
1296
static QAElement scrollAreaGetScrollBar(const QAInterface &scrollArea, Qt::Orientation orientation)
 
1297
{
 
1298
    return accessibleHierarchyManager()->lookup(scrollAreaGetScrollBarInterface(scrollArea, orientation));
 
1299
}
 
1300
 
 
1301
static QAElement scrollAreaGetContents(const QAInterface &scrollArea)
 
1302
{
 
1303
    // Child 1 is the contents widget,
 
1304
    return accessibleHierarchyManager()->lookup(scrollArea.navigate(QAccessible::Child, 1));
 
1305
}
 
1306
 
 
1307
static QAElement tabWidgetGetContents(const QAInterface &interface)
 
1308
{
 
1309
    // A kAXTabGroup has a kAXContents attribute, which consists of the
 
1310
    // ui elements for the current tab page. Get the current tab page
 
1311
    // from the QStackedWidget, where the current visible page can
 
1312
    // be found at index 1.
 
1313
    QAInterface stackedWidget = interface.childAt(1);
 
1314
    accessibleHierarchyManager()->registerChildren(stackedWidget);
 
1315
    QAInterface tabPageInterface = stackedWidget.childAt(1);
 
1316
    return accessibleHierarchyManager()->lookup(tabPageInterface);
 
1317
}
 
1318
 
 
1319
static QList<QAElement> tabBarGetTabs(const QAInterface &interface)
 
1320
{
 
1321
    // Get the tabs by searching for children with the "PageTab" role.
 
1322
    // This filters out the left/right navigation buttons.
 
1323
    accessibleHierarchyManager()->registerChildren(interface);
 
1324
    QList<QAElement> tabs;
 
1325
    const int numChildren = interface.childCount();
 
1326
    for (int i = 1; i < numChildren + 1; ++i) {
 
1327
        QAInterface child = interface.navigate(QAccessible::Child, i);
 
1328
        if (child.isValid() && child.role() == QAccessible::PageTab) {
 
1329
            tabs.append(accessibleHierarchyManager()->lookup(child));
 
1330
        }
 
1331
    }
 
1332
    return tabs;
 
1333
}
 
1334
 
 
1335
static QList<QAElement> tabWidgetGetTabs(const QAInterface &interface)
 
1336
{
 
1337
    // Each QTabWidget has two children, a QStackedWidget and a QTabBar.
 
1338
    // Get the tabs from the QTabBar.
 
1339
    return tabBarGetTabs(interface.childAt(2));
 
1340
}
 
1341
 
 
1342
static QList<QAElement> tabWidgetGetChildren(const QAInterface &interface)
 
1343
{
 
1344
    // The children for a kAXTabGroup should consist of the tabs and the
 
1345
    // contents of the current open tab page.
 
1346
    QList<QAElement> children = tabWidgetGetTabs(interface);
 
1347
    children += tabWidgetGetContents(interface);
 
1348
    return children;
 
1349
}
 
1350
#endif //QT_MAC_USE_COCOA
 
1351
 
 
1352
/*
 
1353
    Returns the label (buddy) interface for interface, or 0 if it has none.
 
1354
*/
 
1355
/*
 
1356
static QAInterface findLabel(const QAInterface &interface)
 
1357
{
 
1358
    return interface.navigate(QAccessible::Label, 1);
 
1359
}
 
1360
*/
 
1361
/*
 
1362
    Returns a list of interfaces this interface labels, or an empty list if it doesn't label any.
 
1363
*/
 
1364
/*
 
1365
static QList<QAInterface> findLabelled(const QAInterface &interface)
 
1366
{
 
1367
    QList<QAInterface> interfaceList;
 
1368
 
 
1369
    int count = 1;
 
1370
    const QAInterface labelled = interface.navigate(QAccessible::Labelled, count);
 
1371
    while (labelled.isValid()) {
 
1372
        interfaceList.append(labelled);
 
1373
        ++count;
 
1374
    }
 
1375
    return interfaceList;
 
1376
}
 
1377
*/
 
1378
/*
 
1379
    Tests if the given QAInterface has data for a mac attribute.
 
1380
*/
 
1381
#ifndef QT_MAC_USE_COCOA
 
1382
static bool supportsAttribute(CFStringRef attribute, const QAInterface &interface)
 
1383
{
 
1384
    const int text = textForRoleAndAttribute(interface.role(), attribute);
 
1385
 
 
1386
    // Special case: Static texts don't have a title.
 
1387
    if (interface.role() == QAccessible::StaticText && attribute == CFStringRef(QAXTitleAttribute))
 
1388
        return false;
 
1389
 
 
1390
    // Return true if we the attribute matched a QAccessible::Role and we get text for that role from the interface.
 
1391
    if (text != -1) {
 
1392
        if (text == QAccessible::Value) // Special case for Value, see getValue()
 
1393
            return !getValue(interface).isEmpty();
 
1394
        else
 
1395
            return !interface.text((QAccessible::Text)text).isEmpty();
 
1396
    }
 
1397
 
 
1398
    if (CFStringCompare(attribute, CFStringRef(QAXChildrenAttribute),  0) == kCFCompareEqualTo) {
 
1399
        if (interface.childCount() > 0)
 
1400
            return true;
 
1401
    }
 
1402
 
 
1403
    if (CFStringCompare(attribute, CFStringRef(QAXSubroleAttribute),  0) == kCFCompareEqualTo) {
 
1404
        return (subrole(interface) != QCFString());
 
1405
    }
 
1406
 
 
1407
    return false;
 
1408
}
 
1409
 
 
1410
static void appendIfSupported(CFMutableArrayRef array, CFStringRef attribute, const QAInterface &interface)
 
1411
{
 
1412
    if (supportsAttribute(attribute, interface))
 
1413
        qt_mac_append_cf_uniq(array, attribute);
 
1414
}
 
1415
 
 
1416
/*
 
1417
    Returns the names of the attributes the give QAInterface supports.
 
1418
*/
 
1419
static OSStatus getAllAttributeNames(EventRef event, const QAInterface &interface, EventHandlerCallRef next_ref)
 
1420
{
 
1421
    // Call system event handler.
 
1422
    OSStatus err = CallNextEventHandler(next_ref, event);
 
1423
    if(err != noErr && err != eventNotHandledErr)
 
1424
        return err;
 
1425
    CFMutableArrayRef attrs = 0;
 
1426
    GetEventParameter(event, kEventParamAccessibleAttributeNames, typeCFMutableArrayRef, 0,
 
1427
                      sizeof(attrs), 0, &attrs);
 
1428
 
 
1429
    if (!attrs)
 
1430
        return eventNotHandledErr;
 
1431
 
 
1432
    // Append attribute names that are always supported.
 
1433
    qt_mac_append_cf_uniq(attrs, CFStringRef(QAXPositionAttribute));
 
1434
    qt_mac_append_cf_uniq(attrs, CFStringRef(QAXSizeAttribute));
 
1435
    qt_mac_append_cf_uniq(attrs, CFStringRef(QAXRoleAttribute));
 
1436
    qt_mac_append_cf_uniq(attrs, CFStringRef(QAXEnabledAttribute));
 
1437
    qt_mac_append_cf_uniq(attrs, CFStringRef(QAXWindowAttribute));
 
1438
    qt_mac_append_cf_uniq(attrs, CFStringRef(QAXTopLevelUIElementAttribute));
 
1439
 
 
1440
    // Append these names if the QInterafceItem returns any data for them.
 
1441
    appendIfSupported(attrs, CFStringRef(QAXTitleAttribute), interface);
 
1442
    appendIfSupported(attrs, CFStringRef(QAXValueAttribute), interface);
 
1443
    appendIfSupported(attrs, CFStringRef(QAXDescriptionAttribute), interface);
 
1444
    appendIfSupported(attrs, CFStringRef(QAXLinkedUIElementsAttribute), interface);
 
1445
    appendIfSupported(attrs, CFStringRef(QAXHelpAttribute), interface);
 
1446
    appendIfSupported(attrs, CFStringRef(QAXTitleUIElementAttribute), interface);
 
1447
    appendIfSupported(attrs, CFStringRef(QAXChildrenAttribute), interface);
 
1448
    appendIfSupported(attrs, CFStringRef(QAXSubroleAttribute), interface);
 
1449
 
 
1450
    // Append attribute names based on the interaface role.
 
1451
    switch (interface.role())  {
 
1452
        case QAccessible::Window:
 
1453
            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMainAttribute));
 
1454
            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMinimizedAttribute));
 
1455
            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXCloseButtonAttribute));
 
1456
            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXZoomButtonAttribute));
 
1457
            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMinimizeButtonAttribute));
 
1458
            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXToolbarButtonAttribute));
 
1459
            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXGrowAreaAttribute));
 
1460
        break;
 
1461
        case QAccessible::RadioButton:
 
1462
        case QAccessible::CheckBox:
 
1463
            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMinValueAttribute));
 
1464
            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMaxValueAttribute));
 
1465
        break;
 
1466
        case QAccessible::ScrollBar:
 
1467
            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXOrientationAttribute));
 
1468
        break;
 
1469
        case QAccessible::Splitter:
 
1470
            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXSplittersAttribute));
 
1471
        break;
 
1472
        case QAccessible::Table:
 
1473
            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXRowsAttribute));
 
1474
            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXVisibleRowsAttribute));
 
1475
            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXSelectedRowsAttribute));
 
1476
        break;
 
1477
        default:
 
1478
        break;
 
1479
    }
 
1480
 
 
1481
    // Append attribute names based on the mac accessibility role.
 
1482
    const QCFString mac_role = macRole(interface);
 
1483
    if (mac_role == CFStringRef(QAXSplitterRole)) {
 
1484
        qt_mac_append_cf_uniq(attrs, CFStringRef(QAXPreviousContentsAttribute));
 
1485
        qt_mac_append_cf_uniq(attrs, CFStringRef(QAXNextContentsAttribute));
 
1486
        qt_mac_append_cf_uniq(attrs, CFStringRef(QAXOrientationAttribute));
 
1487
    } else if (mac_role == CFStringRef(QAXScrollAreaRole)) {
 
1488
        if (scrollAreaHasScrollBar(interface, Qt::Horizontal))
 
1489
            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXHorizontalScrollBarAttribute));
 
1490
        if (scrollAreaHasScrollBar(interface, Qt::Vertical))
 
1491
            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXVerticalScrollBarAttribute));
 
1492
        qt_mac_append_cf_uniq(attrs, CFStringRef(QAXContentsAttribute));
 
1493
    } else if (mac_role == CFStringRef(QAXTabGroupRole)) {
 
1494
        qt_mac_append_cf_uniq(attrs, CFStringRef(QAXTabsAttribute));
 
1495
        // Only tab widgets can have the contents attribute, there is no way of getting
 
1496
        // the contents from a QTabBar.
 
1497
        if (isTabWidget(interface)) 
 
1498
            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXContentsAttribute));
 
1499
    }
 
1500
 
 
1501
    return noErr;
 
1502
}
 
1503
 
 
1504
static void handleStringAttribute(EventRef event, QAccessible::Text text, const QAInterface &interface)
 
1505
{
 
1506
    QString str = interface.text(text);
 
1507
    if (str.isEmpty())
 
1508
        return;
 
1509
 
 
1510
    // Remove any html markup from the text string, or VoiceOver will read the html tags.
 
1511
    static QTextDocument document;
 
1512
    document.setHtml(str);
 
1513
    str = document.toPlainText();
 
1514
 
 
1515
    CFStringRef cfstr = QCFString::toCFStringRef(str);
 
1516
    SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFStringRef, sizeof(cfstr), &cfstr);
 
1517
}
 
1518
 
 
1519
/*
 
1520
    Handles the parent attribute for a interface.
 
1521
    There are basically three cases here:
 
1522
    1. interface is a HIView and has only HIView children.
 
1523
    2. interface is a HIView but has children that is not a HIView
 
1524
    3. interface is not a HIView.
 
1525
*/
 
1526
static OSStatus handleChildrenAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
 
1527
{
 
1528
   // Add the children for this interface to the global QAccessibelHierachyManager.
 
1529
    accessibleHierarchyManager()->registerChildren(interface);
 
1530
 
 
1531
    if (isTabWidget(interface)) {
 
1532
        QList<QAElement> children = tabWidgetGetChildren(interface);
 
1533
        const int childCount = children.count();
 
1534
 
 
1535
        CFMutableArrayRef array = 0;
 
1536
        array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks);
 
1537
        for (int i = 0; i < childCount; ++i)  {
 
1538
            qt_mac_append_cf_uniq(array, children.at(i).element());
 
1539
        }
 
1540
 
 
1541
        OSStatus err;
 
1542
        err = SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFArrayRef, sizeof(array), &array);
 
1543
        if (err != noErr)
 
1544
            qWarning("Qt:Internal error (%s:%d)", __FILE__, __LINE__);
 
1545
 
 
1546
        return noErr;
 
1547
    }
 
1548
 
 
1549
    const QList<QAElement> children = lookup(interface.children());
 
1550
    const int childCount = children.count();
 
1551
 
 
1552
    OSStatus err = eventNotHandledErr;
 
1553
    if (interface.isHIView())
 
1554
        err = CallNextEventHandler(next_ref, event);
 
1555
 
 
1556
    CFMutableArrayRef array = 0;
 
1557
    int arraySize = 0;
 
1558
    if (err == noErr) {
 
1559
        CFTypeRef obj = 0;
 
1560
        err = GetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, NULL , sizeof(obj), NULL, &obj);
 
1561
        if (err == noErr && obj != 0) {
 
1562
            array = (CFMutableArrayRef)obj;
 
1563
            arraySize = CFArrayGetCount(array);
 
1564
        }
 
1565
    }
 
1566
 
 
1567
    if (array) {
 
1568
        CFArrayRemoveAllValues(array);
 
1569
        for (int i = 0; i < childCount; ++i)  {
 
1570
            qt_mac_append_cf_uniq(array, children.at(i).element());
 
1571
        }
 
1572
    } else {
 
1573
        array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks);
 
1574
        for (int i = 0; i < childCount; ++i)  {
 
1575
            qt_mac_append_cf_uniq(array, children.at(i).element());
 
1576
        }
 
1577
 
 
1578
        err = SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFArrayRef, sizeof(array), &array);
 
1579
        if (err != noErr)
 
1580
            qWarning("Qt:Internal error (%s:%d)", __FILE__, __LINE__);
 
1581
    }
 
1582
 
 
1583
    return noErr;
 
1584
}
 
1585
 
 
1586
/*
 
1587
 
 
1588
*/
 
1589
static OSStatus handleParentAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
 
1590
{
 
1591
    OSStatus err = eventNotHandledErr;
 
1592
    if (interface.isHIView()) {
 
1593
         err = CallNextEventHandler(next_ref, event);
 
1594
    }
 
1595
    if (err == noErr)
 
1596
        return err;
 
1597
 
 
1598
    const QAInterface parentInterface  = interface.navigate(QAccessible::Ancestor, 1);
 
1599
    const QAElement parentElement = accessibleHierarchyManager()->lookup(parentInterface);
 
1600
 
 
1601
    if (parentElement.isValid() == false)
 
1602
        return eventNotHandledErr;
 
1603
 
 
1604
    AXUIElementRef elementRef = parentElement.element();
 
1605
    SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof(elementRef), &elementRef);
 
1606
    return noErr;
 
1607
}
 
1608
#endif
 
1609
 
 
1610
struct IsWindowTest
 
1611
{
 
1612
    static inline bool test(const QAInterface &interface)
 
1613
    {
 
1614
        return (interface.role() == QAccessible::Window);
 
1615
    }
 
1616
};
 
1617
 
 
1618
struct IsWindowAndNotDrawerOrSheetTest
 
1619
{
 
1620
    static inline bool test(const QAInterface &interface)
 
1621
    {
 
1622
        QWidget * const widget = qobject_cast<QWidget*>(interface.object());
 
1623
        return (interface.role() == QAccessible::Window &&
 
1624
                widget && widget->isWindow() &&
 
1625
                !qt_mac_is_macdrawer(widget) &&
 
1626
                !qt_mac_is_macsheet(widget));
 
1627
    }
 
1628
};
 
1629
 
 
1630
/*
 
1631
    Navigates up the iterfaces ancestor hierachy until a QAccessibleInterface that
 
1632
    passes the Test is found. If we reach a interface that is a HIView we stop the
 
1633
    search and call AXUIElementCopyAttributeValue.
 
1634
*/
 
1635
template <typename TestType>
 
1636
OSStatus navigateAncestors(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface, CFStringRef attribute)
 
1637
{
 
1638
    if (interface.isHIView())
 
1639
        return CallNextEventHandler(next_ref, event);
 
1640
 
 
1641
    QAInterface current = interface;
 
1642
    QAElement element;
 
1643
    while (current.isValid()) {
 
1644
        if (TestType::test(interface)) {
 
1645
            element = accessibleHierarchyManager()->lookup(current);
 
1646
            break;
 
1647
        }
 
1648
 
 
1649
        // If we reach an InterfaceItem that is a HiView we can hand of the search to
 
1650
        // the system event handler. This is the common case.
 
1651
        if (current.isHIView()) {
 
1652
            CFTypeRef value = 0;
 
1653
            const QAElement currentElement = accessibleHierarchyManager()->lookup(current);
 
1654
            AXError err = AXUIElementCopyAttributeValue(currentElement.element(), attribute, &value);
 
1655
            AXUIElementRef newElement = (AXUIElementRef)value;
 
1656
 
 
1657
            if (err == noErr)
 
1658
                element = QAElement(newElement);
 
1659
 
 
1660
            if (newElement != 0)
 
1661
                CFRelease(newElement);
 
1662
            break;
 
1663
        }
 
1664
 
 
1665
        QAInterface next = current.parent();
 
1666
        if (next.isValid() == false)
 
1667
            break;
 
1668
        if (next == current)
 
1669
            break;
 
1670
        current = next;
 
1671
    }
 
1672
 
 
1673
    if (element.isValid() == false)
 
1674
        return eventNotHandledErr;
 
1675
 
 
1676
 
 
1677
    AXUIElementRef elementRef = element.element();
 
1678
    SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef,
 
1679
                                      sizeof(elementRef), &elementRef);
 
1680
    return noErr;
 
1681
}
 
1682
 
 
1683
/*
 
1684
    Returns the top-level window for an interface, which is the closest ancestor interface that
 
1685
    has the Window role, but is not a sheet or a drawer.
 
1686
*/
 
1687
#ifndef QT_MAC_USE_COCOA
 
1688
static OSStatus handleWindowAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
 
1689
{
 
1690
    return navigateAncestors<IsWindowAndNotDrawerOrSheetTest>(next_ref, event, interface, CFStringRef(QAXWindowAttribute));
 
1691
}
 
1692
 
 
1693
/*
 
1694
    Returns the top-level window for an interface, which is the closest ancestor interface that
 
1695
    has the Window role. (Can also be a sheet or a drawer)
 
1696
*/
 
1697
static OSStatus handleTopLevelUIElementAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
 
1698
{
 
1699
    return navigateAncestors<IsWindowTest>(next_ref, event, interface, CFStringRef(QAXTopLevelUIElementAttribute));
 
1700
}
 
1701
 
 
1702
/*
 
1703
    Returns the tab buttons for an interface.
 
1704
*/
 
1705
static OSStatus handleTabsAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
 
1706
{
 
1707
    Q_UNUSED(next_ref);
 
1708
    if (isTabWidget(interface))
 
1709
        return setAttributeValue(event, tabWidgetGetTabs(interface));
 
1710
    else
 
1711
        return setAttributeValue(event, tabBarGetTabs(interface));
 
1712
}
 
1713
 
 
1714
static OSStatus handlePositionAttribute(EventHandlerCallRef, EventRef event, const QAInterface &interface)
 
1715
{
 
1716
    QPoint qpoint(interface.rect().topLeft());
 
1717
    HIPoint point;
 
1718
    point.x = qpoint.x();
 
1719
    point.y = qpoint.y();
 
1720
    SetEventParameter(event, kEventParamAccessibleAttributeValue, typeHIPoint, sizeof(point), &point);
 
1721
    return noErr;
 
1722
}
 
1723
 
 
1724
static OSStatus handleSizeAttribute(EventHandlerCallRef, EventRef event, const QAInterface &interface)
 
1725
{
 
1726
    QSize qSize(interface.rect().size());
 
1727
    HISize size;
 
1728
    size.width = qSize.width();
 
1729
    size.height = qSize.height();
 
1730
    SetEventParameter(event, kEventParamAccessibleAttributeValue, typeHISize, sizeof(size), &size);
 
1731
    return noErr;
 
1732
}
 
1733
 
 
1734
static OSStatus handleSubroleAttribute(EventHandlerCallRef, EventRef event, const QAInterface &interface)
 
1735
{
 
1736
    const QCFString role = subrole(interface);
 
1737
    CFStringRef rolestr = (CFStringRef)role;
 
1738
    SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof(rolestr), &rolestr);
 
1739
    return noErr;
 
1740
}
 
1741
 
 
1742
static OSStatus handleOrientationAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
 
1743
{
 
1744
    QObject *const object = interface.object();
 
1745
    Qt::Orientation orientation;
 
1746
    if (interface.role() == QAccessible::ScrollBar) {
 
1747
        orientation  = scrollBarOrientation(interface);
 
1748
    } else if (QSplitterHandle * const splitter = qobject_cast<QSplitterHandle * const>(object)) {
 
1749
        // Qt reports the layout orientation, but we want the splitter handle orientation.
 
1750
        orientation = (splitter->orientation() == Qt::Horizontal) ? Qt::Vertical : Qt::Horizontal;
 
1751
    } else {
 
1752
        return CallNextEventHandler(next_ref, event);
 
1753
    }
 
1754
    const CFStringRef orientationString = (orientation == Qt::Vertical)
 
1755
        ? CFStringRef(QAXVerticalOrientationValue) : CFStringRef(QAXHorizontalOrientationValue);
 
1756
    SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFStringRef, sizeof(orientationString), &orientationString);
 
1757
    return noErr;
 
1758
}
 
1759
 
 
1760
/*
 
1761
    Figures out the next or previous contents for a splitter.
 
1762
*/
 
1763
static OSStatus handleSplitterContentsAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface, QCFString nextOrPrev)
 
1764
{
 
1765
    if (interface.isValid() == false || interface.role() != QAccessible::Grip)
 
1766
        return eventNotHandledErr;
 
1767
 
 
1768
    const QAInterface parent = interface.parent();
 
1769
    if (parent.isValid() == false)
 
1770
        return CallNextEventHandler(next_ref, event);
 
1771
 
 
1772
    if (parent.role() != QAccessible::Splitter)
 
1773
        return CallNextEventHandler(next_ref, event);
 
1774
 
 
1775
    const QSplitter * const splitter = qobject_cast<const QSplitter * const>(parent.object());
 
1776
    if (splitter == 0)
 
1777
        return CallNextEventHandler(next_ref, event);
 
1778
 
 
1779
    QWidget * const splitterHandle = qobject_cast<QWidget * const>(interface.object());
 
1780
    const int splitterHandleIndex = splitter->indexOf(splitterHandle);
 
1781
    const int widgetIndex = (nextOrPrev == QCFString(CFStringRef(QAXPreviousContentsAttribute))) ? splitterHandleIndex - 1 : splitterHandleIndex;
 
1782
    const QAElement contentsElement = accessibleHierarchyManager()->lookup(splitter->widget(widgetIndex), 0);
 
1783
    return setAttributeValue(event, QList<QAElement>() << contentsElement);
 
1784
}
 
1785
 
 
1786
/*
 
1787
    Creates a list of all splitter handles the splitter contains.
 
1788
*/
 
1789
static OSStatus handleSplittersAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
 
1790
{
 
1791
    const QSplitter * const splitter = qobject_cast<const QSplitter * const>(interface.object());
 
1792
    if (splitter == 0)
 
1793
        return CallNextEventHandler(next_ref, event);
 
1794
 
 
1795
    accessibleHierarchyManager()->registerChildren(interface);
 
1796
 
 
1797
    QList<QAElement> handles;
 
1798
    const int visibleSplitterCount = splitter->count() -1; // skip first handle, it's always invisible.
 
1799
    for (int i = 0; i < visibleSplitterCount; ++i)
 
1800
        handles.append(accessibleHierarchyManager()->lookup(splitter->handle(i + 1), 0));
 
1801
 
 
1802
    return setAttributeValue(event, handles);
 
1803
}
 
1804
 
 
1805
// This handler gets the scroll bars for a scroll area
 
1806
static OSStatus handleScrollBarAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &scrollArea, Qt::Orientation orientation)
 
1807
{
 
1808
    QAElement scrollBar = scrollAreaGetScrollBar(scrollArea, orientation);
 
1809
    if (scrollBar.isValid() == false)
 
1810
        return CallNextEventHandler(next_ref, event);
 
1811
 
 
1812
    AXUIElementRef elementRef = scrollBar.element();
 
1813
    SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof(elementRef), &elementRef);
 
1814
    return noErr;
 
1815
}
 
1816
 
 
1817
// This handler gets the contents for a scroll area or tab widget.
 
1818
static OSStatus handleContentsAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
 
1819
{
 
1820
    const QCFString mac_role = macRole(interface);
 
1821
 
 
1822
    QAElement contents;
 
1823
 
 
1824
    if (mac_role == kAXTabGroupRole) {
 
1825
        contents = tabWidgetGetContents(interface);
 
1826
    } else {
 
1827
        contents = scrollAreaGetContents(interface);
 
1828
        if (contents.isValid() == false)
 
1829
            return CallNextEventHandler(next_ref, event);
 
1830
    }
 
1831
 
 
1832
    return setAttributeValue(event, QList<QAElement>() << contents);
 
1833
}
 
1834
 
 
1835
static OSStatus handleRowsAttribute(EventHandlerCallRef, EventRef event, QAInterface &tableView)
 
1836
{
 
1837
    QList<QAElement> rows = lookup(tableView.children());
 
1838
 
 
1839
    // kill the first row which is the horizontal header.
 
1840
    rows.removeAt(0);
 
1841
 
 
1842
    return setAttributeValue(event, rows);
 
1843
}
 
1844
 
 
1845
static OSStatus handleVisibleRowsAttribute(EventHandlerCallRef, EventRef event, QAInterface &tableView)
 
1846
{
 
1847
    QList<QAElement> visibleRows;
 
1848
 
 
1849
    QList<QAInterface> rows = tableView.children();
 
1850
    // kill the first row which is the horizontal header.
 
1851
    rows.removeAt(0);
 
1852
 
 
1853
    foreach (const QAInterface &interface, rows)
 
1854
        if ((interface.state() & QAccessible::Invisible) == false)
 
1855
            visibleRows.append(accessibleHierarchyManager()->lookup(interface));
 
1856
 
 
1857
    return setAttributeValue(event, visibleRows);
 
1858
}
 
1859
 
 
1860
static OSStatus handleSelectedRowsAttribute(EventHandlerCallRef, EventRef event, QAInterface &tableView)
 
1861
{
 
1862
    QList<QAElement> selectedRows;
 
1863
    foreach (const QAInterface &interface, tableView.children())
 
1864
        if ((interface.state() & QAccessible::Selected))
 
1865
            selectedRows.append(accessibleHierarchyManager()->lookup(interface));
 
1866
 
 
1867
    return setAttributeValue(event, selectedRows);
 
1868
}
 
1869
 
 
1870
static OSStatus getNamedAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
 
1871
{
 
1872
    CFStringRef var;
 
1873
    GetEventParameter(event, kEventParamAccessibleAttributeName, typeCFStringRef, 0,
 
1874
                              sizeof(var), 0, &var);
 
1875
 
 
1876
    if (CFStringCompare(var, CFStringRef(QAXChildrenAttribute), 0) == kCFCompareEqualTo) {
 
1877
        return handleChildrenAttribute(next_ref, event, interface);
 
1878
    } else if(CFStringCompare(var, CFStringRef(QAXTopLevelUIElementAttribute), 0) == kCFCompareEqualTo) {
 
1879
        return handleTopLevelUIElementAttribute(next_ref, event, interface);
 
1880
    } else if(CFStringCompare(var, CFStringRef(QAXWindowAttribute), 0) == kCFCompareEqualTo) {
 
1881
        return handleWindowAttribute(next_ref, event, interface);
 
1882
    } else if(CFStringCompare(var, CFStringRef(QAXParentAttribute), 0) == kCFCompareEqualTo) {
 
1883
        return handleParentAttribute(next_ref, event, interface);
 
1884
    } else if (CFStringCompare(var, CFStringRef(QAXPositionAttribute), 0) == kCFCompareEqualTo) {
 
1885
        return handlePositionAttribute(next_ref, event, interface);
 
1886
    } else if (CFStringCompare(var, CFStringRef(QAXSizeAttribute), 0) == kCFCompareEqualTo) {
 
1887
        return handleSizeAttribute(next_ref, event, interface);
 
1888
    } else  if (CFStringCompare(var, CFStringRef(QAXRoleAttribute), 0) == kCFCompareEqualTo) {
 
1889
        CFStringRef role = macRole(interface);
 
1890
// ###
 
1891
//        QWidget * const widget = qobject_cast<QWidget *>(interface.object());
 
1892
//        if (role == CFStringRef(QAXUnknownRole) && widget && widget->isWindow())
 
1893
//            role = CFStringRef(QAXWindowRole);
 
1894
 
 
1895
        SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFStringRef,
 
1896
                          sizeof(role), &role);
 
1897
 
 
1898
    } else if (CFStringCompare(var, CFStringRef(QAXEnabledAttribute), 0) == kCFCompareEqualTo) {
 
1899
        Boolean val =  !((interface.state() & QAccessible::Unavailable))
 
1900
                     && !((interface.state() & QAccessible::Invisible));
 
1901
        SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
 
1902
                          sizeof(val), &val);
 
1903
    } else if (CFStringCompare(var, CFStringRef(QAXExpandedAttribute), 0) == kCFCompareEqualTo) {
 
1904
        Boolean val = (interface.state() & QAccessible::Expanded);
 
1905
        SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
 
1906
                          sizeof(val), &val);
 
1907
    } else if (CFStringCompare(var, CFStringRef(QAXSelectedAttribute), 0) == kCFCompareEqualTo) {
 
1908
        Boolean val = (interface.state() & QAccessible::Selection);
 
1909
        SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
 
1910
                          sizeof(val), &val);
 
1911
    } else if (CFStringCompare(var, CFStringRef(QAXFocusedAttribute), 0) == kCFCompareEqualTo) {
 
1912
        Boolean val = (interface.state() & QAccessible::Focus);
 
1913
        SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
 
1914
                          sizeof(val), &val);
 
1915
    } else if (CFStringCompare(var, CFStringRef(QAXSelectedChildrenAttribute), 0) == kCFCompareEqualTo) {
 
1916
        const int cc = interface.childCount();
 
1917
        QList<QAElement> selected;
 
1918
        for (int i = 1; i <= cc; ++i) {
 
1919
            const QAInterface child_iface = interface.navigate(QAccessible::Child, i);
 
1920
            if (child_iface.isValid() && child_iface.state() & QAccessible::Selected)
 
1921
                selected.append(accessibleHierarchyManager()->lookup(child_iface));
 
1922
        }
 
1923
 
 
1924
        return setAttributeValue(event, selected);
 
1925
 
 
1926
      } else if (CFStringCompare(var, CFStringRef(QAXCloseButtonAttribute), 0) == kCFCompareEqualTo) {
 
1927
        if(interface.object() && interface.object()->isWidgetType()) {
 
1928
            Boolean val = true; //do we want to add a WState for this?
 
1929
            SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
 
1930
                              sizeof(val), &val);
 
1931
        }
 
1932
    } else if (CFStringCompare(var, CFStringRef(QAXZoomButtonAttribute), 0) == kCFCompareEqualTo) {
 
1933
        if(interface.object() && interface.object()->isWidgetType()) {
 
1934
            QWidget *widget = (QWidget*)interface.object();
 
1935
            Boolean val = (widget->windowFlags() & Qt::WindowMaximizeButtonHint);
 
1936
            SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
 
1937
                              sizeof(val), &val);
 
1938
        }
 
1939
    } else if (CFStringCompare(var, CFStringRef(QAXMinimizeButtonAttribute), 0) == kCFCompareEqualTo) {
 
1940
        if(interface.object() && interface.object()->isWidgetType()) {
 
1941
            QWidget *widget = (QWidget*)interface.object();
 
1942
            Boolean val = (widget->windowFlags() & Qt::WindowMinimizeButtonHint);
 
1943
            SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
 
1944
                              sizeof(val), &val);
 
1945
        }
 
1946
    } else if (CFStringCompare(var, CFStringRef(QAXToolbarButtonAttribute), 0) == kCFCompareEqualTo) {
 
1947
        if(interface.object() && interface.object()->isWidgetType()) {
 
1948
            QWidget *widget = (QWidget*)interface.object();
 
1949
            Boolean val = qobject_cast<QMainWindow *>(widget) != 0;
 
1950
            SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
 
1951
                              sizeof(val), &val);
 
1952
        }
 
1953
    } else if (CFStringCompare(var, CFStringRef(QAXGrowAreaAttribute), 0) == kCFCompareEqualTo) {
 
1954
        if(interface.object() && interface.object()->isWidgetType()) {
 
1955
            Boolean val = true; //do we want to add a WState for this?
 
1956
            SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
 
1957
                              sizeof(val), &val);
 
1958
        }
 
1959
    } else if (CFStringCompare(var, CFStringRef(QAXMinimizedAttribute), 0) == kCFCompareEqualTo) {
 
1960
        if (interface.object() && interface.object()->isWidgetType()) {
 
1961
            QWidget *widget = (QWidget*)interface.object();
 
1962
            Boolean val = (widget->windowState() & Qt::WindowMinimized);
 
1963
            SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
 
1964
                              sizeof(val), &val);
 
1965
        }
 
1966
    } else if (CFStringCompare(var, CFStringRef(QAXSubroleAttribute), 0) == kCFCompareEqualTo) {
 
1967
        return handleSubroleAttribute(next_ref, event, interface);
 
1968
    } else if (CFStringCompare(var, CFStringRef(QAXRoleDescriptionAttribute), 0) == kCFCompareEqualTo) {
 
1969
#if !defined(QT_MAC_USE_COCOA)
 
1970
        if (HICopyAccessibilityRoleDescription) {
 
1971
            const CFStringRef roleDescription = HICopyAccessibilityRoleDescription(macRole(interface), 0);
 
1972
            SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFStringRef,
 
1973
                          sizeof(roleDescription), &roleDescription);
 
1974
        } else
 
1975
#endif
 
1976
        {
 
1977
            // Just use Qt::Description on 10.3
 
1978
            handleStringAttribute(event, QAccessible::Description, interface);
 
1979
        }
 
1980
    } else if (CFStringCompare(var, CFStringRef(QAXTitleAttribute), 0) == kCFCompareEqualTo) {
 
1981
        const QAccessible::Role role = interface.role();
 
1982
        const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var);
 
1983
        handleStringAttribute(event, text, interface);
 
1984
    } else if (CFStringCompare(var, CFStringRef(QAXValueAttribute), 0) == kCFCompareEqualTo) {
 
1985
        const QAccessible::Role role = interface.role();
 
1986
        const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var);
 
1987
        if (role == QAccessible::CheckBox || role == QAccessible::RadioButton) {
 
1988
            int value = buttonValue(interface);
 
1989
            SetEventParameter(event, kEventParamAccessibleAttributeValue, typeUInt32, sizeof(value), &value);
 
1990
        } else {
 
1991
            handleStringAttribute(event, text, interface);
 
1992
        }
 
1993
    } else if (CFStringCompare(var, CFStringRef(QAXDescriptionAttribute), 0) == kCFCompareEqualTo) {
 
1994
        const QAccessible::Role role = interface.role();
 
1995
        const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var);
 
1996
        handleStringAttribute(event, text, interface);
 
1997
    } else if (CFStringCompare(var, CFStringRef(QAXLinkedUIElementsAttribute), 0) == kCFCompareEqualTo) {
 
1998
        return CallNextEventHandler(next_ref, event);
 
1999
    } else if (CFStringCompare(var, CFStringRef(QAXHelpAttribute), 0) == kCFCompareEqualTo) {
 
2000
        const QAccessible::Role role = interface.role();
 
2001
        const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var);
 
2002
        handleStringAttribute(event, text, interface);
 
2003
    } else if (CFStringCompare(var, kAXTitleUIElementAttribute, 0) == kCFCompareEqualTo) {
 
2004
        return CallNextEventHandler(next_ref, event);
 
2005
    } else if (CFStringCompare(var, CFStringRef(QAXTabsAttribute), 0) == kCFCompareEqualTo) {
 
2006
        return handleTabsAttribute(next_ref, event, interface);
 
2007
    } else if (CFStringCompare(var, CFStringRef(QAXMinValueAttribute), 0) == kCFCompareEqualTo) {
 
2008
        // tabs we first go to the tab bar which is child #2.
 
2009
        QAInterface tabBarInterface = interface.childAt(2);
 
2010
        return handleTabsAttribute(next_ref, event, tabBarInterface);
 
2011
    } else if (CFStringCompare(var, CFStringRef(QAXMinValueAttribute), 0) == kCFCompareEqualTo) {
 
2012
        if (interface.role() == QAccessible::RadioButton || interface.role() == QAccessible::CheckBox) {
 
2013
            uint value = 0;
 
2014
            SetEventParameter(event, kEventParamAccessibleAttributeValue, typeUInt32, sizeof(value), &value);
 
2015
        } else {
 
2016
            return CallNextEventHandler(next_ref, event);
 
2017
        }
 
2018
    } else if (CFStringCompare(var, CFStringRef(QAXMaxValueAttribute), 0) == kCFCompareEqualTo) {
 
2019
        if (interface.role() == QAccessible::RadioButton || interface.role() == QAccessible::CheckBox) {
 
2020
            uint value = 2;
 
2021
            SetEventParameter(event, kEventParamAccessibleAttributeValue, typeUInt32, sizeof(value), &value);
 
2022
        } else {
 
2023
            return CallNextEventHandler(next_ref, event);
 
2024
        }
 
2025
    } else if (CFStringCompare(var, CFStringRef(QAXOrientationAttribute), 0) == kCFCompareEqualTo) {
 
2026
        return handleOrientationAttribute(next_ref, event, interface);
 
2027
    } else if (CFStringCompare(var, CFStringRef(QAXPreviousContentsAttribute), 0) == kCFCompareEqualTo) {
 
2028
        return handleSplitterContentsAttribute(next_ref, event, interface, CFStringRef(QAXPreviousContentsAttribute));
 
2029
    } else if (CFStringCompare(var, CFStringRef(QAXNextContentsAttribute), 0) == kCFCompareEqualTo) {
 
2030
        return handleSplitterContentsAttribute(next_ref, event, interface, CFStringRef(QAXNextContentsAttribute));
 
2031
    } else if (CFStringCompare(var, CFStringRef(QAXSplittersAttribute), 0) == kCFCompareEqualTo) {
 
2032
        return handleSplittersAttribute(next_ref, event, interface);
 
2033
    } else if (CFStringCompare(var, CFStringRef(QAXHorizontalScrollBarAttribute), 0) == kCFCompareEqualTo) {
 
2034
        return handleScrollBarAttribute(next_ref, event, interface, Qt::Horizontal);
 
2035
    } else if (CFStringCompare(var, CFStringRef(QAXVerticalScrollBarAttribute), 0) == kCFCompareEqualTo) {
 
2036
        return handleScrollBarAttribute(next_ref, event, interface, Qt::Vertical);
 
2037
    } else if (CFStringCompare(var, CFStringRef(QAXContentsAttribute), 0) == kCFCompareEqualTo) {
 
2038
        return handleContentsAttribute(next_ref, event, interface);
 
2039
    } else if (CFStringCompare(var, CFStringRef(QAXRowsAttribute), 0) == kCFCompareEqualTo) {
 
2040
        return handleRowsAttribute(next_ref, event, interface);
 
2041
    } else if (CFStringCompare(var, CFStringRef(QAXVisibleRowsAttribute), 0) == kCFCompareEqualTo) {
 
2042
        return handleVisibleRowsAttribute(next_ref, event, interface);
 
2043
    } else if (CFStringCompare(var, CFStringRef(QAXSelectedRowsAttribute), 0) == kCFCompareEqualTo) {
 
2044
        return handleSelectedRowsAttribute(next_ref, event, interface);
 
2045
    } else {
 
2046
        return CallNextEventHandler(next_ref, event);
 
2047
    }
 
2048
    return noErr;
 
2049
}
 
2050
 
 
2051
static OSStatus isNamedAttributeSettable(EventRef event, const QAInterface &interface)
 
2052
{
 
2053
    CFStringRef var;
 
2054
    GetEventParameter(event, kEventParamAccessibleAttributeName, typeCFStringRef, 0,
 
2055
                      sizeof(var), 0, &var);
 
2056
    Boolean settable = false;
 
2057
    if (CFStringCompare(var, CFStringRef(QAXFocusedAttribute), 0) == kCFCompareEqualTo) {
 
2058
        settable = true;
 
2059
    } else {
 
2060
        for (int r = 0; text_bindings[r][0].qt != -1; r++) {
 
2061
            if(interface.role() == (QAccessible::Role)text_bindings[r][0].qt) {
 
2062
                for (int a = 1; text_bindings[r][a].qt != -1; a++) {
 
2063
                    if (CFStringCompare(var, CFStringRef(text_bindings[r][a].mac), 0) == kCFCompareEqualTo) {
 
2064
                        settable = text_bindings[r][a].settable;
 
2065
                        break;
 
2066
                    }
 
2067
                }
 
2068
            }
 
2069
        }
 
2070
    }
 
2071
    SetEventParameter(event, kEventParamAccessibleAttributeSettable, typeBoolean,
 
2072
                      sizeof(settable), &settable);
 
2073
    return noErr;
 
2074
}
 
2075
 
 
2076
static OSStatus getChildAtPoint(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
 
2077
{
 
2078
    Q_UNUSED(next_ref);
 
2079
    if (interface.isValid() == false)
 
2080
        return eventNotHandledErr;
 
2081
 
 
2082
    // Add the children for this interface to the global QAccessibelHierachyManager.
 
2083
    accessibleHierarchyManager()->registerChildren(interface);
 
2084
 
 
2085
    Point where;
 
2086
    GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, 0, sizeof(where), 0, &where);
 
2087
    const QAInterface childInterface = interface.childAt(where.h, where.v);
 
2088
 
 
2089
    if (childInterface.isValid() == false || childInterface == interface)
 
2090
        return eventNotHandledErr;
 
2091
 
 
2092
    const QAElement element = accessibleHierarchyManager()->lookup(childInterface);
 
2093
    if (element.isValid() == false)
 
2094
        return eventNotHandledErr;
 
2095
 
 
2096
    AXUIElementRef elementRef = element.element();
 
2097
    CFRetain(elementRef);
 
2098
    SetEventParameter(event, kEventParamAccessibleChild, typeCFTypeRef,
 
2099
                                  sizeof(elementRef), &elementRef);
 
2100
 
 
2101
    return noErr;
 
2102
}
 
2103
 
 
2104
/*
 
2105
    Returns a list of actions the given interface supports.
 
2106
    Currently implemented by getting the interface role and deciding based on that.
 
2107
*/
 
2108
static QList<QAccessible::Action> supportedPredefinedActions(const QAInterface &interface)
 
2109
{
 
2110
    QList<QAccessible::Action> actions;
 
2111
    switch (interface.role()) {
 
2112
        default:
 
2113
            // Most things can be pressed.
 
2114
            actions.append(QAccessible::Press);
 
2115
        break;
 
2116
    }
 
2117
 
 
2118
    return actions;
 
2119
}
 
2120
 
 
2121
/*
 
2122
    Translates a predefined QAccessible::Action to a Mac action constant.
 
2123
    Returns an empty string if the Qt Action has no mac equivalent.
 
2124
*/
 
2125
static QCFString translateAction(const QAccessible::Action action)
 
2126
{
 
2127
    switch (action) {
 
2128
        case QAccessible::Press:
 
2129
            return CFStringRef(QAXPressAction);
 
2130
        break;
 
2131
        case QAccessible::Increase:
 
2132
            return CFStringRef(QAXIncrementAction);
 
2133
        break;
 
2134
        case QAccessible::Decrease:
 
2135
            return CFStringRef(QAXDecrementAction);
 
2136
        break;
 
2137
        case QAccessible::Accept:
 
2138
            return CFStringRef(QAXConfirmAction);
 
2139
        break;
 
2140
        case QAccessible::Select:
 
2141
            return CFStringRef(QAXPickAction);
 
2142
        break;
 
2143
        case QAccessible::Cancel:
 
2144
            return CFStringRef(QAXCancelAction);
 
2145
        break;
 
2146
        default:
 
2147
            return QCFString();
 
2148
        break;
 
2149
    }
 
2150
}
 
2151
 
 
2152
/*
 
2153
    Translates between a Mac action constant and a QAccessible::Action.
 
2154
    Returns QAccessible::Default action if there is no Qt predefined equivalent.
 
2155
*/
 
2156
static QAccessible::Action translateAction(const CFStringRef actionName)
 
2157
{
 
2158
    if(CFStringCompare(actionName, CFStringRef(QAXPressAction), 0) == kCFCompareEqualTo) {
 
2159
        return QAccessible::Press;
 
2160
    } else if(CFStringCompare(actionName, CFStringRef(QAXIncrementAction), 0) == kCFCompareEqualTo) {
 
2161
        return QAccessible::Increase;
 
2162
    } else if(CFStringCompare(actionName, CFStringRef(QAXDecrementAction), 0) == kCFCompareEqualTo) {
 
2163
        return QAccessible::Decrease;
 
2164
    } else if(CFStringCompare(actionName, CFStringRef(QAXConfirmAction), 0) == kCFCompareEqualTo) {
 
2165
        return QAccessible::Accept;
 
2166
    } else if(CFStringCompare(actionName, CFStringRef(QAXPickAction), 0) == kCFCompareEqualTo) {
 
2167
        return QAccessible::Select;
 
2168
    } else if(CFStringCompare(actionName, CFStringRef(QAXCancelAction), 0) == kCFCompareEqualTo) {
 
2169
        return QAccessible::Cancel;
 
2170
    } else {
 
2171
        return QAccessible::DefaultAction;
 
2172
    }
 
2173
}
 
2174
#endif // QT_MAC_USE_COCOA
 
2175
 
 
2176
/*
 
2177
    Copies the translated names all supported actions for an interface into the kEventParamAccessibleActionNames
 
2178
    event parameter.
 
2179
*/
 
2180
#ifndef QT_MAC_USE_COCOA
 
2181
static OSStatus getAllActionNames(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
 
2182
{
 
2183
    Q_UNUSED(next_ref);
 
2184
 
 
2185
    CFMutableArrayRef actions = 0;
 
2186
    GetEventParameter(event, kEventParamAccessibleActionNames, typeCFMutableArrayRef, 0,
 
2187
                      sizeof(actions), 0, &actions);
 
2188
 
 
2189
    // Add supported predefined actions.
 
2190
    const QList<QAccessible::Action> predefinedActions = supportedPredefinedActions(interface);
 
2191
    for (int i = 0; i < predefinedActions.count(); ++i) {
 
2192
        const QCFString action = translateAction(predefinedActions.at(i));
 
2193
        if (action != QCFString())
 
2194
            qt_mac_append_cf_uniq(actions, action);
 
2195
    }
 
2196
 
 
2197
    // Add user actions
 
2198
    const int actionCount = interface.userActionCount();
 
2199
    for (int i = 0; i < actionCount; ++i) {
 
2200
        const QString actionName = interface.actionText(i, QAccessible::Name);
 
2201
        qt_mac_append_cf_uniq(actions, QCFString::toCFStringRef(actionName));
 
2202
    }
 
2203
 
 
2204
    return noErr;
 
2205
}
 
2206
#endif
 
2207
 
 
2208
/*
 
2209
    Handles the perforNamedAction event.
 
2210
*/
 
2211
#ifndef QT_MAC_USE_COCOA
 
2212
static OSStatus performNamedAction(EventHandlerCallRef next_ref, EventRef event, const QAInterface& interface)
 
2213
{
 
2214
    Q_UNUSED(next_ref);
 
2215
 
 
2216
    CFStringRef act;
 
2217
    GetEventParameter(event, kEventParamAccessibleActionName, typeCFStringRef, 0,
 
2218
                      sizeof(act), 0, &act);
 
2219
 
 
2220
    const QAccessible::Action action = translateAction(act);
 
2221
 
 
2222
    // Perform built-in action
 
2223
    if (action != QAccessible::DefaultAction) {
 
2224
        interface.doAction(action, QVariantList());
 
2225
        return noErr;
 
2226
    }
 
2227
 
 
2228
    // Search for user-defined actions and perform it if found.
 
2229
    const int actCount = interface.userActionCount();
 
2230
    const QString qAct = QCFString::toQString(act);
 
2231
    for(int i = 0; i < actCount; i++) {
 
2232
        if(interface.actionText(i, QAccessible::Name) == qAct) {
 
2233
            interface.doAction(i, QVariantList());
 
2234
            break;
 
2235
        }
 
2236
    }
 
2237
    return noErr;
 
2238
}
 
2239
 
 
2240
static OSStatus setNamedAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
 
2241
{
 
2242
    Q_UNUSED(next_ref);
 
2243
    Q_UNUSED(event);
 
2244
 
 
2245
    CFStringRef var;
 
2246
    GetEventParameter(event, kEventParamAccessibleAttributeName, typeCFStringRef, 0,
 
2247
                      sizeof(var), 0, &var);
 
2248
    if(CFStringCompare(var, CFStringRef(QAXFocusedAttribute), 0) == kCFCompareEqualTo) {
 
2249
        CFTypeRef val;
 
2250
        if(GetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, 0,
 
2251
                             sizeof(val), 0, &val) == noErr) {
 
2252
            if(CFGetTypeID(val) == CFBooleanGetTypeID() &&
 
2253
               CFEqual(static_cast<CFBooleanRef>(val), kCFBooleanTrue)) {
 
2254
                interface.doAction(QAccessible::SetFocus);
 
2255
            }
 
2256
        }
 
2257
    } else {
 
2258
        bool found = false;
 
2259
        for(int r = 0; text_bindings[r][0].qt != -1; r++) {
 
2260
            if(interface.role() == (QAccessible::Role)text_bindings[r][0].qt) {
 
2261
                for(int a = 1; text_bindings[r][a].qt != -1; a++) {
 
2262
                    if(CFStringCompare(var, CFStringRef(text_bindings[r][a].mac), 0) == kCFCompareEqualTo) {
 
2263
                        if(!text_bindings[r][a].settable) {
 
2264
                        } else {
 
2265
                            CFTypeRef val;
 
2266
                            if(GetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, 0,
 
2267
                                                 sizeof(val), 0, &val) == noErr) {
 
2268
                                if(CFGetTypeID(val) == CFStringGetTypeID())
 
2269
                                    interface.setText((QAccessible::Text)text_bindings[r][a].qt,
 
2270
                                                   QCFString::toQString(static_cast<CFStringRef>(val)));
 
2271
 
 
2272
                            }
 
2273
                        }
 
2274
                        found = true;
 
2275
                        break;
 
2276
                    }
 
2277
                }
 
2278
                break;
 
2279
            }
 
2280
        }
 
2281
    }
 
2282
    return noErr;
 
2283
}
 
2284
 
 
2285
/*
 
2286
    This is the main accessibility event handler.
 
2287
*/
 
2288
static OSStatus accessibilityEventHandler(EventHandlerCallRef next_ref, EventRef event, void *data)
 
2289
{
 
2290
    Q_UNUSED(data)
 
2291
 
 
2292
    // Return if this event is not a AccessibleGetNamedAttribute event.
 
2293
    const UInt32 eclass = GetEventClass(event);
 
2294
    if (eclass != kEventClassAccessibility)
 
2295
        return eventNotHandledErr;
 
2296
 
 
2297
    // Get the AXUIElementRef and QAInterface pointer
 
2298
    AXUIElementRef element = 0;
 
2299
    GetEventParameter(event, kEventParamAccessibleObject, typeCFTypeRef, 0, sizeof(element), 0, &element);
 
2300
    QAInterface interface = accessibleHierarchyManager()->lookup(element);
 
2301
    if (interface.isValid() == false)
 
2302
        return eventNotHandledErr;
 
2303
 
 
2304
    const UInt32 ekind = GetEventKind(event);
 
2305
    OSStatus status = noErr;
 
2306
    switch (ekind) {
 
2307
        case kEventAccessibleGetAllAttributeNames:
 
2308
             status = getAllAttributeNames(event, interface, next_ref);
 
2309
        break;
 
2310
        case kEventAccessibleGetNamedAttribute:
 
2311
             status = getNamedAttribute(next_ref, event, interface);
 
2312
        break;
 
2313
        case kEventAccessibleIsNamedAttributeSettable:
 
2314
             status = isNamedAttributeSettable(event, interface);
 
2315
        break;
 
2316
        case kEventAccessibleGetChildAtPoint:
 
2317
            status = getChildAtPoint(next_ref, event, interface);
 
2318
        break;
 
2319
        case kEventAccessibleGetAllActionNames:
 
2320
            status = getAllActionNames(next_ref, event, interface);
 
2321
        break;
 
2322
        case kEventAccessibleGetFocusedChild:
 
2323
            status = CallNextEventHandler(next_ref, event);
 
2324
        break;
 
2325
        case kEventAccessibleSetNamedAttribute:
 
2326
            status = setNamedAttribute(next_ref, event, interface);
 
2327
        break;
 
2328
        case kEventAccessiblePerformNamedAction:
 
2329
            status = performNamedAction(next_ref, event, interface);
 
2330
        break;
 
2331
        default:
 
2332
            status = CallNextEventHandler(next_ref, event);
 
2333
        break;
 
2334
    };
 
2335
    return status;
 
2336
}
 
2337
#endif
 
2338
 
 
2339
void QAccessible::initialize()
 
2340
{
 
2341
#ifndef QT_MAC_USE_COCOA
 
2342
    registerQtAccessibilityHIObjectSubclass();
 
2343
    installApplicationEventhandler();
 
2344
#endif
 
2345
}
 
2346
 
 
2347
// Sets thre root object for the application
 
2348
void QAccessible::setRootObject(QObject *object)
 
2349
{
 
2350
    // Call installed root object handler if we have one
 
2351
    if (rootObjectHandler) {
 
2352
        rootObjectHandler(object);
 
2353
        return;
 
2354
    }
 
2355
 
 
2356
    rootObject = object;
 
2357
}
 
2358
 
 
2359
void QAccessible::cleanup()
 
2360
{
 
2361
    accessibleHierarchyManager()->reset();
 
2362
#ifndef QT_MAC_USE_COCOA
 
2363
    removeEventhandler(applicationEventHandlerUPP);
 
2364
    removeEventhandler(objectCreateEventHandlerUPP);
 
2365
    removeEventhandler(accessibilityEventHandlerUPP);
 
2366
#endif
 
2367
}
 
2368
 
 
2369
void QAccessible::updateAccessibility(QObject *object, int child, Event reason)
 
2370
{
 
2371
    // Call installed update handler if we have one.
 
2372
    if (updateHandler) {
 
2373
        updateHandler(object, child, reason);
 
2374
        return;
 
2375
    }
 
2376
 
 
2377
#ifndef QT_MAC_USE_COCOA
 
2378
    // Return if the mac accessibility is not enabled.
 
2379
    if(!AXAPIEnabled())
 
2380
        return;
 
2381
 
 
2382
     // Work around crash, disable accessiblity for focus frames.
 
2383
     if (qstrcmp(object->metaObject()->className(), "QFocusFrame") == 0)
 
2384
        return;
 
2385
 
 
2386
//    qDebug() << "updateAccessibility" << object << child << hex << reason;
 
2387
 
 
2388
    if (reason == ObjectShow) {
 
2389
        QAInterface interface = QAInterface(QAccessible::queryAccessibleInterface(object), child);
 
2390
        accessibleHierarchyManager()->registerInterface(interface);
 
2391
    }
 
2392
 
 
2393
    const QAElement element = accessibleHierarchyManager()->lookup(object, child);
 
2394
    if (element.isValid() == false)
 
2395
        return;
 
2396
 
 
2397
 
 
2398
    CFStringRef notification = 0;
 
2399
    if(object && object->isWidgetType() && reason == ObjectCreated) {
 
2400
        notification = CFStringRef(QAXWindowCreatedNotification);
 
2401
    } else if(reason == ValueChanged) {
 
2402
        notification = CFStringRef(QAXValueChangedNotification);
 
2403
    } else if(reason == MenuStart) {
 
2404
        notification = CFStringRef(QAXMenuOpenedNotification);
 
2405
    } else if(reason == MenuEnd) {
 
2406
        notification = CFStringRef(QAXMenuClosedNotification);
 
2407
    } else if(reason == LocationChanged) {
 
2408
        notification = CFStringRef(QAXWindowMovedNotification);
 
2409
    } else if(reason == ObjectShow || reason == ObjectHide ) {
 
2410
        // When a widget is deleted we get a ObjectHide before the destroyed(QObject *)
 
2411
        // signal is emitted (which makes sense). However, at this point we are in the
 
2412
        // middle of the QWidget destructor which means that we have to be careful when
 
2413
        // using the widget pointer. Since we can't control what the accessibilty interfaces
 
2414
        // does when navigate() is called below we ignore the hide update in this case.
 
2415
        // (the widget will be deleted soon anyway.)
 
2416
        extern QWidgetPrivate * qt_widget_private(QWidget *);
 
2417
        if (QWidget *widget = qobject_cast<QWidget*>(object)) {
 
2418
            if (qt_widget_private(widget)->data.in_destructor)
 
2419
                return;
 
2420
 
 
2421
            // Check widget parent as well, special case for preventing crash
 
2422
            // when the viewport() of an abstract scroll area is hidden when
 
2423
            // the QWidget destructor hides all its children.
 
2424
            QWidget *parentWidget = widget->parentWidget();
 
2425
            if (parentWidget && qt_widget_private(parentWidget)->data.in_destructor)
 
2426
                return;
 
2427
        }
 
2428
 
 
2429
        // There is no equivalent Mac notification for ObjectShow/Hide, so we call HIObjectSetAccessibilityIgnored
 
2430
        // and isItIntersting which will mark the HIObject accociated with the element as ignored if the
 
2431
        // QAccessible::Invisible state bit is set.
 
2432
        QAInterface interface = accessibleHierarchyManager()->lookup(element);
 
2433
        if (interface.isValid()) {
 
2434
            HIObjectSetAccessibilityIgnored(element.object(), !isItInteresting(interface));
 
2435
        }
 
2436
 
 
2437
        // If the interface manages its own children, also check if we should ignore those.
 
2438
        if (isItemView(interface) == false && managesChildren(interface)) {
 
2439
            for (int i = 1; i <= interface.childCount(); ++i) {
 
2440
                QAInterface childInterface = interface.navigate(QAccessible::Child, i);
 
2441
                if (childInterface.isValid() && childInterface.isHIView() == false) {
 
2442
                    const QAElement element = accessibleHierarchyManager()->lookup(childInterface);
 
2443
                    if (element.isValid()) {
 
2444
                        HIObjectSetAccessibilityIgnored(element.object(), !isItInteresting(childInterface));
 
2445
                    }
 
2446
                }
 
2447
            }
 
2448
        }
 
2449
 
 
2450
    } else if(reason == Focus) {
 
2451
        if(object && object->isWidgetType()) {
 
2452
            QWidget *w = static_cast<QWidget*>(object);
 
2453
            if(w->isWindow())
 
2454
                notification = CFStringRef(QAXFocusedWindowChangedNotification);
 
2455
            else
 
2456
                notification = CFStringRef(QAXFocusedUIElementChangedNotification);
 
2457
        }
 
2458
    }
 
2459
 
 
2460
    if (!notification)
 
2461
        return;
 
2462
 
 
2463
    AXNotificationHIObjectNotify(notification, element.object(), element.id());
 
2464
#endif
 
2465
}
 
2466
 
 
2467
QT_END_NAMESPACE
 
2468
 
 
2469
#endif // QT_NO_ACCESSIBILITY