138 lines
5.2 KiB
C
138 lines
5.2 KiB
C
// 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;
|
|
case 2: case 3:
|
|
PostMessageW(window, WM_KEYDOWN, VK_DOWN, 1);
|
|
break;
|
|
case 4:
|
|
PostMessageW(window, WM_KEYDOWN, VK_RIGHT, 1);
|
|
break;
|
|
case 5:
|
|
PostMessageW(window, WM_KEYDOWN, VK_ESCAPE, 1);
|
|
break;
|
|
case 6:
|
|
PostMessageW(window, WM_KEYDOWN, VK_ESCAPE, 1);
|
|
break;
|
|
case 7:
|
|
// Context menus use a separate HMENU, unrelated to the menu bar.
|
|
TrackPopupMenu(context, TPM_LEFTALIGN, 200, 200, 0, window, NULL);
|
|
break;
|
|
case 8:
|
|
PostMessageW(window, WM_KEYDOWN, VK_DOWN, 1);
|
|
break;
|
|
case 9:
|
|
PostMessageW(window, WM_KEYDOWN, VK_ESCAPE, 1);
|
|
break;
|
|
case 10:
|
|
AppendMenuW(file, MF_STRING | MF_CHECKED | MF_GRAYED, 104, L"Pinned && &offline\tCtrl+P");
|
|
/* fall through */
|
|
case 11:
|
|
// Also exercise checked/disabled items and duplicate notifications.
|
|
SendMessageW(window, WM_MENUSELECT, MAKEWPARAM(104, MF_CHECKED | MF_GRAYED), (LPARAM)file);
|
|
break;
|
|
case 12:
|
|
SendMessageW(window, WM_MENUSELECT, MAKEWPARAM(0, 0xffff), 0);
|
|
break;
|
|
case 13:
|
|
SendMessageW(window, WM_MENUSELECT, MAKEWPARAM(104, MF_CHECKED | MF_GRAYED), (LPARAM)file);
|
|
break;
|
|
case 14:
|
|
PostMessageW(window, WM_SYSCOMMAND, SC_KEYMENU, 'f');
|
|
break;
|
|
case 15:
|
|
// Move from Open to the submenu using ordinary menu navigation.
|
|
PostMessageW(window, WM_KEYDOWN, VK_DOWN, 1);
|
|
PostMessageW(window, WM_KEYDOWN, VK_DOWN, 1);
|
|
PostMessageW(window, WM_KEYDOWN, VK_DOWN, 1);
|
|
break;
|
|
case 16:
|
|
PostMessageW(window, WM_KEYDOWN, VK_RIGHT, 1);
|
|
break;
|
|
case 17: case 18: case 19:
|
|
PostMessageW(window, WM_KEYDOWN, VK_ESCAPE, 1);
|
|
break;
|
|
default:
|
|
DestroyWindow(window);
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
if (message == WM_DESTROY) { PostQuitMessage(0); return 0; }
|
|
return DefWindowProcW(window, message, wp, lp);
|
|
}
|
|
|
|
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";
|
|
cls.lpfnWndProc = window_proc;
|
|
RegisterClassW(&cls);
|
|
bar = CreateMenu(); file = CreatePopupMenu(); edit = CreatePopupMenu();
|
|
nested = CreatePopupMenu(); context = CreatePopupMenu();
|
|
AppendMenuW(file, MF_STRING, 101, L"&Open\tCtrl+O");
|
|
AppendMenuW(file, MF_STRING | MF_CHECKED, 102, L"&Word wrap");
|
|
AppendMenuW(file, MF_STRING | MF_CHECKED | MF_GRAYED, 103, L"Save && &close\tCtrl+S");
|
|
AppendMenuW(nested, MF_STRING, 401, L"&Nested action");
|
|
AppendMenuW(file, MF_POPUP, (UINT_PTR)nested, L"&Favorites");
|
|
AppendMenuW(edit, MF_STRING, 302, L"&Cut\tCtrl+X");
|
|
AppendMenuW(context, MF_STRING, 201, L"&Context action");
|
|
AppendMenuW(bar, MF_POPUP, (UINT_PTR)file, L"&File");
|
|
AppendMenuW(bar, MF_POPUP, (UINT_PTR)edit, L"&Edit");
|
|
HWND window = CreateWindowW(cls.lpszClassName, L"Wine menu fixture", WS_OVERLAPPEDWINDOW,
|
|
120, 120, 400, 240, NULL, bar, instance, NULL);
|
|
ShowWindow(window, SW_SHOW);
|
|
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;
|
|
}
|