Read native Wine list-view rows in 32-bit and 64-bit applications

This commit is contained in:
Storm Dragon committed 2026-10-10 02:03:56 -04:00
1 parent 9aad6748e0
commit d7ea005a1f
8 files changed
+356 -4

No files matched your search

+27 -3
View File
@@ -16,10 +16,13 @@ from gi.repository import Gio, GLib
parser = argparse.ArgumentParser()
parser.add_argument("--build-dir", default="build")
parser.add_argument("--session", action="store_true")
parser.add_argument("--fixture", choices=("menu", "edit", "notepad"), default="menu")
parser.add_argument("--fixture", choices=("menu", "edit", "notepad", "list"), default="menu")
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 != "list":
parser.error("32-bit checks currently require --fixture list")
if (args.late_helper or args.restart_helper) and args.fixture != "edit":
parser.error("helper lifecycle checks require --fixture edit")
build = Path(args.build_dir).resolve()
@@ -27,6 +30,7 @@ if not args.session:
sys.exit(subprocess.call(["dbus-run-session", "--", sys.executable,
__file__, "--session", "--build-dir", str(build),
"--fixture", args.fixture,
*(["--32-bit"] if args.is32Bit else []),
*(["--late-helper"] if args.late_helper else []),
*(["--restart-helper"] if args.restart_helper else [])]))
@@ -56,9 +60,10 @@ with tempfile.TemporaryDirectory(prefix="wine-access-menus-") as temporary:
ready = Path(temporary) / "ready"
env["WINE_ACCESS_FIXTURE_READY"] = "Z:" + str(ready).replace("/", "\\")
fixture = Path(temporary) / "menu-fixture.exe"
subprocess.run(["x86_64-w64-mingw32-gcc", "-Wall", "-Wextra", "-mwindows",
compiler = "i686-w64-mingw32-gcc" if args.is32Bit else "x86_64-w64-mingw32-gcc"
subprocess.run([compiler, "-Wall", "-Wextra", "-mwindows",
"-o", str(fixture), str(Path(__file__).with_name(args.fixture + "_fixture.c")),
"-luser32"], check=True)
"-luser32", "-lcomctl32"], check=True)
helper = None
app = None
try:
@@ -104,6 +109,25 @@ with tempfile.TemporaryDirectory(prefix="wine-access-menus-") as temporary:
focused = event[0]
elif event[1] == "text":
assert event[0] == focused, f"text sent without establishing focus: {event!r}"
if args.fixture == "list":
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] == "Required components" and
e[4] == "Pending, Runtime & tools β" and e[7:9] == (1, 2)
and e[5] == "" for e in listEvents), "unselected initial row or label missing"
assert any(e[1] == "selection" and e[4] == "Installed, Second component" and
e[7:9] == (2, 2) for e in listEvents), "Down lost second row/columns"
assert any(e[1] == "selection" and e[4] == "Pending, Runtime & tools β" and
e[7:9] == (1, 2) for e in listEvents), "Up lost first row"
assert any(e[1] == "focus" and e[4] == "Pending, Runtime & tools β" and
e[5] == "selected" for e in listEvents), "return to list lost selection"
assert any(e[4] == "Ready, Runtime & tools β" for e in listEvents), "value event lost changed row text"
assert any(e[4] == "" and e[7:9] == (0, 0) for e in listEvents), "empty list retained stale row"
assert any(e[2] == "Return to control" for e in events), "button focus missing"
assert not any(e[2] == "List1" for e in events), "generic MSAA client leaked"
print("PASS: native list focus, columns, Unicode, navigation, return, and empty list")
sys.exit(0)
if args.fixture == "notepad":
dialogEvents = [e for e in events if e[2] in ("Yes", "No", "Cancel")]
for event in dialogEvents: