oleacc: Added Client_get_accChild implementation.
[wine.git] / dlls / oleacc / client.c
blob9456f813faf9d3f6f0e87dc546604d114de4d864
1 /*
2 * Copyright 2014 Piotr Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
21 #include "oleacc_private.h"
23 #include "wine/unicode.h"
24 #include "wine/debug.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(oleacc);
28 typedef struct {
29 IAccessible IAccessible_iface;
30 IOleWindow IOleWindow_iface;
32 LONG ref;
34 HWND hwnd;
35 } Client;
37 static inline Client* impl_from_Client(IAccessible *iface)
39 return CONTAINING_RECORD(iface, Client, IAccessible_iface);
42 static HRESULT WINAPI Client_QueryInterface(IAccessible *iface, REFIID riid, void **ppv)
44 Client *This = impl_from_Client(iface);
46 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
48 if(IsEqualIID(riid, &IID_IAccessible) ||
49 IsEqualIID(riid, &IID_IDispatch) ||
50 IsEqualIID(riid, &IID_IUnknown)) {
51 *ppv = iface;
52 }else if(IsEqualIID(riid, &IID_IOleWindow)) {
53 *ppv = &This->IOleWindow_iface;
54 }else {
55 WARN("no interface: %s\n", debugstr_guid(riid));
56 *ppv = NULL;
57 return E_NOINTERFACE;
60 IAccessible_AddRef(iface);
61 return S_OK;
64 static ULONG WINAPI Client_AddRef(IAccessible *iface)
66 Client *This = impl_from_Client(iface);
67 ULONG ref = InterlockedIncrement(&This->ref);
69 TRACE("(%p) ref = %u\n", This, ref);
70 return ref;
73 static ULONG WINAPI Client_Release(IAccessible *iface)
75 Client *This = impl_from_Client(iface);
76 ULONG ref = InterlockedDecrement(&This->ref);
78 TRACE("(%p) ref = %u\n", This, ref);
80 if(!ref)
81 heap_free(This);
82 return ref;
85 static HRESULT WINAPI Client_GetTypeInfoCount(IAccessible *iface, UINT *pctinfo)
87 Client *This = impl_from_Client(iface);
88 FIXME("(%p)->(%p)\n", This, pctinfo);
89 return E_NOTIMPL;
92 static HRESULT WINAPI Client_GetTypeInfo(IAccessible *iface,
93 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
95 Client *This = impl_from_Client(iface);
96 FIXME("(%p)->(%u %x %p)\n", This, iTInfo, lcid, ppTInfo);
97 return E_NOTIMPL;
100 static HRESULT WINAPI Client_GetIDsOfNames(IAccessible *iface, REFIID riid,
101 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
103 Client *This = impl_from_Client(iface);
104 FIXME("(%p)->(%s %p %u %x %p)\n", This, debugstr_guid(riid),
105 rgszNames, cNames, lcid, rgDispId);
106 return E_NOTIMPL;
109 static HRESULT WINAPI Client_Invoke(IAccessible *iface, DISPID dispIdMember,
110 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
111 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
113 Client *This = impl_from_Client(iface);
114 FIXME("(%p)->(%x %s %x %x %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
115 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
116 return E_NOTIMPL;
119 static HRESULT WINAPI Client_get_accParent(IAccessible *iface, IDispatch **ppdispParent)
121 Client *This = impl_from_Client(iface);
123 TRACE("(%p)->(%p)\n", This, ppdispParent);
125 return AccessibleObjectFromWindow(This->hwnd, OBJID_WINDOW,
126 &IID_IDispatch, (void**)ppdispParent);
129 static HRESULT WINAPI Client_get_accChildCount(IAccessible *iface, LONG *pcountChildren)
131 Client *This = impl_from_Client(iface);
132 HWND cur;
134 TRACE("(%p)->(%p)\n", This, pcountChildren);
136 *pcountChildren = 0;
137 for(cur = GetWindow(This->hwnd, GW_CHILD); cur; cur = GetWindow(cur, GW_HWNDNEXT))
138 (*pcountChildren)++;
140 return S_OK;
143 static HRESULT WINAPI Client_get_accChild(IAccessible *iface,
144 VARIANT varChildID, IDispatch **ppdispChild)
146 Client *This = impl_from_Client(iface);
148 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varChildID), ppdispChild);
150 *ppdispChild = NULL;
151 return E_INVALIDARG;
154 static HRESULT WINAPI Client_get_accName(IAccessible *iface, VARIANT varID, BSTR *pszName)
156 Client *This = impl_from_Client(iface);
157 WCHAR name[1024];
158 UINT i, len;
160 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszName);
162 *pszName = NULL;
163 if(convert_child_id(&varID) != CHILDID_SELF || !IsWindow(This->hwnd))
164 return E_INVALIDARG;
166 len = SendMessageW(This->hwnd, WM_GETTEXT, sizeof(name)/sizeof(WCHAR), (LPARAM)name);
167 if(!len)
168 return S_FALSE;
170 for(i=0; i<len; i++) {
171 if(name[i] == '&') {
172 len--;
173 memmove(name+i, name+i+1, (len-i)*sizeof(WCHAR));
174 break;
178 *pszName = SysAllocStringLen(name, len);
179 return *pszName ? S_OK : E_OUTOFMEMORY;
182 static HRESULT WINAPI Client_get_accValue(IAccessible *iface, VARIANT varID, BSTR *pszValue)
184 Client *This = impl_from_Client(iface);
186 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszValue);
188 *pszValue = NULL;
189 if(convert_child_id(&varID) != CHILDID_SELF)
190 return E_INVALIDARG;
191 return S_FALSE;
194 static HRESULT WINAPI Client_get_accDescription(IAccessible *iface,
195 VARIANT varID, BSTR *pszDescription)
197 Client *This = impl_from_Client(iface);
199 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszDescription);
201 *pszDescription = NULL;
202 if(convert_child_id(&varID) != CHILDID_SELF)
203 return E_INVALIDARG;
204 return S_FALSE;
207 static HRESULT WINAPI Client_get_accRole(IAccessible *iface, VARIANT varID, VARIANT *pvarRole)
209 Client *This = impl_from_Client(iface);
211 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pvarRole);
213 if(convert_child_id(&varID) != CHILDID_SELF) {
214 V_VT(pvarRole) = VT_EMPTY;
215 return E_INVALIDARG;
218 V_VT(pvarRole) = VT_I4;
219 V_I4(pvarRole) = ROLE_SYSTEM_CLIENT;
220 return S_OK;
223 static HRESULT WINAPI Client_get_accState(IAccessible *iface, VARIANT varID, VARIANT *pvarState)
225 Client *This = impl_from_Client(iface);
226 LONG style;
228 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pvarState);
230 if(convert_child_id(&varID) != CHILDID_SELF) {
231 V_VT(pvarState) = VT_EMPTY;
232 return E_INVALIDARG;
235 V_VT(pvarState) = VT_I4;
236 V_I4(pvarState) = 0;
238 style = GetWindowLongW(This->hwnd, GWL_STYLE);
239 if(style & WS_DISABLED)
240 V_I4(pvarState) |= STATE_SYSTEM_UNAVAILABLE;
241 else if(IsWindow(This->hwnd))
242 V_I4(pvarState) |= STATE_SYSTEM_FOCUSABLE;
243 if(GetFocus() == This->hwnd)
244 V_I4(pvarState) |= STATE_SYSTEM_FOCUSED;
245 if(!(style & WS_VISIBLE))
246 V_I4(pvarState) |= STATE_SYSTEM_INVISIBLE;
247 return S_OK;
250 static HRESULT WINAPI Client_get_accHelp(IAccessible *iface, VARIANT varID, BSTR *pszHelp)
252 Client *This = impl_from_Client(iface);
254 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszHelp);
256 *pszHelp = NULL;
257 if(convert_child_id(&varID) != CHILDID_SELF)
258 return E_INVALIDARG;
259 return S_FALSE;
262 static HRESULT WINAPI Client_get_accHelpTopic(IAccessible *iface,
263 BSTR *pszHelpFile, VARIANT varID, LONG *pidTopic)
265 Client *This = impl_from_Client(iface);
266 FIXME("(%p)->(%p %s %p)\n", This, pszHelpFile, debugstr_variant(&varID), pidTopic);
267 return E_NOTIMPL;
270 static HRESULT WINAPI Client_get_accKeyboardShortcut(IAccessible *iface,
271 VARIANT varID, BSTR *pszKeyboardShortcut)
273 static const WCHAR shortcut_fmt[] = {'A','l','t','+','!',0};
274 Client *This = impl_from_Client(iface);
275 WCHAR name[1024];
276 UINT i, len;
278 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszKeyboardShortcut);
280 *pszKeyboardShortcut = NULL;
281 if(convert_child_id(&varID) != CHILDID_SELF)
282 return E_INVALIDARG;
284 len = SendMessageW(This->hwnd, WM_GETTEXT, sizeof(name)/sizeof(WCHAR), (LPARAM)name);
285 for(i=0; i<len; i++) {
286 if(name[i] == '&')
287 break;
289 if(i+1 >= len)
290 return S_FALSE;
292 *pszKeyboardShortcut = SysAllocString(shortcut_fmt);
293 if(!*pszKeyboardShortcut)
294 return E_OUTOFMEMORY;
296 (*pszKeyboardShortcut)[4] = name[i+1];
297 return S_OK;
300 static HRESULT WINAPI Client_get_accFocus(IAccessible *iface, VARIANT *pvarID)
302 Client *This = impl_from_Client(iface);
303 FIXME("(%p)->(%p)\n", This, pvarID);
304 return E_NOTIMPL;
307 static HRESULT WINAPI Client_get_accSelection(IAccessible *iface, VARIANT *pvarID)
309 Client *This = impl_from_Client(iface);
310 FIXME("(%p)->(%p)\n", This, pvarID);
311 return E_NOTIMPL;
314 static HRESULT WINAPI Client_get_accDefaultAction(IAccessible *iface,
315 VARIANT varID, BSTR *pszDefaultAction)
317 Client *This = impl_from_Client(iface);
319 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszDefaultAction);
321 *pszDefaultAction = NULL;
322 if(convert_child_id(&varID) != CHILDID_SELF)
323 return E_INVALIDARG;
324 return S_FALSE;
327 static HRESULT WINAPI Client_accSelect(IAccessible *iface, LONG flagsSelect, VARIANT varID)
329 Client *This = impl_from_Client(iface);
330 FIXME("(%p)->(%x %s)\n", This, flagsSelect, debugstr_variant(&varID));
331 return E_NOTIMPL;
334 static HRESULT WINAPI Client_accLocation(IAccessible *iface, LONG *pxLeft,
335 LONG *pyTop, LONG *pcxWidth, LONG *pcyHeight, VARIANT varID)
337 Client *This = impl_from_Client(iface);
338 RECT rect;
339 POINT pt;
341 TRACE("(%p)->(%p %p %p %p %s)\n", This, pxLeft, pyTop,
342 pcxWidth, pcyHeight, debugstr_variant(&varID));
344 *pxLeft = *pyTop = *pcxWidth = *pcyHeight = 0;
345 if(convert_child_id(&varID) != CHILDID_SELF)
346 return E_INVALIDARG;
348 if(!GetClientRect(This->hwnd, &rect))
349 return S_OK;
351 pt.x = rect.left,
352 pt.y = rect.top;
353 MapWindowPoints(This->hwnd, NULL, &pt, 1);
354 *pxLeft = pt.x;
355 *pyTop = pt.y;
357 pt.x = rect.right;
358 pt.y = rect.bottom;
359 MapWindowPoints(This->hwnd, NULL, &pt, 1);
360 *pcxWidth = pt.x - *pxLeft;
361 *pcyHeight = pt.y - *pyTop;
362 return S_OK;
365 static HRESULT WINAPI Client_accNavigate(IAccessible *iface,
366 LONG navDir, VARIANT varStart, VARIANT *pvarEnd)
368 Client *This = impl_from_Client(iface);
369 FIXME("(%p)->(%d %s %p)\n", This, navDir, debugstr_variant(&varStart), pvarEnd);
370 return E_NOTIMPL;
373 static HRESULT WINAPI Client_accHitTest(IAccessible *iface,
374 LONG xLeft, LONG yTop, VARIANT *pvarID)
376 Client *This = impl_from_Client(iface);
377 HWND child;
378 POINT pt;
380 TRACE("(%p)->(%d %d %p)\n", This, xLeft, yTop, pvarID);
382 V_VT(pvarID) = VT_I4;
383 V_I4(pvarID) = 0;
385 pt.x = xLeft;
386 pt.y = yTop;
387 if(!IsWindowVisible(This->hwnd) || !ScreenToClient(This->hwnd, &pt))
388 return S_OK;
390 child = ChildWindowFromPointEx(This->hwnd, pt, CWP_SKIPINVISIBLE);
391 if(!child || child==This->hwnd)
392 return S_OK;
394 V_VT(pvarID) = VT_DISPATCH;
395 return AccessibleObjectFromWindow(child, OBJID_WINDOW,
396 &IID_IDispatch, (void**)&V_DISPATCH(pvarID));
399 static HRESULT WINAPI Client_accDoDefaultAction(IAccessible *iface, VARIANT varID)
401 Client *This = impl_from_Client(iface);
402 FIXME("(%p)->(%s)\n", This, debugstr_variant(&varID));
403 return E_NOTIMPL;
406 static HRESULT WINAPI Client_put_accName(IAccessible *iface, VARIANT varID, BSTR pszName)
408 Client *This = impl_from_Client(iface);
409 FIXME("(%p)->(%s %s)\n", This, debugstr_variant(&varID), debugstr_w(pszName));
410 return E_NOTIMPL;
413 static HRESULT WINAPI Client_put_accValue(IAccessible *iface, VARIANT varID, BSTR pszValue)
415 Client *This = impl_from_Client(iface);
416 FIXME("(%p)->(%s %s)\n", This, debugstr_variant(&varID), debugstr_w(pszValue));
417 return E_NOTIMPL;
420 static const IAccessibleVtbl ClientVtbl = {
421 Client_QueryInterface,
422 Client_AddRef,
423 Client_Release,
424 Client_GetTypeInfoCount,
425 Client_GetTypeInfo,
426 Client_GetIDsOfNames,
427 Client_Invoke,
428 Client_get_accParent,
429 Client_get_accChildCount,
430 Client_get_accChild,
431 Client_get_accName,
432 Client_get_accValue,
433 Client_get_accDescription,
434 Client_get_accRole,
435 Client_get_accState,
436 Client_get_accHelp,
437 Client_get_accHelpTopic,
438 Client_get_accKeyboardShortcut,
439 Client_get_accFocus,
440 Client_get_accSelection,
441 Client_get_accDefaultAction,
442 Client_accSelect,
443 Client_accLocation,
444 Client_accNavigate,
445 Client_accHitTest,
446 Client_accDoDefaultAction,
447 Client_put_accName,
448 Client_put_accValue
451 static inline Client* impl_from_Client_OleWindow(IOleWindow *iface)
453 return CONTAINING_RECORD(iface, Client, IOleWindow_iface);
456 static HRESULT WINAPI Client_OleWindow_QueryInterface(IOleWindow *iface, REFIID riid, void **ppv)
458 Client *This = impl_from_Client_OleWindow(iface);
459 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, ppv);
462 static ULONG WINAPI Client_OleWindow_AddRef(IOleWindow *iface)
464 Client *This = impl_from_Client_OleWindow(iface);
465 return IAccessible_AddRef(&This->IAccessible_iface);
468 static ULONG WINAPI Client_OleWindow_Release(IOleWindow *iface)
470 Client *This = impl_from_Client_OleWindow(iface);
471 return IAccessible_Release(&This->IAccessible_iface);
474 static HRESULT WINAPI Client_OleWindow_GetWindow(IOleWindow *iface, HWND *phwnd)
476 Client *This = impl_from_Client_OleWindow(iface);
478 TRACE("(%p)->(%p)\n", This, phwnd);
480 *phwnd = This->hwnd;
481 return S_OK;
484 static HRESULT WINAPI Client_OleWindow_ContextSensitiveHelp(IOleWindow *iface, BOOL fEnterMode)
486 Client *This = impl_from_Client_OleWindow(iface);
487 FIXME("(%p)->(%x)\n", This, fEnterMode);
488 return E_NOTIMPL;
491 static const IOleWindowVtbl ClientOleWindowVtbl = {
492 Client_OleWindow_QueryInterface,
493 Client_OleWindow_AddRef,
494 Client_OleWindow_Release,
495 Client_OleWindow_GetWindow,
496 Client_OleWindow_ContextSensitiveHelp
499 HRESULT create_client_object(HWND hwnd, const IID *iid, void **obj)
501 Client *client;
502 HRESULT hres;
504 if(!IsWindow(hwnd))
505 return E_FAIL;
507 client = heap_alloc_zero(sizeof(Client));
508 if(!client)
509 return E_OUTOFMEMORY;
511 client->IAccessible_iface.lpVtbl = &ClientVtbl;
512 client->IOleWindow_iface.lpVtbl = &ClientOleWindowVtbl;
513 client->ref = 1;
514 client->hwnd = hwnd;
516 hres = IAccessible_QueryInterface(&client->IAccessible_iface, iid, obj);
517 IAccessible_Release(&client->IAccessible_iface);
518 return hres;