oleacc: Reorganize class specific behaviour handling.

Signed-off-by: Piotr Caban <piotr@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Piotr Caban 2021-09-27 16:10:51 +02:00 committed by Alexandre Julliard
parent 9e133a9a22
commit 589be8c1be
5 changed files with 146 additions and 72 deletions

View File

@ -19,6 +19,7 @@
#define COBJMACROS
#include "oleacc_private.h"
#include "commctrl.h"
#include "wine/debug.h"
#include "wine/heap.h"
@ -650,6 +651,38 @@ static const IEnumVARIANTVtbl ClientEnumVARIANTVtbl = {
Client_EnumVARIANT_Clone
};
static const struct win_class_data classes[] = {
{WC_LISTBOXW, 0x10000, TRUE},
{L"#32768", 0x10001, TRUE}, /* menu */
{WC_BUTTONW, 0x10002, TRUE},
{WC_STATICW, 0x10003, TRUE},
{WC_EDITW, 0x10004, TRUE},
{WC_COMBOBOXW, 0x10005, TRUE},
{L"#32770", 0x10006, TRUE}, /* dialog */
{L"#32771", 0x10007, TRUE}, /* winswitcher */
{L"MDIClient", 0x10008, TRUE},
{L"#32769", 0x10009, TRUE}, /* desktop */
{WC_SCROLLBARW, 0x1000a, TRUE},
{STATUSCLASSNAMEW, 0x1000b, TRUE},
{TOOLBARCLASSNAMEW, 0x1000c, TRUE},
{PROGRESS_CLASSW, 0x1000d, TRUE},
{ANIMATE_CLASSW, 0x1000e, TRUE},
{WC_TABCONTROLW, 0x1000f, TRUE},
{HOTKEY_CLASSW, 0x10010, TRUE},
{WC_HEADERW, 0x10011, TRUE},
{TRACKBAR_CLASSW, 0x10012, TRUE},
{WC_LISTVIEWW, 0x10013, TRUE},
{UPDOWN_CLASSW, 0x10016, TRUE},
{TOOLTIPS_CLASSW, 0x10018, TRUE},
{WC_TREEVIEWW, 0x10019, TRUE},
{DATETIMEPICK_CLASSW, 0, TRUE},
{WC_IPADDRESSW, 0, TRUE},
{L"RICHEDIT", 0x1001c, TRUE},
{L"RichEdit20A", 0, TRUE},
{L"RichEdit20W", 0, TRUE},
{NULL}
};
HRESULT create_client_object(HWND hwnd, const IID *iid, void **obj)
{
Client *client;
@ -662,6 +695,8 @@ HRESULT create_client_object(HWND hwnd, const IID *iid, void **obj)
if(!client)
return E_OUTOFMEMORY;
find_class_data(hwnd, classes);
client->IAccessible_iface.lpVtbl = &ClientVtbl;
client->IOleWindow_iface.lpVtbl = &ClientOleWindowVtbl;
client->IEnumVARIANT_iface.lpVtbl = &ClientEnumVARIANTVtbl;

View File

@ -20,13 +20,6 @@
#define COBJMACROS
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "ole2.h"
#include "commctrl.h"
#include "rpcproxy.h"
#include "initguid.h"
#include "oleacc_private.h"
#include "resource.h"
@ -37,50 +30,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(oleacc);
static const WCHAR lresult_atom_prefix[] = {'w','i','n','e','_','o','l','e','a','c','c',':'};
typedef HRESULT (*accessible_create)(HWND, const IID*, void**);
extern HRESULT WINAPI OLEACC_DllGetClassObject(REFCLSID, REFIID, void**) DECLSPEC_HIDDEN;
extern BOOL WINAPI OLEACC_DllMain(HINSTANCE, DWORD, void*) DECLSPEC_HIDDEN;
extern HRESULT WINAPI OLEACC_DllRegisterServer(void) DECLSPEC_HIDDEN;
extern HRESULT WINAPI OLEACC_DllUnregisterServer(void) DECLSPEC_HIDDEN;
static struct {
const WCHAR *name;
DWORD idx;
accessible_create create_client;
accessible_create create_window;
} builtin_classes[] = {
{WC_LISTBOXW, 0x10000, NULL, NULL},
{L"#32768", 0x10001, NULL, NULL}, /* menu */
{WC_BUTTONW, 0x10002, NULL, NULL},
{WC_STATICW, 0x10003, NULL, NULL},
{WC_EDITW, 0x10004, NULL, NULL},
{WC_COMBOBOXW, 0x10005, NULL, NULL},
{L"#32770", 0x10006, NULL, NULL}, /* dialog */
{L"#32771", 0x10007, NULL, NULL}, /* winswitcher */
{L"MDIClient", 0x10008, NULL, NULL},
{L"#32769", 0x10009, NULL, NULL}, /* desktop */
{WC_SCROLLBARW, 0x1000a, NULL, NULL},
{STATUSCLASSNAMEW, 0x1000b, NULL, NULL},
{TOOLBARCLASSNAMEW, 0x1000c, NULL, NULL},
{PROGRESS_CLASSW, 0x1000d, NULL, NULL},
{ANIMATE_CLASSW, 0x1000e, NULL, NULL},
{WC_TABCONTROLW, 0x1000f, NULL, NULL},
{HOTKEY_CLASSW, 0x10010, NULL, NULL},
{WC_HEADERW, 0x10011, NULL, NULL},
{TRACKBAR_CLASSW, 0x10012, NULL, NULL},
{WC_LISTVIEWW, 0x10013, NULL, NULL},
{UPDOWN_CLASSW, 0x10016, NULL, NULL},
{TOOLTIPS_CLASSW, 0x10018, NULL, NULL},
{WC_TREEVIEWW, 0x10019, NULL, NULL},
{MONTHCAL_CLASSW, 0, NULL, NULL},
{DATETIMEPICK_CLASSW, 0, NULL, NULL},
{WC_IPADDRESSW, 0, NULL, NULL},
{L"RICHEDIT", 0x1001c, NULL, NULL},
{L"RichEdit20A", 0, NULL, NULL},
{L"RichEdit20W", 0, NULL, NULL},
};
static HINSTANCE oleacc_handle = 0;
int convert_child_id(VARIANT *v)
@ -94,7 +48,7 @@ int convert_child_id(VARIANT *v)
}
}
static accessible_create get_builtin_accessible_obj(HWND hwnd, LONG objid)
const struct win_class_data* find_class_data(HWND hwnd, const struct win_class_data *classes)
{
WCHAR class_name[64];
int i, idx;
@ -103,31 +57,21 @@ static accessible_create get_builtin_accessible_obj(HWND hwnd, LONG objid)
return NULL;
TRACE("got window class: %s\n", debugstr_w(class_name));
for(i=0; i<ARRAY_SIZE(builtin_classes); i++) {
if(!wcsicmp(class_name, builtin_classes[i].name)) {
accessible_create ret;
ret = (objid==OBJID_CLIENT ?
builtin_classes[i].create_client :
builtin_classes[i].create_window);
if(!ret)
for(i=0; classes[i].name; i++) {
if(!wcsicmp(class_name, classes[i].name)) {
if(classes[i].stub)
FIXME("unhandled window class: %s\n", debugstr_w(class_name));
return ret;
return &classes[i];
}
}
idx = SendMessageW(hwnd, WM_GETOBJECT, 0, OBJID_QUERYCLASSNAMEIDX);
if(idx) {
for(i=0; i<ARRAY_SIZE(builtin_classes); i++) {
if(idx == builtin_classes[i].idx) {
accessible_create ret;
ret = (objid==OBJID_CLIENT ?
builtin_classes[i].create_client :
builtin_classes[i].create_window);
if(!ret)
FIXME("unhandled class name idx: %x\n", idx);
return ret;
for(i=0; classes[i].name; i++) {
if(idx == classes[i].idx) {
if(classes[i].stub)
FIXME("unhandled window class: %s\n", debugstr_w(class_name));
return &classes[i];
}
}
@ -140,19 +84,13 @@ static accessible_create get_builtin_accessible_obj(HWND hwnd, LONG objid)
HRESULT WINAPI CreateStdAccessibleObject( HWND hwnd, LONG idObject,
REFIID riidInterface, void** ppvObject )
{
accessible_create create;
TRACE("%p %d %s %p\n", hwnd, idObject,
debugstr_guid( riidInterface ), ppvObject );
switch(idObject) {
case OBJID_CLIENT:
create = get_builtin_accessible_obj(hwnd, idObject);
if(create) return create(hwnd, riidInterface, ppvObject);
return create_client_object(hwnd, riidInterface, ppvObject);
case OBJID_WINDOW:
create = get_builtin_accessible_obj(hwnd, idObject);
if(create) return create(hwnd, riidInterface, ppvObject);
return create_window_object(hwnd, riidInterface, ppvObject);
default:
FIXME("unhandled object id: %d\n", idObject);

View File

@ -18,6 +18,13 @@
#include "oleacc_classes.h"
struct win_class_data {
const WCHAR *name;
DWORD idx;
BOOL stub;
};
const struct win_class_data* find_class_data(HWND, const struct win_class_data*) DECLSPEC_HIDDEN;
HRESULT create_client_object(HWND, const IID*, void**) DECLSPEC_HIDDEN;
HRESULT create_window_object(HWND, const IID*, void**) DECLSPEC_HIDDEN;
HRESULT get_accpropservices_factory(REFIID, void**) DECLSPEC_HIDDEN;

View File

@ -24,6 +24,8 @@
#include <stdio.h>
#include "initguid.h"
#include <ole2.h>
#include <commctrl.h>
#include <oleacc.h>
#define DEFINE_EXPECT(func) \
@ -50,6 +52,7 @@
expect_ ## func = called_ ## func = FALSE; \
}while(0)
DEFINE_EXPECT(winproc_GETOBJECT);
DEFINE_EXPECT(Accessible_QI_IEnumVARIANT);
DEFINE_EXPECT(Accessible_get_accChildCount);
DEFINE_EXPECT(Accessible_get_accChild);
@ -1313,6 +1316,87 @@ static void test_CAccPropServices(void)
IAccPropServices_Release(acc_prop_services);
}
static LRESULT WINAPI test_query_class(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
if (msg != WM_GETOBJECT)
return 0;
CHECK_EXPECT(winproc_GETOBJECT);
ok(!wparam, "wparam = %lx\n", wparam);
ok(lparam == OBJID_QUERYCLASSNAMEIDX, "lparam = %lx\n", lparam);
return 0;
}
static void test_CreateStdAccessibleObject_classes(void)
{
static const struct {
const WCHAR *class;
BOOL window; /* uses default window accessibility object */
BOOL client; /* uses default client accessibility object */
} tests[] =
{
{ WC_LISTBOXW },
{ L"#32768" },
{ WC_BUTTONW, TRUE },
{ WC_STATICW, TRUE },
{ WC_EDITW, TRUE },
{ WC_COMBOBOXW, TRUE },
{ L"#32770", TRUE },
{ L"#32769", TRUE },
{ WC_SCROLLBARW, TRUE },
{ STATUSCLASSNAMEW, TRUE },
{ TOOLBARCLASSNAMEW, TRUE },
{ PROGRESS_CLASSW, TRUE },
{ ANIMATE_CLASSW, TRUE },
{ WC_TABCONTROLW, TRUE },
{ HOTKEY_CLASSW, TRUE },
{ WC_HEADERW, TRUE },
{ TRACKBAR_CLASSW, TRUE },
{ WC_LISTVIEWW, TRUE },
{ UPDOWN_CLASSW, TRUE },
{ TOOLTIPS_CLASSW, TRUE },
{ WC_TREEVIEWW, TRUE },
{ MONTHCAL_CLASSW, TRUE, TRUE },
{ DATETIMEPICK_CLASSW, TRUE },
{ WC_IPADDRESSW, TRUE }
};
LRESULT (WINAPI *win_proc)(HWND, UINT, WPARAM, LPARAM);
IAccessible *acc;
HRESULT hr;
HWND hwnd;
int i;
for(i=0; i<ARRAY_SIZE(tests); i++)
{
winetest_push_context("class = %s", wine_dbgstr_w(tests[i].class));
hwnd = CreateWindowW(tests[i].class, L"name", WS_OVERLAPPEDWINDOW,
0, 0, 0, 0, NULL, NULL, NULL, NULL);
ok(hwnd != NULL, "CreateWindow failed\n");
win_proc = (void*)SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)test_query_class);
if (tests[i].client)
SET_EXPECT(winproc_GETOBJECT);
hr = CreateStdAccessibleObject(hwnd, OBJID_CLIENT, &IID_IAccessible, (void**)&acc);
ok(hr == S_OK, "CreateStdAccessibleObject failed %x\n", hr);
if (tests[i].client)
CHECK_CALLED(winproc_GETOBJECT);
IAccessible_Release(acc);
if (tests[i].window)
SET_EXPECT(winproc_GETOBJECT);
hr = CreateStdAccessibleObject(hwnd, OBJID_WINDOW, &IID_IAccessible, (void**)&acc);
ok(hr == S_OK, "CreateStdAccessibleObject failed %x\n", hr);
if (tests[i].window)
CHECK_CALLED(winproc_GETOBJECT);
IAccessible_Release(acc);
SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)win_proc);
CloseWindow(hwnd);
winetest_pop_context();
}
}
START_TEST(main)
{
int argc;
@ -1351,6 +1435,7 @@ START_TEST(main)
test_default_client_accessible_object();
test_AccessibleChildren(&Accessible);
test_AccessibleObjectFromEvent();
test_CreateStdAccessibleObject_classes();
unregister_window_class();
CoUninitialize();

View File

@ -19,6 +19,7 @@
#define COBJMACROS
#include "oleacc_private.h"
#include "commctrl.h"
#include "wine/debug.h"
#include "wine/heap.h"
@ -416,6 +417,12 @@ static const IEnumVARIANTVtbl WindowEnumVARIANTVtbl = {
Window_EnumVARIANT_Clone
};
static const struct win_class_data classes[] = {
{WC_LISTBOXW, 0x10000, TRUE},
{L"#32768", 0x10001, TRUE}, /* menu */
{NULL}
};
HRESULT create_window_object(HWND hwnd, const IID *iid, void **obj)
{
Window *window;
@ -428,6 +435,8 @@ HRESULT create_window_object(HWND hwnd, const IID *iid, void **obj)
if(!window)
return E_OUTOFMEMORY;
find_class_data(hwnd, classes);
window->IAccessible_iface.lpVtbl = &WindowVtbl;
window->IOleWindow_iface.lpVtbl = &WindowOleWindowVtbl;
window->IEnumVARIANT_iface.lpVtbl = &WindowEnumVARIANTVtbl;