From kde-accessibility Thu Nov 28 13:43:00 2002 From: "Volker Hilsheimer" Date: Thu, 28 Nov 2002 13:43:00 +0000 To: kde-accessibility Subject: Re: [Kde-accessibility] understanding the whole picture X-MARC-Message: https://marc.info/?l=kde-accessibility&m=103849116623673 MIME-Version: 1 Content-Type: multipart/mixed; boundary="------=_NextPart_000_0192_01C296EC.72F8C730" This is a multi-part message in MIME format. ------=_NextPart_000_0192_01C296EC.72F8C730 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit > > So, we should put that code somewhere (still don't know where) but my main > > question is that we'll need a AtkObject *QWidget::getAccessible() function > > (or AtkObject *QObject::getAccessible() function), right ? > > If you look closely at the AtkImplementor interface you will see that > any GObject type/instance can implement accessibility; in such cases you > will need to create appropriate AtkObjectFactories for the type. > > > That stats that QWidget or QObject should understand about AtkObject (as > > GtkWidget does), right ? well, that's not going to happen :\ > > No, this is not a necessary conclusion. What you need to do is subclass > AtkObject (create a KatObject or something that derives from AtkObject), > and then provide new implementations of all the virtual methods that > need to be changed for KDE, for instance those that assume that the > backing objects are GObjects). Then you need to provide implementations > for some of the basic ATK utility methods (for instance as is done in > gailutil.c for GAIL-based accessibility) for getting the "root > accessible" of an application/process. Your widgets don't need to know > anything about this, but they need to provide enough information for you > to implement all the appropriate Atk methods on their behalf. > > Note that ATK has a number of queryable interfaces and UI > objects/instances should implement only those interfaces that make sense > for them; The ATK docs contain definitions of what the various > interfaces are intended to do. > > > Should we then, get a QAccessibleObject object and make katk 'cast' it to an > > AtkObject ? > > No, that's not likely to work (at least not with anything like a true > 'cast'). And it's not necessary for you to have a special > QAccessibleObject type at all. > > best regards, > > > -Bill > QAccessibleInterface and friends are already a wrapper around QObject/QWidget, and neither QObject nor QWidget know anything about it. ONLY the factory inside QAccessible::queryAccessibleObject() knows about which factory can create a QAccessibleInterface implementation for which class. The QAccessibleInterface implementation inside the plugin of course knows everything about the QObject/QWidget. Another class, QWindowsAccessible, implements the MSAA interface IAccessible (which makes it a COM object), and has a QAccessibleInterface as a member. The COM RPC server then calls the IAccessible API that QWindowsAccessible implements, and QWindowsAccessible delegates the calls to it's QAccessibleInterface member. Since the QAccessibleInterface had been designed with IAccessible in mind it's fairly trivial to do that. I've attached the qaccessible_win.cpp file so you can get an idea about what's going on. It's not documented, but should be easy enough to understand. The global function qt_createWindowsAccessible is the one that QApplication calls when it receives a WM_GETOBJECT message (for completeness, here's the respective part of the window procedure: case WM_GETOBJECT: { // Ignoring all requests while starting up if ( qApp->startingUp() || !qApp->loopLevel() || lParam != OBJID_CLIENT ) { result = FALSE; break; } typedef LRESULT (WINAPI *PtrLresultFromObject)(REFIID, WPARAM, LPUNKNOWN ); static PtrLresultFromObject ptrLresultFromObject = 0; static bool oleaccChecked = FALSE; if ( !oleaccChecked ) { oleaccChecked = TRUE; ptrLresultFromObject = (PtrLresultFromObject)QLibrary::resolve( "oleacc.dll", "LresultFromObject" ); } if ( ptrLresultFromObject ) { QAccessibleInterface *acc = 0; QAccessible::queryAccessibleInterface( widget, &acc ); if ( !acc ) { result = FALSE; break; } QCustomEvent e( QEvent::Accessibility, acc ); QApplication::sendEvent( widget, &e ); // and get an instance of the IAccessibile implementation IAccessible *iface = qt_createWindowsAccessible( acc ); acc->release(); LRESULT res = ptrLresultFromObject( IID_IAccessible, wParam, iface ); // ref == 2 iface->Release(); // the client will release the object again, and then it will destroy itself if ( res > 0 ) RETURN(res); } } result = FALSE; break; LresultFromObject is some magic function that associates a unsigned long with a IAccessible* or something, so that the ulong return value of the SendMessage() call is usable for the accessibility client, or at least that's what I guess). A UNIX counterpart for QWindowsAccessible, and of above message handler is what is missing. The central questions for us (Trolltech) are - what is missing from our interfaces? All we implement right now with our accessibility objects is the QAccessibleInterface class - obviously, we need more interfaces to provide a reasonable mapping between our objects and ATK or AT-SPI. Which interfaces are those? Since we have no know how about the requirements we will have to have a thorough look at ATK, and work with the feedback we receive from here. - how does the accessibility infrastructure communicate with the "server" application? How to implement the RPC to get and call the QAccessibleInterface implementations? How to implement the notification? DCOP seems like the natural way to go here, or at least like a smallest common denominator that can easily be bridged to other RPC technologies. - How to bridge QAccessibleInterface (and similar interfaces extending the API, e.g. QAccessibleRelationInterface or whatnot) to "something" the RPC infrastructure can use? Once we know all that we can probably provide an implementation of qaccessible_unix.cpp. For KDE, it is probably the easiest to work directly on QAccessibleInterface (or a thin wrapper around it that DCOP can work on), but that won't handle other platforms without extra work (but then it will be hardly possible for Qt applications to be accessible through all infrastructures on all platforms). -- Volker ------=_NextPart_000_0192_01C296EC.72F8C730 Content-Type: application/octet-stream; name="qaccessible_win.cpp" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="qaccessible_win.cpp" /************************************************************************= **** ** $Id$ ** ** Implementation of QAccessible class for Win32 ** ** Copyright (C) 2000-2001 Trolltech AS. All rights reserved. ** ** This file is part of the kernel module of the Qt GUI Toolkit. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional = Edition ** licenses for Windows may use this file in accordance with the Qt = Commercial ** License Agreement provided with the Software. ** ** This file is not available for use under any other license without ** express written permission from the copyright holder. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING = THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR = PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email = sales@trolltech.com for ** information about Qt Commercial License Agreements. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "qaccessible.h" #if defined(QT_ACCESSIBILITY_SUPPORT) #include "qapplication.h" #include "qt_windows.h" #include "qwidget.h" #include "qobjectlist.h" #include "qmessagebox.h" // ### dependency #include "qlibrary.h" #include #include #ifndef Q_CC_BOR #include #endif void QAccessible::updateAccessibility( QObject *o, int who, Event reason = ) { Q_ASSERT(o); QString soundName; switch ( reason ) { case PopupMenuStart: soundName =3D "MenuPopup"; break; case MenuCommand: soundName =3D "MenuCommand"; break; case Alert: if ( o->inherits( "QMessageBox" ) ) { QMessageBox *mb =3D (QMessageBox*)o; switch ( mb->icon() ) { case QMessageBox::Warning: soundName =3D "SystemExclamation"; break; case QMessageBox::Critical: soundName =3D "SystemHand"; break; case QMessageBox::Information: soundName =3D "SystemAsterisk"; break; default: break; } } else { soundName =3D "SystemAsterisk"; } break; default: break; } if ( !!soundName ) { #if defined(UNICODE) if ( qWinVersion() & Qt::WV_NT_based ) PlaySoundW( (TCHAR*)qt_winTchar( soundName, TRUE ), NULL, SND_ALIAS = | SND_ASYNC | SND_NODEFAULT | SND_NOWAIT ); else #endif PlaySoundA( soundName.local8Bit(), NULL, SND_ALIAS | SND_ASYNC | = SND_NODEFAULT | SND_NOWAIT ); } typedef void (WINAPI *PtrNotifyWinEvent)(DWORD, HWND, LONG, LONG ); =20 static PtrNotifyWinEvent ptrNotifyWinEvent =3D 0; static bool resolvedNWE =3D FALSE; if ( !resolvedNWE ) { resolvedNWE =3D TRUE; ptrNotifyWinEvent =3D (PtrNotifyWinEvent)QLibrary::resolve( "user32", = "NotifyWinEvent" ); } if ( !ptrNotifyWinEvent ) return; // An event has to be associated with a window,=20 // so find the first parent that is a widget. QWidget *w =3D 0; if ( o->isWidgetType() ) { w =3D (QWidget*)o; } else { QObject *p =3D o; while ( ( p =3D p->parent() ) !=3D 0 ) { if ( p->isWidgetType() ) { w =3D (QWidget*)p; break; } } } if ( !w ) { if ( reason !=3D QAccessible::ContextHelpStart &&=20 reason !=3D QAccessible::ContextHelpEnd ) w =3D qApp->focusWidget(); if ( !w ) { w =3D qApp->activeWindow(); if ( !w ) { w =3D qApp->mainWidget(); if ( !w ) return; } } } if ( reason !=3D MenuCommand ) // MenuCommand is faked ptrNotifyWinEvent( reason, w->winId(), OBJID_CLIENT, who ); } class QWindowsEnumerate : public IEnumVARIANT { public: QWindowsEnumerate( const QMemArray &a ) : ref( 0 ), current( 0 ),array( a ) { } HRESULT STDMETHODCALLTYPE QueryInterface( REFIID, LPVOID * ); ULONG STDMETHODCALLTYPE AddRef(); ULONG STDMETHODCALLTYPE Release(); HRESULT STDMETHODCALLTYPE Clone( IEnumVARIANT **ppEnum ); HRESULT STDMETHODCALLTYPE Next( unsigned long celt, VARIANT FAR* = rgVar, unsigned long FAR* pCeltFetched ); HRESULT STDMETHODCALLTYPE Reset(); HRESULT STDMETHODCALLTYPE Skip( unsigned long celt ); private: ULONG ref; ULONG current; QMemArray array; }; HRESULT STDMETHODCALLTYPE QWindowsEnumerate::QueryInterface( REFIID id, = LPVOID *iface ) { *iface =3D 0; if ( id =3D=3D IID_IUnknown ) *iface =3D (IUnknown*)this; else if ( id =3D=3D IID_IEnumVARIANT ) *iface =3D (IEnumVARIANT*)this; if ( *iface ) { AddRef(); return S_OK; } return E_NOINTERFACE; } ULONG STDMETHODCALLTYPE QWindowsEnumerate::AddRef() { return ++ref; } ULONG STDMETHODCALLTYPE QWindowsEnumerate::Release() { if ( !--ref ) { delete this; return 0; } return ref; } HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Clone( IEnumVARIANT = **ppEnum ) { QWindowsEnumerate *penum =3D NULL; *ppEnum =3D NULL; penum =3D new QWindowsEnumerate( array ); if ( !penum ) return E_OUTOFMEMORY; penum->current =3D current; penum->array =3D array; penum->AddRef(); *ppEnum =3D penum; return S_OK; } HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Next( unsigned long celt, = VARIANT FAR* rgVar, unsigned long FAR* pCeltFetched ) { if ( pCeltFetched !=3D NULL ) *pCeltFetched =3D 0; ULONG l; for ( l =3D 0; l < celt; l++ ) { VariantInit( &rgVar[l] ); if ( (current+1) > array.size() ) { *pCeltFetched =3D l; return S_FALSE; } rgVar[l].vt =3D VT_I4; rgVar[l].lVal =3D array[(int)current]; ++current; } *pCeltFetched =3D l; return S_OK; } HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Reset() { current =3D 0; return S_OK; } HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Skip( unsigned long celt ) { current +=3D celt; if ( current > array.size() ) { current =3D array.size(); return S_FALSE; } return S_OK; } /* */ class QWindowsAccessible : public IAccessible, QAccessible { public: QWindowsAccessible( QAccessibleInterface *a ) : ref( 0 ), accessible( a ) { accessible->addRef(); } ~QWindowsAccessible() { accessible->release(); } HRESULT STDMETHODCALLTYPE QueryInterface( REFIID, LPVOID * ); ULONG STDMETHODCALLTYPE AddRef(); ULONG STDMETHODCALLTYPE Release(); HRESULT STDMETHODCALLTYPE GetTypeInfoCount( unsigned int * ); HRESULT STDMETHODCALLTYPE GetTypeInfo( unsigned int, unsigned long, = ITypeInfo ** ); HRESULT STDMETHODCALLTYPE GetIDsOfNames( const _GUID &, wchar_t **, = unsigned int, unsigned long, long * ); HRESULT STDMETHODCALLTYPE Invoke( long, const _GUID &, unsigned = long, unsigned short, tagDISPPARAMS *, tagVARIANT *, tagEXCEPINFO *, = unsigned int * ); HRESULT STDMETHODCALLTYPE accHitTest( long xLeft, long yTop, VARIANT = *pvarID ); HRESULT STDMETHODCALLTYPE accLocation( long *pxLeft, long *pyTop, = long *pcxWidth, long *pcyHeight, VARIANT varID ); HRESULT STDMETHODCALLTYPE accNavigate( long navDir, VARIANT = varStart, VARIANT *pvarEnd ); HRESULT STDMETHODCALLTYPE get_accChild( VARIANT varChildID, = IDispatch** ppdispChild ); HRESULT STDMETHODCALLTYPE get_accChildCount( long* pcountChildren ); HRESULT STDMETHODCALLTYPE get_accParent( IDispatch** ppdispParent ); HRESULT STDMETHODCALLTYPE accDoDefaultAction( VARIANT varID ); HRESULT STDMETHODCALLTYPE get_accDefaultAction( VARIANT varID, BSTR* = pszDefaultAction ); HRESULT STDMETHODCALLTYPE get_accDescription( VARIANT varID, BSTR* = pszDescription ); HRESULT STDMETHODCALLTYPE get_accHelp( VARIANT varID, BSTR *pszHelp = ); HRESULT STDMETHODCALLTYPE get_accHelpTopic( BSTR *pszHelpFile, = VARIANT varChild, long *pidTopic ); HRESULT STDMETHODCALLTYPE get_accKeyboardShortcut( VARIANT varID, = BSTR *pszKeyboardShortcut ); HRESULT STDMETHODCALLTYPE get_accName( VARIANT varID, BSTR* pszName = ); HRESULT STDMETHODCALLTYPE put_accName( VARIANT varChild, BSTR szName = ); HRESULT STDMETHODCALLTYPE get_accRole( VARIANT varID, VARIANT = *pvarRole ); HRESULT STDMETHODCALLTYPE get_accState( VARIANT varID, VARIANT = *pvarState ); HRESULT STDMETHODCALLTYPE get_accValue( VARIANT varID, BSTR* = pszValue ); HRESULT STDMETHODCALLTYPE put_accValue( VARIANT varChild, BSTR = szValue ); HRESULT STDMETHODCALLTYPE accSelect( long flagsSelect, VARIANT varID = ); HRESULT STDMETHODCALLTYPE get_accFocus( VARIANT *pvarID ); HRESULT STDMETHODCALLTYPE get_accSelection( VARIANT *pvarChildren ); private: ULONG ref; QAccessibleInterface *accessible; }; static inline BSTR QStringToBSTR( const QString &str ) { BSTR bstrVal; int wlen =3D str.length(); bstrVal =3D SysAllocStringByteLen( 0, wlen*2 ); memcpy( bstrVal, str.unicode(), sizeof(QChar)*(wlen) ); bstrVal[wlen] =3D 0; return bstrVal; } /* */ IAccessible *qt_createWindowsAccessible( QAccessibleInterface *access ) { QWindowsAccessible *acc =3D new QWindowsAccessible( access ); IAccessible *iface; acc->QueryInterface( IID_IAccessible, (void**)&iface ); return iface; } /* IUnknown */ HRESULT STDMETHODCALLTYPE QWindowsAccessible::QueryInterface( REFIID id, = LPVOID *iface ) { *iface =3D 0; if ( id =3D=3D IID_IUnknown ) *iface =3D (IUnknown*)this; else if ( id =3D=3D IID_IDispatch ) *iface =3D (IDispatch*)this; else if ( id =3D=3D IID_IAccessible ) *iface =3D (IAccessible*)this; if ( *iface ) { AddRef(); return S_OK; } return E_NOINTERFACE; } ULONG STDMETHODCALLTYPE QWindowsAccessible::AddRef() { return ++ref; } ULONG STDMETHODCALLTYPE QWindowsAccessible::Release() { if ( !--ref ) { delete this; return 0; } return ref; } /* IDispatch */ HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetTypeInfoCount( unsigned = int * pctinfo) { // We don't use a type library *pctinfo =3D 0; return S_OK; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetTypeInfo( unsigned int, = unsigned long, ITypeInfo **pptinfo ) { // We don't use a type library *pptinfo =3D NULL; return S_OK; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetIDsOfNames( const _GUID = &, wchar_t **rgszNames, unsigned int, unsigned long, long *rgdispid ) { #ifndef Q_CC_BOR // PROPERTIES: Hierarchical if ( _bstr_t(rgszNames[0]) =3D=3D _bstr_t(L"accParent") )=20 rgdispid[0] =3D DISPID_ACC_PARENT; else if( _bstr_t(rgszNames[0]) =3D=3D _bstr_t(L"accChildCount") )=20 rgdispid[0] =3D DISPID_ACC_CHILDCOUNT; else if( _bstr_t(rgszNames[0]) =3D=3D _bstr_t(L"accChild") )=20 rgdispid[0] =3D DISPID_ACC_CHILD; // PROPERTIES: Descriptional else if( _bstr_t(rgszNames[0]) =3D=3D _bstr_t(L"accName(") )=20 rgdispid[0] =3D DISPID_ACC_NAME; else if( _bstr_t(rgszNames[0]) =3D=3D _bstr_t(L"accValue") )=20 rgdispid[0] =3D DISPID_ACC_VALUE; else if( _bstr_t(rgszNames[0]) =3D=3D _bstr_t(L"accDescription") )=20 rgdispid[0] =3D DISPID_ACC_DESCRIPTION; else if( _bstr_t(rgszNames[0]) =3D=3D _bstr_t(L"accRole") )=20 rgdispid[0] =3D DISPID_ACC_ROLE; else if( _bstr_t(rgszNames[0]) =3D=3D _bstr_t(L"accState") )=20 rgdispid[0] =3D DISPID_ACC_STATE; else if( _bstr_t(rgszNames[0]) =3D=3D _bstr_t(L"accHelp") )=20 rgdispid[0] =3D DISPID_ACC_HELP; else if( _bstr_t(rgszNames[0]) =3D=3D _bstr_t(L"accHelpTopic") )=20 rgdispid[0] =3D DISPID_ACC_HELPTOPIC; else if( _bstr_t(rgszNames[0]) =3D=3D = _bstr_t(L"accKeyboardShortcut") )=20 rgdispid[0] =3D DISPID_ACC_KEYBOARDSHORTCUT; else if( _bstr_t(rgszNames[0]) =3D=3D _bstr_t(L"accFocus") )=20 rgdispid[0] =3D DISPID_ACC_FOCUS; else if( _bstr_t(rgszNames[0]) =3D=3D _bstr_t(L"accSelection") )=20 rgdispid[0] =3D DISPID_ACC_SELECTION; else if( _bstr_t(rgszNames[0]) =3D=3D _bstr_t(L"accDefaultAction") ) = rgdispid[0] =3D DISPID_ACC_DEFAULTACTION; // METHODS else if( _bstr_t(rgszNames[0]) =3D=3D _bstr_t(L"accSelect") )=20 rgdispid[0] =3D DISPID_ACC_SELECT; else if( _bstr_t(rgszNames[0]) =3D=3D _bstr_t(L"accLocation") )=20 rgdispid[0] =3D DISPID_ACC_LOCATION; else if( _bstr_t(rgszNames[0]) =3D=3D _bstr_t(L"accNavigate") )=20 rgdispid[0] =3D DISPID_ACC_NAVIGATE; else if( _bstr_t(rgszNames[0]) =3D=3D _bstr_t(L"accHitTest") )=20 rgdispid[0] =3D DISPID_ACC_HITTEST; else if( _bstr_t(rgszNames[0]) =3D=3D _bstr_t(L"accDoDefaultAction") = )=20 rgdispid[0] =3D DISPID_ACC_DODEFAULTACTION; else=20 return DISP_E_UNKNOWNINTERFACE; return S_OK; #else Q_UNUSED( rgszNames ); Q_UNUSED( rgdispid ); return DISP_E_MEMBERNOTFOUND; #endif } HRESULT STDMETHODCALLTYPE QWindowsAccessible::Invoke( long dispIdMember, = const _GUID &, unsigned long, unsigned short wFlags, tagDISPPARAMS = *pDispParams, tagVARIANT *pVarResult, tagEXCEPINFO *, unsigned int * ) {=20 HRESULT hr =3D DISP_E_MEMBERNOTFOUND; switch( dispIdMember ) { case DISPID_ACC_PARENT: if ( wFlags =3D=3D DISPATCH_PROPERTYGET ) { if ( pVarResult =3D=3D NULL ) return E_INVALIDARG; hr =3D get_accParent( &pVarResult->pdispVal ); } else { hr =3D DISP_E_MEMBERNOTFOUND; } break; case DISPID_ACC_CHILDCOUNT: if ( wFlags =3D=3D DISPATCH_PROPERTYGET ) { if ( pVarResult =3D=3D NULL ) return E_INVALIDARG; hr =3D get_accChildCount( &pVarResult->lVal ); } else { hr =3D DISP_E_MEMBERNOTFOUND; } break; =09 case DISPID_ACC_CHILD: if ( wFlags =3D=3D DISPATCH_PROPERTYGET ) hr =3D get_accChild( pDispParams->rgvarg[0], &pVarResult->pdispVal ); else hr =3D DISP_E_MEMBERNOTFOUND; break; case DISPID_ACC_NAME: if ( wFlags =3D=3D DISPATCH_PROPERTYGET ) hr =3D get_accName( pDispParams->rgvarg[0], &pVarResult->bstrVal ); else if ( wFlags =3D=3D DISPATCH_PROPERTYPUT ) hr =3D put_accName( pDispParams->rgvarg[0], pVarResult->bstrVal ); else hr =3D DISP_E_MEMBERNOTFOUND; break; case DISPID_ACC_VALUE: if ( wFlags =3D=3D DISPATCH_PROPERTYGET ) hr =3D get_accValue( pDispParams->rgvarg[0], &pVarResult->bstrVal ); else if ( wFlags =3D=3D DISPATCH_PROPERTYPUT ) hr =3D put_accValue( pDispParams->rgvarg[0], pVarResult->bstrVal ); else hr =3D DISP_E_MEMBERNOTFOUND; break; case DISPID_ACC_DESCRIPTION: if ( wFlags =3D=3D DISPATCH_PROPERTYGET ) hr =3D get_accDescription( pDispParams->rgvarg[0], = &pVarResult->bstrVal ); else hr =3D DISP_E_MEMBERNOTFOUND; break; case DISPID_ACC_ROLE: if ( wFlags =3D=3D DISPATCH_PROPERTYGET ) hr =3D get_accRole( pDispParams->rgvarg[0], pVarResult ); else hr =3D DISP_E_MEMBERNOTFOUND; break; case DISPID_ACC_STATE: if ( wFlags =3D=3D DISPATCH_PROPERTYGET ) hr =3D get_accState( pDispParams->rgvarg[0], pVarResult ); else hr =3D DISP_E_MEMBERNOTFOUND; break; case DISPID_ACC_HELP: if ( wFlags =3D=3D DISPATCH_PROPERTYGET ) hr =3D get_accHelp( pDispParams->rgvarg[0], &pVarResult->bstrVal ); else hr =3D DISP_E_MEMBERNOTFOUND; break; case DISPID_ACC_HELPTOPIC: if ( wFlags =3D=3D DISPATCH_PROPERTYGET ) hr =3D get_accHelpTopic( &pDispParams->rgvarg[2].bstrVal, = pDispParams->rgvarg[1], &pDispParams->rgvarg[0].lVal ); else hr =3D DISP_E_MEMBERNOTFOUND; break; case DISPID_ACC_KEYBOARDSHORTCUT: if ( wFlags =3D=3D DISPATCH_PROPERTYGET ) hr =3D get_accKeyboardShortcut( pDispParams->rgvarg[0], = &pVarResult->bstrVal ); else hr =3D DISP_E_MEMBERNOTFOUND; break; case DISPID_ACC_FOCUS: if ( wFlags =3D=3D DISPATCH_PROPERTYGET ) hr =3D get_accFocus( pVarResult ); else hr =3D DISP_E_MEMBERNOTFOUND; break; case DISPID_ACC_SELECTION: if ( wFlags =3D=3D DISPATCH_PROPERTYGET ) hr =3D get_accSelection( pVarResult ); else hr =3D DISP_E_MEMBERNOTFOUND; break; case DISPID_ACC_DEFAULTACTION: if ( wFlags =3D=3D DISPATCH_PROPERTYGET ) hr =3D get_accDefaultAction( pDispParams->rgvarg[0], = &pVarResult->bstrVal ); else hr =3D DISP_E_MEMBERNOTFOUND; break; case DISPID_ACC_SELECT: if ( wFlags =3D=3D DISPATCH_METHOD ) hr =3D accSelect( pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0] = ); else hr =3D DISP_E_MEMBERNOTFOUND; break; case DISPID_ACC_LOCATION: if ( wFlags =3D=3D DISPATCH_METHOD ) hr =3D accLocation( &pDispParams->rgvarg[4].lVal, = &pDispParams->rgvarg[3].lVal, &pDispParams->rgvarg[2].lVal, = &pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0] ); else hr =3D DISP_E_MEMBERNOTFOUND; break; case DISPID_ACC_NAVIGATE: if ( wFlags =3D=3D DISPATCH_METHOD ) hr =3D accNavigate( pDispParams->rgvarg[1].lVal, = pDispParams->rgvarg[0], pVarResult ); else hr =3D DISP_E_MEMBERNOTFOUND; break; case DISPID_ACC_HITTEST: if ( wFlags =3D=3D DISPATCH_METHOD ) hr =3D accHitTest( pDispParams->rgvarg[1].lVal, = pDispParams->rgvarg[0].lVal, pVarResult ); else hr =3D DISP_E_MEMBERNOTFOUND; break; case DISPID_ACC_DODEFAULTACTION: if ( wFlags =3D=3D DISPATCH_METHOD ) hr =3D accDoDefaultAction( pDispParams->rgvarg[0] ); else hr =3D DISP_E_MEMBERNOTFOUND; break; default: hr =3D DISP_E_MEMBERNOTFOUND; break; }=20 =20 return hr; } /*=20 IAccessible */ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accHitTest( long xLeft, = long yTop, VARIANT *pvarID ) {=20 if ( !accessible->isValid() ) return E_FAIL; int control =3D accessible->controlAt( xLeft, yTop ); if ( control =3D=3D -1 ) { (*pvarID).vt =3D VT_EMPTY; return S_FALSE; } QAccessibleInterface *acc =3D 0; if ( control ) accessible->queryChild( control, &acc ); if ( !acc ) { (*pvarID).vt =3D VT_I4; (*pvarID).lVal =3D control; return S_OK; } QWindowsAccessible* wacc =3D new QWindowsAccessible( acc ); acc->release(); IDispatch *iface =3D 0; wacc->QueryInterface( IID_IDispatch, (void**)&iface ); if ( iface ) { (*pvarID).vt =3D VT_DISPATCH; (*pvarID).pdispVal =3D iface; return S_OK; } else { delete wacc; } (*pvarID).vt =3D VT_EMPTY; return S_FALSE; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::accLocation( long *pxLeft, = long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID ) {=20 if ( !accessible->isValid() ) return E_FAIL; QRect rect =3D accessible->rect( varID.lVal ); if ( rect.isValid() ) { *pxLeft =3D rect.x(); *pyTop =3D rect.y(); *pcxWidth =3D rect.width(); *pcyHeight =3D rect.height(); } else { *pxLeft =3D 0; *pyTop =3D 0; *pcxWidth =3D 0; *pcyHeight =3D 0; } return S_OK; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::accNavigate( long navDir, = VARIANT varStart, VARIANT *pvarEnd ) { if ( !accessible->isValid() ) return E_FAIL; int control =3D accessible->navigate( (NavDirection)navDir, = varStart.lVal ); if ( control =3D=3D -1 ) { (*pvarEnd).vt =3D VT_EMPTY; return S_FALSE; } QAccessibleInterface *acc =3D 0; if ( control ) { if ( varStart.lVal || navDir =3D=3D NavFirstChild || navDir =3D=3D = NavLastChild || navDir =3D=3D NavFocusChild ) { accessible->queryChild( control, &acc ); } else { QAccessibleInterface *parent =3D 0; accessible->queryParent( &parent ); if ( parent ) { parent->queryChild( control, &acc ); parent->release(); } } } else { acc =3D accessible; acc->addRef(); } if ( !acc ) { (*pvarEnd).vt =3D VT_I4; (*pvarEnd).lVal =3D control; return S_OK; } =20 QWindowsAccessible* wacc =3D new QWindowsAccessible( acc ); acc->release(); IDispatch *iface =3D 0; wacc->QueryInterface( IID_IDispatch, (void**)&iface ); if ( iface ) { (*pvarEnd).vt =3D VT_DISPATCH; (*pvarEnd).pdispVal =3D iface; return S_OK; } else { delete wacc; } (*pvarEnd).vt =3D VT_EMPTY; return S_FALSE; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild( VARIANT = varChildID, IDispatch** ppdispChild ) {=20 if ( !accessible->isValid() ) return E_FAIL; if ( varChildID.vt =3D=3D VT_EMPTY ) return E_INVALIDARG; QAccessibleInterface *acc =3D 0; if ( !varChildID.lVal ) { acc =3D accessible; acc->addRef(); } else { accessible->queryChild( varChildID.lVal, &acc ); } if ( acc ) { QWindowsAccessible* wacc =3D new QWindowsAccessible( acc ); acc->release(); wacc->QueryInterface( IID_IDispatch, (void**)ppdispChild ); return S_OK; } *ppdispChild =3D NULL; return S_FALSE; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChildCount( long* = pcountChildren ) {=20 if ( !accessible->isValid() ) return E_FAIL; *pcountChildren =3D accessible->childCount(); return S_OK; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accParent( IDispatch** = ppdispParent ) {=20 if ( !accessible->isValid() ) return E_FAIL; QAccessibleInterface *acc =3D 0; accessible->queryParent( &acc ); if ( acc ) { QWindowsAccessible* wacc =3D new QWindowsAccessible( acc ); acc->release(); wacc->QueryInterface( IID_IDispatch, (void**)ppdispParent ); if ( *ppdispParent ) return S_OK; } *ppdispParent =3D NULL; return S_FALSE; } /* Properties and methods */ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accDoDefaultAction( = VARIANT varID ) { if ( !accessible->isValid() ) return E_FAIL; if ( accessible->doDefaultAction( varID.lVal ) ) return S_OK; return DISP_E_MEMBERNOTFOUND; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDefaultAction( = VARIANT varID, BSTR* pszDefaultAction ) {=20 if ( !accessible->isValid() ) return E_FAIL; QString def =3D accessible->text( DefaultAction, varID.lVal ); if ( !!def ) { *pszDefaultAction =3D QStringToBSTR( def ); return S_OK; } *pszDefaultAction =3D NULL; return S_FALSE; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDescription( = VARIANT varID, BSTR* pszDescription ) {=20 if ( !accessible->isValid() ) return E_FAIL; QString descr =3D accessible->text( Description, varID.lVal ); if ( !!descr ) { *pszDescription =3D QStringToBSTR( descr ); return S_OK; } *pszDescription =3D NULL; return S_FALSE; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accHelp( VARIANT = varID, BSTR *pszHelp ) { if ( !accessible->isValid() ) return E_FAIL; QString help =3D accessible->text( Help, varID.lVal ); if ( !!help ) { *pszHelp =3D QStringToBSTR( help ); return S_OK; } =20 *pszHelp =3D NULL; return S_FALSE; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accHelpTopic( BSTR *, = VARIANT, long * ) {=20 return DISP_E_MEMBERNOTFOUND; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accKeyboardShortcut( = VARIANT varID, BSTR *pszKeyboardShortcut ) {=20 if ( !accessible->isValid() ) return E_FAIL; QString sc =3D accessible->text( Accelerator, varID.lVal ); if ( !!sc ) { *pszKeyboardShortcut =3D QStringToBSTR( sc ); return S_OK; } *pszKeyboardShortcut =3D NULL; return S_FALSE; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accName( VARIANT = varID, BSTR* pszName ) { if ( !accessible->isValid() ) return E_FAIL; QString n =3D accessible->text( Name, varID.lVal ); if ( !!n ) { *pszName =3D QStringToBSTR( n ); return S_OK; } *pszName =3D NULL; return S_FALSE; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::put_accName( VARIANT, BSTR = ) {=20 return DISP_E_MEMBERNOTFOUND; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accRole( VARIANT = varID, VARIANT *pvarRole ) {=20 if ( !accessible->isValid() ) return E_FAIL; Role role =3D accessible->role( varID.lVal ); if ( role !=3D NoRole ) { (*pvarRole).vt =3D VT_I4; (*pvarRole).lVal =3D role;=09 } else { (*pvarRole).vt =3D VT_EMPTY; } return S_OK; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accState( VARIANT = varID, VARIANT *pvarState ) { if ( !accessible->isValid() ) return E_FAIL; (*pvarState).vt =3D VT_I4; (*pvarState).lVal =3D accessible->state( varID.lVal ); return S_OK; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accValue( VARIANT = varID, BSTR* pszValue ) {=20 if ( !accessible->isValid() ) return E_FAIL; QString value =3D accessible->text( Value, varID.lVal ); if ( !value.isNull() ) { *pszValue =3D QStringToBSTR( value ); return S_OK; } *pszValue =3D NULL; return S_FALSE; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::put_accValue( VARIANT, = BSTR ) {=20 return DISP_E_MEMBERNOTFOUND; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::accSelect( long = flagsSelect, VARIANT varID ) {=20 if ( !accessible->isValid() ) return E_FAIL; bool res =3D FALSE; if ( flagsSelect & SELFLAG_TAKEFOCUS ) res =3D accessible->setFocus( varID.lVal ); if ( flagsSelect & SELFLAG_TAKESELECTION ) { accessible->clearSelection(); res =3D accessible->setSelected( varID.lVal, TRUE, FALSE ); } if ( flagsSelect & SELFLAG_EXTENDSELECTION ) res =3D accessible->setSelected( varID.lVal, TRUE, TRUE ); if ( flagsSelect & SELFLAG_ADDSELECTION ) res =3D accessible->setSelected( varID.lVal, TRUE, FALSE ); if ( flagsSelect & SELFLAG_REMOVESELECTION ) res =3D accessible->setSelected( varID.lVal, FALSE, FALSE ); return res ? S_OK : S_FALSE; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accFocus( VARIANT = *pvarID ) {=20 if ( !accessible->isValid() ) return E_FAIL; int control =3D accessible->navigate( NavFocusChild, 0 ); if ( control =3D=3D -1 ) { (*pvarID).vt =3D VT_EMPTY; return S_FALSE; } QAccessibleInterface *acc =3D 0; if ( control ) accessible->queryChild( control, &acc ); if ( !acc ) { (*pvarID).vt =3D VT_I4; (*pvarID).lVal =3D control; return S_OK; } =20 QWindowsAccessible* wacc =3D new QWindowsAccessible( acc ); acc->release(); IDispatch *iface =3D 0; wacc->QueryInterface( IID_IDispatch, (void**)&iface ); if ( iface ) { (*pvarID).vt =3D VT_DISPATCH; (*pvarID).pdispVal =3D iface; return S_OK; } else { delete wacc; } (*pvarID).vt =3D VT_EMPTY; return S_FALSE; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accSelection( VARIANT = *pvarChildren ) {=20 if ( !accessible->isValid() ) return E_FAIL; QMemArray sel =3D accessible->selection(); if ( sel.isEmpty() ) { (*pvarChildren).vt =3D VT_EMPTY; return S_FALSE; } if ( sel.size() =3D=3D 1 ) { (*pvarChildren).vt =3D VT_I4; (*pvarChildren).lVal =3D sel[0]; return S_OK; } IEnumVARIANT *iface =3D new QWindowsEnumerate( sel ); IUnknown *uiface; iface->QueryInterface( IID_IUnknown, (void**)&uiface ); (*pvarChildren).vt =3D VT_UNKNOWN; (*pvarChildren).punkVal =3D uiface; =20 return S_OK; } #endif ------=_NextPart_000_0192_01C296EC.72F8C730-- _______________________________________________ kde-accessibility mailing list kde-accessibility@mail.kde.org http://mail.kde.org/mailman/listinfo/kde-accessibility