From: Esme Povirk esme@codeweavers.com
--- dlls/comctl32/Makefile.in | 2 +- dlls/comctl32/syslink.c | 274 +++++++++++++++++++++++++++++++++- dlls/comctl32/tests/syslink.c | 14 +- 3 files changed, 283 insertions(+), 7 deletions(-)
diff --git a/dlls/comctl32/Makefile.in b/dlls/comctl32/Makefile.in index 8e9a6e44577..383faee35ad 100644 --- a/dlls/comctl32/Makefile.in +++ b/dlls/comctl32/Makefile.in @@ -1,7 +1,7 @@ EXTRADEFS = -D_COMCTL32_ MODULE = comctl32.dll IMPORTLIB = comctl32 -IMPORTS = uuid user32 gdi32 advapi32 imm32 kernelbase +IMPORTS = uuid user32 gdi32 advapi32 imm32 kernelbase oleacc DELAYIMPORTS = winmm uxtheme
SOURCES = \ diff --git a/dlls/comctl32/syslink.c b/dlls/comctl32/syslink.c index f5a70e982c3..76d95b77848 100644 --- a/dlls/comctl32/syslink.c +++ b/dlls/comctl32/syslink.c @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#define COBJMACROS #include <stdarg.h> #include <string.h> #include "windef.h" @@ -27,6 +28,9 @@ #include "winnls.h" #include "commctrl.h" #include "comctl32.h" +#include "oaidl.h" +#include "initguid.h" +#include "oleacc.h" #include "wine/debug.h" #include "wine/list.h"
@@ -70,7 +74,16 @@ typedef struct _DOC_ITEM WCHAR Text[1]; /* Text of the document item */ } DOC_ITEM, *PDOC_ITEM;
+typedef struct SYSLINK_INFO SYSLINK_INFO; + typedef struct +{ + IAccessible IAccessible_iface; + struct SYSLINK_INFO *infoPtr; + LONG refcount; +} SYSLINK_ACC; + +struct SYSLINK_INFO { HWND Self; /* The window handle for this control */ HWND Notify; /* The parent handle to receive notifications */ @@ -85,7 +98,8 @@ typedef struct COLORREF VisitedColor; /* Color of visited links */ WCHAR BreakChar; /* Break Character for the current font */ BOOL IgnoreReturn; /* (infoPtr->Style & LWS_IGNORERETURN) on creation */ -} SYSLINK_INFO; + SYSLINK_ACC *AccessibleImpl; /* IAccessible implementation */ +};
/* Control configuration constants */
@@ -94,6 +108,251 @@ typedef struct #define SL_RIGHTMARGIN (0) #define SL_BOTTOMMARGIN (0)
+static inline SYSLINK_ACC *impl_from_IAccessible(IAccessible *iface) +{ + return CONTAINING_RECORD(iface, SYSLINK_ACC, IAccessible_iface); +} + +static HRESULT WINAPI Accessible_QueryInterface(IAccessible *iface, REFIID iid, void **ppv) +{ + SYSLINK_ACC *This = impl_from_IAccessible(iface); + TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); + + if (!ppv) return E_INVALIDARG; + + if (IsEqualIID(&IID_IUnknown, iid) || + IsEqualIID(&IID_IAccessible, iid)) + { + *ppv = &This->IAccessible_iface; + } + else + { + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI Accessible_AddRef(IAccessible *iface) +{ + SYSLINK_ACC *This = impl_from_IAccessible(iface); + return InterlockedIncrement(&This->refcount); +} + +static ULONG WINAPI Accessible_Release(IAccessible *iface) +{ + SYSLINK_ACC *This = impl_from_IAccessible(iface); + ULONG ref = InterlockedDecrement(&This->refcount); + + if (ref == 0) + Free(This); + + return ref; +} + +static HRESULT WINAPI Accessible_GetTypeInfo(IAccessible *iface, UINT index, LCID lcid, ITypeInfo **info) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_GetIDsOfNames(IAccessible *iface, REFIID iid, LPOLESTR *names, UINT count, LCID lcid, DISPID *dispid) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_Invoke(IAccessible *iface, DISPID dispid, REFIID iid, LCID lcid, + WORD flags, DISPPARAMS *dispparams, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_GetTypeInfoCount(IAccessible *iface, UINT *count) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_get_accParent(IAccessible *iface, IDispatch** disp) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_get_accChildCount(IAccessible *iface, long *count) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_get_accChild(IAccessible *iface, VARIANT childid, IDispatch **disp) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_get_accName(IAccessible *iface, VARIANT childid, BSTR *name) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_get_accValue(IAccessible *iface, VARIANT childid, BSTR *value) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_get_accDescription(IAccessible *iface, VARIANT childid, BSTR *description) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_get_accRole(IAccessible *iface, VARIANT childid, VARIANT *role) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_get_accState(IAccessible *iface, VARIANT childid, VARIANT *state) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_get_accHelp(IAccessible *iface, VARIANT childid, BSTR *help) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_get_accHelpTopic(IAccessible *iface, BSTR *helpFile, VARIANT childid, long *topic) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_get_accKeyboardShortcut(IAccessible *iface, VARIANT childid, BSTR *shortcut) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_get_accFocus(IAccessible *iface, VARIANT *childid) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_get_accSelection(IAccessible *iface, VARIANT *childid) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_get_accDefaultAction(IAccessible *iface, VARIANT childid, BSTR *action) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_accSelect(IAccessible *iface, long flags, VARIANT childid) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_accLocation(IAccessible *iface, long *left, long *top, long *width, long *height, VARIANT childid) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_accNavigate(IAccessible *iface, long dir, VARIANT start, VARIANT *end) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_accHitTest(IAccessible *iface, long left, long top, VARIANT* childid) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_accDoDefaultAction(IAccessible *iface, VARIANT childid) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_put_accName(IAccessible *iface, VARIANT childid, BSTR name) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI Accessible_put_accValue(IAccessible *iface, VARIANT childid, BSTR value) +{ + FIXME("%p\n", iface); + return E_NOTIMPL; +} + +static const IAccessibleVtbl Accessible_Vtbl = { + Accessible_QueryInterface, + Accessible_AddRef, + Accessible_Release, + Accessible_GetTypeInfoCount, + Accessible_GetTypeInfo, + Accessible_GetIDsOfNames, + Accessible_Invoke, + Accessible_get_accParent, + Accessible_get_accChildCount, + Accessible_get_accChild, + Accessible_get_accName, + Accessible_get_accValue, + Accessible_get_accDescription, + Accessible_get_accRole, + Accessible_get_accState, + Accessible_get_accHelp, + Accessible_get_accHelpTopic, + Accessible_get_accKeyboardShortcut, + Accessible_get_accFocus, + Accessible_get_accSelection, + Accessible_get_accDefaultAction, + Accessible_accSelect, + Accessible_accLocation, + Accessible_accNavigate, + Accessible_accHitTest, + Accessible_accDoDefaultAction, + Accessible_put_accName, + Accessible_put_accValue +}; + +static void Accessible_Create(SYSLINK_INFO* infoPtr) +{ + SYSLINK_ACC *This; + + This = Alloc(sizeof(*This)); + if (!This) return; + + This->IAccessible_iface.lpVtbl = &Accessible_Vtbl; + This->infoPtr = infoPtr; + This->refcount = 1; + infoPtr->AccessibleImpl = This; +} + +static void Accessible_WindowDestroyed(SYSLINK_ACC *This) +{ + This->infoPtr = NULL; + IAccessible_Release(&This->IAccessible_iface); +} + /*********************************************************************** * SYSLINK_FreeDocItem * Frees all data and gdi objects associated with a document item @@ -1713,9 +1972,22 @@ static LRESULT WINAPI SysLinkWindowProc(HWND hwnd, UINT message, SYSLINK_ClearDoc(infoPtr); if(infoPtr->LinkFont != 0) DeleteObject(infoPtr->LinkFont); SetWindowLongPtrW(hwnd, 0, 0); + if(infoPtr->AccessibleImpl) Accessible_WindowDestroyed(infoPtr->AccessibleImpl); Free (infoPtr); return 0;
+ case WM_GETOBJECT: + { + if ((DWORD)lParam == (DWORD)OBJID_CLIENT) { + if (!infoPtr->AccessibleImpl) + Accessible_Create(infoPtr); + + if (infoPtr->AccessibleImpl) + return LresultFromObject(&IID_IAccessible, wParam, (IUnknown*)&infoPtr->AccessibleImpl->IAccessible_iface); + } + return DefWindowProcW(hwnd, message, wParam, lParam); + } + case WM_SYSCOLORCHANGE: COMCTL32_RefreshSysColors(); return 0; diff --git a/dlls/comctl32/tests/syslink.c b/dlls/comctl32/tests/syslink.c index 318a68961ec..4ce0daa8c0e 100644 --- a/dlls/comctl32/tests/syslink.c +++ b/dlls/comctl32/tests/syslink.c @@ -295,7 +295,7 @@ static void test_msaa(void) ok(hwnd != NULL, "Failed to create SysLink window.\n");
lr = SendMessageA(hwnd, WM_GETOBJECT, 0, OBJID_CLIENT); - todo_wine ok(lr != 0, "No IAccessible object\n"); + ok(lr != 0, "No IAccessible object\n"); if (lr == 0) { DestroyWindow(hwnd); @@ -311,6 +311,7 @@ static void test_msaa(void) V_VT(&varChild) = VT_I4; V_I4(&varChild) = CHILDID_SELF;
+todo_wine { hr = IAccessible_get_accRole(acc, varChild, &varResult); ok(hr == S_OK, "accRole failed, hr=%lx\n", hr); ok(V_VT(&varResult) == VT_I4, "accRole returned vt=%x\n", V_VT(&varResult)); @@ -418,12 +419,15 @@ static void test_msaa(void)
hr = IAccessible_QueryInterface(acc, &IID_IOleWindow, (void**)&ole_window); ok(hr == S_OK, "QueryInterface failed, hr=%lx\n", hr); +}
- hr = IOleWindow_GetWindow(ole_window, &ret_hwnd); - ok(hr == S_OK, "GetWindow failed, hr=%lx\n", hr); - ok(ret_hwnd == hwnd, "GetWindow returned wrong hwnd\n"); + if (SUCCEEDED(hr)) { + hr = IOleWindow_GetWindow(ole_window, &ret_hwnd); + ok(hr == S_OK, "GetWindow failed, hr=%lx\n", hr); + ok(ret_hwnd == hwnd, "GetWindow returned wrong hwnd\n");
- IOleWindow_Release(ole_window); + IOleWindow_Release(ole_window); + }
IAccessible_Release(acc);