Map QAccessible::Role to the proper IA2Role.
[profile/ivi/qtbase.git] / src / plugins / platforms / windows / accessible / iaccessible2.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include <QtCore/QtConfig>
42 #ifndef QT_NO_ACCESSIBILITY
43
44 #include "iaccessible2.h"
45 #include "qwindowsaccessibility.h"
46
47 #include <QtGui/qaccessible2.h>
48 #include <QtWidgets/qapplication.h>
49 #include <QtCore/qdebug.h>
50
51 QT_BEGIN_NAMESPACE
52
53 /**************************************************************\
54  *                     AccessibleApplication                  *
55  **************************************************************/
56 //  IUnknown
57 HRESULT STDMETHODCALLTYPE AccessibleApplication::QueryInterface(REFIID id, LPVOID *iface)
58 {
59     *iface = 0;
60     if (id == IID_IUnknown) {
61         accessibleDebug("AccessibleApplication::QI(): IID_IUnknown");
62         *iface = (IUnknown*)this;
63     } else if (id == IID_IAccessibleApplication) {
64         accessibleDebug("AccessibleApplication::QI(): IID_IAccessibleApplication");
65         *iface = static_cast<IAccessibleApplication*>(this);
66     }
67
68     if (*iface) {
69         AddRef();
70         return S_OK;
71     }
72     return E_NOINTERFACE;
73 }
74
75 ULONG STDMETHODCALLTYPE AccessibleApplication::AddRef()
76 {
77     return ++m_ref;
78 }
79
80 ULONG STDMETHODCALLTYPE AccessibleApplication::Release()
81 {
82     if (!--m_ref) {
83         delete this;
84         return 0;
85     }
86     return m_ref;
87 }
88
89 /* IAccessibleApplication */
90 HRESULT STDMETHODCALLTYPE AccessibleApplication::get_appName(/* [retval][out] */ BSTR *name)
91 {
92     const QString appName = QGuiApplication::applicationName();
93     *name = QStringToBSTR(appName);
94     return S_OK;
95 }
96
97 HRESULT STDMETHODCALLTYPE AccessibleApplication::get_appVersion(/* [retval][out] */ BSTR *version)
98 {
99     const QString appName = QGuiApplication::applicationVersion();
100     *version = QStringToBSTR(appName);
101     return S_OK;
102 }
103
104 HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitName(/* [retval][out] */ BSTR *name)
105 {
106     *name = ::SysAllocString(L"Qt");
107     return S_OK;
108 }
109
110 HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitVersion(/* [retval][out] */ BSTR *version)
111 {
112     *version = ::SysAllocString(QT_UNICODE_LITERAL(QT_VERSION_STR));
113     return S_OK;
114 }
115
116
117 /**************************************************************\
118  *                     AccessibleRelation                     *
119  **************************************************************/
120 AccessibleRelation::AccessibleRelation(const QList<QAccessibleInterface *> &targets,
121                     QAccessible::Relation relation)
122     : m_targets(targets), m_relation(relation), m_ref(1)
123 {
124     Q_ASSERT(m_targets.count());
125 }
126
127 /* IUnknown */
128 HRESULT STDMETHODCALLTYPE AccessibleRelation::QueryInterface(REFIID id, LPVOID *iface)
129 {
130     *iface = 0;
131     if (id == IID_IUnknown)
132         *iface = (IUnknown*)this;
133
134     if (*iface) {
135         AddRef();
136         return S_OK;
137     }
138
139     return E_NOINTERFACE;
140 }
141
142 ULONG STDMETHODCALLTYPE AccessibleRelation::AddRef()
143 {
144     return ++m_ref;
145 }
146
147 ULONG STDMETHODCALLTYPE AccessibleRelation::Release()
148 {
149     if (!--m_ref) {
150         delete this;
151         return 0;
152     }
153     return m_ref;
154 }
155
156 /* IAccessibleRelation */
157 HRESULT STDMETHODCALLTYPE AccessibleRelation::get_relationType(
158     /* [retval][out] */ BSTR *relationType)
159 {
160     *relationType = relationToBSTR(m_relation);
161     return S_OK;
162 }
163
164 HRESULT STDMETHODCALLTYPE AccessibleRelation::get_localizedRelationType(
165     /* [retval][out] */ BSTR *localizedRelationType)
166 {
167     // Who ever needs this???
168     *localizedRelationType = relationToBSTR(m_relation);
169     return S_OK;
170 }
171
172 HRESULT STDMETHODCALLTYPE AccessibleRelation::get_nTargets(
173     /* [retval][out] */ long *nTargets)
174 {
175     // ### always one target
176     *nTargets = m_targets.count();
177     return S_OK;
178 }
179
180 /*!
181   \internal
182   Client allocates and deallocates array
183   (see "Special Consideration when using Arrays", in Accessible2.idl)
184   */
185 HRESULT STDMETHODCALLTYPE AccessibleRelation::get_target(
186     /* [in] */ long targetIndex,
187     /* [retval][out] */ IUnknown **target)
188 {
189     if (targetIndex >= 0 && targetIndex < m_targets.count()) {
190         QAccessibleInterface *iface = m_targets.at(targetIndex);
191         *target = QWindowsAccessibility::wrap(iface);
192         if (*target)
193             return S_OK;
194         return E_FAIL;
195     }
196     return E_INVALIDARG;
197 }
198
199 /*!
200   \internal
201   Client allocates and deallocates \a targets array
202   (see "Special Consideration when using Arrays", in Accessible2.idl)
203   */
204 HRESULT STDMETHODCALLTYPE AccessibleRelation::get_targets(
205     /* [in] */ long maxTargets,
206     /* [length_is][size_is][out] */ IUnknown **targets,
207     /* [retval][out] */ long *nTargets)
208 {
209
210     const int numTargets = qMin((int)maxTargets, m_targets.count());
211     for (int i = 0; i < numTargets; ++i) {
212         QAccessibleInterface *iface = m_targets.at(i);
213         IAccessible *iacc = QWindowsAccessibility::wrap(iface);
214         if (!iacc)
215             return E_FAIL;
216         *targets = iacc;
217         ++targets;
218     }
219     *nTargets = numTargets;
220     // \a targets array is allocated by client.
221     return numTargets > 0 ? S_OK : S_FALSE;
222 }
223
224
225 /**************************************************************\
226  *                                                             *
227  *                        IUnknown                             *
228  *                                                             *
229  **************************************************************/
230 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryInterface(REFIID id, LPVOID *iface)
231 {
232     HRESULT hr = QWindowsMsaaAccessible::QueryInterface(id, iface);
233     if (!SUCCEEDED(hr)) {
234         if (id == IID_IServiceProvider) {
235             *iface = (IServiceProvider*)this;
236         } else if (id == IID_IAccessible2) {
237             *iface = (IAccessible2*)this;
238         } else if (id == IID_IAccessibleAction) {
239             if (accessible->actionInterface())
240                 *iface = (IAccessibleAction*)this;
241         } else if (id == IID_IAccessibleComponent) {
242             *iface = (IAccessibleComponent*)this;
243         } else if (id == IID_IAccessibleEditableText) {
244             //if (accessible->editableTextInterface()) {
245                 //*iface = (IAccessibleEditableText*)this;
246             //}
247         } else if (id == IID_IAccessibleHyperlink) {
248             //*iface = (IAccessibleHyperlink*)this;
249         } else if (id == IID_IAccessibleHypertext) {
250             //*iface = (IAccessibleHypertext*)this;
251         } else if (id == IID_IAccessibleImage) {
252             //*iface = (IAccessibleImage*)this;
253         } else if (id == IID_IAccessibleRelation) {
254             *iface = (IAccessibleRelation*)this;
255         } else if (id == IID_IAccessibleTable) {
256             //*iface = (IAccessibleTable*)this; // not supported
257         } else if (id == IID_IAccessibleTable2) {
258             if (accessible->tableInterface())
259                 *iface = (IAccessibleTable2*)this;
260         } else if (id == IID_IAccessibleTableCell) {
261             if (accessible->tableCellInterface())
262                 *iface = (IAccessibleTableCell*)this;
263         } else if (id == IID_IAccessibleText) {
264             if (accessible->textInterface())
265                 *iface = (IAccessibleText*)this;
266         } else if (id == IID_IAccessibleValue) {
267             if (accessible->valueInterface())
268                 *iface = (IAccessibleValue*)this;
269         }
270         if (*iface) {
271             AddRef();
272             hr = S_OK;
273         } else {
274             hr = E_NOINTERFACE;
275         }
276     }
277     return hr;
278 }
279
280
281 /* Note that IUnknown is inherited from several interfaces. Therefore we must reimplement all its
282    functions in the concrete class to avoid ambiguity.
283 */
284 ULONG STDMETHODCALLTYPE QWindowsIA2Accessible::AddRef()
285 {
286     return QWindowsMsaaAccessible::AddRef();
287 }
288
289 ULONG STDMETHODCALLTYPE QWindowsIA2Accessible::Release()
290 {
291     return QWindowsMsaaAccessible::Release();
292 }
293
294 /**************************************************************\
295  *                                                             *
296  *                        IAccessible2                         *
297  *                                                             *
298  **************************************************************/
299 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nRelations(long *nRelations)
300 {
301     accessibleDebugClientCalls(accessible);
302     if (!nRelations)
303       return E_INVALIDARG;
304     if (!accessible->isValid())
305         return E_FAIL;
306
307     return getRelationsHelper(0, 0, 0, nRelations);
308 }
309
310 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_relation(long relationIndex, IAccessibleRelation **relation)
311 {
312     accessibleDebugClientCalls(accessible);
313     if (!relation)
314       return E_INVALIDARG;
315     if (!accessible->isValid())
316         return E_FAIL;
317
318     return getRelationsHelper(relation, relationIndex,  1);
319 }
320
321 /*!
322   \internal
323   Client allocates and deallocates array
324   (see "Special Consideration when using Arrays", in Accessible2.idl)
325   */
326 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_relations(long maxRelations,
327                                         IAccessibleRelation **relations,
328                                         long *nRelations)
329 {
330     accessibleDebugClientCalls(accessible);
331     if (!accessible->isValid())
332         return E_FAIL;
333
334     return getRelationsHelper(relations, 0, maxRelations, nRelations);
335 }
336
337
338 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::role(long *ia2role)
339 {
340     accessibleDebugClientCalls(accessible);
341     if (!accessible->isValid())
342         return E_FAIL;
343
344     long r = accessible->role();
345
346     switch (r) {
347     case QAccessible::LayeredPane: r = IA2_ROLE_LAYERED_PANE; break;
348     case QAccessible::Terminal: r = IA2_ROLE_TERMINAL; break;
349     case QAccessible::Desktop: r = IA2_ROLE_DESKTOP_PANE; break;
350     default: break;
351     }
352
353     *ia2role = r;
354     return S_OK;
355 }
356
357
358 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollTo(enum IA2ScrollType /*scrollType*/)
359 {
360     //### Ignore for now
361     return E_NOTIMPL;
362 }
363
364
365 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollToPoint(enum IA2CoordinateType /*coordinateType*/, long /*x*/, long /*y*/)
366 {
367     //### Ignore for now
368     return E_NOTIMPL;
369 }
370
371
372 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_groupPosition(long *groupLevel,
373                                             long *similarItemsInGroup,
374                                             long *positionInGroup)
375 {
376     // ### Ignore for now. Not sure what this is used for.....
377     *groupLevel = 0;            // Not applicable
378     *similarItemsInGroup = 0;   // Not applicable
379     *positionInGroup = 0;       // Not applicable
380     return S_FALSE;
381 }
382
383
384 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_states(AccessibleStates *states)
385 {
386     accessibleDebugClientCalls(accessible);
387     if (!accessible->isValid())
388         return E_FAIL;
389     if (!states)
390         return E_POINTER;
391     QAccessible::State st = accessible->state();
392     AccessibleStates ia2states = 0;
393     if (st.active)
394         ia2states |= IA2_STATE_ACTIVE;
395     if (st.invalid)
396         ia2states |= IA2_STATE_DEFUNCT;
397     if (st.editable)
398         ia2states |= IA2_STATE_EDITABLE;
399     if (st.multiLine)
400         ia2states |= IA2_STATE_MULTI_LINE;
401     if (st.selectableText)
402         ia2states |= IA2_STATE_SELECTABLE_TEXT;
403     if (st.supportsAutoCompletion)
404         ia2states |= IA2_STATE_SUPPORTS_AUTOCOMPLETION;
405
406     *states = ia2states;
407     return S_OK;
408 }
409
410
411 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_extendedRole(BSTR *extendedRole)
412 {
413     //###
414     *extendedRole = 0;
415     return E_NOTIMPL;   // mozilla does this
416     //return S_FALSE;
417 }
418
419
420 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedExtendedRole(BSTR *localizedExtendedRole)
421 {
422     //###
423     *localizedExtendedRole = 0;
424     return E_NOTIMPL;   // mozilla does this
425     //return S_FALSE;
426 }
427
428
429 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nExtendedStates(long *nExtendedStates)
430 {
431     // Who will ever intepret these values into something meaningful??
432     *nExtendedStates = 0;
433     return E_NOTIMPL;   // mozilla does this
434     //return S_FALSE;
435 }
436
437
438 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_extendedStates(long /*maxExtendedStates*/,
439                                              BSTR **extendedStates,
440                                              long *nExtendedStates)
441 {
442     *extendedStates = 0;
443     *nExtendedStates = 0;
444     return E_NOTIMPL;   // mozilla does this
445     //return S_FALSE;
446 }
447
448
449 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedExtendedStates(long /*maxLocalizedExtendedStates*/,
450                                                       BSTR **localizedExtendedStates,
451                                                       long *nLocalizedExtendedStates)
452 {
453     *localizedExtendedStates = 0;
454     *nLocalizedExtendedStates = 0;
455     return E_NOTIMPL;   // mozilla does this
456     //return S_FALSE;
457 }
458
459
460 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_uniqueID(long *outUniqueID)
461 {
462     accessibleDebugClientCalls(accessible);
463     if (!accessible->isValid())
464         return E_FAIL;
465     // ### FIXME SERIOUSLY, NOT A STABLE SOLUTION IF NODES ARE DELETED ETC
466     // Return 0 if no object and no parent. This is really an error case.
467     uint uid = uniqueID();
468     accessibleDebug("uniqueID: %08x", uid);
469
470     *outUniqueID = (long)uid;
471     return uid ? S_OK : S_FALSE;
472 }
473
474
475 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_windowHandle(HWND *windowHandle)
476 {
477     accessibleDebugClientCalls(accessible);
478     if (!accessible->isValid())
479         return E_FAIL;
480     return GetWindow(windowHandle);
481 }
482
483
484 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_indexInParent(long *indexInParent)
485 {
486     accessibleDebugClientCalls(accessible);
487     if (!accessible->isValid())
488         return E_FAIL;
489     if (!indexInParent)
490       return E_INVALIDARG;
491     QAccessibleInterface *par = accessible->parent();
492     if (!par) {
493         *indexInParent = -1;
494         return S_FALSE;
495     }
496     int indexOfChild = par->indexOfChild(accessible);
497     delete par;
498     Q_ASSERT(indexOfChild >= 0);
499     *indexInParent = indexOfChild;
500     return S_OK;
501 }
502
503 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_locale(IA2Locale *locale)
504 {
505     accessibleDebugClientCalls(accessible);
506     if (!accessible->isValid())
507         return E_FAIL;
508     IA2Locale res;
509     QLocale l;
510     res.country = QStringToBSTR(QLocale::countryToString(l.country()));
511     res.language = QStringToBSTR(QLocale::languageToString(l.language()));
512     *locale = res;
513     return S_OK;
514 }
515
516
517 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_attributes(BSTR *attributes)
518 {
519     accessibleDebugClientCalls(accessible);
520     if (!accessible->isValid())
521         return E_FAIL;
522     *attributes = 0;//QStringToBSTR(QString());
523     return S_FALSE;
524 }
525
526 /**************************************************************\
527  *                      IAccessibleAction                      *
528  **************************************************************/
529 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::nActions(long *nActions)
530 {
531     accessibleDebugClientCalls(accessible);
532     if (!accessible->isValid())
533         return E_FAIL;
534     *nActions = 0;
535
536     if (QAccessibleActionInterface *actionIface = actionInterface())
537         *nActions = actionIface->actionNames().count();
538     return S_OK;
539 }
540
541 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::doAction(long actionIndex)
542 {
543     accessibleDebugClientCalls(accessible);
544     if (!accessible->isValid())
545         return E_FAIL;
546     if (QAccessibleActionInterface *actionIface = actionInterface()) {
547         const QStringList actionNames = actionIface->actionNames();
548         if (actionIndex < 0 || actionIndex >= actionNames.count())
549             return E_INVALIDARG;
550         const QString actionName = actionNames.at(actionIndex);
551         actionIface->doAction(actionName);
552         return S_OK;
553     }
554     return S_FALSE;
555 }
556
557 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_description(long actionIndex, BSTR *description)
558 {
559     accessibleDebugClientCalls(accessible);
560     if (!accessible->isValid())
561         return E_FAIL;
562     *description = 0;
563     if (QAccessibleActionInterface *actionIface = actionInterface()) {
564         const QStringList actionNames = actionIface->actionNames();
565         if (actionIndex < 0 || actionIndex >= actionNames.count())
566             return E_INVALIDARG;
567         const QString actionName = actionNames.at(actionIndex);
568         *description = QStringToBSTR(actionIface->localizedActionDescription(actionName));
569     }
570     return *description ? S_OK : S_FALSE;
571 }
572
573 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_keyBinding(long actionIndex, long nMaxBindings, BSTR **keyBindings, long *nBindings)
574 {
575     accessibleDebugClientCalls(accessible);
576     if (!accessible->isValid())
577         return E_FAIL;
578     Q_UNUSED(nMaxBindings);
579     BSTR *arrayOfBindingsToReturn = 0;
580     int numBindings = 0;
581     if (QAccessibleActionInterface *actionIface = actionInterface()) {
582         const QStringList actionNames = actionIface->actionNames();
583         if (actionIndex < 0 || actionIndex >= actionNames.count())
584             return E_INVALIDARG;
585         const QString actionName = actionNames.at(actionIndex);
586         const QStringList keyBindings = actionIface->keyBindingsForAction(actionName);
587         numBindings = keyBindings.count();
588         if (numBindings > 0) {
589             // The IDL documents that the client must free with CoTaskMemFree
590             arrayOfBindingsToReturn = (BSTR*)::CoTaskMemAlloc(sizeof(BSTR) * numBindings);
591             for (int i = 0; i < numBindings; ++i)
592                 arrayOfBindingsToReturn[i] = QStringToBSTR(keyBindings.at(i));
593         }
594     }
595     *keyBindings = arrayOfBindingsToReturn;
596     *nBindings = numBindings;
597
598     return numBindings ? S_OK : S_FALSE;
599 }
600
601 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_name(long actionIndex, BSTR *name)
602 {
603     accessibleDebugClientCalls(accessible);
604     if (!accessible->isValid())
605         return E_FAIL;
606     *name = 0;
607     if (QAccessibleActionInterface *actionIface = actionInterface()) {
608         const QStringList actionNames = actionIface->actionNames();
609         if (actionIndex < 0 || actionIndex >= actionNames.count())
610             return E_INVALIDARG;
611         const QString actionName = actionNames.at(actionIndex);
612         *name = QStringToBSTR(actionName);
613     }
614     return *name ? S_OK : S_FALSE;
615 }
616
617 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedName(long actionIndex, BSTR *localizedName)
618 {
619     accessibleDebugClientCalls(accessible);
620     if (!accessible->isValid())
621         return E_FAIL;
622     *localizedName = 0;
623     if (QAccessibleActionInterface *actionIface = actionInterface()) {
624         const QStringList actionNames = actionIface->actionNames();
625         if (actionIndex < 0 || actionIndex >= actionNames.count())
626             return E_INVALIDARG;
627
628         const QString actionName = actionNames.at(actionIndex);
629         *localizedName = QStringToBSTR(actionIface->localizedActionName(actionName));
630     }
631     return *localizedName ? S_OK : S_FALSE;
632 }
633
634 /**************************************************************\
635  *                     IAccessibleComponent                    *
636  **************************************************************/
637 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_locationInParent(long *x, long *y)
638 {
639     accessibleDebugClientCalls(accessible);
640     if (!accessible->isValid())
641         return E_FAIL;
642
643     QPoint topLeft = accessible->rect().topLeft();
644
645     if (QAccessibleInterface *parentIface = accessible->parent())
646         topLeft -= parentIface->rect().topLeft();
647
648     *x = topLeft.x();
649     *y = topLeft.y();
650     return S_OK;
651 }
652
653 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_foreground(IA2Color *foreground)
654 {
655     accessibleDebugClientCalls(accessible);
656     if (!accessible->isValid())
657         return E_FAIL;
658
659     // IA2Color is a typedef for long
660     *foreground = (IA2Color)accessible->foregroundColor().rgb();
661     return S_OK;
662 }
663
664 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_background(IA2Color *background)
665 {
666     accessibleDebugClientCalls(accessible);
667     if (!accessible->isValid())
668         return E_FAIL;
669
670     // IA2Color is a typedef for long
671     *background = (IA2Color)accessible->backgroundColor().rgb();
672     return S_OK;
673 }
674
675 /**************************************************************\
676  *                     IAccessibleTable2                      *
677  **************************************************************/
678 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_cellAt( long row, long column, IUnknown **cell)
679 {
680     accessibleDebugClientCalls(accessible);
681     if (!accessible->isValid())
682         return E_FAIL;
683
684     *cell = 0;
685     if (QAccessibleTableInterface *tableIface = tableInterface()) {
686         if (QAccessibleInterface *qtCell = tableIface->cellAt(row, column)) {
687             *cell = QWindowsAccessibility::wrap(qtCell);
688         }
689     }
690     accessibleDebug("found cell? %p", *cell);
691     return *cell ? S_OK : S_FALSE;
692 }
693
694 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_caption( IUnknown **captionInterface)
695 {
696     accessibleDebugClientCalls(accessible);
697     if (!accessible->isValid())
698         return E_FAIL;
699
700     *captionInterface = 0;
701     if (QAccessibleTableInterface *tableIface = tableInterface()) {
702         if (QAccessibleInterface *iface = tableIface->caption())
703             *captionInterface = QWindowsAccessibility::wrap(iface);
704     }
705     return *captionInterface ? S_OK : S_FALSE;
706 }
707
708 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnDescription( long column, BSTR *description)
709 {
710     accessibleDebugClientCalls(accessible);
711     if (!accessible->isValid())
712         return E_FAIL;
713
714     *description = 0;
715     if (QAccessibleTableInterface *tableIface = tableInterface()) {
716         const QString qtDesc = tableIface->columnDescription(column);
717         if (!qtDesc.isEmpty())
718             *description = QStringToBSTR(qtDesc);
719     }
720     return *description ? S_OK : S_FALSE;
721 }
722
723 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nColumns( long *columnCount)
724 {
725     accessibleDebugClientCalls(accessible);
726     if (!accessible->isValid())
727         return E_FAIL;
728
729     if (QAccessibleTableInterface *tableIface = tableInterface()) {
730         *columnCount = tableIface->columnCount();
731         return S_OK;
732     }
733     return E_FAIL;
734 }
735
736 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nRows(long *rowCount)
737 {
738     accessibleDebugClientCalls(accessible);
739     if (!accessible->isValid())
740         return E_FAIL;
741
742     if (QAccessibleTableInterface *tableIface = tableInterface()) {
743         *rowCount = tableIface->rowCount();
744         return S_OK;
745     }
746     return E_FAIL;
747 }
748
749 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedCells(long *cellCount)
750 {
751     accessibleDebugClientCalls(accessible);
752     if (!accessible->isValid())
753         return E_FAIL;
754
755     if (QAccessibleTableInterface *tableIface = tableInterface()) {
756         *cellCount = tableIface->selectedCellCount();
757         return S_OK;
758     }
759     return E_FAIL;
760 }
761
762 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedColumns(long *columnCount)
763 {
764     accessibleDebugClientCalls(accessible);
765     if (!accessible->isValid())
766         return E_FAIL;
767
768     if (QAccessibleTableInterface *tableIface = tableInterface()) {
769         *columnCount = tableIface->selectedColumnCount();
770         return S_OK;
771     }
772     return E_FAIL;
773 }
774
775 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedRows(long *rowCount)
776 {
777     accessibleDebugClientCalls(accessible);
778     if (!accessible->isValid())
779         return E_FAIL;
780
781     if (QAccessibleTableInterface *tableIface = tableInterface()) {
782         *rowCount = tableIface->selectedRowCount();
783         return S_OK;
784     }
785     return E_FAIL;
786 }
787
788 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowDescription(long row, BSTR *description)
789 {
790     accessibleDebugClientCalls(accessible);
791     if (!accessible->isValid())
792         return E_FAIL;
793
794     *description = 0;
795     if (QAccessibleTableInterface *tableIface = tableInterface()) {
796         const QString qtDesc = tableIface->columnDescription(row);
797         if (!qtDesc.isEmpty())
798             *description = QStringToBSTR(qtDesc);
799     }
800     return *description ? S_OK : S_FALSE;
801 }
802
803 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedCells(IUnknown ***cells, long *nSelectedCells)
804 {
805     accessibleDebugClientCalls(accessible);
806     Q_UNUSED(cells);
807     Q_UNUSED(nSelectedCells);
808     if (!accessible->isValid())
809         return E_FAIL;
810
811     QList<QAccessibleInterface*> selectedCells = tableInterface()->selectedCells();
812     return wrapListOfCells(selectedCells, cells, nSelectedCells);
813 }
814
815 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedColumns(long **selectedColumns, long *nColumns)
816 {
817     accessibleDebugClientCalls(accessible);
818     if (!accessible->isValid())
819         return E_FAIL;
820
821     if (QAccessibleTableInterface *tableIface = tableInterface()) {
822         const QList<int> selectedIndices = tableIface->selectedColumns();
823         const int &count = selectedIndices.count();
824         long *selected = (count ? (long*)::CoTaskMemAlloc(sizeof(long) * count) : (long*)0);
825         for (int i = 0; i < count; ++i)
826             selected[i] = selectedIndices.at(i);
827         *selectedColumns = selected;
828         *nColumns = count;
829         return count ? S_OK : S_FALSE;
830     }
831     return E_FAIL;
832
833 }
834
835 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedRows(long **selectedRows, long *nRows)
836 {
837     accessibleDebugClientCalls(accessible);
838     if (!accessible->isValid())
839         return E_FAIL;
840
841     if (QAccessibleTableInterface *tableIface = tableInterface()) {
842         const QList<int> selectedIndices = tableIface->selectedRows();
843         const int &count = selectedIndices.count();
844         long *selected = (count ? (long*)::CoTaskMemAlloc(sizeof(long) * count) : (long*)0);
845         for (int i = 0; i < count; ++i)
846             selected[i] = selectedIndices.at(i);
847         *selectedRows = selected;
848         *nRows = count;
849         return count ? S_OK : S_FALSE;
850     }
851     return E_FAIL;
852
853 }
854
855 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_summary(IUnknown **summaryInterface)
856 {
857     accessibleDebugClientCalls(accessible);
858     if (!accessible->isValid())
859         return E_FAIL;
860
861     *summaryInterface = 0;
862     if (QAccessibleTableInterface *tableIface = tableInterface()) {
863         if (QAccessibleInterface *iface = tableIface->summary())
864             *summaryInterface = QWindowsAccessibility::wrap(iface);
865     }
866     return *summaryInterface ? S_OK : S_FALSE;
867 }
868
869 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isColumnSelected(long column, boolean *isSelected)
870 {
871     accessibleDebugClientCalls(accessible);
872     if (!accessible->isValid())
873         return E_FAIL;
874
875     if (QAccessibleTableInterface *tableIface = tableInterface()) {
876         *isSelected = tableIface->isColumnSelected(column);
877         return S_OK;
878     }
879     return E_FAIL;
880 }
881
882 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isRowSelected(long row, boolean *isSelected)
883 {
884     accessibleDebugClientCalls(accessible);
885     if (!accessible->isValid())
886         return E_FAIL;
887
888     if (QAccessibleTableInterface *tableIface = tableInterface()) {
889         *isSelected = tableIface->isRowSelected(row);
890         return S_OK;
891     }
892     return E_FAIL;
893 }
894
895 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::selectRow(long row)
896 {
897     accessibleDebugClientCalls(accessible);
898     if (!accessible->isValid())
899         return E_FAIL;
900
901     if (QAccessibleTableInterface *tableIface = tableInterface()) {
902         bool ok = tableIface->selectRow(row);
903         return ok ? S_OK : E_INVALIDARG;    //### Not sure of the return value if it fails???
904     }
905     return E_FAIL;
906 }
907
908 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::selectColumn(long column)
909 {
910     accessibleDebugClientCalls(accessible);
911     if (!accessible->isValid())
912         return E_FAIL;
913
914     if (QAccessibleTableInterface *tableIface = tableInterface()) {
915         bool ok = tableIface->selectColumn(column);
916         return ok ? S_OK : E_INVALIDARG;    //### Not sure of the return value if it fails???
917     }
918     return E_FAIL;
919 }
920
921 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::unselectRow(long row)
922 {
923     accessibleDebugClientCalls(accessible);
924     if (!accessible->isValid())
925         return E_FAIL;
926
927     if (QAccessibleTableInterface *tableIface = tableInterface()) {
928         bool ok = tableIface->unselectRow(row);
929         return ok ? S_OK : E_INVALIDARG;    //### Not sure of the return value if it fails???
930     }
931     return E_FAIL;
932 }
933
934 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::unselectColumn(long column)
935 {
936     accessibleDebugClientCalls(accessible);
937     if (!accessible->isValid())
938         return E_FAIL;
939
940     if (QAccessibleTableInterface *tableIface = tableInterface()) {
941         bool ok = tableIface->unselectColumn(column);
942         return ok ? S_OK : E_INVALIDARG;    //### Not sure of the return value if it fails???
943     }
944     return E_FAIL;
945 }
946
947 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_modelChange( IA2TableModelChange * /*modelChange*/)
948 {
949     accessibleDebugClientCalls(accessible);
950     if (!accessible->isValid())
951         return E_FAIL;
952     return E_NOTIMPL;
953 }
954
955 /**************************************************************\
956  *                     IAccessibleTableCell                   *
957 \**************************************************************/
958 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnExtent(long *nColumnsSpanned)
959 {
960     accessibleDebugClientCalls(accessible);
961     if (!accessible->isValid())
962         return E_FAIL;
963
964     *nColumnsSpanned = tableCellInterface()->columnExtent();
965     return S_OK;
966 }
967
968 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnHeaderCells(IUnknown ***cellAccessibles,
969                                                                     long *nColumnHeaderCells)
970 {
971     accessibleDebugClientCalls(accessible);
972     if (!accessible->isValid())
973         return E_FAIL;
974     const QList<QAccessibleInterface*> headerCells = tableCellInterface()->columnHeaderCells();
975     return wrapListOfCells(headerCells, cellAccessibles, nColumnHeaderCells);
976 }
977
978 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnIndex(long *columnIndex)
979 {
980     accessibleDebugClientCalls(accessible);
981     if (!accessible->isValid())
982         return E_FAIL;
983     *columnIndex = tableCellInterface()->columnIndex();
984     return S_OK;
985 }
986
987 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowExtent(long *nRowsSpanned)
988 {
989     accessibleDebugClientCalls(accessible);
990     if (!accessible->isValid())
991         return E_FAIL;
992     *nRowsSpanned = tableCellInterface()->rowExtent();
993     return S_OK;
994 }
995
996 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowHeaderCells(IUnknown ***cellAccessibles,
997                                                                  long *nRowHeaderCells)
998 {
999     accessibleDebugClientCalls(accessible);
1000     if (!accessible->isValid())
1001         return E_FAIL;
1002     const QList<QAccessibleInterface*> headerCells = tableCellInterface()->rowHeaderCells();
1003     return wrapListOfCells(headerCells, cellAccessibles, nRowHeaderCells);
1004 }
1005
1006 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowIndex(long *rowIndex)
1007 {
1008     accessibleDebugClientCalls(accessible);
1009     if (!accessible->isValid())
1010         return E_FAIL;
1011     *rowIndex = tableCellInterface()->rowIndex();
1012     return S_OK;
1013 }
1014
1015 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isSelected( boolean *isSelected)
1016 {
1017     accessibleDebugClientCalls(accessible);
1018     if (!accessible->isValid())
1019         return E_FAIL;
1020     *isSelected = tableCellInterface()->isSelected();
1021     return S_OK;
1022 }
1023
1024 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowColumnExtents(long *row, long *column,
1025                                                long *rowExtents, long *columnExtents,
1026                                                boolean *isSelected)
1027 {
1028     accessibleDebugClientCalls(accessible);
1029     if (!accessible->isValid())
1030         return E_FAIL;
1031
1032     tableCellInterface()->rowColumnExtents((int*)row, (int*)column, (int*)rowExtents, (int*)columnExtents, (bool*)isSelected);
1033     return S_OK;
1034 }
1035
1036 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_table(IUnknown **table)
1037 {
1038     accessibleDebugClientCalls(accessible);
1039     if (!accessible->isValid())
1040         return E_FAIL;
1041
1042     QAccessibleInterface *tableIface = tableCellInterface()->table();
1043
1044     *table = QWindowsAccessibility::wrap(tableIface);
1045     return S_OK;
1046 }
1047
1048 /**************************************************************\
1049  *                     IAccessibleText                        *
1050 \**************************************************************/
1051 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::addSelection(long startOffset,
1052                                                            long endOffset)
1053 {
1054     accessibleDebugClientCalls(accessible);
1055     if (QAccessibleTextInterface *text = textInterface()) {
1056         text->addSelection(startOffset, endOffset);
1057         return S_OK;
1058     }
1059     return E_FAIL;
1060 }
1061
1062 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_attributes(long offset,
1063                                                              long *startOffset,
1064                                                              long *endOffset,
1065                                                              BSTR *textAttributes)
1066 {
1067     accessibleDebugClientCalls(accessible);
1068     if (QAccessibleTextInterface *text = textInterface()) {
1069         const QString attrs = text->attributes(offset, (int*)startOffset, (int*)endOffset);
1070         *textAttributes = QStringToBSTR(attrs);
1071         return S_OK;
1072     }
1073     return E_FAIL;
1074 }
1075
1076 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_caretOffset(long *offset)
1077 {
1078     accessibleDebugClientCalls(accessible);
1079     if (QAccessibleTextInterface *text = textInterface()) {
1080         *offset = text->cursorPosition();
1081         return S_OK;
1082     }
1083     return E_FAIL;
1084 }
1085
1086
1087 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_characterExtents(long offset,
1088                                                                    enum IA2CoordinateType coordType,
1089                                                                    long *x,
1090                                                                    long *y,
1091                                                                    long *width,
1092                                                                    long *height)
1093 {
1094     accessibleDebugClientCalls(accessible);
1095     if (QAccessibleTextInterface *text = textInterface()) {
1096         QRect rect = text->characterRect(offset);
1097         mapFromScreenPos(coordType, rect.topLeft(), x, y);
1098         *width = rect.width();
1099         *height = rect.height();
1100         return S_OK;
1101     }
1102     return E_FAIL;
1103 }
1104
1105 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelections(long *nSelections)
1106 {
1107     accessibleDebugClientCalls(accessible);
1108     if (QAccessibleTextInterface *text = textInterface()) {
1109         *nSelections = text->selectionCount();
1110         return S_OK;
1111     }
1112     return E_FAIL;
1113 }
1114
1115 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_offsetAtPoint(long x,
1116                                                                 long y,
1117                                                                 enum IA2CoordinateType coordType,
1118                                                                 long *offset)
1119 {
1120     accessibleDebugClientCalls(accessible);
1121     if (QAccessibleTextInterface *text = textInterface()) {
1122         QPoint screenPos = mapToScreenPos(coordType, x, y);
1123         *offset = text->offsetAtPoint(screenPos);
1124         return (*offset >=0 ? S_OK : S_FALSE);
1125     }
1126     return E_FAIL;
1127
1128 }
1129
1130 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selection(long selectionIndex,
1131                                                             long *startOffset,
1132                                                             long *endOffset)
1133 {
1134     accessibleDebugClientCalls(accessible);
1135     if (QAccessibleTextInterface *text = textInterface()) {
1136         text->selection(selectionIndex, (int*)startOffset, (int*)endOffset);
1137         return S_OK;
1138     }
1139     return E_FAIL;
1140 }
1141
1142 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_text(long startOffset,
1143                                                        long endOffset,
1144                                                        BSTR *text)
1145 {
1146     accessibleDebugClientCalls(accessible);
1147     if (QAccessibleTextInterface *textif = textInterface()) {
1148         const QString t = textif->text(startOffset, endOffset);
1149         if (!t.isEmpty()) {
1150             *text = QStringToBSTR(t);
1151             return S_OK;
1152         }
1153         return E_INVALIDARG;
1154     }
1155     return E_FAIL;
1156 }
1157
1158 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textBeforeOffset(long offset,
1159                                                enum IA2TextBoundaryType boundaryType,
1160                                                long *startOffset,
1161                                                long *endOffset,
1162                                                BSTR *text)
1163 {
1164     accessibleDebugClientCalls(accessible);
1165     if (QAccessibleTextInterface *textIface = textInterface()) {
1166         const QString txt = textIface->textBeforeOffset(offset, (QAccessible2::BoundaryType)boundaryType, (int*)startOffset, (int*)endOffset);
1167         if (!txt.isEmpty()) {
1168             *text = QStringToBSTR(txt);
1169             return S_OK;
1170         }
1171         return S_FALSE;
1172     }
1173     return E_FAIL;
1174 }
1175
1176 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textAfterOffset(
1177     long offset,
1178     enum IA2TextBoundaryType boundaryType,
1179     long *startOffset,
1180     long *endOffset,
1181     BSTR *text)
1182 {
1183     accessibleDebugClientCalls(accessible);
1184     if (QAccessibleTextInterface *textIface = textInterface()) {
1185         const QString txt = textIface->textAfterOffset(offset, (QAccessible2::BoundaryType)boundaryType, (int*)startOffset, (int*)endOffset);
1186         if (!txt.isEmpty()) {
1187             *text = QStringToBSTR(txt);
1188             return S_OK;
1189         }
1190         return S_FALSE;
1191     }
1192     return E_FAIL;
1193 }
1194
1195 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textAtOffset(long offset,
1196                                                                enum IA2TextBoundaryType boundaryType,
1197                                                                long *startOffset,
1198                                                                long *endOffset,
1199                                                                BSTR *text)
1200 {
1201     accessibleDebugClientCalls(accessible);
1202     if (QAccessibleTextInterface *textIface = textInterface()) {
1203         const QString txt = textIface->textAtOffset(offset, (QAccessible2::BoundaryType)boundaryType, (int*)startOffset, (int*)endOffset);
1204         if (!txt.isEmpty()) {
1205             *text = QStringToBSTR(txt);
1206             return S_OK;
1207         }
1208         return S_FALSE;
1209     }
1210     return E_FAIL;
1211 }
1212
1213 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::removeSelection(long selectionIndex)
1214 {
1215     accessibleDebugClientCalls(accessible);
1216     if (QAccessibleTextInterface *textIface = textInterface()) {
1217         textIface->removeSelection(selectionIndex);
1218         return S_OK;
1219     }
1220     return E_FAIL;
1221 }
1222
1223 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setCaretOffset(long offset)
1224 {
1225     accessibleDebugClientCalls(accessible);
1226     if (QAccessibleTextInterface *textIface = textInterface()) {
1227         textIface->setCursorPosition(offset);
1228         return S_OK;
1229     }
1230     return E_FAIL;
1231 }
1232
1233 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setSelection(long selectionIndex,
1234                                                            long startOffset,
1235                                                            long endOffset)
1236 {
1237     accessibleDebugClientCalls(accessible);
1238     if (QAccessibleTextInterface *textIface = textInterface()) {
1239         textIface->setSelection(selectionIndex, startOffset, endOffset);
1240         return S_OK;
1241     }
1242     return E_FAIL;
1243 }
1244
1245 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nCharacters(long *nCharacters)
1246 {
1247     accessibleDebugClientCalls(accessible);
1248     if (QAccessibleTextInterface *textIface = textInterface()) {
1249         *nCharacters = textIface->characterCount();
1250         return S_OK;
1251     }
1252     return E_FAIL;
1253 }
1254
1255 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollSubstringTo(long startIndex,
1256                                                                 long endIndex,
1257                                                                 enum IA2ScrollType scrollType)
1258 {
1259     accessibleDebugClientCalls(accessible);
1260     if (QAccessibleTextInterface *textIface = textInterface()) {
1261         Q_UNUSED(scrollType);   //###
1262         textIface->scrollToSubstring(startIndex, endIndex);
1263         return S_OK;
1264     }
1265     return E_FAIL;
1266 }
1267
1268 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollSubstringToPoint(long startIndex,
1269                                                                      long endIndex,
1270                                                                      enum IA2CoordinateType coordinateType,
1271                                                                      long x,
1272                                                                      long y)
1273 {
1274     Q_UNUSED(startIndex);
1275     Q_UNUSED(endIndex);
1276     Q_UNUSED(coordinateType);
1277     Q_UNUSED(x);
1278     Q_UNUSED(y);
1279
1280     return E_NOTIMPL;
1281 }
1282
1283 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_newText(IA2TextSegment *newText)
1284 {
1285     Q_UNUSED(newText);
1286     return E_NOTIMPL;
1287 }
1288
1289 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_oldText(IA2TextSegment *oldText)
1290 {
1291     Q_UNUSED(oldText);
1292     return E_NOTIMPL;
1293 }
1294
1295 /**************************************************************\
1296  *                         IAccessibleValue                    *
1297  **************************************************************/
1298 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_currentValue(VARIANT *currentValue)
1299 {
1300     accessibleDebugClientCalls(accessible);
1301     if (!accessible->isValid())
1302         return E_FAIL;
1303     if (QAccessibleValueInterface *valueIface = valueInterface()) {
1304         const QVariant var = valueIface->currentValue();
1305         if (QVariantToVARIANT(var, *currentValue, QByteArray(), false))
1306             return S_OK;
1307
1308     }
1309     currentValue->vt = VT_EMPTY;
1310     return S_FALSE;
1311 }
1312
1313 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setCurrentValue(VARIANT value)
1314 {
1315     accessibleDebugClientCalls(accessible);
1316     if (!accessible->isValid())
1317         return E_FAIL;
1318     HRESULT hr = S_FALSE;
1319     if (QAccessibleValueInterface *valueIface = valueInterface()) {
1320         hr = VariantChangeType(&value, &value, 0, VT_R8);
1321         if (SUCCEEDED(hr)) {
1322             // ### works only for numbers (not date, strings, etc)
1323             valueIface->setCurrentValue(QVariant(value.dblVal));
1324         }
1325     }
1326     return hr;
1327 }
1328
1329 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_maximumValue(VARIANT *maximumValue)
1330 {
1331     accessibleDebugClientCalls(accessible);
1332     if (!accessible->isValid())
1333         return E_FAIL;
1334     if (QAccessibleValueInterface *valueIface = valueInterface()) {
1335         const QVariant var = valueIface->maximumValue();
1336         if (QVariantToVARIANT(var, *maximumValue, QByteArray(), false))
1337             return S_OK;
1338     }
1339     maximumValue->vt = VT_EMPTY;
1340     return S_FALSE;
1341 }
1342
1343 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_minimumValue(VARIANT *minimumValue)
1344 {
1345     accessibleDebugClientCalls(accessible);
1346     if (!accessible->isValid())
1347         return E_FAIL;
1348     if (QAccessibleValueInterface *valueIface = valueInterface()) {
1349         const QVariant var = valueIface->minimumValue();
1350         if (QVariantToVARIANT(var, *minimumValue, QByteArray(), false))
1351             return S_OK;
1352     }
1353     minimumValue->vt = VT_EMPTY;
1354     return S_FALSE;
1355 }
1356
1357
1358 /**************************************************************\
1359  *                      IServiceProvider                       *
1360  **************************************************************/
1361 /*!
1362   \internal
1363   Reimplemented from IServiceProvider
1364 */
1365 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryService(REFGUID guidService, REFIID riid, void **iface)
1366 {
1367     if (!iface)
1368         return E_POINTER;
1369     Q_UNUSED(guidService);
1370     *iface = 0;
1371     accessibleDebug("QWindowsIA2Accessible::QS(): %s", IIDToString(riid).constData());
1372
1373     if (guidService == IID_IAccessible && riid == IID_IAccessible2) {
1374         // The conditions for entering here should be ok (from _dicoveringInterfaces in IAccessible2.idl)
1375         *iface = static_cast<IAccessible2*>(this);
1376     } else if (guidService == IID_IAccessible && (riid == IID_IAccessible || riid == IID_IUnknown || riid == IID_IDispatch)) {
1377         // The above conditions works with AccProbe and NVDA.
1378         *iface = static_cast<IAccessible*>(this);
1379     } else if (riid == IID_IAccessibleApplication) {
1380         *iface = new AccessibleApplication;
1381         return S_OK;
1382     }
1383     if (*iface) {
1384         AddRef();
1385         return S_OK;
1386     }
1387
1388     return E_NOINTERFACE;
1389 }
1390
1391
1392 /*!
1393   \internal
1394   private function..
1395   \a maxRelations max number of relations to return in \a relations
1396   \a relations the array of relations matching
1397   \a startIndex Index to start to return from,
1398                    it will return only that specific relation in \a relations
1399
1400   If \a relations is null, \a startIndex and \a maxRelations are ignored, causing
1401   it to return the number of relations in \a nRelations
1402 */
1403 HRESULT QWindowsIA2Accessible::getRelationsHelper(IAccessibleRelation **relations, int startIndex, long maxRelations, long *nRelations /* = 0*/)
1404 {
1405     if (nRelations)
1406         *nRelations = 0;
1407     typedef QPair<QAccessibleInterface *, QAccessible::Relation> RelationEntry;
1408     QVector<RelationEntry> rels = accessible->relations();
1409     QMap<QAccessible::Relation, QAccessibleInterface *> relationMap;
1410     for (QVector<RelationEntry>::const_iterator it = rels.constBegin(); it != rels.constEnd(); ++it)
1411     {
1412         RelationEntry e = *it;
1413         relationMap.insertMulti(e.second, e.first);
1414     }
1415
1416     QList<QAccessible::Relation> keys = relationMap.keys();
1417     const int numRelations = keys.count();
1418     if (relations) {
1419         for (int i = startIndex; i < qMin(startIndex + (int)maxRelations, numRelations); ++i) {
1420             QAccessible::Relation relation = keys.at(i);
1421             QList<QAccessibleInterface*> targets = relationMap.values(relation);
1422             AccessibleRelation *rel = new AccessibleRelation(targets, relation);
1423             *relations = rel;
1424             ++relations;
1425         }
1426     }
1427     if (nRelations)
1428         *nRelations = numRelations;
1429
1430     return numRelations > 0 ? S_OK : S_FALSE;
1431 }
1432
1433
1434
1435
1436 /*!
1437   \internal
1438   helper to wrap a QList<QAccessibleInterface*> inside an array of IAccessible*
1439   The IAccessible* array is returned as a IUnknown*
1440 */
1441 HRESULT QWindowsIA2Accessible::wrapListOfCells(const QList<QAccessibleInterface*> &inputCells, IUnknown ***outputAccessibles, long *nCellCount)
1442 {
1443     const int count = inputCells.count();
1444     // Server allocates array
1445     IUnknown **outputCells = count ? (IUnknown**)::CoTaskMemAlloc(sizeof(IUnknown*) * count ) : (IUnknown**)0;
1446     for (int i = 0; i < count; ++i)
1447         outputCells[i] = QWindowsAccessibility::wrap(inputCells.at(i));
1448
1449     *outputAccessibles = outputCells;
1450     *nCellCount = count;
1451     return count > 0 ? S_OK : S_FALSE;
1452 }
1453
1454 uint QWindowsIA2Accessible::uniqueID() const
1455 {
1456     uint uid = 0;
1457     if (QObject *obj = accessible->object())
1458         uid = qHash(obj);
1459
1460     if (!uid) {
1461         QAccessibleInterface *acc = accessible;
1462         QVector<int> indexOfNodes;
1463         while (acc && !acc->object()) {
1464             QAccessibleInterface *par = acc->parent();
1465             indexOfNodes.append(par->indexOfChild(acc));
1466             if (acc != accessible)
1467                 delete acc;
1468             acc = par;
1469         }
1470         if (acc) {
1471             if (acc->object()) {
1472                 uid = qHash(acc->object());
1473                 for (int i = 0; i < indexOfNodes.count(); ++i)
1474                     uid = qHash(uid + indexOfNodes.at(i));
1475
1476             }
1477             if (acc != accessible)
1478                 delete acc;
1479         }
1480     }
1481     return uid;
1482 }
1483
1484
1485 #define IF_EQUAL_RETURN_IIDSTRING(id, iid) if (id == iid) return QByteArray(#iid)
1486
1487 QByteArray QWindowsIA2Accessible::IIDToString(REFIID id)
1488 {
1489     QByteArray strGuid = QWindowsMsaaAccessible::IIDToString(id);
1490     if (!strGuid.isEmpty())
1491         return strGuid;
1492
1493     IF_EQUAL_RETURN_IIDSTRING(id, IID_IUnknown);
1494     IF_EQUAL_RETURN_IIDSTRING(id, IID_IDispatch);
1495     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessible);
1496     IF_EQUAL_RETURN_IIDSTRING(id, IID_IOleWindow);
1497     IF_EQUAL_RETURN_IIDSTRING(id, IID_IServiceProvider);
1498     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessible2);
1499     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleAction);
1500     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleApplication);
1501     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleComponent);
1502     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleEditableText);
1503     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleHyperlink);
1504     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleHypertext);
1505     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleImage);
1506     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleRelation);
1507     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTable);
1508     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTable2);
1509     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTableCell);
1510     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleText);
1511     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleValue);
1512
1513     // else...
1514 #if 0   // Can be useful for debugging, but normally we'd like to reduce the noise a bit...
1515     OLECHAR szGuid[39]={0};
1516     ::StringFromGUID2(id, szGuid, 39);
1517     strGuid.reserve(40);
1518     ::WideCharToMultiByte(CP_UTF8, 0, szGuid, 39, strGuid.data(), 39, NULL, NULL);
1519     strGuid[38] = '\0';
1520 #endif
1521     return strGuid;
1522 }
1523
1524
1525 QT_END_NAMESPACE
1526
1527 #endif //QT_NO_ACCESSIBILITY