Some lists were not auto reading results. Hopefully fixed.

This commit is contained in:
Storm Dragon committed 2026-10-12 04:55:31 -04:00
1 parent 0f59809e9a
commit d9aa40e16c
6 files changed
+151 -4

No files matched your search

+17
View File
@@ -31,6 +31,23 @@ characters, selections, deletion, protected fields and keypad review with live
speech and braille. When an Orca integration exists, repeat those workflows
with `--reader orca`, including return to Linux controls and reader restart.
## List-box navigation
For list-box navigation, run these checks sequentially:
```sh
xvfb-run -a python3 tests/menu_integration.py --build-dir build --fixture listbox
xvfb-run -a python3 tests/menu_integration.py --build-dir build --fixture listbox --32-bit
```
They cover native Up/Down navigation, Unicode text, positions, focus return,
duplicate suppression, background changes and an emptied list. After installing
the helper and restarting the reader, open AudioQuake's LDL tutorial/example map
chooser and use Up/Down without leaving the list. Check that speech and braille
follow each map and position, then Tab to OK/Cancel and Shift+Tab back. Recheck
combo-box arrows, ordinary list views, tabs/trees and return from Wine menus.
Recorded events alone do not establish audible speech or physical braille.
## Virtual desktop focus recovery
`xvfb-run -a ctest --test-dir build -R foreground-focus --output-on-failure`
+62
View File
@@ -0,0 +1,62 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
#include <windows.h>
static HWND list, button;
static int step;
static LRESULT CALLBACK window_proc(HWND window, UINT message, WPARAM wp, LPARAM lp) {
if (message == WM_TIMER) {
switch (++step) {
case 1: case 2: SendMessageW(list, WM_KEYDOWN, VK_DOWN, 1); break;
case 3: SendMessageW(list, WM_KEYDOWN, VK_UP, 1); break;
case 4: SetFocus(button); break;
case 5:
// A background change must not be announced or steal focus.
SendMessageW(list, LB_INSERTSTRING, 0, (LPARAM)L"Background-only map");
SendMessageW(list, LB_SETCURSEL, 0, 0);
NotifyWinEvent(EVENT_OBJECT_VALUECHANGE, list, OBJID_CLIENT, CHILDID_SELF);
break;
case 6:
if (GetFocus() != button) return 0;
SendMessageW(list, LB_DELETESTRING, 0, 0);
SendMessageW(list, LB_SETCURSEL, 0, 0);
SetFocus(list);
break;
case 7: SendMessageW(list, LB_RESETCONTENT, 0, 0); break;
default: DestroyWindow(window);
}
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;
WNDCLASSW cls = {0};
cls.hInstance = instance;
cls.lpszClassName = L"WineAccessListBoxFixture";
cls.lpfnWndProc = window_proc;
RegisterClassW(&cls);
HWND window = CreateWindowW(cls.lpszClassName, L"Select map", WS_OVERLAPPEDWINDOW,
120, 120, 600, 300, NULL, NULL, instance, NULL);
CreateWindowW(L"Static", L"Tutorial maps", WS_CHILD | WS_VISIBLE,
10, 10, 550, 30, window, NULL, instance, NULL);
list = CreateWindowW(L"ListBox", L"", WS_CHILD | WS_VISIBLE | WS_TABSTOP | LBS_NOTIFY,
10, 50, 550, 160, window, NULL, instance, NULL);
button = CreateWindowW(L"Button", L"OK", WS_CHILD | WS_VISIBLE | WS_TABSTOP,
10, 220, 100, 30, window, NULL, instance, NULL);
SendMessageW(list, LB_ADDSTRING, 0, (LPARAM)L"First map");
SendMessageW(list, LB_ADDSTRING, 0, (LPARAM)L"Second map β");
SendMessageW(list, LB_ADDSTRING, 0, (LPARAM)L"Third map");
SendMessageW(list, LB_SETCURSEL, 0, 0);
ShowWindow(window, SW_SHOW);
SetForegroundWindow(window);
SetFocus(list);
SetTimer(window, 1, 500, NULL);
MSG message;
while (GetMessageW(&message, NULL, 0, 0) > 0) {
TranslateMessage(&message); DispatchMessageW(&message);
}
return 0;
}
+21 -3
View File
@@ -18,15 +18,15 @@ parser = argparse.ArgumentParser()
parser.add_argument("--build-dir", default="build")
parser.add_argument("--session", action="store_true")
parser.add_argument("--reader", choices=("cthulhu", "orca"))
parser.add_argument("--fixture", choices=("menu", "edit", "notepad", "list", "delphi", "winforms", "controls", "scintilla", "goldwave"), default="menu")
parser.add_argument("--fixture", choices=("menu", "edit", "notepad", "list", "listbox", "delphi", "winforms", "controls", "scintilla", "goldwave"), default="menu")
parser.add_argument("--notepadpp-exe", type=Path)
parser.add_argument("--goldwave-exe", type=Path)
parser.add_argument("--32-bit", dest="is32Bit", action="store_true")
parser.add_argument("--late-helper", action="store_true")
parser.add_argument("--restart-helper", action="store_true")
args = parser.parse_args()
if args.is32Bit and args.fixture not in ("menu", "edit", "winforms", "list", "delphi", "controls"):
parser.error("32-bit checks currently require --fixture menu, edit, winforms, list, delphi or controls")
if args.is32Bit and args.fixture not in ("menu", "edit", "winforms", "list", "listbox", "delphi", "controls"):
parser.error("32-bit checks currently require --fixture menu, edit, winforms, list, listbox, delphi or controls")
if (args.late_helper or args.restart_helper) and args.fixture not in ("edit", "winforms", "scintilla"):
parser.error("helper lifecycle checks require --fixture edit, winforms or scintilla")
if args.fixture == "scintilla" and (not args.notepadpp_exe or not args.notepadpp_exe.is_file()):
@@ -203,6 +203,24 @@ with tempfile.TemporaryDirectory(prefix="wine-access-menus-") as temporary:
assert not any(e[2] == "List1" for e in events), "Delphi generic client leaked"
print("PASS: Delphi list labels, rows, keyboard navigation, checkbox toggles, return, buttons and empty state")
sys.exit(0)
if args.fixture == "listbox":
listEvents = [e for e in events if e[3] == "list"]
for event in listEvents:
print(event[1:9])
assert any(e[1] == "focus" and e[2] == "Tutorial maps" and
e[4] == "First map" and e[7:9] == (1, 3)
for e in listEvents), "initial map or label missing"
selections = [(e[4], e[7], e[8]) for e in listEvents if e[1] == "selection"]
assert selections == [("Second map β", 2, 3), ("Third map", 3, 3),
("Second map β", 2, 3), ("", 0, 0)], \
f"map navigation/empty state missing or duplicated: {selections}"
assert sum(e[1] == "focus" and e[4] == "First map"
for e in listEvents) == 2, "return to map list missing or duplicated"
assert any(e[1] == "focus" and e[2] == "OK" for e in events), "button focus missing"
assert not any("Background-only" in str(e) for e in events), "background map leaked"
assert len({e[0] for e in listEvents}) == 1, "map events changed source identity"
print("PASS: list-box arrows, Unicode, positions, focus return, background exclusion and empty state")
sys.exit(0)
if args.fixture == "list":
listEvents = [e for e in events if e[3] == "list"]
for event in listEvents: