Qt 4.8
qaccessible_win.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include "qaccessible.h"
42 #ifndef QT_NO_ACCESSIBILITY
43 
44 #include "qapplication.h"
45 #include <private/qsystemlibrary_p.h>
46 #include "qmessagebox.h" // ### dependency
47 #include "qt_windows.h"
48 #include "qwidget.h"
49 #include "qsettings.h"
50 #include <QtCore/qmap.h>
51 #include <QtCore/qpair.h>
52 #include <QtCore/qpointer.h>
53 #include <QtGui/qgraphicsitem.h>
54 #include <QtGui/qgraphicsscene.h>
55 #include <QtGui/qgraphicsview.h>
56 
57 #include <winuser.h>
58 #if !defined(WINABLEAPI)
59 # if defined(Q_WS_WINCE)
60 # include <bldver.h>
61 # endif
62 # include <winable.h>
63 #endif
64 
65 #include <oleacc.h>
66 #if !defined(Q_CC_BOR) && !defined (Q_CC_GNU)
67 #include <comdef.h>
68 #endif
69 
70 #ifdef Q_WS_WINCE
71 #include "qguifunctions_wince.h"
72 #endif
73 
75 
76 //#define DEBUG_SHOW_ATCLIENT_COMMANDS
77 #ifdef DEBUG_SHOW_ATCLIENT_COMMANDS
79 #include <qdebug.h>
81 
82 static const char *roleString(QAccessible::Role role)
83 {
84  static const char *roles[] = {
85  "NoRole" /* = 0x00000000 */,
86  "TitleBar" /* = 0x00000001 */,
87  "MenuBar" /* = 0x00000002 */,
88  "ScrollBar" /* = 0x00000003 */,
89  "Grip" /* = 0x00000004 */,
90  "Sound" /* = 0x00000005 */,
91  "Cursor" /* = 0x00000006 */,
92  "Caret" /* = 0x00000007 */,
93  "AlertMessage" /* = 0x00000008 */,
94  "Window" /* = 0x00000009 */,
95  "Client" /* = 0x0000000A */,
96  "PopupMenu" /* = 0x0000000B */,
97  "MenuItem" /* = 0x0000000C */,
98  "ToolTip" /* = 0x0000000D */,
99  "Application" /* = 0x0000000E */,
100  "Document" /* = 0x0000000F */,
101  "Pane" /* = 0x00000010 */,
102  "Chart" /* = 0x00000011 */,
103  "Dialog" /* = 0x00000012 */,
104  "Border" /* = 0x00000013 */,
105  "Grouping" /* = 0x00000014 */,
106  "Separator" /* = 0x00000015 */,
107  "ToolBar" /* = 0x00000016 */,
108  "StatusBar" /* = 0x00000017 */,
109  "Table" /* = 0x00000018 */,
110  "ColumnHeader" /* = 0x00000019 */,
111  "RowHeader" /* = 0x0000001A */,
112  "Column" /* = 0x0000001B */,
113  "Row" /* = 0x0000001C */,
114  "Cell" /* = 0x0000001D */,
115  "Link" /* = 0x0000001E */,
116  "HelpBalloon" /* = 0x0000001F */,
117  "Assistant" /* = 0x00000020 */,
118  "List" /* = 0x00000021 */,
119  "ListItem" /* = 0x00000022 */,
120  "Tree" /* = 0x00000023 */,
121  "TreeItem" /* = 0x00000024 */,
122  "PageTab" /* = 0x00000025 */,
123  "PropertyPage" /* = 0x00000026 */,
124  "Indicator" /* = 0x00000027 */,
125  "Graphic" /* = 0x00000028 */,
126  "StaticText" /* = 0x00000029 */,
127  "EditableText" /* = 0x0000002A */, // Editable, selectable, etc.
128  "PushButton" /* = 0x0000002B */,
129  "CheckBox" /* = 0x0000002C */,
130  "RadioButton" /* = 0x0000002D */,
131  "ComboBox" /* = 0x0000002E */,
132  "DropList" /* = 0x0000002F */, // commented out
133  "ProgressBar" /* = 0x00000030 */,
134  "Dial" /* = 0x00000031 */,
135  "HotkeyField" /* = 0x00000032 */,
136  "Slider" /* = 0x00000033 */,
137  "SpinBox" /* = 0x00000034 */,
138  "Canvas" /* = 0x00000035 */,
139  "Animation" /* = 0x00000036 */,
140  "Equation" /* = 0x00000037 */,
141  "ButtonDropDown" /* = 0x00000038 */,
142  "ButtonMenu" /* = 0x00000039 */,
143  "ButtonDropGrid" /* = 0x0000003A */,
144  "Whitespace" /* = 0x0000003B */,
145  "PageTabList" /* = 0x0000003C */,
146  "Clock" /* = 0x0000003D */,
147  "Splitter" /* = 0x0000003E */,
148  "LayeredPane" /* = 0x0000003F */,
149  "UserRole" /* = 0x0000ffff*/
150  };
151 
152  if (role >=0x40)
153  role = QAccessible::UserRole;
154  return roles[int(role)];
155 }
156 
157 static const char *eventString(QAccessible::Event ev)
158 {
159  static const char *events[] = {
160  "null", // 0
161  "SoundPlayed" /*= 0x0001*/,
162  "Alert" /*= 0x0002*/,
163  "ForegroundChanged" /*= 0x0003*/,
164  "MenuStart" /*= 0x0004*/,
165  "MenuEnd" /*= 0x0005*/,
166  "PopupMenuStart" /*= 0x0006*/,
167  "PopupMenuEnd" /*= 0x0007*/,
168  "ContextHelpStart" /*= 0x000C*/, // 8
169  "ContextHelpEnd" /*= 0x000D*/,
170  "DragDropStart" /*= 0x000E*/,
171  "DragDropEnd" /*= 0x000F*/,
172  "DialogStart" /*= 0x0010*/,
173  "DialogEnd" /*= 0x0011*/,
174  "ScrollingStart" /*= 0x0012*/,
175  "ScrollingEnd" /*= 0x0013*/,
176  "MenuCommand" /*= 0x0018*/, // 16
177 
178  // Values from IAccessible2
179  "ActionChanged" /*= 0x0101*/, // 17
180  "ActiveDescendantChanged",
181  "AttributeChanged",
182  "DocumentContentChanged",
183  "DocumentLoadComplete",
184  "DocumentLoadStopped",
185  "DocumentReload",
186  "HyperlinkEndIndexChanged",
187  "HyperlinkNumberOfAnchorsChanged",
188  "HyperlinkSelectedLinkChanged",
189  "HypertextLinkActivated",
190  "HypertextLinkSelected",
191  "HyperlinkStartIndexChanged",
192  "HypertextChanged",
193  "HypertextNLinksChanged",
194  "ObjectAttributeChanged",
195  "PageChanged",
196  "SectionChanged",
197  "TableCaptionChanged",
198  "TableColumnDescriptionChanged",
199  "TableColumnHeaderChanged",
200  "TableModelChanged",
201  "TableRowDescriptionChanged",
202  "TableRowHeaderChanged",
203  "TableSummaryChanged",
204  "TextAttributeChanged",
205  "TextCaretMoved",
206  // TextChanged, deprecated, use TextUpdated
207  //TextColumnChanged = TextCaretMoved + 2,
208  "TextInserted",
209  "TextRemoved",
210  "TextUpdated",
211  "TextSelectionChanged",
212  "VisibleDataChanged", /*= 0x0101+32*/
213  "ObjectCreated" /*= 0x8000*/, // 49
214  "ObjectDestroyed" /*= 0x8001*/,
215  "ObjectShow" /*= 0x8002*/,
216  "ObjectHide" /*= 0x8003*/,
217  "ObjectReorder" /*= 0x8004*/,
218  "Focus" /*= 0x8005*/,
219  "Selection" /*= 0x8006*/,
220  "SelectionAdd" /*= 0x8007*/,
221  "SelectionRemove" /*= 0x8008*/,
222  "SelectionWithin" /*= 0x8009*/,
223  "StateChanged" /*= 0x800A*/,
224  "LocationChanged" /*= 0x800B*/,
225  "NameChanged" /*= 0x800C*/,
226  "DescriptionChanged" /*= 0x800D*/,
227  "ValueChanged" /*= 0x800E*/,
228  "ParentChanged" /*= 0x800F*/,
229  "HelpChanged" /*= 0x80A0*/,
230  "DefaultActionChanged" /*= 0x80B0*/,
231  "AcceleratorChanged" /*= 0x80C0*/
232  };
233  int e = int(ev);
234  if (e <= 0x80c0) {
235  const int last = sizeof(events)/sizeof(char*) - 1;
236 
237  if (e <= 0x07)
238  return events[e];
239  else if (e <= 0x13)
240  return events[e - 0x0c + 8];
241  else if (e == 0x18)
242  return events[16];
243  else if (e <= 0x0101 + 32)
244  return events[e - 0x101 + 17];
245  else if (e <= 0x800f)
246  return events[e - 0x8000 + 49];
247  else if (e == 0x80a0)
248  return events[last - 2];
249  else if (e == 0x80b0)
250  return events[last - 1];
251  else if (e == 0x80c0)
252  return events[last];
253  }
254  return "unknown";
255 };
256 
257 void showDebug(const char* funcName, const QAccessibleInterface *iface)
258 {
259  qDebug() << "Role:" << roleString(iface->role(0))
260  << "Name:" << iface->text(QAccessible::Name, 0)
261  << "State:" << QString::number(int(iface->state(0)), 16)
262  << QLatin1String(funcName);
263 }
264 #else
265 # define showDebug(f, iface)
266 #endif
267 
268 // This stuff is used for widgets/items with no window handle:
270 Q_GLOBAL_STATIC(NotifyMap, qAccessibleRecentSentEvents)
271 static int eventNum = 0;
272 
273 
274 void QAccessible::initialize()
275 {
276 
277 }
279 {
280 
281 }
282 
283 void QAccessible::updateAccessibility(QObject *o, int who, Event reason)
284 {
285  Q_ASSERT(o);
286 
287  if (updateHandler) {
288  updateHandler(o, who, reason);
289  return;
290  }
291 
292  QString soundName;
293  switch (reason) {
294  case PopupMenuStart:
295  soundName = QLatin1String("MenuPopup");
296  break;
297 
298  case MenuCommand:
299  soundName = QLatin1String("MenuCommand");
300  break;
301 
302  case Alert:
303  {
304 #ifndef QT_NO_MESSAGEBOX
306  if (mb) {
307  switch (mb->icon()) {
309  soundName = QLatin1String("SystemExclamation");
310  break;
312  soundName = QLatin1String("SystemHand");
313  break;
315  soundName = QLatin1String("SystemAsterisk");
316  break;
317  default:
318  break;
319  }
320  } else
321 #endif // QT_NO_MESSAGEBOX
322  {
323  soundName = QLatin1String("SystemAsterisk");
324  }
325 
326  }
327  break;
328  default:
329  break;
330  }
331 
332  if (soundName.size()) {
333 #ifndef QT_NO_SETTINGS
334  QSettings settings(QLatin1String("HKEY_CURRENT_USER\\AppEvents\\Schemes\\Apps\\.Default\\") + soundName,
336  QString file = settings.value(QLatin1String(".Current/.")).toString();
337 #else
338  QString file;
339 #endif
340  if (!file.isEmpty()) {
341  PlaySound(reinterpret_cast<const wchar_t *>(soundName.utf16()), 0, SND_ALIAS | SND_ASYNC | SND_NODEFAULT | SND_NOWAIT);
342  }
343  }
344 
345  if (!isActive())
346  return;
347 
348  typedef void (WINAPI *PtrNotifyWinEvent)(DWORD, HWND, LONG, LONG);
349 
350 #if defined(Q_WS_WINCE) // ### TODO: check for NotifyWinEvent in CE 6.0
351  // There is no user32.lib nor NotifyWinEvent for CE
352  return;
353 #else
354  static PtrNotifyWinEvent ptrNotifyWinEvent = 0;
355  static bool resolvedNWE = false;
356  if (!resolvedNWE) {
357  ptrNotifyWinEvent = (PtrNotifyWinEvent)QSystemLibrary::resolve(QLatin1String("user32"), "NotifyWinEvent");
358  resolvedNWE = true;
359  }
360  if (!ptrNotifyWinEvent)
361  return;
362 
363  // An event has to be associated with a window,
364  // so find the first parent that is a widget.
365  QWidget *w = 0;
366  QObject *p = o;
367  do {
368  if (p->isWidgetType()) {
369  w = static_cast<QWidget*>(p);
370  if (w->internalWinId())
371  break;
372  }
373  if (QGraphicsObject *gfxObj = qobject_cast<QGraphicsObject*>(p)) {
374  QGraphicsItem *parentItem = gfxObj->parentItem();
375  if (parentItem) {
376  p = parentItem->toGraphicsObject();
377  } else {
378  QGraphicsView *view = 0;
379  if (QGraphicsScene *scene = gfxObj->scene()) {
381  const QList<QGraphicsView*> views = scene->views();
382  for (int i = 0 ; i < views.count() && view != fw; ++i) {
383  view = views.at(i);
384  }
385  }
386  p = view;
387  }
388  } else {
389  p = p->parent();
390  }
391 
392  } while (p);
393 
394  //qDebug() << "updateAccessibility(), hwnd:" << w << ", object:" << o << "," << eventString(reason);
395  if (!w) {
396  if (reason != QAccessible::ContextHelpStart &&
397  reason != QAccessible::ContextHelpEnd)
399  if (!w) {
401 
402  if (!w)
403  return;
404 
405 // ### Fixme
406 // if (!w) {
407 // w = qApp->mainWidget();
408 // if (!w)
409 // return;
410 // }
411  }
412  }
413 
414  WId wid = w->internalWinId();
415  if (reason != MenuCommand) { // MenuCommand is faked
416  if (w != o) {
417  // See comment "SENDING EVENTS TO OBJECTS WITH NO WINDOW HANDLE"
418  if (reason != QAccessible::ObjectDestroyed) {
419  /* In some rare occasions, the server (Qt) might get a ::get_accChild call with a
420  childId that references an entry in the cache where there was a dangling
421  QObject-pointer. Previously we crashed on this.
422 
423  There is no point in actually notifying the AT client that the object got destroyed,
424  because the AT client won't query for get_accChild if the event is ObjectDestroyed
425  anyway, and we have no other way of mapping the eventId argument to the actual
426  child/descendant object. (Firefox seems to simply completely ignore
427  EVENT_OBJECT_DESTROY).
428 
429  We therefore guard each QObject in the cache with a QPointer, and only notify the AT
430  client if the type is not ObjectDestroyed.
431  */
432  eventNum %= 50; //[0..49]
433  int eventId = - eventNum - 1;
434  qAccessibleRecentSentEvents()->insert(eventId, qMakePair(QPointer<QObject>(o), who));
435  ptrNotifyWinEvent(reason, wid, OBJID_CLIENT, eventId );
436  ++eventNum;
437  }
438  } else {
439  ptrNotifyWinEvent(reason, wid, OBJID_CLIENT, who);
440  }
441  }
442 #endif // Q_WS_WINCE
443 }
444 
445 /* == SENDING EVENTS TO OBJECTS WITH NO WINDOW HANDLE ==
446 
447  If the user requested to send the event to a widget with no window,
448  we need to send an event to an object with no hwnd.
449  The way we do that is to send it to the *first* ancestor widget
450  with a window.
451  Then we'll need a way of identifying the child:
452  We'll just keep a list of the most recent events that we have sent,
453  where each entry in the list is identified by a negative value
454  between [-50,-1]. This negative value we will pass on to
455  NotifyWinEvent() as the child id. When the negative value have
456  reached -50, it will wrap around to -1. This seems to be enough
457 
458  Now, when the client receives that event, he will first call
459  AccessibleObjectFromEvent() where dwChildID is the special
460  negative value. AccessibleObjectFromEvent does two steps:
461  1. It will first sent a WM_GETOBJECT to the server, asking
462  for the IAccessible interface for the HWND.
463  2. With the IAccessible interface it got hold of it will call
464  acc_getChild where the child id argument is the special
465  negative identifier. In our reimplementation of get_accChild
466  we check for this if the child id is negative. If it is, then
467  we'll look up in our table for the entry that is associated
468  with that value.
469  The entry will then contain a pointer to the QObject /QWidget
470  that we can use to call queryAccessibleInterface() on.
471 
472 
473  The following figure shows how the interaction between server and
474  client is in the case when the server is sending an event.
475 
476 SERVER (Qt) | CLIENT |
477 --------------------------------------------+---------------------------------------+
478  |
479 acc->updateAccessibility(obj, childIndex) |
480  |
481 recentEvents()->insert(- 1 - eventNum, |
482  qMakePair(obj, childIndex) |
483 NotifyWinEvent(hwnd, childId) => |
484  | AccessibleObjectFromEvent(event, hwnd, OBJID_CLIENT, childId )
485  | will do:
486  <=== 1. send WM_GETOBJECT(hwnd, OBJID_CLIENT)
487 widget ~= hwnd
488 iface = queryAccessibleInteface(widget)
489 (create IAccessible interface wrapper for
490  iface)
491  return iface ===> IAccessible* iface; (for hwnd)
492  |
493  <=== call iface->get_accChild(childId)
494 get_accChild() { |
495  if (varChildID.lVal < 0) {
496  QPair ref = recentEvents().value(varChildID.lVal);
497  [...]
498  }
499 */
500 
501 
503 {
504  if (rootObjectHandler) {
506  }
507 }
508 
509 class QWindowsEnumerate : public IEnumVARIANT
510 {
511 public:
513  : ref(0), current(0),array(a)
514  {
515  }
516 
517  virtual ~QWindowsEnumerate() {}
518 
519  HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *);
520  ULONG STDMETHODCALLTYPE AddRef();
521  ULONG STDMETHODCALLTYPE Release();
522 
523  HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT **ppEnum);
524  HRESULT STDMETHODCALLTYPE Next(unsigned long celt, VARIANT FAR* rgVar, unsigned long FAR* pCeltFetched);
525  HRESULT STDMETHODCALLTYPE Reset();
526  HRESULT STDMETHODCALLTYPE Skip(unsigned long celt);
527 
528 private:
529  ULONG ref;
530  ULONG current;
532 };
533 
534 HRESULT STDMETHODCALLTYPE QWindowsEnumerate::QueryInterface(REFIID id, LPVOID *iface)
535 {
536  *iface = 0;
537  if (id == IID_IUnknown)
538  *iface = (IUnknown*)this;
539  else if (id == IID_IEnumVARIANT)
540  *iface = (IEnumVARIANT*)this;
541 
542  if (*iface) {
543  AddRef();
544  return S_OK;
545  }
546 
547  return E_NOINTERFACE;
548 }
549 
550 ULONG STDMETHODCALLTYPE QWindowsEnumerate::AddRef()
551 {
552  return ++ref;
553 }
554 
555 ULONG STDMETHODCALLTYPE QWindowsEnumerate::Release()
556 {
557  if (!--ref) {
558  delete this;
559  return 0;
560  }
561  return ref;
562 }
563 
564 HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Clone(IEnumVARIANT **ppEnum)
565 {
566  QWindowsEnumerate *penum = 0;
567  *ppEnum = 0;
568 
569  penum = new QWindowsEnumerate(array);
570  if (!penum)
571  return E_OUTOFMEMORY;
572  penum->current = current;
573  penum->array = array;
574  penum->AddRef();
575  *ppEnum = penum;
576 
577  return S_OK;
578 }
579 
580 HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Next(unsigned long celt, VARIANT FAR* rgVar, unsigned long FAR* pCeltFetched)
581 {
582  if (pCeltFetched)
583  *pCeltFetched = 0;
584 
585  ULONG l;
586  for (l = 0; l < celt; l++) {
587  VariantInit(&rgVar[l]);
588  if ((current+1) > (ULONG)array.size()) {
589  *pCeltFetched = l;
590  return S_FALSE;
591  }
592 
593  rgVar[l].vt = VT_I4;
594  rgVar[l].lVal = array[(int)current];
595  ++current;
596  }
597  *pCeltFetched = l;
598  return S_OK;
599 }
600 
602 {
603  current = 0;
604  return S_OK;
605 }
606 
607 HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Skip(unsigned long celt)
608 {
609  current += celt;
610  if (current > (ULONG)array.size()) {
611  current = array.size();
612  return S_FALSE;
613  }
614  return S_OK;
615 }
616 
618  AccessibleElement(int entryId, QAccessibleInterface *accessible) {
619  if (entryId < 0) {
620  QPair<QPointer<QObject>, int> ref = qAccessibleRecentSentEvents()->value(entryId);
621  iface = QAccessible::queryAccessibleInterface(ref.first.data());
622  entry = ref.second;
623  cleanupInterface = true;
624  } else {
625  iface = accessible;
626  entry = entryId;
627  cleanupInterface = false;
628  }
629  }
630 
632  return iface ? iface->text(t, entry) : QString();
633  }
634 
636  if (cleanupInterface)
637  delete iface;
638  }
639 
641  int entry;
642 private:
644 };
645 
646 /*
647 */
648 class QWindowsAccessible : public IAccessible, IOleWindow, QAccessible
649 {
650 public:
652  : ref(0), accessible(a)
653  {
654  }
655 
657  {
658  delete accessible;
659  }
660 
661  /* IUnknown */
662  HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *);
663  ULONG STDMETHODCALLTYPE AddRef();
664  ULONG STDMETHODCALLTYPE Release();
665 
666  /* IDispatch */
667  HRESULT STDMETHODCALLTYPE GetTypeInfoCount(unsigned int *);
668  HRESULT STDMETHODCALLTYPE GetTypeInfo(unsigned int, unsigned long, ITypeInfo **);
669  HRESULT STDMETHODCALLTYPE GetIDsOfNames(const _GUID &, wchar_t **, unsigned int, unsigned long, long *);
670  HRESULT STDMETHODCALLTYPE Invoke(long, const _GUID &, unsigned long, unsigned short, tagDISPPARAMS *, tagVARIANT *, tagEXCEPINFO *, unsigned int *);
671 
672  /* IAccessible */
673  HRESULT STDMETHODCALLTYPE accHitTest(long xLeft, long yTop, VARIANT *pvarID);
674  HRESULT STDMETHODCALLTYPE accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID);
675  HRESULT STDMETHODCALLTYPE accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd);
676  HRESULT STDMETHODCALLTYPE get_accChild(VARIANT varChildID, IDispatch** ppdispChild);
677  HRESULT STDMETHODCALLTYPE get_accChildCount(long* pcountChildren);
678  HRESULT STDMETHODCALLTYPE get_accParent(IDispatch** ppdispParent);
679 
680  HRESULT STDMETHODCALLTYPE accDoDefaultAction(VARIANT varID);
681  HRESULT STDMETHODCALLTYPE get_accDefaultAction(VARIANT varID, BSTR* pszDefaultAction);
682  HRESULT STDMETHODCALLTYPE get_accDescription(VARIANT varID, BSTR* pszDescription);
683  HRESULT STDMETHODCALLTYPE get_accHelp(VARIANT varID, BSTR *pszHelp);
684  HRESULT STDMETHODCALLTYPE get_accHelpTopic(BSTR *pszHelpFile, VARIANT varChild, long *pidTopic);
685  HRESULT STDMETHODCALLTYPE get_accKeyboardShortcut(VARIANT varID, BSTR *pszKeyboardShortcut);
686  HRESULT STDMETHODCALLTYPE get_accName(VARIANT varID, BSTR* pszName);
687  HRESULT STDMETHODCALLTYPE put_accName(VARIANT varChild, BSTR szName);
688  HRESULT STDMETHODCALLTYPE get_accRole(VARIANT varID, VARIANT *pvarRole);
689  HRESULT STDMETHODCALLTYPE get_accState(VARIANT varID, VARIANT *pvarState);
690  HRESULT STDMETHODCALLTYPE get_accValue(VARIANT varID, BSTR* pszValue);
691  HRESULT STDMETHODCALLTYPE put_accValue(VARIANT varChild, BSTR szValue);
692 
693  HRESULT STDMETHODCALLTYPE accSelect(long flagsSelect, VARIANT varID);
694  HRESULT STDMETHODCALLTYPE get_accFocus(VARIANT *pvarID);
695  HRESULT STDMETHODCALLTYPE get_accSelection(VARIANT *pvarChildren);
696 
697  /* IOleWindow */
698  HRESULT STDMETHODCALLTYPE GetWindow(HWND *phwnd);
699  HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
700 
701 private:
702  ULONG ref;
704 };
705 
706 static inline BSTR QStringToBSTR(const QString &str)
707 {
708  return SysAllocStringLen((OLECHAR*)str.unicode(), str.length());
709 }
710 
711 /*
712 */
714 {
715  QWindowsAccessible *acc = new QWindowsAccessible(access);
716  IAccessible *iface;
717  acc->QueryInterface(IID_IAccessible, (void**)&iface);
718 
719  return iface;
720 }
721 
722 /*
723  IUnknown
724 */
725 HRESULT STDMETHODCALLTYPE QWindowsAccessible::QueryInterface(REFIID id, LPVOID *iface)
726 {
727  *iface = 0;
728  if (id == IID_IUnknown)
729  *iface = (IUnknown*)(IDispatch*)this;
730  else if (id == IID_IDispatch)
731  *iface = (IDispatch*)this;
732  else if (id == IID_IAccessible)
733  *iface = (IAccessible*)this;
734  else if (id == IID_IOleWindow)
735  *iface = (IOleWindow*)this;
736  else
737  return E_NOINTERFACE;
738 
739  AddRef();
740  return S_OK;
741 }
742 
743 ULONG STDMETHODCALLTYPE QWindowsAccessible::AddRef()
744 {
745  return ++ref;
746 }
747 
748 ULONG STDMETHODCALLTYPE QWindowsAccessible::Release()
749 {
750  if (!--ref) {
751  delete this;
752  return 0;
753  }
754  return ref;
755 }
756 
757 /*
758  IDispatch
759 */
760 
761 HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetTypeInfoCount(unsigned int * pctinfo)
762 {
763  // We don't use a type library
764  *pctinfo = 0;
765  return S_OK;
766 }
767 
768 HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetTypeInfo(unsigned int, unsigned long, ITypeInfo **pptinfo)
769 {
770  // We don't use a type library
771  *pptinfo = 0;
772  return S_OK;
773 }
774 
775 HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetIDsOfNames(const _GUID &, wchar_t **rgszNames, unsigned int, unsigned long, long *rgdispid)
776 {
777 #if !defined(Q_CC_BOR) && !defined(Q_CC_GNU)
778  // PROPERTIES: Hierarchical
779  if (_bstr_t(rgszNames[0]) == _bstr_t(L"accParent"))
780  rgdispid[0] = DISPID_ACC_PARENT;
781  else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accChildCount"))
782  rgdispid[0] = DISPID_ACC_CHILDCOUNT;
783  else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accChild"))
784  rgdispid[0] = DISPID_ACC_CHILD;
785 
786  // PROPERTIES: Descriptional
787  else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accName("))
788  rgdispid[0] = DISPID_ACC_NAME;
789  else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accValue"))
790  rgdispid[0] = DISPID_ACC_VALUE;
791  else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accDescription"))
792  rgdispid[0] = DISPID_ACC_DESCRIPTION;
793  else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accRole"))
794  rgdispid[0] = DISPID_ACC_ROLE;
795  else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accState"))
796  rgdispid[0] = DISPID_ACC_STATE;
797  else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accHelp"))
798  rgdispid[0] = DISPID_ACC_HELP;
799  else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accHelpTopic"))
800  rgdispid[0] = DISPID_ACC_HELPTOPIC;
801  else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accKeyboardShortcut"))
802  rgdispid[0] = DISPID_ACC_KEYBOARDSHORTCUT;
803  else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accFocus"))
804  rgdispid[0] = DISPID_ACC_FOCUS;
805  else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accSelection"))
806  rgdispid[0] = DISPID_ACC_SELECTION;
807  else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accDefaultAction"))
808  rgdispid[0] = DISPID_ACC_DEFAULTACTION;
809 
810  // METHODS
811  else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accSelect"))
812  rgdispid[0] = DISPID_ACC_SELECT;
813  else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accLocation"))
814  rgdispid[0] = DISPID_ACC_LOCATION;
815  else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accNavigate"))
816  rgdispid[0] = DISPID_ACC_NAVIGATE;
817  else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accHitTest"))
818  rgdispid[0] = DISPID_ACC_HITTEST;
819  else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accDoDefaultAction"))
820  rgdispid[0] = DISPID_ACC_DODEFAULTACTION;
821  else
822  return DISP_E_UNKNOWNINTERFACE;
823 
824  return S_OK;
825 #else
826  Q_UNUSED(rgszNames);
827  Q_UNUSED(rgdispid);
828 
829  return DISP_E_MEMBERNOTFOUND;
830 #endif
831 }
832 
833 HRESULT STDMETHODCALLTYPE QWindowsAccessible::Invoke(long dispIdMember, const _GUID &, unsigned long, unsigned short wFlags, tagDISPPARAMS *pDispParams, tagVARIANT *pVarResult, tagEXCEPINFO *, unsigned int *)
834 {
835  HRESULT hr = DISP_E_MEMBERNOTFOUND;
836 
837  switch(dispIdMember)
838  {
839  case DISPID_ACC_PARENT:
840  if (wFlags == DISPATCH_PROPERTYGET) {
841  if (!pVarResult)
842  return E_INVALIDARG;
843  hr = get_accParent(&pVarResult->pdispVal);
844  } else {
845  hr = DISP_E_MEMBERNOTFOUND;
846  }
847  break;
848 
849  case DISPID_ACC_CHILDCOUNT:
850  if (wFlags == DISPATCH_PROPERTYGET) {
851  if (!pVarResult)
852  return E_INVALIDARG;
853  hr = get_accChildCount(&pVarResult->lVal);
854  } else {
855  hr = DISP_E_MEMBERNOTFOUND;
856  }
857  break;
858 
859  case DISPID_ACC_CHILD:
860  if (wFlags == DISPATCH_PROPERTYGET)
861  hr = get_accChild(pDispParams->rgvarg[0], &pVarResult->pdispVal);
862  else
863  hr = DISP_E_MEMBERNOTFOUND;
864  break;
865 
866  case DISPID_ACC_NAME:
867  if (wFlags == DISPATCH_PROPERTYGET)
868  hr = get_accName(pDispParams->rgvarg[0], &pVarResult->bstrVal);
869  else if (wFlags == DISPATCH_PROPERTYPUT)
870  hr = put_accName(pDispParams->rgvarg[0], pVarResult->bstrVal);
871  else
872  hr = DISP_E_MEMBERNOTFOUND;
873  break;
874 
875  case DISPID_ACC_VALUE:
876  if (wFlags == DISPATCH_PROPERTYGET)
877  hr = get_accValue(pDispParams->rgvarg[0], &pVarResult->bstrVal);
878  else if (wFlags == DISPATCH_PROPERTYPUT)
879  hr = put_accValue(pDispParams->rgvarg[0], pVarResult->bstrVal);
880  else
881  hr = DISP_E_MEMBERNOTFOUND;
882  break;
883 
884  case DISPID_ACC_DESCRIPTION:
885  if (wFlags == DISPATCH_PROPERTYGET)
886  hr = get_accDescription(pDispParams->rgvarg[0], &pVarResult->bstrVal);
887  else
888  hr = DISP_E_MEMBERNOTFOUND;
889  break;
890 
891  case DISPID_ACC_ROLE:
892  if (wFlags == DISPATCH_PROPERTYGET)
893  hr = get_accRole(pDispParams->rgvarg[0], pVarResult);
894  else
895  hr = DISP_E_MEMBERNOTFOUND;
896  break;
897 
898  case DISPID_ACC_STATE:
899  if (wFlags == DISPATCH_PROPERTYGET)
900  hr = get_accState(pDispParams->rgvarg[0], pVarResult);
901  else
902  hr = DISP_E_MEMBERNOTFOUND;
903  break;
904 
905  case DISPID_ACC_HELP:
906  if (wFlags == DISPATCH_PROPERTYGET)
907  hr = get_accHelp(pDispParams->rgvarg[0], &pVarResult->bstrVal);
908  else
909  hr = DISP_E_MEMBERNOTFOUND;
910  break;
911 
912  case DISPID_ACC_HELPTOPIC:
913  if (wFlags == DISPATCH_PROPERTYGET)
914  hr = get_accHelpTopic(&pDispParams->rgvarg[2].bstrVal, pDispParams->rgvarg[1], &pDispParams->rgvarg[0].lVal);
915  else
916  hr = DISP_E_MEMBERNOTFOUND;
917  break;
918 
919  case DISPID_ACC_KEYBOARDSHORTCUT:
920  if (wFlags == DISPATCH_PROPERTYGET)
921  hr = get_accKeyboardShortcut(pDispParams->rgvarg[0], &pVarResult->bstrVal);
922  else
923  hr = DISP_E_MEMBERNOTFOUND;
924  break;
925 
926  case DISPID_ACC_FOCUS:
927  if (wFlags == DISPATCH_PROPERTYGET)
928  hr = get_accFocus(pVarResult);
929  else
930  hr = DISP_E_MEMBERNOTFOUND;
931  break;
932 
933  case DISPID_ACC_SELECTION:
934  if (wFlags == DISPATCH_PROPERTYGET)
935  hr = get_accSelection(pVarResult);
936  else
937  hr = DISP_E_MEMBERNOTFOUND;
938  break;
939 
940  case DISPID_ACC_DEFAULTACTION:
941  if (wFlags == DISPATCH_PROPERTYGET)
942  hr = get_accDefaultAction(pDispParams->rgvarg[0], &pVarResult->bstrVal);
943  else
944  hr = DISP_E_MEMBERNOTFOUND;
945  break;
946 
947  case DISPID_ACC_SELECT:
948  if (wFlags == DISPATCH_METHOD)
949  hr = accSelect(pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0]);
950  else
951  hr = DISP_E_MEMBERNOTFOUND;
952  break;
953 
954  case DISPID_ACC_LOCATION:
955  if (wFlags == DISPATCH_METHOD)
956  hr = accLocation(&pDispParams->rgvarg[4].lVal, &pDispParams->rgvarg[3].lVal, &pDispParams->rgvarg[2].lVal, &pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0]);
957  else
958  hr = DISP_E_MEMBERNOTFOUND;
959  break;
960 
961  case DISPID_ACC_NAVIGATE:
962  if (wFlags == DISPATCH_METHOD)
963  hr = accNavigate(pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0], pVarResult);
964  else
965  hr = DISP_E_MEMBERNOTFOUND;
966  break;
967 
968  case DISPID_ACC_HITTEST:
969  if (wFlags == DISPATCH_METHOD)
970  hr = accHitTest(pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0].lVal, pVarResult);
971  else
972  hr = DISP_E_MEMBERNOTFOUND;
973  break;
974 
975  case DISPID_ACC_DODEFAULTACTION:
976  if (wFlags == DISPATCH_METHOD)
977  hr = accDoDefaultAction(pDispParams->rgvarg[0]);
978  else
979  hr = DISP_E_MEMBERNOTFOUND;
980  break;
981 
982  default:
983  hr = DISP_E_MEMBERNOTFOUND;
984  break;
985  }
986 
987  if (!SUCCEEDED(hr)) {
988  return hr;
989  }
990  return hr;
991 }
992 
993 /*
994  IAccessible
995 */
996 HRESULT STDMETHODCALLTYPE QWindowsAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarID)
997 {
998  showDebug(__FUNCTION__, accessible);
999  if (!accessible->isValid())
1000  return E_FAIL;
1001 
1002  int control = accessible->childAt(xLeft, yTop);
1003  if (control == -1) {
1004  (*pvarID).vt = VT_EMPTY;
1005  return S_FALSE;
1006  }
1007  QAccessibleInterface *acc = 0;
1008  if (control)
1009  accessible->navigate(Child, control, &acc);
1010  if (!acc) {
1011  (*pvarID).vt = VT_I4;
1012  (*pvarID).lVal = control;
1013  return S_OK;
1014  }
1015 
1016  QWindowsAccessible* wacc = new QWindowsAccessible(acc);
1017  IDispatch *iface = 0;
1018  wacc->QueryInterface(IID_IDispatch, (void**)&iface);
1019  if (iface) {
1020  (*pvarID).vt = VT_DISPATCH;
1021  (*pvarID).pdispVal = iface;
1022  return S_OK;
1023  } else {
1024  delete wacc;
1025  }
1026 
1027  (*pvarID).vt = VT_EMPTY;
1028  return S_FALSE;
1029 }
1030 
1031 HRESULT STDMETHODCALLTYPE QWindowsAccessible::accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID)
1032 {
1033  showDebug(__FUNCTION__, accessible);
1034  if (!accessible->isValid())
1035  return E_FAIL;
1036 
1037  AccessibleElement elem(varID.lVal, accessible);
1038  QRect rect = elem.iface ? elem.iface->rect(elem.entry) : QRect();
1039  if (rect.isValid()) {
1040  *pxLeft = rect.x();
1041  *pyTop = rect.y();
1042  *pcxWidth = rect.width();
1043  *pcyHeight = rect.height();
1044  } else {
1045  *pxLeft = 0;
1046  *pyTop = 0;
1047  *pcxWidth = 0;
1048  *pcyHeight = 0;
1049  }
1050  return S_OK;
1051 }
1052 
1053 HRESULT STDMETHODCALLTYPE QWindowsAccessible::accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd)
1054 {
1055  showDebug(__FUNCTION__, accessible);
1056  if (!accessible->isValid())
1057  return E_FAIL;
1058 
1059  QAccessibleInterface *acc = 0;
1060  int control = -1;
1061  switch(navDir) {
1062  case NAVDIR_FIRSTCHILD:
1063  control = accessible->navigate(Child, 1, &acc);
1064  break;
1065  case NAVDIR_LASTCHILD:
1066  control = accessible->navigate(Child, accessible->childCount(), &acc);
1067  break;
1068  case NAVDIR_NEXT:
1069  case NAVDIR_PREVIOUS:
1070  if (!varStart.lVal){
1071  QAccessibleInterface *parent = 0;
1072  accessible->navigate(Ancestor, 1, &parent);
1073  if (parent) {
1074  int index = parent->indexOfChild(accessible);
1075  index += (navDir == NAVDIR_NEXT) ? 1 : -1;
1076  if (index > 0 && index <= parent->childCount())
1077  control = parent->navigate(Child, index, &acc);
1078  delete parent;
1079  }
1080  } else {
1081  int index = varStart.lVal;
1082  index += (navDir == NAVDIR_NEXT) ? 1 : -1;
1083  if (index > 0 && index <= accessible->childCount())
1084  control = accessible->navigate(Child, index, &acc);
1085  }
1086  break;
1087  case NAVDIR_UP:
1088  control = accessible->navigate(Up, varStart.lVal, &acc);
1089  break;
1090  case NAVDIR_DOWN:
1091  control = accessible->navigate(Down, varStart.lVal, &acc);
1092  break;
1093  case NAVDIR_LEFT:
1094  control = accessible->navigate(Left, varStart.lVal, &acc);
1095  break;
1096  case NAVDIR_RIGHT:
1097  control = accessible->navigate(Right, varStart.lVal, &acc);
1098  break;
1099  default:
1100  break;
1101  }
1102  if (control == -1) {
1103  (*pvarEnd).vt = VT_EMPTY;
1104  return S_FALSE;
1105  }
1106  if (!acc) {
1107  (*pvarEnd).vt = VT_I4;
1108  (*pvarEnd).lVal = control;
1109  return S_OK;
1110  }
1111 
1112  QWindowsAccessible* wacc = new QWindowsAccessible(acc);
1113 
1114  IDispatch *iface = 0;
1115  wacc->QueryInterface(IID_IDispatch, (void**)&iface);
1116  if (iface) {
1117  (*pvarEnd).vt = VT_DISPATCH;
1118  (*pvarEnd).pdispVal = iface;
1119  return S_OK;
1120  } else {
1121  delete wacc;
1122  }
1123 
1124  (*pvarEnd).vt = VT_EMPTY;
1125  return S_FALSE;
1126 }
1127 
1128 HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild(VARIANT varChildID, IDispatch** ppdispChild)
1129 {
1130  showDebug(__FUNCTION__, accessible);
1131  if (!accessible->isValid())
1132  return E_FAIL;
1133 
1134  if (varChildID.vt == VT_EMPTY)
1135  return E_INVALIDARG;
1136 
1137 
1138  int childIndex = varChildID.lVal;
1139  QAccessibleInterface *acc = 0;
1140 
1141  AccessibleElement elem(childIndex, accessible);
1142  if (elem.iface) {
1143  RelationFlag rel = elem.entry ? Child : Self;
1144  int index = elem.iface->navigate(rel, elem.entry, &acc);
1145  if (index == -1)
1146  return E_INVALIDARG;
1147  }
1148 
1149  if (acc) {
1150  QWindowsAccessible* wacc = new QWindowsAccessible(acc);
1151  wacc->QueryInterface(IID_IDispatch, (void**)ppdispChild);
1152  return S_OK;
1153  }
1154 
1155  *ppdispChild = 0;
1156  return S_FALSE;
1157 }
1158 
1159 HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChildCount(long* pcountChildren)
1160 {
1161  showDebug(__FUNCTION__, accessible);
1162  if (!accessible->isValid())
1163  return E_FAIL;
1164 
1165  *pcountChildren = accessible->childCount();
1166  return S_OK;
1167 }
1168 
1169 HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accParent(IDispatch** ppdispParent)
1170 {
1171  showDebug(__FUNCTION__, accessible);
1172  if (!accessible->isValid())
1173  return E_FAIL;
1174 
1175  QAccessibleInterface *acc = 0;
1176  accessible->navigate(Ancestor, 1, &acc);
1177  if (acc) {
1178  QWindowsAccessible* wacc = new QWindowsAccessible(acc);
1179  wacc->QueryInterface(IID_IDispatch, (void**)ppdispParent);
1180 
1181  if (*ppdispParent)
1182  return S_OK;
1183  }
1184 
1185  *ppdispParent = 0;
1186  return S_FALSE;
1187 }
1188 
1189 /*
1190  Properties and methods
1191 */
1192 HRESULT STDMETHODCALLTYPE QWindowsAccessible::accDoDefaultAction(VARIANT varID)
1193 {
1194  showDebug(__FUNCTION__, accessible);
1195  if (!accessible->isValid())
1196  return E_FAIL;
1197 
1198  AccessibleElement elem(varID.lVal, accessible);
1199  const bool res = elem.iface ? elem.iface->doAction(DefaultAction, elem.entry, QVariantList()) : false;
1200  return res ? S_OK : S_FALSE;
1201 }
1202 
1203 HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDefaultAction(VARIANT varID, BSTR* pszDefaultAction)
1204 {
1205  showDebug(__FUNCTION__, accessible);
1206  if (!accessible->isValid())
1207  return E_FAIL;
1208 
1209  AccessibleElement elem(varID.lVal, accessible);
1210  QString def = elem.iface ? elem.iface->actionText(DefaultAction, Name, elem.entry) : QString();
1211  if (def.isEmpty()) {
1212  *pszDefaultAction = 0;
1213  return S_FALSE;
1214  }
1215 
1216  *pszDefaultAction = QStringToBSTR(def);
1217  return S_OK;
1218 }
1219 
1220 HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDescription(VARIANT varID, BSTR* pszDescription)
1221 {
1222  showDebug(__FUNCTION__, accessible);
1223  if (!accessible->isValid())
1224  return E_FAIL;
1225 
1226  AccessibleElement elem(varID.lVal, accessible);
1227  QString descr = elem.text(Description);
1228  if (descr.size()) {
1229  *pszDescription = QStringToBSTR(descr);
1230  return S_OK;
1231  }
1232 
1233  *pszDescription = 0;
1234  return S_FALSE;
1235 }
1236 
1237 HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accHelp(VARIANT varID, BSTR *pszHelp)
1238 {
1239  showDebug(__FUNCTION__, accessible);
1240  if (!accessible->isValid())
1241  return E_FAIL;
1242 
1243  AccessibleElement elem(varID.lVal, accessible);
1244  QString help = elem.text(Help);
1245  if (help.size()) {
1246  *pszHelp = QStringToBSTR(help);
1247  return S_OK;
1248  }
1249 
1250  *pszHelp = 0;
1251  return S_FALSE;
1252 }
1253 
1254 HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accHelpTopic(BSTR *, VARIANT, long *)
1255 {
1256  return DISP_E_MEMBERNOTFOUND;
1257 }
1258 
1259 HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accKeyboardShortcut(VARIANT varID, BSTR *pszKeyboardShortcut)
1260 {
1261  showDebug(__FUNCTION__, accessible);
1262  if (!accessible->isValid())
1263  return E_FAIL;
1264 
1265  AccessibleElement elem(varID.lVal, accessible);
1266  QString sc = elem.text(Accelerator);
1267  if (sc.size()) {
1268  *pszKeyboardShortcut = QStringToBSTR(sc);
1269  return S_OK;
1270  }
1271 
1272  *pszKeyboardShortcut = 0;
1273  return S_FALSE;
1274 }
1275 
1276 HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accName(VARIANT varID, BSTR* pszName)
1277 {
1278  showDebug(__FUNCTION__, accessible);
1279  if (!accessible->isValid())
1280  return E_FAIL;
1281 
1282  AccessibleElement elem(varID.lVal, accessible);
1283  QString n = elem.text(Name);
1284  if (n.size()) {
1285  *pszName = QStringToBSTR(n);
1286  return S_OK;
1287  }
1288 
1289  *pszName = 0;
1290  return S_FALSE;
1291 }
1292 
1293 HRESULT STDMETHODCALLTYPE QWindowsAccessible::put_accName(VARIANT, BSTR)
1294 {
1295  showDebug(__FUNCTION__, accessible);
1296  return DISP_E_MEMBERNOTFOUND;
1297 }
1298 
1299 HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accRole(VARIANT varID, VARIANT *pvarRole)
1300 {
1301  showDebug(__FUNCTION__, accessible);
1302  if (!accessible->isValid())
1303  return E_FAIL;
1304 
1305  AccessibleElement elem(varID.lVal, accessible);
1306  Role role = elem.iface ? elem.iface->role(elem.entry) : NoRole;
1307  if (role != NoRole) {
1308  if (role == LayeredPane)
1309  role = QAccessible::Pane;
1310  (*pvarRole).vt = VT_I4;
1311  (*pvarRole).lVal = role;
1312  } else {
1313  (*pvarRole).vt = VT_EMPTY;
1314  }
1315  return S_OK;
1316 }
1317 
1318 HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accState(VARIANT varID, VARIANT *pvarState)
1319 {
1320  showDebug(__FUNCTION__, accessible);
1321  if (!accessible->isValid())
1322  return E_FAIL;
1323 
1324  (*pvarState).vt = VT_I4;
1325  AccessibleElement elem(varID.lVal, accessible);
1326  (*pvarState).lVal = elem.iface ? elem.iface->state(elem.entry) : State(Normal);
1327  return S_OK;
1328 }
1329 
1330 HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accValue(VARIANT varID, BSTR* pszValue)
1331 {
1332  showDebug(__FUNCTION__, accessible);
1333  if (!accessible->isValid())
1334  return E_FAIL;
1335 
1336  AccessibleElement elem(varID.lVal, accessible);
1337  QString value = elem.text(Value);
1338  if (!value.isNull()) {
1339  *pszValue = QStringToBSTR(value);
1340  return S_OK;
1341  }
1342 
1343  *pszValue = 0;
1344  return S_FALSE;
1345 }
1346 
1347 HRESULT STDMETHODCALLTYPE QWindowsAccessible::put_accValue(VARIANT, BSTR)
1348 {
1349  showDebug(__FUNCTION__, accessible);
1350  return DISP_E_MEMBERNOTFOUND;
1351 }
1352 
1353 HRESULT STDMETHODCALLTYPE QWindowsAccessible::accSelect(long flagsSelect, VARIANT varID)
1354 {
1355  showDebug(__FUNCTION__, accessible);
1356  if (!accessible->isValid())
1357  return E_FAIL;
1358 
1359  bool res = false;
1360 
1361  AccessibleElement elem(varID.lVal, accessible);
1362  QAccessibleInterface *acc = elem.iface;
1363  if (acc) {
1364  const int entry = elem.entry;
1365  if (flagsSelect & SELFLAG_TAKEFOCUS)
1366  res = acc->doAction(SetFocus, entry, QVariantList());
1367  if (flagsSelect & SELFLAG_TAKESELECTION) {
1368  acc->doAction(ClearSelection, 0, QVariantList()); //### bug, 0 should be entry??
1369  res = acc->doAction(AddToSelection, entry, QVariantList());
1370  }
1371  if (flagsSelect & SELFLAG_EXTENDSELECTION)
1372  res = acc->doAction(ExtendSelection, entry, QVariantList());
1373  if (flagsSelect & SELFLAG_ADDSELECTION)
1374  res = acc->doAction(AddToSelection, entry, QVariantList());
1375  if (flagsSelect & SELFLAG_REMOVESELECTION)
1376  res = acc->doAction(RemoveSelection, entry, QVariantList());
1377  }
1378  return res ? S_OK : S_FALSE;
1379 }
1380 
1381 HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accFocus(VARIANT *pvarID)
1382 {
1383  showDebug(__FUNCTION__, accessible);
1384  if (!accessible->isValid())
1385  return E_FAIL;
1386 
1387  QAccessibleInterface *acc = 0;
1388  int control = accessible->navigate(FocusChild, 1, &acc);
1389  if (control == -1) {
1390  (*pvarID).vt = VT_EMPTY;
1391  return S_FALSE;
1392  }
1393  if (!acc || control == 0) {
1394  (*pvarID).vt = VT_I4;
1395  (*pvarID).lVal = control ? control : CHILDID_SELF;
1396  return S_OK;
1397  }
1398 
1399  QWindowsAccessible* wacc = new QWindowsAccessible(acc);
1400  IDispatch *iface = 0;
1401  wacc->QueryInterface(IID_IDispatch, (void**)&iface);
1402  if (iface) {
1403  (*pvarID).vt = VT_DISPATCH;
1404  (*pvarID).pdispVal = iface;
1405  return S_OK;
1406  } else {
1407  delete wacc;
1408  }
1409 
1410  (*pvarID).vt = VT_EMPTY;
1411  return S_FALSE;
1412 }
1413 
1414 HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accSelection(VARIANT *pvarChildren)
1415 {
1416  showDebug(__FUNCTION__, accessible);
1417  if (!accessible->isValid())
1418  return E_FAIL;
1419 
1420  int cc = accessible->childCount();
1421  QVector<int> sel(cc);
1422  int selIndex = 0;
1423  for (int i = 1; i <= cc; ++i) {
1424  QAccessibleInterface *child = 0;
1425  int i2 = accessible->navigate(Child, i, &child);
1426  bool isSelected = false;
1427  if (child) {
1428  isSelected = child->state(0) & Selected;
1429  delete child;
1430  child = 0;
1431  } else {
1432  isSelected = accessible->state(i2) & Selected;
1433  }
1434  if (isSelected)
1435  sel[selIndex++] = i;
1436  }
1437  sel.resize(selIndex);
1438  if (sel.isEmpty()) {
1439  (*pvarChildren).vt = VT_EMPTY;
1440  return S_FALSE;
1441  }
1442  if (sel.size() == 1) {
1443  (*pvarChildren).vt = VT_I4;
1444  (*pvarChildren).lVal = sel[0];
1445  return S_OK;
1446  }
1447  IEnumVARIANT *iface = new QWindowsEnumerate(sel);
1448  IUnknown *uiface;
1449  iface->QueryInterface(IID_IUnknown, (void**)&uiface);
1450  (*pvarChildren).vt = VT_UNKNOWN;
1451  (*pvarChildren).punkVal = uiface;
1452 
1453  return S_OK;
1454 }
1455 
1456 HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetWindow(HWND *phwnd)
1457 {
1458  *phwnd = 0;
1459  if (!accessible->isValid())
1460  return E_UNEXPECTED;
1461 
1462  QObject *o = accessible->object();
1463  if (!o || !o->isWidgetType())
1464  return E_FAIL;
1465 
1466  *phwnd = static_cast<QWidget*>(o)->effectiveWinId();
1467  return S_OK;
1468 }
1469 
1471 {
1472  return S_OK;
1473 }
1474 
1476 
1477 #endif // QT_NO_ACCESSIBILITY
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qstring.cpp:6448
T qobject_cast(QObject *object)
Definition: qobject.h:375
HRESULT STDMETHODCALLTYPE accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd)
static void updateAccessibility(QObject *, int who, Event reason)
Notifies accessibility clients about a change in object&#39;s accessibility information.
HRESULT STDMETHODCALLTYPE Invoke(long, const _GUID &, unsigned long, unsigned short, tagDISPPARAMS *, tagVARIANT *, tagEXCEPINFO *, unsigned int *)
The QGraphicsScene class provides a surface for managing a large number of 2D graphical items...
virtual int indexOfChild(const QAccessibleInterface *) const =0
Returns the 1-based index of the object child in this object&#39;s children list, or -1 if child is not a...
unsigned long WId
Definition: qwindowdefs.h:119
HRESULT STDMETHODCALLTYPE get_accSelection(VARIANT *pvarChildren)
ULONG STDMETHODCALLTYPE AddRef()
HRESULT STDMETHODCALLTYPE accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID)
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Returns the value for setting key.
Definition: qsettings.cpp:3460
ULONG STDMETHODCALLTYPE Release()
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
HRESULT STDMETHODCALLTYPE get_accDescription(VARIANT varID, BSTR *pszDescription)
HRESULT STDMETHODCALLTYPE put_accValue(VARIANT varChild, BSTR szValue)
HRESULT STDMETHODCALLTYPE accSelect(long flagsSelect, VARIANT varID)
HRESULT STDMETHODCALLTYPE get_accParent(IDispatch **ppdispParent)
Definition: quuid.h:52
static BSTR QStringToBSTR(const QString &str)
HRESULT STDMETHODCALLTYPE get_accRole(VARIANT varID, VARIANT *pvarRole)
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *)
HRESULT STDMETHODCALLTYPE get_accHelpTopic(BSTR *pszHelpFile, VARIANT varChild, long *pidTopic)
The QSettings class provides persistent platform-independent application settings.
Definition: qsettings.h:73
virtual State state(int child) const =0
Returns the current state of the object, or of the object&#39;s child if child is not 0...
Role
This enum defines the role of an accessible object.
Definition: qaccessible.h:188
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
static QWidget * activeWindow()
Returns the application top-level window that has the keyboard input focus, or 0 if no application wi...
The QGraphicsItem class is the base class for all graphical items in a QGraphicsScene.
Definition: qgraphicsitem.h:89
Icon icon
the message box&#39;s icon
Definition: qmessagebox.h:66
T1 first
Definition: qpair.h:65
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
QAccessibleInterface * accessible
The QMessageBox class provides a modal dialog for informing the user or for asking the user a questio...
Definition: qmessagebox.h:59
T2 second
Definition: qpair.h:66
QMap< int, QPair< QPointer< QObject >, int > > NotifyMap
QString toString() const
Returns the variant as a QString if the variant has type() String , Bool , ByteArray ...
Definition: qvariant.cpp:2270
ULONG STDMETHODCALLTYPE Release()
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
HRESULT STDMETHODCALLTYPE Next(unsigned long celt, VARIANT FAR *rgVar, unsigned long FAR *pCeltFetched)
#define QT_END_INCLUDE_NAMESPACE
This macro is equivalent to QT_BEGIN_NAMESPACE.
Definition: qglobal.h:92
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *)
long ASN1_INTEGER_get ASN1_INTEGER * a
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
AccessibleElement(int entryId, QAccessibleInterface *accessible)
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
The QString class provides a Unicode character string.
Definition: qstring.h:83
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
HRESULT STDMETHODCALLTYPE Reset()
static void cleanup()
void resize(int size)
Sets the size of the vector to size.
Definition: qvector.h:342
QVector< int > array
HRESULT STDMETHODCALLTYPE Skip(unsigned long celt)
QString text(QAccessible::Text t) const
QGraphicsObject * toGraphicsObject()
Return the graphics item cast to a QGraphicsObject, if the class is actually a graphics object...
Q_CORE_EXPORT void qDebug(const char *,...)
ULONG STDMETHODCALLTYPE AddRef()
QWindowsAccessible(QAccessibleInterface *a)
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
int access(const char *, int)
int size() const
Returns the number of characters in this string.
Definition: qstring.h:102
virtual int navigate(RelationFlag relation, int index, QAccessibleInterface **iface) const =0
Navigates from this object to an object that has a relationship relation to this object, and returns the respective object in target.
const QChar * unicode() const
Returns a &#39;\0&#39;-terminated Unicode representation of the string.
Definition: qstring.h:706
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
Event
This enum type defines accessible event types.
Definition: qaccessible.h:67
RelationFlag
This enum type defines bit flags that can be combined to indicate the relationship between two access...
Definition: qaccessible.h:268
IAccessible * qt_createWindowsAccessible(QAccessibleInterface *access)
#define Q_GLOBAL_STATIC(TYPE, NAME)
Declares a global static variable with the given type and name.
Definition: qglobal.h:1968
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
static int eventNum
HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode)
HRESULT STDMETHODCALLTYPE get_accHelp(VARIANT varID, BSTR *pszHelp)
HRESULT STDMETHODCALLTYPE GetWindow(HWND *phwnd)
HRESULT STDMETHODCALLTYPE get_accState(VARIANT varID, VARIANT *pvarState)
virtual ~QWindowsEnumerate()
static bool isActive()
Returns true if an accessibility implementation has been requested during the runtime of the applicat...
static QAccessibleInterface * queryAccessibleInterface(QObject *)
If a QAccessibleInterface implementation exists for the given object, this function returns a pointer...
HRESULT STDMETHODCALLTYPE get_accValue(VARIANT varID, BSTR *pszValue)
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition: qstring.h:505
virtual Role role(int child) const =0
Returns the role of the object, or of the object&#39;s child if child is not 0.
long HRESULT
bool isWidgetType() const
Returns true if the object is a widget; otherwise returns false.
Definition: qobject.h:146
QGraphicsItem * parentItem() const
Returns a pointer to this item&#39;s parent item.
HRESULT STDMETHODCALLTYPE GetIDsOfNames(const _GUID &, wchar_t **, unsigned int, unsigned long, long *)
QWindowsEnumerate(const QVector< int > &a)
void * resolve(const char *symbol)
static void setRootObject(QObject *)
Sets the root accessible object of this application to object.
virtual QString actionText(int action, Text t, int child) const =0
Returns the text property t of the action action supported by the object, or of the object&#39;s child if...
HRESULT STDMETHODCALLTYPE put_accName(VARIANT varChild, BSTR szName)
virtual bool doAction(int action, int child, const QVariantList &params=QVariantList())=0
Asks the object, or the object&#39;s child if child is not 0, to execute action using the parameters...
State
Definition: qaudio.h:59
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
The QAccessibleInterface class defines an interface that exposes information about accessible objects...
Definition: qaccessible.h:370
HRESULT STDMETHODCALLTYPE accDoDefaultAction(VARIANT varID)
HRESULT STDMETHODCALLTYPE get_accFocus(VARIANT *pvarID)
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
HRESULT STDMETHODCALLTYPE GetTypeInfo(unsigned int, unsigned long, ITypeInfo **)
Q_OUTOFLINE_TEMPLATE QPair< T1, T2 > qMakePair(const T1 &x, const T2 &y)
Definition: qpair.h:102
QList< QVariant > QVariantList
Definition: qvariant.h:443
virtual QString text(Text t, int child) const =0
Returns the value of the text property t of the object, or of the object&#39;s child if child is not 0...
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
QFactoryLoader * l
#define showDebug(f, iface)
WId internalWinId() const
Returns the window system identifier of the widget, or 0 if the widget is not created yet...
Definition: qwidget.h:244
quint16 index
#define QT_BEGIN_INCLUDE_NAMESPACE
This macro is equivalent to QT_END_NAMESPACE.
Definition: qglobal.h:91
virtual QRect rect(int child) const =0
Returns the geometry of the object, or of the object&#39;s child if child is not 0.
The QGraphicsView class provides a widget for displaying the contents of a QGraphicsScene.
Definition: qgraphicsview.h:64
HRESULT STDMETHODCALLTYPE get_accKeyboardShortcut(VARIANT varID, BSTR *pszKeyboardShortcut)
bool isEmpty() const
Returns true if the vector has size 0; otherwise returns false.
Definition: qvector.h:139
HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT **ppEnum)
HRESULT STDMETHODCALLTYPE get_accName(VARIANT varID, BSTR *pszName)
HRESULT STDMETHODCALLTYPE get_accDefaultAction(VARIANT varID, BSTR *pszDefaultAction)
HRESULT STDMETHODCALLTYPE get_accChildCount(long *pcountChildren)
Text
This enum specifies string information that an accessible object returns.
Definition: qaccessible.h:259
bool isValid() const
Returns true if the rectangle is valid, otherwise returns false.
Definition: qrect.h:237
HRESULT STDMETHODCALLTYPE GetTypeInfoCount(unsigned int *)
The QGraphicsObject class provides a base class for all graphics items that require signals...
QAccessibleInterface * iface
HRESULT STDMETHODCALLTYPE get_accChild(VARIANT varChildID, IDispatch **ppdispChild)
static QWidget * focusWidget()
Returns the application widget that has the keyboard input focus, or 0 if no widget in this applicati...
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
static UpdateHandler updateHandler
Definition: qaccessible.h:337
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
HRESULT STDMETHODCALLTYPE accHitTest(long xLeft, long yTop, VARIANT *pvarID)
static RootObjectHandler rootObjectHandler
Definition: qaccessible.h:338
The QMap class is a template class that provides a skip-list-based dictionary.
Definition: qdatastream.h:67
The QAccessible class provides enums and static functions relating to accessibility.
Definition: qaccessible.h:64
The QList class is a template class that provides lists.
Definition: qdatastream.h:62
const ushort * utf16() const
Returns the QString as a &#39;\0\&#39;-terminated array of unsigned shorts.
Definition: qstring.cpp:5290