Fix updateAccessibility for QGraphicsObjects
authorJan-Arve Sæther <jan-arve.saether@nokia.com>
Thu, 5 May 2011 14:19:16 +0000 (16:19 +0200)
committerJan-Arve Sæther <jan-arve.saether@nokia.com>
Tue, 10 May 2011 10:35:49 +0000 (12:35 +0200)
If updateAccessibility is called on a QGraphicsObject, walk up and find
the closest ancestor widget with a HWND.
(cherry picked from commit d4291591dfb6a7b1f5c7d00879e8162e84d9ab1b)

Reviewed-by: Frederik Gladhorn
(cherry picked from commit 96406a7dd609e75340f7b4a05726c60c197786b8)

src/gui/accessible/qaccessible_win.cpp

index 0e69a5e..98db529 100644 (file)
@@ -49,6 +49,9 @@
 #include "qsettings.h"
 #include <QtCore/qmap.h>
 #include <QtCore/qpair.h>
+#include <QtGui/qgraphicsitem.h>
+#include <QtGui/qgraphicsscene.h>
+#include <QtGui/qgraphicsview.h>
 
 #include <winuser.h>
 #if !defined(WINABLEAPI)
@@ -150,6 +153,106 @@ static const char *roleString(QAccessible::Role role)
    return roles[int(role)];
 }
 
+static const char *eventString(QAccessible::Event ev)
+{
+    static const char *events[] = {
+        "null",                                 // 0
+        "SoundPlayed"          /*= 0x0001*/,
+        "Alert"                /*= 0x0002*/,
+        "ForegroundChanged"    /*= 0x0003*/,
+        "MenuStart"            /*= 0x0004*/,
+        "MenuEnd"              /*= 0x0005*/,
+        "PopupMenuStart"       /*= 0x0006*/,
+        "PopupMenuEnd"         /*= 0x0007*/,
+        "ContextHelpStart"     /*= 0x000C*/,    // 8
+        "ContextHelpEnd"       /*= 0x000D*/,
+        "DragDropStart"        /*= 0x000E*/,
+        "DragDropEnd"          /*= 0x000F*/,
+        "DialogStart"          /*= 0x0010*/,
+        "DialogEnd"            /*= 0x0011*/,
+        "ScrollingStart"       /*= 0x0012*/,
+        "ScrollingEnd"         /*= 0x0013*/,
+        "MenuCommand"          /*= 0x0018*/,    // 16
+
+        // Values from IAccessible2
+        "ActionChanged"        /*= 0x0101*/,    // 17
+        "ActiveDescendantChanged",
+        "AttributeChanged",
+        "DocumentContentChanged",
+        "DocumentLoadComplete",
+        "DocumentLoadStopped",
+        "DocumentReload",
+        "HyperlinkEndIndexChanged",
+        "HyperlinkNumberOfAnchorsChanged",
+        "HyperlinkSelectedLinkChanged",
+        "HypertextLinkActivated",
+        "HypertextLinkSelected",
+        "HyperlinkStartIndexChanged",
+        "HypertextChanged",
+        "HypertextNLinksChanged",
+        "ObjectAttributeChanged",
+        "PageChanged",
+        "SectionChanged",
+        "TableCaptionChanged",
+        "TableColumnDescriptionChanged",
+        "TableColumnHeaderChanged",
+        "TableModelChanged",
+        "TableRowDescriptionChanged",
+        "TableRowHeaderChanged",
+        "TableSummaryChanged",
+        "TextAttributeChanged",
+        "TextCaretMoved",
+        // TextChanged, deprecated, use TextUpdated
+        //TextColumnChanged = TextCaretMoved + 2,
+        "TextInserted",
+        "TextRemoved",
+        "TextUpdated",
+        "TextSelectionChanged",
+        "VisibleDataChanged",  /*= 0x0101+32*/
+        "ObjectCreated"        /*= 0x8000*/,    // 49
+        "ObjectDestroyed"      /*= 0x8001*/,
+        "ObjectShow"           /*= 0x8002*/,
+        "ObjectHide"           /*= 0x8003*/,
+        "ObjectReorder"        /*= 0x8004*/,
+        "Focus"                /*= 0x8005*/,
+        "Selection"            /*= 0x8006*/,
+        "SelectionAdd"         /*= 0x8007*/,
+        "SelectionRemove"      /*= 0x8008*/,
+        "SelectionWithin"      /*= 0x8009*/,
+        "StateChanged"         /*= 0x800A*/,
+        "LocationChanged"      /*= 0x800B*/,
+        "NameChanged"          /*= 0x800C*/,
+        "DescriptionChanged"   /*= 0x800D*/,
+        "ValueChanged"         /*= 0x800E*/,
+        "ParentChanged"        /*= 0x800F*/,
+        "HelpChanged"          /*= 0x80A0*/,
+        "DefaultActionChanged" /*= 0x80B0*/,
+        "AcceleratorChanged"   /*= 0x80C0*/
+    };
+    int e = int(ev);
+    if (e <= 0x80c0) {
+        const int last = sizeof(events)/sizeof(char*) - 1;
+
+        if (e <= 0x07)
+            return events[e];
+        else if (e <= 0x13)
+            return events[e - 0x0c + 8];
+        else if (e == 0x18)
+            return events[16];
+        else if (e <= 0x0101 + 32)
+            return events[e - 0x101 + 17];
+        else if (e <= 0x800f)
+            return events[e - 0x8000 + 49];
+        else if (e == 0x80a0)
+            return events[last - 2];
+        else if (e == 0x80b0)
+            return events[last - 1];
+        else if (e == 0x80c0)
+            return events[last];
+    }
+    return "unknown";
+};
+
 void showDebug(const char* funcName, const QAccessibleInterface *iface)
 {
     qDebug() << "Role:" << roleString(iface->role(0)) 
@@ -266,9 +369,28 @@ void QAccessible::updateAccessibility(QObject *o, int who, Event reason)
             if (w->internalWinId())
                 break;
         }
-        p = p->parent();
+        if (QGraphicsObject *gfxObj = qobject_cast<QGraphicsObject*>(p)) {
+            QGraphicsItem *parentItem = gfxObj->parentItem();
+            if (parentItem) {
+                p = parentItem->toGraphicsObject();
+            } else {
+                QGraphicsView *view = 0;
+                if (QGraphicsScene *scene = gfxObj->scene()) {
+                    QWidget *fw = QApplication::focusWidget();
+                    const QList<QGraphicsView*> views = scene->views();
+                    for (int i = 0 ; i < views.count() && view != fw; ++i) {
+                        view = views.at(i);
+                    }
+                }
+                p = view;
+            }
+        } else {
+            p = p->parent();
+        }
+
     } while (p);
 
+    //qDebug() << "updateAccessibility(), hwnd:" << w << ", object:" << o << "," << eventString(reason);
     if (!w) {
         if (reason != QAccessible::ContextHelpStart &&
              reason != QAccessible::ContextHelpEnd)