Coupple regressions fixed.
This commit is contained in:
1 parent
39b7488aea
commit
9aad6748e0
7 files changed
+54
-5
No files matched your search
@@ -95,6 +95,9 @@ contents are excluded, and read-only edits do not report unsuccessful deletions.
|
|||||||
Undo refreshes the text snapshot used by subsequent navigation. It can attach to
|
Undo refreshes the text snapshot used by subsequent navigation. It can attach to
|
||||||
an already-focused editor and resume after the helper restarts.
|
an already-focused editor and resume after the helper restarts.
|
||||||
|
|
||||||
|
Backspace reports only the removed text, such as `t`. Delete and Cut retain
|
||||||
|
their deletion feedback, such as `t deleted`.
|
||||||
|
|
||||||
Editor actions use `PresentAccessibleEvent` with event type `text`; actual focus
|
Editor actions use `PresentAccessibleEvent` with event type `text`; actual focus
|
||||||
uses `focus`. Cthulhu-Go must include the corresponding editor-event support so
|
uses `focus`. Cthulhu-Go must include the corresponding editor-event support so
|
||||||
rapid actions and repeated characters bypass focus coalescing. UTF-16 selection
|
rapid actions and repeated characters bypass focus coalescing. UTF-16 selection
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Maintainer: Storm Dragon <storm_dragon@stormux.org>
|
# Maintainer: Storm Dragon <storm_dragon@stormux.org>
|
||||||
pkgname=wine-access-git
|
pkgname=wine-access-git
|
||||||
pkgver=r8.gc5657ee
|
pkgver=r9.g39b7488
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc='Wine accessibility helper with MSAA, NVDA Controller, and Tolk compatibility for Cthulhu'
|
pkgdesc='Wine accessibility helper with MSAA, NVDA Controller, and Tolk compatibility for Cthulhu'
|
||||||
arch=('x86_64')
|
arch=('x86_64')
|
||||||
|
|||||||
+3
-1
@@ -175,7 +175,9 @@ static LRESULT CALLBACK edit_proc(HWND window, UINT message, WPARAM wp, LPARAM l
|
|||||||
(message == WM_CHAR && wp == VK_BACK) ||
|
(message == WM_CHAR && wp == VK_BACK) ||
|
||||||
(message == WM_KEYDOWN && wp == VK_DELETE))) {
|
(message == WM_KEYDOWN && wp == VK_DELETE))) {
|
||||||
lstrcpynW(text, removed, 1024);
|
lstrcpynW(text, removed, 1024);
|
||||||
kind = WINE_ACCESS_TEXT_DELETED; report = TRUE;
|
kind = message == WM_CHAR && wp == VK_BACK
|
||||||
|
? WINE_ACCESS_TEXT_BACKSPACED : WINE_ACCESS_TEXT_DELETED;
|
||||||
|
report = TRUE;
|
||||||
}
|
}
|
||||||
if (report) notify_text(window, kind, text, start, end);
|
if (report) notify_text(window, kind, text, start, end);
|
||||||
state->busy = FALSE;
|
state->busy = FALSE;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#define WINE_ACCESS_TEXT_DELETED 4
|
#define WINE_ACCESS_TEXT_DELETED 4
|
||||||
#define WINE_ACCESS_TEXT_READ 5
|
#define WINE_ACCESS_TEXT_READ 5
|
||||||
#define WINE_ACCESS_TEXT_PASSWORD 6
|
#define WINE_ACCESS_TEXT_PASSWORD 6
|
||||||
|
#define WINE_ACCESS_TEXT_BACKSPACED 7
|
||||||
|
|
||||||
typedef struct WineAccessTextEvent {
|
typedef struct WineAccessTextEvent {
|
||||||
ULONGLONG owner;
|
ULONGLONG owner;
|
||||||
|
|||||||
+9
-1
@@ -91,7 +91,7 @@ Close existing Notepad windows after saving any work so the updated hook can loa
|
|||||||
5. Press Home, Shift+Right twice, then Shift+Left twice. Expect `s selected`,
|
5. Press Home, Shift+Right twice, then Shift+Left twice. Expect `s selected`,
|
||||||
`e selected`, `e unselected`, `s unselected`. Focus stays in the edit area.
|
`e selected`, `e unselected`, `s unselected`. Focus stays in the edit area.
|
||||||
Delete should say `s deleted`. Right followed by Backspace should say
|
Delete should say `s deleted`. Right followed by Backspace should say
|
||||||
`e deleted`; the second line is now `cond line`.
|
`e`; the second line is now `cond line`.
|
||||||
6. Press Alt to enter the menus and Escape to return (Escape again if needed).
|
6. Press Alt to enter the menus and Escape to return (Escape again if needed).
|
||||||
Expect menu labels while navigating and `edit, cond line` on return, not
|
Expect menu labels while navigating and `edit, cond line` on return, not
|
||||||
the start of the document. Arrows must continue to reach Notepad.
|
the start of the document. Arrows must continue to reach Notepad.
|
||||||
@@ -104,3 +104,11 @@ not establish a routable editor buffer. Report the step, exact speech and
|
|||||||
braille, focused control, and any key that behaved differently. For unexpected
|
braille, focused control, and any key that behaved differently. For unexpected
|
||||||
results inspect `~/devel/cthulhu-go.log`; debug `Wine editor feedback` records
|
results inspect `~/devel/cthulhu-go.log`; debug `Wine editor feedback` records
|
||||||
include source IDs, native UTF-16 selection ranges, action kinds and output text.
|
include source IDs, native UTF-16 selection ranges, action kinds and output text.
|
||||||
|
|
||||||
|
The Notepad fixture also opens the unsaved-document dialog and presses Tab,
|
||||||
|
Tab, Shift+Tab and Escape. It records the actual Yes/No/Cancel focus and state
|
||||||
|
sequence. Wine sends a focus-loss state event for the previous button before
|
||||||
|
the new focus event; the Go presenter must suppress that unchanged state
|
||||||
|
presentation. For live acceptance, change the document, close Notepad and
|
||||||
|
verify each Tab announces only the newly focused button, including reverse
|
||||||
|
navigation. Escape must return to the editor without discarding the document.
|
||||||
@@ -105,6 +105,10 @@ with tempfile.TemporaryDirectory(prefix="wine-access-menus-") as temporary:
|
|||||||
elif event[1] == "text":
|
elif event[1] == "text":
|
||||||
assert event[0] == focused, f"text sent without establishing focus: {event!r}"
|
assert event[0] == focused, f"text sent without establishing focus: {event!r}"
|
||||||
if args.fixture == "notepad":
|
if args.fixture == "notepad":
|
||||||
|
dialogEvents = [e for e in events if e[2] in ("Yes", "No", "Cancel")]
|
||||||
|
for event in dialogEvents:
|
||||||
|
print("Save dialog:", event[:7])
|
||||||
|
assert [e[2] for e in dialogEvents if e[1] == "focus"] == ["Yes", "No", "Cancel", "No"], "save dialog focus order changed"
|
||||||
text_events = [e for e in events if e[0].endswith(":text")]
|
text_events = [e for e in events if e[0].endswith(":text")]
|
||||||
spoken = [e[2] for e in text_events]
|
spoken = [e[2] for e in text_events]
|
||||||
for expected in ("e", "l", "beta", "Notepad second line", "N selected",
|
for expected in ("e", "l", "beta", "Notepad second line", "N selected",
|
||||||
@@ -120,7 +124,7 @@ with tempfile.TemporaryDirectory(prefix="wine-access-menus-") as temporary:
|
|||||||
print(event[2:7])
|
print(event[2:7])
|
||||||
spoken = [e[2] for e in text_events]
|
spoken = [e[2] for e in text_events]
|
||||||
for expected in ("l", "beta", "second line", "s selected", "e selected",
|
for expected in ("l", "beta", "second line", "s selected", "e selected",
|
||||||
"e unselected", "s unselected", "s deleted", "e deleted",
|
"e unselected", "s unselected", "s deleted", "e",
|
||||||
"alpha selected", "alpha deleted", "😀"):
|
"alpha selected", "alpha deleted", "😀"):
|
||||||
assert expected in spoken, f"missing editor feedback: {expected!r}"
|
assert expected in spoken, f"missing editor feedback: {expected!r}"
|
||||||
assert any(e[3] == "edit" and e[4] == "alpha beta" for e in text_events), "initial line missing"
|
assert any(e[3] == "edit" and e[4] == "alpha beta" for e in text_events), "initial line missing"
|
||||||
@@ -131,7 +135,10 @@ with tempfile.TemporaryDirectory(prefix="wine-access-menus-") as temporary:
|
|||||||
assert "hello deleted" not in spoken, "replacement misreported as deletion"
|
assert "hello deleted" not in spoken, "replacement misreported as deletion"
|
||||||
assert sum(e[1] == "text" and e[2] == "l" for e in text_events) == 3, "rapid repeated letters lost"
|
assert sum(e[1] == "text" and e[2] == "l" for e in text_events) == 3, "rapid repeated letters lost"
|
||||||
assert any(e[3] == "edit" and e[4] == "menu return line" for e in text_events), "menu return lost caret line"
|
assert any(e[3] == "edit" and e[4] == "menu return line" for e in text_events), "menu return lost caret line"
|
||||||
assert spoken.count("new line deleted") == 2, "CRLF deletion feedback missing"
|
assert any(e[1] == "text" and e[2] == "e" and "kind=7" in e[5] for e in text_events), "Backspace did not report only the removed character"
|
||||||
|
assert "e deleted" not in spoken, "Backspace retained the deletion suffix"
|
||||||
|
assert sum(e[2] == "new line" and "kind=7" in e[5] for e in text_events) == 1, "CRLF Backspace feedback missing"
|
||||||
|
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 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"
|
assert "d" in spoken and "undo restored" in spoken, "Undo left stale text snapshot"
|
||||||
print("PASS: editor focus, characters, words, lines, selection, deletion, Unicode, passwords, and read-only controls")
|
print("PASS: editor focus, characters, words, lines, selection, deletion, Unicode, passwords, and read-only controls")
|
||||||
|
|||||||
@@ -4,6 +4,20 @@
|
|||||||
|
|
||||||
static DWORD notepad_pid;
|
static DWORD notepad_pid;
|
||||||
static HWND notepad;
|
static HWND notepad;
|
||||||
|
static HWND saveDialog;
|
||||||
|
|
||||||
|
static BOOL CALLBACK find_save_dialog(HWND window, LPARAM unused) {
|
||||||
|
(void)unused;
|
||||||
|
DWORD pid;
|
||||||
|
GetWindowThreadProcessId(window, &pid);
|
||||||
|
if (pid == notepad_pid && IsWindowVisible(window) &&
|
||||||
|
GetDlgItem(window, IDYES) && GetDlgItem(window, IDNO) &&
|
||||||
|
GetDlgItem(window, IDCANCEL)) {
|
||||||
|
saveDialog = window;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static BOOL CALLBACK find_notepad(HWND window, LPARAM unused) {
|
static BOOL CALLBACK find_notepad(HWND window, LPARAM unused) {
|
||||||
(void)unused;
|
(void)unused;
|
||||||
@@ -65,6 +79,20 @@ int WINAPI WinMain(HINSTANCE instance, HINSTANCE previous, LPSTR args, int show)
|
|||||||
WCHAR text[80] = {0};
|
WCHAR text[80] = {0};
|
||||||
SendMessageW(edit, WM_GETTEXT, 80, (LPARAM)text);
|
SendMessageW(edit, WM_GETTEXT, 80, (LPARAM)text);
|
||||||
if (!lstrcmpW(text, L"hello beta\r\notepad second line")) result = 0;
|
if (!lstrcmpW(text, L"hello beta\r\notepad second line")) result = 0;
|
||||||
|
PostMessageW(notepad, WM_CLOSE, 0, 0);
|
||||||
|
for (int i = 0; i < 100 && !saveDialog; ++i) {
|
||||||
|
EnumWindows(find_save_dialog, 0);
|
||||||
|
Sleep(50);
|
||||||
|
}
|
||||||
|
if (!saveDialog) result = 2;
|
||||||
|
else {
|
||||||
|
SetForegroundWindow(saveDialog);
|
||||||
|
Sleep(400);
|
||||||
|
key(VK_TAB, FALSE, FALSE); // Yes -> No
|
||||||
|
key(VK_TAB, FALSE, FALSE); // No -> Cancel
|
||||||
|
key(VK_TAB, FALSE, TRUE); // Cancel -> No
|
||||||
|
key(VK_ESCAPE, FALSE, FALSE);
|
||||||
|
}
|
||||||
// Suppress the save prompt only in this test-owned, unsaved document.
|
// Suppress the save prompt only in this test-owned, unsaved document.
|
||||||
SendMessageW(edit, EM_SETMODIFY, FALSE, 0);
|
SendMessageW(edit, EM_SETMODIFY, FALSE, 0);
|
||||||
PostMessageW(notepad, WM_CLOSE, 0, 0);
|
PostMessageW(notepad, WM_CLOSE, 0, 0);
|
||||||
|
|||||||
Reference in new issue
Block a user