]> git.saurik.com Git - wxWidgets.git/commitdiff
Some improvements to accessibility behaviour
authorJulian Smart <julian@anthemion.co.uk>
Tue, 18 Feb 2003 09:33:42 +0000 (09:33 +0000)
committerJulian Smart <julian@anthemion.co.uk>
Tue, 18 Feb 2003 09:33:42 +0000 (09:33 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@19241 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/access.h
src/common/wincmn.cpp
src/msw/ole/access.cpp

index 21faf9df3f67e2fea667e20744b5b0bf6b3ed183..7e06de9a1677e084eed41611306f31dee121952d 100644 (file)
@@ -25,6 +25,7 @@
 typedef enum
 {
     wxACC_FAIL,
+    wxACC_FALSE,
     wxACC_OK,
     wxACC_NOT_IMPLEMENTED,
     wxACC_NOT_SUPPORTED
index b701f7aa6df3fac1a58cb1eb450502c8209daa22..221d6dbf2fce6374f4efe9a2dc24915f3cdc300a 100644 (file)
@@ -2113,6 +2113,28 @@ wxAccStatus wxWindowAccessible::GetLocation(wxRect& rect, int elementId)
     if (!GetWindow())
         return wxACC_FAIL;
 
+    wxWindow* win = NULL;
+    if (elementId == 0)
+    {
+        win = GetWindow();
+    }
+    else
+    {
+        if (elementId <= (int) GetWindow()->GetChildren().GetCount())
+        {
+            win = (wxWindow*) GetWindow()->GetChildren().Nth(elementId-1)->GetData();
+        }
+        else
+            return wxACC_FAIL;
+    }
+    if (win)
+    {
+        rect = win->GetRect();
+        if (win->GetParent() && !win->IsKindOf(CLASSINFO(wxTopLevelWindow)))
+            rect.SetPosition(win->GetParent()->ClientToScreen(rect.GetPosition()));
+        return wxACC_OK;
+    }
+
     return wxACC_NOT_IMPLEMENTED;
 }
 
@@ -2124,6 +2146,86 @@ wxAccStatus wxWindowAccessible::Navigate(wxNavDir navDir, int fromId,
     if (!GetWindow())
         return wxACC_FAIL;
 
+    switch (navDir)
+    {
+    case wxNAVDIR_FIRSTCHILD:
+        {
+            if (GetWindow()->GetChildren().GetCount() == 0)
+                return wxACC_FALSE;
+            wxWindow* childWindow = (wxWindow*) GetWindow()->GetChildren().GetFirst()->GetData();
+            *toObject = childWindow->GetOrCreateAccessible();
+
+            return wxACC_OK;
+        }
+    case wxNAVDIR_LASTCHILD:
+        {
+            if (GetWindow()->GetChildren().GetCount() == 0)
+                return wxACC_FALSE;
+            wxWindow* childWindow = (wxWindow*) GetWindow()->GetChildren().GetLast()->GetData();
+            *toObject = childWindow->GetOrCreateAccessible();
+
+            return wxACC_OK;
+        }
+    case wxNAVDIR_RIGHT:
+    case wxNAVDIR_DOWN:
+    case wxNAVDIR_NEXT:
+        {
+            wxWindowList::Node *node = NULL;
+            if (fromId == 0)
+            {
+                // Can't navigate to sibling of this window
+                // if we're a top-level window.
+                if (!GetWindow()->GetParent())
+                    return wxACC_NOT_IMPLEMENTED;
+
+                node = GetWindow()->GetParent()->GetChildren().Find(GetWindow());
+            }
+            else
+            {
+                if (fromId <= (int) GetWindow()->GetChildren().GetCount())
+                    node = (wxWindowList::Node*) GetWindow()->GetChildren().Nth(fromId-1);
+            }
+
+            if (node && node->GetNext())
+            {
+                wxWindow* nextWindow = (wxWindow*) node->GetNext()->Data();
+                *toObject = nextWindow->GetOrCreateAccessible();
+                return wxACC_OK;
+            }
+            else
+                return wxACC_FALSE;
+        }
+    case wxNAVDIR_LEFT:
+    case wxNAVDIR_UP:
+    case wxNAVDIR_PREVIOUS:
+        {
+            wxWindowList::Node *node = NULL;
+            if (fromId == 0)
+            {
+                // Can't navigate to sibling of this window
+                // if we're a top-level window.
+                if (!GetWindow()->GetParent())
+                    return wxACC_NOT_IMPLEMENTED;
+
+                node = GetWindow()->GetParent()->GetChildren().Find(GetWindow());
+            }
+            else
+            {
+                if (fromId <= (int) GetWindow()->GetChildren().GetCount())
+                    node = (wxWindowList::Node*) GetWindow()->GetChildren().Nth(fromId-1);
+            }
+
+            if (node && node->GetPrevious())
+            {
+                wxWindow* previousWindow = (wxWindow*) node->GetPrevious()->Data();
+                *toObject = previousWindow->GetOrCreateAccessible();
+                return wxACC_OK;
+            }
+            else
+                return wxACC_FALSE;
+        }
+    }
+
     return wxACC_NOT_IMPLEMENTED;
 }
 
@@ -2190,7 +2292,7 @@ wxAccStatus wxWindowAccessible::GetParent(wxAccessible** parent)
         return wxACC_FAIL;
 
     wxWindow* parentWindow = GetWindow()->GetParent();
-    if (!parent)
+    if (!parentWindow)
     {
         *parent = NULL;
         return wxACC_OK;
index 7c1e16e3f192e254bf7376bb6f2a85f7be5d5a20..834751f4ee68945f0b89795d6e8a722ee62843a8 100644 (file)
@@ -326,6 +326,12 @@ public:
                         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, 
                         unsigned int *puArgErr );
 
+// Helpers
+
+    // Gets the standard IAccessible interface for the given child or object.
+    // Call Release if this is non-NULL.
+    IAccessible* GetChildStdAccessible(int id);
+
 private:
     wxAccessible *m_pAccessible;      // pointer to C++ class we belong to
 
@@ -359,6 +365,7 @@ wxIAccessible::wxIAccessible(wxAccessible *pAccessible)
 
 STDMETHODIMP wxIAccessible::accHitTest(long xLeft, long yLeft, VARIANT* pVarID)
 {
+    wxLogDebug("accHitTest");
     wxASSERT (m_pAccessible != NULL);
     if (!m_pAccessible)
         return E_FAIL;
@@ -396,11 +403,11 @@ STDMETHODIMP wxIAccessible::accHitTest(long xLeft, long yLeft, VARIANT* pVarID)
             if (!childIA)
                 return E_FAIL;
 
-               if (childIA->QueryInterface(IID_IDispatch, (LPVOID*) pVarID->pdispVal) != S_OK)
+               if (childIA->QueryInterface(IID_IDispatch, (LPVOID*) pVarID->pdispVal) != S_OK)
                    return E_FAIL;
             
             pVarID->vt = VT_DISPATCH;
-            pVarID->pdispVal->AddRef();
+//            pVarID->pdispVal->AddRef();
             return S_OK;
         }
     }
@@ -424,6 +431,7 @@ STDMETHODIMP wxIAccessible::accHitTest(long xLeft, long yLeft, VARIANT* pVarID)
 
 STDMETHODIMP wxIAccessible::accLocation ( long* pxLeft, long* pyTop, long* pcxWidth, long* pcyHeight, VARIANT varID)
 {
+    wxLogDebug("accLocation");
     wxASSERT (m_pAccessible != NULL);
     if (!m_pAccessible)
         return E_FAIL;
@@ -463,58 +471,89 @@ STDMETHODIMP wxIAccessible::accNavigate ( long navDir, VARIANT varStart, VARIANT
     wxASSERT (m_pAccessible != NULL);
     if (!m_pAccessible)
         return E_FAIL;
+    wxLogDebug(wxString(wxT("accNavigate for ")) + m_pAccessible->GetWindow()->GetClassInfo()->GetClassName());
 
-    if (varStart.vt != VT_I4)
+    if ((varStart.vt != VT_I4 && varStart.vt != VT_EMPTY) || varStart.vt < 0)
+    {
+        wxLogDebug("Invalid arg for accNavigate");
         return E_INVALIDARG;
+    }
     
     wxAccessible* elementObject = NULL;
     int elementId = 0;
     VariantInit(pVarEnd);
     wxNavDir navDirWX = wxNAVDIR_FIRSTCHILD;
 
+    wxString navStr;
+
     switch (navDir)
     {
     case NAVDIR_DOWN:
         navDirWX = wxNAVDIR_DOWN;
+        navStr = wxT("wxNAVDIR_DOWN");
         break;
 
     case NAVDIR_FIRSTCHILD:
         navDirWX = wxNAVDIR_FIRSTCHILD;
+        navStr = wxT("wxNAVDIR_FIRSTCHILD");
         break;
 
     case NAVDIR_LASTCHILD:
         navDirWX = wxNAVDIR_LASTCHILD;
+        navStr = wxT("wxNAVDIR_LASTCHILD");
         break;
 
     case NAVDIR_LEFT:
         navDirWX = wxNAVDIR_LEFT;
+        navStr = wxT("wxNAVDIR_LEFT");
         break;
 
     case NAVDIR_NEXT:
         navDirWX = wxNAVDIR_NEXT;
+        navStr = wxT("wxNAVDIR_NEXT");
         break;
 
     case NAVDIR_PREVIOUS:
         navDirWX = wxNAVDIR_PREVIOUS;
+        navStr = wxT("wxNAVDIR_PREVIOUS");
         break;
 
     case NAVDIR_RIGHT:
         navDirWX = wxNAVDIR_RIGHT;
+        navStr = wxT("wxNAVDIR_RIGHT");
         break;
 
     case NAVDIR_UP:
         navDirWX = wxNAVDIR_UP;
+        navStr = wxT("wxNAVDIR_UP");
         break;
+    default:
+        {
+            wxLogDebug(wxT("Unknown NAVDIR symbol"));
+            break;
+        }
     }
+    wxLogDebug(navStr);
     
     wxAccStatus status = m_pAccessible->Navigate(navDirWX, varStart.lVal, & elementId,
         & elementObject);
 
     if (status == wxACC_FAIL)
+    {
+        wxLogDebug("wxAccessible::Navigate failed");
         return E_FAIL;
+    }
+    
+    if (status == wxACC_FALSE)
+    {
+        wxLogDebug("wxAccessible::Navigate found no object in this direction");
+        return S_FALSE;
+    }
     
     if (status == wxACC_NOT_IMPLEMENTED)
     {
+        wxLogDebug("Navigate not implemented");
+
         // Use standard interface instead.
         IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd();
         if (!stdInterface)
@@ -526,30 +565,42 @@ STDMETHODIMP wxIAccessible::accNavigate ( long navDir, VARIANT varStart, VARIANT
     {
         if (elementObject)
         {
+            wxLogDebug("Getting wxIAccessible and calling QueryInterface for Navigate");
             wxIAccessible* objectIA = elementObject->GetIAccessible();
             if (!objectIA)
+            {
+                wxLogDebug("No wxIAccessible");
                 return E_FAIL;
+            }
 
-               if (objectIA->QueryInterface(IID_IDispatch, (LPVOID*) pVarEnd->pdispVal) != S_OK)
+               HRESULT hResult = objectIA->QueryInterface(IID_IDispatch, (LPVOID*) & pVarEnd->pdispVal);
+            if (hResult != S_OK)
+            {
+                wxLogDebug("QueryInterface failed");
                    return E_FAIL;
+            }
             
+            wxLogDebug("Called QueryInterface for Navigate");
             pVarEnd->vt = VT_DISPATCH;
-            pVarEnd->pdispVal->AddRef();
+//            pVarEnd->pdispVal->AddRef();
             return S_OK;
         }
         else if (elementId > 0)
         {
+            wxLogDebug("Returning element id from Navigate");
             pVarEnd->vt = VT_I4;
             pVarEnd->lVal = elementId;
             return S_OK;
         }
         else
         {
+            wxLogDebug("No object in accNavigate");
             pVarEnd->vt = VT_EMPTY;
             return S_FALSE;
         }
     }
 
+    wxLogDebug("Failing Navigate");
     return E_FAIL;
 }
 
@@ -558,12 +609,16 @@ STDMETHODIMP wxIAccessible::accNavigate ( long navDir, VARIANT varStart, VARIANT
     
 STDMETHODIMP wxIAccessible::get_accChild ( VARIANT varChildID, IDispatch** ppDispChild)
 {
+    wxLogDebug("get_accChild");
     wxASSERT (m_pAccessible != NULL);
     if (!m_pAccessible)
         return E_FAIL;
     
     if (varChildID.vt != VT_I4)
+    {
+        wxLogDebug("Invalid arg for get_accChild");
         return E_INVALIDARG;
+    }
 
     if (varChildID.lVal == CHILDID_SELF)
     {
@@ -576,7 +631,10 @@ STDMETHODIMP wxIAccessible::get_accChild ( VARIANT varChildID, IDispatch** ppDis
 
     wxAccStatus status = m_pAccessible->GetChild(varChildID.lVal, & child);
     if (status == wxACC_FAIL)
+    {
+        wxLogDebug("GetChild failed");
         return E_FAIL;
+    }
     
     if (status == wxACC_NOT_IMPLEMENTED)
     {
@@ -585,7 +643,10 @@ STDMETHODIMP wxIAccessible::get_accChild ( VARIANT varChildID, IDispatch** ppDis
         if (!stdInterface)
             return E_FAIL;
         else
+        {
+            wxLogDebug("Using standard interface for get_accChild");
             return stdInterface->get_accChild (varChildID, ppDispChild);
+        }
     }
     else
     {
@@ -596,13 +657,19 @@ STDMETHODIMP wxIAccessible::get_accChild ( VARIANT varChildID, IDispatch** ppDis
                 return E_FAIL;
 
                if (objectIA->QueryInterface(IID_IDispatch, (LPVOID*) ppDispChild) != S_OK)
+            {
+                wxLogDebug("QueryInterface failed in get_accChild");
                    return E_FAIL;
+            }
             
-            (*ppDispChild)->AddRef();
+//            (*ppDispChild)->AddRef();
             return S_OK;
         }
         else
+        {
+            wxLogDebug("Not an accessible object");
             return S_FALSE; // Indicates it's not an accessible object
+        }
     }
 
     return E_FAIL;
@@ -613,6 +680,7 @@ STDMETHODIMP wxIAccessible::get_accChild ( VARIANT varChildID, IDispatch** ppDis
     
 STDMETHODIMP wxIAccessible::get_accChildCount ( long* pCountChildren)
 {
+    wxLogDebug("get_accChildCount");
     wxASSERT (m_pAccessible != NULL);
     if (!m_pAccessible)
         return E_FAIL;
@@ -629,7 +697,14 @@ STDMETHODIMP wxIAccessible::get_accChildCount ( long* pCountChildren)
         if (!stdInterface)
             return E_FAIL;
         else
-            return stdInterface->get_accChildCount (pCountChildren);
+        {
+            wxLogDebug("Using standard interface for get_accChildCount");
+            HRESULT res = stdInterface->get_accChildCount (pCountChildren);
+            wxString str;
+            str.Printf(wxT("Number of children was %d"), (int) (*pCountChildren));
+            wxLogDebug(str);
+            return res;
+        }
     }
     else
     {
@@ -645,17 +720,23 @@ STDMETHODIMP wxIAccessible::get_accChildCount ( long* pCountChildren)
     
 STDMETHODIMP wxIAccessible::get_accParent ( IDispatch** ppDispParent)
 {
+    wxLogDebug("get_accParent");
     wxASSERT (m_pAccessible != NULL);
     if (!m_pAccessible)
         return E_FAIL;
     
     wxAccessible* parent = NULL;
     wxAccStatus status = m_pAccessible->GetParent(& parent);
+
     if (status == wxACC_FAIL)
         return E_FAIL;
-    
-    if (status == wxACC_NOT_IMPLEMENTED)
+
+    // It doesn't seem acceptable to return S_FALSE with a NULL
+    // ppDispParent, so if we have no wxWindows parent, we leave
+    // it to the standard interface.
+    if (status == wxACC_NOT_IMPLEMENTED || !parent)
     {
+        wxLogDebug("Using standard interface to get the parent.");
         // Use standard interface instead.
         IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd();
         if (!stdInterface)
@@ -671,10 +752,15 @@ STDMETHODIMP wxIAccessible::get_accParent ( IDispatch** ppDispParent)
             if (!objectIA)
                 return E_FAIL;
 
+            wxLogDebug("About to call QueryInterface");
                if (objectIA->QueryInterface(IID_IDispatch, (LPVOID*) ppDispParent) != S_OK)
+            {
+                wxLogDebug("Failed QueryInterface");
                    return E_FAIL;
+            }
             
-            (*ppDispParent)->AddRef();
+//            (*ppDispParent)->AddRef();
+            wxLogDebug("Returning S_OK for get_accParent");
             return S_OK;
 /*
             wxIAccessible* objectIA = parent->GetIAccessible();
@@ -687,8 +773,11 @@ STDMETHODIMP wxIAccessible::get_accParent ( IDispatch** ppDispParent)
         }
         else
         {
+            // This doesn't seem to be allowed, despite the documentation,
+            // so we handle it higher up by using the standard interface.
+            wxLogDebug("Returning NULL parent because there was none");
             *ppDispParent = NULL;
-            return S_OK;
+            return S_FALSE;
         }
     }
 
@@ -700,12 +789,16 @@ STDMETHODIMP wxIAccessible::get_accParent ( IDispatch** ppDispParent)
     
 STDMETHODIMP wxIAccessible::accDoDefaultAction(VARIANT varID)
 {
+    wxLogDebug("accDoDefaultAction");
     wxASSERT (m_pAccessible != NULL);
     if (!m_pAccessible)
         return E_FAIL;
     
     if (varID.vt != VT_I4)
+    {
+        wxLogDebug("Invalid arg for accDoDefaultAction");
         return E_INVALIDARG;
+    }
     
     wxAccStatus status = m_pAccessible->DoDefaultAction(varID.lVal);
     if (status == wxACC_FAIL)
@@ -731,12 +824,16 @@ STDMETHODIMP wxIAccessible::accDoDefaultAction(VARIANT varID)
     
 STDMETHODIMP wxIAccessible::get_accDefaultAction ( VARIANT varID, BSTR* pszDefaultAction)
 {
+    wxLogDebug("get_accDefaultAction");
     wxASSERT (m_pAccessible != NULL);
     if (!m_pAccessible)
         return E_FAIL;
     
     if (varID.vt != VT_I4)
+    {
+        wxLogDebug("Invalid arg for get_accDefaultAction");
         return E_INVALIDARG;
+    }
     
     wxString defaultAction;
     wxAccStatus status = m_pAccessible->GetDefaultAction(varID.lVal, & defaultAction);
@@ -777,12 +874,16 @@ STDMETHODIMP wxIAccessible::get_accDefaultAction ( VARIANT varID, BSTR* pszDefau
 
 STDMETHODIMP wxIAccessible::get_accDescription ( VARIANT varID, BSTR* pszDescription)
 {
+    wxLogDebug("get_accDescription");
     wxASSERT (m_pAccessible != NULL);
     if (!m_pAccessible)
         return E_FAIL;
     
     if (varID.vt != VT_I4)
+    {
+        wxLogDebug("Invalid arg for get_accDescription");
         return E_INVALIDARG;
+    }
     
     wxString description;
     wxAccStatus status = m_pAccessible->GetDescription(varID.lVal, & description);
@@ -820,12 +921,16 @@ STDMETHODIMP wxIAccessible::get_accDescription ( VARIANT varID, BSTR* pszDescrip
 
 STDMETHODIMP wxIAccessible::get_accHelp ( VARIANT varID, BSTR* pszHelp)
 {
+    wxLogDebug("get_accHelp");
     wxASSERT (m_pAccessible != NULL);
     if (!m_pAccessible)
         return E_FAIL;
     
     if (varID.vt != VT_I4)
+    {
+        wxLogDebug("Invalid arg for get_accHelp");
         return E_INVALIDARG;
+    }
     
     wxString helpString;
     wxAccStatus status = m_pAccessible->GetHelpText(varID.lVal, & helpString);
@@ -866,12 +971,16 @@ STDMETHODIMP wxIAccessible::get_accHelp ( VARIANT varID, BSTR* pszHelp)
         
 STDMETHODIMP wxIAccessible::get_accHelpTopic ( BSTR* pszHelpFile, VARIANT varChild, long* pidTopic)
 {
+    wxLogDebug("get_accHelpTopic");
     wxASSERT (m_pAccessible != NULL);
     if (!m_pAccessible)
         return E_FAIL;
     
     if (varChild.vt != VT_I4)
+    {
+        wxLogDebug("Invalid arg for get_accHelpTopic");
         return E_INVALIDARG;
+    }
     
     wxAccStatus status = wxACC_NOT_IMPLEMENTED;
     if (status == wxACC_FAIL)
@@ -895,6 +1004,7 @@ STDMETHODIMP wxIAccessible::get_accHelpTopic ( BSTR* pszHelpFile, VARIANT varChi
         
 STDMETHODIMP wxIAccessible::get_accKeyboardShortcut ( VARIANT varID, BSTR* pszKeyboardShortcut)
 {
+    wxLogDebug("get_accKeyboardShortcut");
     *pszKeyboardShortcut = NULL;
 
     wxASSERT (m_pAccessible != NULL);
@@ -902,7 +1012,10 @@ STDMETHODIMP wxIAccessible::get_accKeyboardShortcut ( VARIANT varID, BSTR* pszKe
         return E_FAIL;
     
     if (varID.vt != VT_I4)
+    {
+        wxLogDebug("Invalid arg for get_accKeyboardShortcut");
         return E_INVALIDARG;
+    }
     
     wxString keyboardShortcut;
     wxAccStatus status = m_pAccessible->GetHelpText(varID.lVal, & keyboardShortcut);
@@ -940,6 +1053,7 @@ STDMETHODIMP wxIAccessible::get_accKeyboardShortcut ( VARIANT varID, BSTR* pszKe
     
 STDMETHODIMP wxIAccessible::get_accName ( VARIANT varID, BSTR* pszName)
 {
+    wxLogDebug("get_accName");
     *pszName = NULL;
 
     wxASSERT (m_pAccessible != NULL);
@@ -947,7 +1061,10 @@ STDMETHODIMP wxIAccessible::get_accName ( VARIANT varID, BSTR* pszName)
         return E_FAIL;
 
     if (varID.vt != VT_I4)
+    {
+        wxLogDebug("Invalid arg for get_accName");
         return E_INVALIDARG;
+    }
     
     wxString name;
     
@@ -958,12 +1075,25 @@ STDMETHODIMP wxIAccessible::get_accName ( VARIANT varID, BSTR* pszName)
     
     if (status == wxACC_NOT_IMPLEMENTED)
     {
+#if 0
         // Use standard interface instead.
         IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd();
         if (!stdInterface)
             return E_FAIL;
         else
             return stdInterface->get_accName (varID, pszName);
+#endif
+        // Turn child reference into object reference.
+        IAccessible* stdInterface = GetChildStdAccessible(varID.lVal);
+        if (stdInterface)
+        {
+            varID.lVal = 0;
+            HRESULT hResult = stdInterface->get_accName(varID, pszName);
+            stdInterface->Release();
+            return hResult;
+        }
+        else
+            return E_FAIL;
     }
     else
     {
@@ -979,12 +1109,16 @@ STDMETHODIMP wxIAccessible::get_accName ( VARIANT varID, BSTR* pszName)
 
 STDMETHODIMP wxIAccessible::get_accRole ( VARIANT varID, VARIANT* pVarRole)
 {
+    wxLogDebug("get_accRole");
     wxASSERT (m_pAccessible != NULL);
     if (!m_pAccessible)
         return E_FAIL;
     
     if (varID.vt != VT_I4)
+    {
+        wxLogDebug("Invalid arg for get_accRole");
         return E_INVALIDARG;
+    }
     
     VariantInit(pVarRole);
 
@@ -1025,12 +1159,16 @@ STDMETHODIMP wxIAccessible::get_accRole ( VARIANT varID, VARIANT* pVarRole)
     
 STDMETHODIMP wxIAccessible::get_accState ( VARIANT varID, VARIANT* pVarState)
 {
+    wxLogDebug("get_accState");
     wxASSERT (m_pAccessible != NULL);
     if (!m_pAccessible)
         return E_FAIL;
     
     if (varID.vt != VT_I4)
+    {
+        wxLogDebug("Invalid arg for get_accState");
         return E_INVALIDARG;
+    }
 
     long wxstate = 0;
     
@@ -1062,12 +1200,16 @@ STDMETHODIMP wxIAccessible::get_accState ( VARIANT varID, VARIANT* pVarState)
 
 STDMETHODIMP wxIAccessible::get_accValue ( VARIANT varID, BSTR* pszValue)
 {
+    wxLogDebug("get_accValue");
     wxASSERT (m_pAccessible != NULL);
     if (!m_pAccessible)
         return E_FAIL;
     
     if (varID.vt != VT_I4)
+    {
+        wxLogDebug("Invalid arg for get_accValue");
         return E_INVALIDARG;
+    }
     
     wxString strValue;
     
@@ -1100,12 +1242,16 @@ STDMETHODIMP wxIAccessible::get_accValue ( VARIANT varID, BSTR* pszValue)
 
 STDMETHODIMP wxIAccessible::accSelect ( long flagsSelect, VARIANT varID )
 {
+    wxLogDebug("get_accSelect");
     wxASSERT (m_pAccessible != NULL);
     if (!m_pAccessible)
         return E_FAIL;
     
-    if (varID.vt != VT_I4)
+    if (varID.vt != VT_I4 && varID.vt != VT_EMPTY)
+    {
+        wxLogDebug("Invalid arg for accSelect");
         return E_INVALIDARG;
+    }
     
     wxAccSelectionFlags wxsel = wxConvertFromWindowsSelFlag(flagsSelect);
 
@@ -1133,6 +1279,7 @@ STDMETHODIMP wxIAccessible::accSelect ( long flagsSelect, VARIANT varID )
         
 STDMETHODIMP wxIAccessible::get_accFocus ( VARIANT* pVarID)
 {
+    wxLogDebug("get_accFocus");
     wxASSERT (m_pAccessible != NULL);
     if (!m_pAccessible)
         return E_FAIL;
@@ -1160,19 +1307,18 @@ STDMETHODIMP wxIAccessible::get_accFocus ( VARIANT* pVarID)
         {
             pVarID->vt = VT_I4;
             pVarID->lVal = CHILDID_SELF;
-            return S_OK;
-        }
+            return S_OK;        }
         else
         {
             wxIAccessible* childIA = childObject->GetIAccessible();
             if (!childIA)
                 return E_FAIL;
 
-               if (childIA->QueryInterface(IID_IDispatch, (LPVOID*) pVarID->pdispVal) != S_OK)
+               if (childIA->QueryInterface(IID_IDispatch, (LPVOID*) pVarID->pdispVal) != S_OK)
                    return E_FAIL;
             
             pVarID->vt = VT_DISPATCH;
-            pVarID->pdispVal->AddRef();
+//            pVarID->pdispVal->AddRef();
             return S_OK;
         }
     }
@@ -1196,6 +1342,7 @@ STDMETHODIMP wxIAccessible::get_accFocus ( VARIANT* pVarID)
         
 STDMETHODIMP wxIAccessible::get_accSelection ( VARIANT * pVarChildren)
 {
+    wxLogDebug("get_accSelection");
     wxASSERT (m_pAccessible != NULL);
     if (!m_pAccessible)
         return E_FAIL;
@@ -1232,11 +1379,11 @@ STDMETHODIMP wxIAccessible::get_accSelection ( VARIANT * pVarChildren)
             if (!childIA)
                 return E_FAIL;
 
-               if (childIA->QueryInterface(IID_IDispatch, (LPVOID*) pVarChildren->pdispVal) != S_OK)
+               if (childIA->QueryInterface(IID_IDispatch, (LPVOID*) pVarChildren->pdispVal) != S_OK)
                    return E_FAIL;
             
             pVarChildren->vt = VT_DISPATCH;
-            pVarChildren->pdispVal->AddRef();
+//            pVarChildren->pdispVal->AddRef();
 
             return S_OK;
         }
@@ -1291,6 +1438,85 @@ STDMETHODIMP wxIAccessible::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
     return E_NOTIMPL;
 }
 
+// Gets the IAccessible interface for the given child or object.
+// Call Release if this is non-NULL.
+IAccessible* wxIAccessible::GetChildStdAccessible(int id)
+{
+    if (id == 0)
+    {
+        IAccessible* obj = (IAccessible*)m_pAccessible->GetIAccessibleStd();
+
+        obj->AddRef();
+        return obj;
+    }
+    else
+    {
+        VARIANT var;
+        VariantInit(& var);
+        var.vt = VT_I4;
+        var.lVal = id;
+        IDispatch* pDispatch = NULL;
+        if (S_OK == get_accChild ( var, & pDispatch))
+        {
+            IAccessible* childAccessible = NULL;
+            if (pDispatch->QueryInterface(IID_IAccessible, (LPVOID*) & childAccessible) == S_OK)
+            {
+                pDispatch->Release();
+                wxIAccessible* c = (wxIAccessible*) childAccessible;
+                IAccessible* stdChildAccessible = (IAccessible*) c->m_pAccessible->GetIAccessibleStd();
+                stdChildAccessible->AddRef();
+                childAccessible->Release();
+                return stdChildAccessible;
+            }
+            else
+            {
+                pDispatch->Release();
+            }                                    
+        }
+    }
+
+#if 0
+    {
+        // Loop until we find the right id
+        long nChildren = 0;
+        this->get_accChildCount(& nChildren);
+
+        int i;
+        for (i = 0; i < nChildren; i++)
+        {
+            long obtained = 0;
+            VARIANT var;
+            VariantInit(& var);
+            var.vt = VT_I4;
+            if (S_OK == AccessibleChildren(this, i, 1, & var, &obtained))
+            {
+                if (var.lVal == id)
+                {
+                    VariantInit(& var);
+                    var.vt = VT_DISPATCH;
+                    if (S_OK == AccessibleChildren(this, i, 1, & var, &obtained))
+                    {
+                        IAccessible* childAccessible = NULL;
+                        if (var.pdispVal->QueryInterface(IID_IAccessible, (LPVOID*) & childAccessible) == S_OK)
+                        {
+                            var.pdispVal->Release();
+                            return childAccessible;
+                        }
+                        else
+                        {
+                            var.pdispVal->Release();
+                        }                        
+                    }
+                }
+                break;
+            }
+        }
+    }
+#endif
+    return NULL;
+}
+
+
 // ----------------------------------------------------------------------------
 // wxAccessible implementation
 // ----------------------------------------------------------------------------