oleacc: Add Client_accHitTest implementation.
[wine/wine-gecko.git] / dlls / oleacc / client.c
blobd557de934f6c22606cb728626c26e7c88dc58edb
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;
31 LONG ref;
33 HWND hwnd;
34 } Client;
36 static inline Client* impl_from_Client(IAccessible *iface)
38 return CONTAINING_RECORD(iface, Client, IAccessible_iface);
41 static HRESULT WINAPI Client_QueryInterface(IAccessible *iface, REFIID riid, void **ppv)
43 Client *This = impl_from_Client(iface);
45 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
47 if(IsEqualIID(riid, &IID_IAccessible) ||
48 IsEqualIID(riid, &IID_IDispatch) ||
49 IsEqualIID(riid, &IID_IUnknown)) {
50 *ppv = iface;
51 IAccessible_AddRef(iface);
52 return S_OK;
55 return E_NOINTERFACE;
58 static ULONG WINAPI Client_AddRef(IAccessible *iface)
60 Client *This = impl_from_Client(iface);
61 ULONG ref = InterlockedIncrement(&This->ref);
63 TRACE("(%p) ref = %u\n", This, ref);
64 return ref;
67 static ULONG WINAPI Client_Release(IAccessible *iface)
69 Client *This = impl_from_Client(iface);
70 ULONG ref = InterlockedDecrement(&This->ref);
72 TRACE("(%p) ref = %u\n", This, ref);
74 if(!ref)
75 heap_free(This);
76 return ref;
79 static HRESULT WINAPI Client_GetTypeInfoCount(IAccessible *iface, UINT *pctinfo)
81 Client *This = impl_from_Client(iface);
82 FIXME("(%p)->(%p)\n", This, pctinfo);
83 return E_NOTIMPL;
86 static HRESULT WINAPI Client_GetTypeInfo(IAccessible *iface,
87 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
89 Client *This = impl_from_Client(iface);
90 FIXME("(%p)->(%u %x %p)\n", This, iTInfo, lcid, ppTInfo);
91 return E_NOTIMPL;
94 static HRESULT WINAPI Client_GetIDsOfNames(IAccessible *iface, REFIID riid,
95 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
97 Client *This = impl_from_Client(iface);
98 FIXME("(%p)->(%s %p %u %x %p)\n", This, debugstr_guid(riid),
99 rgszNames, cNames, lcid, rgDispId);
100 return E_NOTIMPL;
103 static HRESULT WINAPI Client_Invoke(IAccessible *iface, DISPID dispIdMember,
104 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
105 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
107 Client *This = impl_from_Client(iface);
108 FIXME("(%p)->(%x %s %x %x %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
109 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
110 return E_NOTIMPL;
113 static HRESULT WINAPI Client_get_accParent(IAccessible *iface, IDispatch **ppdispParent)
115 Client *This = impl_from_Client(iface);
116 FIXME("(%p)->(%p)\n", This, ppdispParent);
117 return E_NOTIMPL;
120 static HRESULT WINAPI Client_get_accChildCount(IAccessible *iface, LONG *pcountChildren)
122 Client *This = impl_from_Client(iface);
123 HWND cur;
125 TRACE("(%p)->(%p)\n", This, pcountChildren);
127 *pcountChildren = 0;
128 for(cur = GetWindow(This->hwnd, GW_CHILD); cur; cur = GetWindow(cur, GW_HWNDNEXT))
129 (*pcountChildren)++;
131 return S_OK;
134 static HRESULT WINAPI Client_get_accChild(IAccessible *iface,
135 VARIANT varChildID, IDispatch **ppdispChild)
137 Client *This = impl_from_Client(iface);
138 FIXME("(%p)->(%s %p)\n", This, debugstr_variant(&varChildID), ppdispChild);
139 return E_NOTIMPL;
142 static HRESULT WINAPI Client_get_accName(IAccessible *iface, VARIANT varID, BSTR *pszName)
144 Client *This = impl_from_Client(iface);
145 WCHAR name[1024];
146 UINT i, len;
148 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszName);
150 *pszName = NULL;
151 if(convert_child_id(&varID) != CHILDID_SELF || !IsWindow(This->hwnd))
152 return E_INVALIDARG;
154 len = SendMessageW(This->hwnd, WM_GETTEXT, sizeof(name)/sizeof(WCHAR), (LPARAM)name);
155 if(!len)
156 return S_FALSE;
158 for(i=0; i<len; i++) {
159 if(name[i] == '&') {
160 len--;
161 memmove(name+i, name+i+1, (len-i)*sizeof(WCHAR));
162 break;
166 *pszName = SysAllocStringLen(name, len);
167 return *pszName ? S_OK : E_OUTOFMEMORY;
170 static HRESULT WINAPI Client_get_accValue(IAccessible *iface, VARIANT varID, BSTR *pszValue)
172 Client *This = impl_from_Client(iface);
174 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszValue);
176 *pszValue = NULL;
177 if(convert_child_id(&varID) != CHILDID_SELF)
178 return E_INVALIDARG;
179 return S_FALSE;
182 static HRESULT WINAPI Client_get_accDescription(IAccessible *iface,
183 VARIANT varID, BSTR *pszDescription)
185 Client *This = impl_from_Client(iface);
187 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszDescription);
189 *pszDescription = NULL;
190 if(convert_child_id(&varID) != CHILDID_SELF)
191 return E_INVALIDARG;
192 return S_FALSE;
195 static HRESULT WINAPI Client_get_accRole(IAccessible *iface, VARIANT varID, VARIANT *pvarRole)
197 Client *This = impl_from_Client(iface);
199 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pvarRole);
201 if(convert_child_id(&varID) != CHILDID_SELF) {
202 V_VT(pvarRole) = VT_EMPTY;
203 return E_INVALIDARG;
206 V_VT(pvarRole) = VT_I4;
207 V_I4(pvarRole) = ROLE_SYSTEM_CLIENT;
208 return S_OK;
211 static HRESULT WINAPI Client_get_accState(IAccessible *iface, VARIANT varID, VARIANT *pvarState)
213 Client *This = impl_from_Client(iface);
214 LONG style;
216 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pvarState);
218 if(convert_child_id(&varID) != CHILDID_SELF) {
219 V_VT(pvarState) = VT_EMPTY;
220 return E_INVALIDARG;
223 V_VT(pvarState) = VT_I4;
224 V_I4(pvarState) = 0;
226 style = GetWindowLongW(This->hwnd, GWL_STYLE);
227 if(style & WS_DISABLED)
228 V_I4(pvarState) |= STATE_SYSTEM_UNAVAILABLE;
229 else if(IsWindow(This->hwnd))
230 V_I4(pvarState) |= STATE_SYSTEM_FOCUSABLE;
231 if(GetFocus() == This->hwnd)
232 V_I4(pvarState) |= STATE_SYSTEM_FOCUSED;
233 if(!(style & WS_VISIBLE))
234 V_I4(pvarState) |= STATE_SYSTEM_INVISIBLE;
235 return S_OK;
238 static HRESULT WINAPI Client_get_accHelp(IAccessible *iface, VARIANT varID, BSTR *pszHelp)
240 Client *This = impl_from_Client(iface);
242 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszHelp);
244 *pszHelp = NULL;
245 if(convert_child_id(&varID) != CHILDID_SELF)
246 return E_INVALIDARG;
247 return S_FALSE;
250 static HRESULT WINAPI Client_get_accHelpTopic(IAccessible *iface,
251 BSTR *pszHelpFile, VARIANT varID, LONG *pidTopic)
253 Client *This = impl_from_Client(iface);
254 FIXME("(%p)->(%p %s %p)\n", This, pszHelpFile, debugstr_variant(&varID), pidTopic);
255 return E_NOTIMPL;
258 static HRESULT WINAPI Client_get_accKeyboardShortcut(IAccessible *iface,
259 VARIANT varID, BSTR *pszKeyboardShortcut)
261 static const WCHAR shortcut_fmt[] = {'A','l','t','+','!',0};
262 Client *This = impl_from_Client(iface);
263 WCHAR name[1024];
264 UINT i, len;
266 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszKeyboardShortcut);
268 *pszKeyboardShortcut = NULL;
269 if(convert_child_id(&varID) != CHILDID_SELF)
270 return E_INVALIDARG;
272 len = SendMessageW(This->hwnd, WM_GETTEXT, sizeof(name)/sizeof(WCHAR), (LPARAM)name);
273 for(i=0; i<len; i++) {
274 if(name[i] == '&')
275 break;
277 if(i+1 >= len)
278 return S_FALSE;
280 *pszKeyboardShortcut = SysAllocString(shortcut_fmt);
281 if(!*pszKeyboardShortcut)
282 return E_OUTOFMEMORY;
284 (*pszKeyboardShortcut)[4] = name[i+1];
285 return S_OK;
288 static HRESULT WINAPI Client_get_accFocus(IAccessible *iface, VARIANT *pvarID)
290 Client *This = impl_from_Client(iface);
291 FIXME("(%p)->(%p)\n", This, pvarID);
292 return E_NOTIMPL;
295 static HRESULT WINAPI Client_get_accSelection(IAccessible *iface, VARIANT *pvarID)
297 Client *This = impl_from_Client(iface);
298 FIXME("(%p)->(%p)\n", This, pvarID);
299 return E_NOTIMPL;
302 static HRESULT WINAPI Client_get_accDefaultAction(IAccessible *iface,
303 VARIANT varID, BSTR *pszDefaultAction)
305 Client *This = impl_from_Client(iface);
307 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszDefaultAction);
309 *pszDefaultAction = NULL;
310 if(convert_child_id(&varID) != CHILDID_SELF)
311 return E_INVALIDARG;
312 return S_FALSE;
315 static HRESULT WINAPI Client_accSelect(IAccessible *iface, LONG flagsSelect, VARIANT varID)
317 Client *This = impl_from_Client(iface);
318 FIXME("(%p)->(%x %s)\n", This, flagsSelect, debugstr_variant(&varID));
319 return E_NOTIMPL;
322 static HRESULT WINAPI Client_accLocation(IAccessible *iface, LONG *pxLeft,
323 LONG *pyTop, LONG *pcxWidth, LONG *pcyHeight, VARIANT varID)
325 Client *This = impl_from_Client(iface);
326 FIXME("(%p)->(%p %p %p %p %s)\n", This, pxLeft, pyTop,
327 pcxWidth, pcyHeight, debugstr_variant(&varID));
328 return E_NOTIMPL;
331 static HRESULT WINAPI Client_accNavigate(IAccessible *iface,
332 LONG navDir, VARIANT varStart, VARIANT *pvarEnd)
334 Client *This = impl_from_Client(iface);
335 FIXME("(%p)->(%d %s %p)\n", This, navDir, debugstr_variant(&varStart), pvarEnd);
336 return E_NOTIMPL;
339 static HRESULT WINAPI Client_accHitTest(IAccessible *iface,
340 LONG xLeft, LONG yTop, VARIANT *pvarID)
342 Client *This = impl_from_Client(iface);
343 HWND child;
344 POINT pt;
346 TRACE("(%p)->(%d %d %p)\n", This, xLeft, yTop, pvarID);
348 V_VT(pvarID) = VT_I4;
349 V_I4(pvarID) = 0;
351 pt.x = xLeft;
352 pt.y = yTop;
353 if(!IsWindowVisible(This->hwnd) || !ScreenToClient(This->hwnd, &pt))
354 return S_OK;
356 child = ChildWindowFromPointEx(This->hwnd, pt, CWP_SKIPINVISIBLE);
357 if(!child || child==This->hwnd)
358 return S_OK;
360 V_VT(pvarID) = VT_DISPATCH;
361 return AccessibleObjectFromWindow(child, OBJID_WINDOW,
362 &IID_IDispatch, (void**)&V_DISPATCH(pvarID));
365 static HRESULT WINAPI Client_accDoDefaultAction(IAccessible *iface, VARIANT varID)
367 Client *This = impl_from_Client(iface);
368 FIXME("(%p)->(%s)\n", This, debugstr_variant(&varID));
369 return E_NOTIMPL;
372 static HRESULT WINAPI Client_put_accName(IAccessible *iface, VARIANT varID, BSTR pszName)
374 Client *This = impl_from_Client(iface);
375 FIXME("(%p)->(%s %s)\n", This, debugstr_variant(&varID), debugstr_w(pszName));
376 return E_NOTIMPL;
379 static HRESULT WINAPI Client_put_accValue(IAccessible *iface, VARIANT varID, BSTR pszValue)
381 Client *This = impl_from_Client(iface);
382 FIXME("(%p)->(%s %s)\n", This, debugstr_variant(&varID), debugstr_w(pszValue));
383 return E_NOTIMPL;
386 static const IAccessibleVtbl ClientVtbl = {
387 Client_QueryInterface,
388 Client_AddRef,
389 Client_Release,
390 Client_GetTypeInfoCount,
391 Client_GetTypeInfo,
392 Client_GetIDsOfNames,
393 Client_Invoke,
394 Client_get_accParent,
395 Client_get_accChildCount,
396 Client_get_accChild,
397 Client_get_accName,
398 Client_get_accValue,
399 Client_get_accDescription,
400 Client_get_accRole,
401 Client_get_accState,
402 Client_get_accHelp,
403 Client_get_accHelpTopic,
404 Client_get_accKeyboardShortcut,
405 Client_get_accFocus,
406 Client_get_accSelection,
407 Client_get_accDefaultAction,
408 Client_accSelect,
409 Client_accLocation,
410 Client_accNavigate,
411 Client_accHitTest,
412 Client_accDoDefaultAction,
413 Client_put_accName,
414 Client_put_accValue
417 HRESULT create_client_object(HWND hwnd, const IID *iid, void **obj)
419 Client *client;
420 HRESULT hres;
422 if(!IsWindow(hwnd))
423 return E_FAIL;
425 client = heap_alloc_zero(sizeof(Client));
426 if(!client)
427 return E_OUTOFMEMORY;
429 client->IAccessible_iface.lpVtbl = &ClientVtbl;
430 client->ref = 1;
431 client->hwnd = hwnd;
433 hres = IAccessible_QueryInterface(&client->IAccessible_iface, iid, obj);
434 IAccessible_Release(&client->IAccessible_iface);
435 return hres;