Read Windows Forms login fields and associate their labels
This commit is contained in:
1 parent
d7ea005a1f
commit
25e38907d3
9 files changed
+149
-25
No files matched your search
@@ -99,6 +99,37 @@ Check arrows and Tab/Shift+Tab back to Install/Cancel. Also check a multirow
|
||||
native list, normal menus, editor navigation, switching to a native Linux
|
||||
application, and reader shutdown. Verify speech and physical braille separately.
|
||||
|
||||
## Windows Forms login fields
|
||||
|
||||
```sh
|
||||
xvfb-run -a python3 tests/menu_integration.py --build-dir build --fixture winforms
|
||||
xvfb-run -a python3 tests/menu_integration.py --build-dir build --fixture winforms --late-helper
|
||||
```
|
||||
|
||||
This reuses the editing workflow with native controls registered under
|
||||
Windows Forms class names and labels created after the fields. It verifies
|
||||
`Email, edit` focus, `Password, edit, password` with no protected value,
|
||||
navigation/selection/deletion and unrelated-label exclusion. It does not run
|
||||
the .NET framework itself or establish live BARD speech/braille acceptance.
|
||||
The ordinary and late-helper managed fixtures passed on October 10, together
|
||||
with the existing native editor, Notepad, menu and 32/64-bit list regressions.
|
||||
|
||||
Read-only inspection of the BARD login on October 10 confirmed a 64-bit
|
||||
Windows Forms application with `WindowsForms10.EDIT.app.*` email/password
|
||||
controls, adjacent visible `Email:`/`Password:` labels, and the `ES_PASSWORD`
|
||||
style on the password field. Its MSAA objects were unavailable to the probe;
|
||||
the previous exact `Edit` class checks missed both fields. The helper now
|
||||
recognizes the managed native-control class names in its standard reader and
|
||||
editor hook. Existing native controls keep their original label lookup.
|
||||
|
||||
After installing the updated package, close BARD and restart Cthulhu so its
|
||||
helper and the application load the new DLL together. Reopen BARD in its own
|
||||
prefix. Tab and Shift+Tab between Email, Password, Sign in and Work Offline.
|
||||
Expect labels and edit/password roles; navigate and select ordinary email
|
||||
text, and confirm password contents stay excluded. Recheck native Notepad,
|
||||
menus, the installer list and switching to Linux applications. Typing echo
|
||||
and routable Wine review remain separate unfinished features.
|
||||
|
||||
## Live Notepad acceptance
|
||||
|
||||
Install all three helper files together and use the matching Cthulhu-Go source.
|
||||
|
||||
+32
-4
@@ -1,6 +1,21 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef WINE_ACCESS_WINFORMS_FIXTURE
|
||||
static const WCHAR *editClass = L"WindowsForms10.EDIT.app.0.fixture_r7_ad1";
|
||||
static const WCHAR *staticClass = L"WindowsForms10.STATIC.app.0.fixture_r7_ad1";
|
||||
static void register_control(HINSTANCE instance, const WCHAR *nativeName, const WCHAR *managedName) {
|
||||
WNDCLASSEXW cls = {0};
|
||||
cls.cbSize = sizeof(cls);
|
||||
if (!GetClassInfoExW(NULL, nativeName, &cls)) ExitProcess(3);
|
||||
cls.hInstance = instance;
|
||||
cls.lpszClassName = managedName;
|
||||
if (!RegisterClassExW(&cls)) ExitProcess(4);
|
||||
}
|
||||
#else
|
||||
static const WCHAR *editClass = L"Edit";
|
||||
#endif
|
||||
|
||||
static HWND editor, password;
|
||||
static int step;
|
||||
|
||||
@@ -115,17 +130,30 @@ 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;
|
||||
#ifdef WINE_ACCESS_WINFORMS_FIXTURE
|
||||
register_control(instance, L"Edit", editClass);
|
||||
register_control(instance, L"Static", staticClass);
|
||||
#endif
|
||||
WNDCLASSW cls = {0};
|
||||
cls.hInstance = instance; cls.lpszClassName = L"WineAccessEditFixture";
|
||||
cls.lpfnWndProc = window_proc; RegisterClassW(&cls);
|
||||
HWND window = CreateWindowW(cls.lpszClassName, L"Wine editor fixture", WS_OVERLAPPEDWINDOW,
|
||||
120, 120, 500, 300, NULL, NULL, instance, NULL);
|
||||
editor = CreateWindowW(L"Edit", L"alpha beta\r\nsecond line",
|
||||
editor = CreateWindowW(editClass, L"alpha beta\r\nsecond line",
|
||||
WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
|
||||
10, 10, 450, 150, window, NULL, instance, NULL);
|
||||
password = CreateWindowW(L"Edit", L"private-password-fixture",
|
||||
WS_CHILD | WS_VISIBLE | ES_PASSWORD, 10, 180, 300, 30,
|
||||
100, 10, 350, 150, window, NULL, instance, NULL);
|
||||
password = CreateWindowW(editClass, L"private-password-fixture",
|
||||
WS_CHILD | WS_VISIBLE | ES_PASSWORD, 100, 180, 300, 30,
|
||||
window, NULL, instance, NULL);
|
||||
#ifdef WINE_ACCESS_WINFORMS_FIXTURE
|
||||
// Labels are created after the fields, like the observed BARD login.
|
||||
CreateWindowW(staticClass, L"Password:", WS_CHILD | WS_VISIBLE, 10, 183, 85, 20,
|
||||
window, NULL, instance, NULL);
|
||||
CreateWindowW(staticClass, L"Email:", WS_CHILD | WS_VISIBLE, 10, 13, 60, 20,
|
||||
window, NULL, instance, NULL);
|
||||
CreateWindowW(staticClass, L"Unrelated:", WS_CHILD | WS_VISIBLE, 10, 220, 80, 20,
|
||||
window, NULL, instance, NULL);
|
||||
#endif
|
||||
HMENU menu = CreateMenu();
|
||||
AppendMenuW(menu, MF_STRING, 1, L"Test menu");
|
||||
SetMenu(window, menu);
|
||||
|
||||
@@ -16,15 +16,15 @@ 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", "list"), default="menu")
|
||||
parser.add_argument("--fixture", choices=("menu", "edit", "notepad", "list", "winforms"), 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")
|
||||
if (args.late_helper or args.restart_helper) and args.fixture not in ("edit", "winforms"):
|
||||
parser.error("helper lifecycle checks require --fixture edit or --fixture winforms")
|
||||
build = Path(args.build_dir).resolve()
|
||||
if not args.session:
|
||||
sys.exit(subprocess.call(["dbus-run-session", "--", sys.executable,
|
||||
@@ -61,8 +61,10 @@ with tempfile.TemporaryDirectory(prefix="wine-access-menus-") as temporary:
|
||||
env["WINE_ACCESS_FIXTURE_READY"] = "Z:" + str(ready).replace("/", "\\")
|
||||
fixture = Path(temporary) / "menu-fixture.exe"
|
||||
compiler = "i686-w64-mingw32-gcc" if args.is32Bit else "x86_64-w64-mingw32-gcc"
|
||||
sourceName = "edit" if args.fixture == "winforms" else args.fixture
|
||||
subprocess.run([compiler, "-Wall", "-Wextra", "-mwindows",
|
||||
"-o", str(fixture), str(Path(__file__).with_name(args.fixture + "_fixture.c")),
|
||||
*(["-DWINE_ACCESS_WINFORMS_FIXTURE"] if args.fixture == "winforms" else []),
|
||||
"-o", str(fixture), str(Path(__file__).with_name(sourceName + "_fixture.c")),
|
||||
"-luser32", "-lcomctl32"], check=True)
|
||||
helper = None
|
||||
app = None
|
||||
@@ -142,7 +144,7 @@ with tempfile.TemporaryDirectory(prefix="wine-access-menus-") as temporary:
|
||||
assert any(e[3] == "edit" and e[4] == "otepad second line" for e in text_events), "Notepad menu return missing"
|
||||
print("PASS: actual Wine Notepad keyboard characters, words, lines, selection, deletion, and menu return")
|
||||
sys.exit(0)
|
||||
if args.fixture == "edit":
|
||||
if args.fixture in ("edit", "winforms"):
|
||||
text_events = [e for e in events if e[0].endswith(":text")]
|
||||
for event in text_events:
|
||||
print(event[2:7])
|
||||
@@ -165,6 +167,12 @@ with tempfile.TemporaryDirectory(prefix="wine-access-menus-") as temporary:
|
||||
assert sum(e[2] == "new line deleted" and "kind=4" in e[5] for e in text_events) == 1, "CRLF Delete feedback missing"
|
||||
assert any(e[4] == "x" * 1022 for e in text_events), "truncated surrogate discarded line"
|
||||
assert "d" in spoken and "undo restored" in spoken, "Undo left stale text snapshot"
|
||||
if args.fixture == "winforms":
|
||||
assert any(e[2] == "Email" and e[3] == "edit" and e[4] == "alpha beta"
|
||||
for e in text_events), "managed email label/focus missing"
|
||||
assert any(e[2] == "Password" and e[3] == "edit" and e[6] == "password"
|
||||
and e[4] == "" for e in text_events), "managed password label/protection missing"
|
||||
assert not any(e[2] == "Unrelated" for e in text_events), "unrelated label associated with field"
|
||||
print("PASS: editor focus, characters, words, lines, selection, deletion, Unicode, passwords, and read-only controls")
|
||||
sys.exit(0)
|
||||
menus = [event for event in events if ":menu:" in event[0]]
|
||||
|
||||
Reference in new issue
Block a user