Initialize COM for application-owned Wine accessibility objects

This commit is contained in:
Storm Dragon committed 2026-10-10 12:41:45 -04:00
1 parent 25e38907d3
commit 6976c83294
4 files changed
+84 -3

No files matched your search

+32 -1
View File
@@ -1,13 +1,34 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
#define COBJMACROS
#include <windows.h>
#include <initguid.h>
#include <oleacc.h>
static HMENU bar, file, edit, nested, context;
static int step;
static HWND marshaledControl;
static HWND button;
static LRESULT CALLBACK provider_proc(HWND window, UINT message, WPARAM wp, LPARAM lp) {
if (message == WM_GETOBJECT && (LONG)lp == OBJID_CLIENT) {
IAccessible *accessible = NULL;
if (SUCCEEDED(CreateStdAccessibleObject(window, OBJID_CLIENT, &IID_IAccessible,
(void **)&accessible))) {
// Returning a marshaled object forces the separate helper to use COM,
// rather than Wine's directly constructed native-control proxy.
LRESULT result = LresultFromObject(&IID_IAccessible, wp, (IUnknown *)accessible);
IAccessible_Release(accessible);
return result;
}
}
return DefWindowProcW(window, message, wp, lp);
}
static LRESULT CALLBACK window_proc(HWND window, UINT message, WPARAM wp, LPARAM lp) {
if (message == WM_TIMER) {
switch (++step) {
case 1:
SetFocus(button);
// Enter File through the application's actual native menu loop.
PostMessageW(window, WM_SYSCOMMAND, SC_KEYMENU, 'f');
break;
@@ -73,6 +94,7 @@ static LRESULT CALLBACK window_proc(HWND window, UINT message, WPARAM wp, LPARAM
int WINAPI WinMain(HINSTANCE instance, HINSTANCE previous, LPSTR args, int show) {
(void)previous; (void)args; (void)show;
if (FAILED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) return 1;
WNDCLASSW cls = {0};
cls.hInstance = instance;
cls.lpszClassName = L"WineAccessMenuFixture";
@@ -92,15 +114,24 @@ int WINAPI WinMain(HINSTANCE instance, HINSTANCE previous, LPSTR args, int show)
HWND window = CreateWindowW(cls.lpszClassName, L"Wine menu fixture", WS_OVERLAPPEDWINDOW,
120, 120, 400, 240, NULL, bar, instance, NULL);
ShowWindow(window, SW_SHOW);
HWND button = CreateWindowW(L"Button", L"Return to control", WS_CHILD | WS_VISIBLE | WS_TABSTOP,
button = CreateWindowW(L"Button", L"Return to control", WS_CHILD | WS_VISIBLE | WS_TABSTOP,
10, 10, 200, 30, window, NULL, instance, NULL);
cls.lpszClassName = L"WineAccessMarshaledFixture";
cls.lpfnWndProc = provider_proc;
RegisterClassW(&cls);
marshaledControl = CreateWindowW(cls.lpszClassName, L"Application-owned accessibility",
WS_CHILD | WS_VISIBLE | WS_TABSTOP,
10, 60, 250, 30, window, NULL, instance, NULL);
SetForegroundWindow(window);
SetFocus(button);
SetFocus(marshaledControl);
NotifyWinEvent(EVENT_OBJECT_FOCUS, marshaledControl, OBJID_CLIENT, CHILDID_SELF);
SetTimer(window, 1, 400, NULL);
MSG message;
while (GetMessageW(&message, NULL, 0, 0) > 0) {
TranslateMessage(&message); DispatchMessageW(&message);
}
DestroyMenu(context);
CoUninitialize();
return 0;
}