Merge branch 'deedra'
This commit is contained in:
commit
4c47cc5fc4
5 files changed
+112
-12
No files matched your search
+17
-10
@@ -304,9 +304,13 @@ Ctrl+End line reading, and Up/Down navigation in a read-only multiline output
|
||||
control. Typing checks include repeated letters, spaces, Enter/Tab, accented
|
||||
characters, surrogate pairs, selection replacement, documents beyond the full
|
||||
snapshot limit, and silence for password/background/read-only fields and
|
||||
input rejected at the text limit. Both 32-bit and 64-bit fixtures use the same
|
||||
assertions. Lifecycle variants attach after the control has focus or
|
||||
restart the helper without closing it. Every text action must have an established
|
||||
input rejected at the text limit. Command-history checks consume queued Up/Down
|
||||
before dispatch, then replace the text and move the caret as MUSHclient does.
|
||||
They require ordered, single announcements for equal-length and rapid recalls
|
||||
and empty input, with no password, background or unrelated programmatic output.
|
||||
Both 32-bit and 64-bit fixtures use the same assertions. Lifecycle variants
|
||||
attach after the control has focus or restart the helper without closing it.
|
||||
Every text action must have an established
|
||||
focus source, matching the Go reader's filtering contract.
|
||||
|
||||
The Notepad fixture launches Wine's actual `notepad.exe` and uses `SendInput`
|
||||
@@ -315,13 +319,16 @@ It checks resulting document text as well as recorded accessibility output. Thes
|
||||
tests use a recording D-Bus service; they do not run the full reader or prove
|
||||
audible typing echo, physical keys, or a physical braille display.
|
||||
|
||||
For live MUSHclient acceptance, install the helper and reopen MUSHclient so the
|
||||
updated 32-bit DLL can load. In the command field, check Left/Right and
|
||||
Ctrl+Left/Right feedback without submitting a command. Use Ctrl+Tab to reach
|
||||
the read-only output notepad supplied by the Aardwolf review-buffer plugin;
|
||||
check Up/Down line reading and Left/Right characters there, then return to
|
||||
the command field. Check plugin menus and dialogs still work, and repeat after
|
||||
restarting the reader. These hooks provide caret feedback; independent review
|
||||
For live MUSHclient acceptance, install the helper, restart Cthulhu and reopen
|
||||
MUSHclient so the updated 32-bit DLL can load. In the command field, check Left/Right and
|
||||
Ctrl+Left/Right feedback without submitting a command. Use Up/Down to recall
|
||||
existing command history. Check each recalled command is spoken once,
|
||||
including equal-length entries and `blank` when returning to empty input.
|
||||
Do not submit recalled commands just to test speech.
|
||||
Use Ctrl+Tab to reach the read-only output notepad supplied by the Aardwolf
|
||||
review-buffer plugin; check Up/Down line reading and Left/Right characters
|
||||
there, then return to the command field. Check plugin menus and dialogs still
|
||||
work, and repeat after restarting the reader. These hooks provide caret feedback; independent review
|
||||
commands use the optional flat-review protocol described above. Native braille
|
||||
routing into Wine text remains unsupported.
|
||||
|
||||
|
||||
+55
-1
@@ -18,8 +18,24 @@ static void register_control(HINSTANCE instance, const WCHAR *nativeName, const
|
||||
static const WCHAR *editClass = L"Edit";
|
||||
#endif
|
||||
|
||||
static HWND editor, password;
|
||||
static HWND editor, password, history;
|
||||
static int step;
|
||||
static int history_position;
|
||||
|
||||
// Model MUSHclient's PreTranslateMessage: consume queued arrows before the
|
||||
// Edit procedure, then use SetWindowText and SetSel to recall a command.
|
||||
static BOOL history_input(const MSG *message) {
|
||||
if (message->hwnd != history || message->message != WM_KEYDOWN ||
|
||||
(message->wParam != VK_UP && message->wParam != VK_DOWN)) return FALSE;
|
||||
if (message->wParam == VK_UP && history_position < 2) ++history_position;
|
||||
else if (message->wParam == VK_DOWN && history_position > 0) --history_position;
|
||||
else return TRUE;
|
||||
const WCHAR *commands[] = {L"", L"history north", L"history south"};
|
||||
SetWindowTextW(history, commands[history_position]);
|
||||
int length = GetWindowTextLengthW(history);
|
||||
SendMessageW(history, EM_SETSEL, length, length);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void key(UINT key, BOOL control, BOOL shift) {
|
||||
BYTE saved[256], state[256];
|
||||
@@ -194,6 +210,43 @@ static LRESULT CALLBACK window_proc(HWND window, UINT message, WPARAM wp, LPARAM
|
||||
SendMessageW(editor, WM_CHAR, L'%', 1);
|
||||
if (GetWindowTextLengthW(editor) != 4) ExitProcess(2);
|
||||
break;
|
||||
case 41:
|
||||
// Keep this field away from the managed-label regression's static labels.
|
||||
history = CreateWindowW(editClass, L"", WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL,
|
||||
100, 150, 300, 25, window, NULL, GetModuleHandleW(NULL), NULL);
|
||||
SetFocus(history);
|
||||
break;
|
||||
case 42: PostMessageW(history, WM_KEYDOWN, VK_UP, 1); break;
|
||||
case 43: PostMessageW(history, WM_KEYDOWN, VK_UP, 1); break;
|
||||
case 44: PostMessageW(history, WM_KEYDOWN, VK_DOWN, 1); break;
|
||||
case 45: PostMessageW(history, WM_KEYDOWN, VK_DOWN, 1); break;
|
||||
case 46:
|
||||
// Rapid recalls must stay ordered, including equal-length commands.
|
||||
PostMessageW(history, WM_KEYDOWN, VK_UP, 1);
|
||||
PostMessageW(history, WM_KEYDOWN, VK_UP, 1);
|
||||
PostMessageW(history, WM_KEYDOWN, VK_DOWN, 1);
|
||||
break;
|
||||
case 47:
|
||||
// Ordinary navigation after a recall must use the refreshed snapshot.
|
||||
PostMessageW(history, WM_KEYDOWN, VK_LEFT, 1);
|
||||
PostMessageW(history, WM_KEYDOWN, VK_RIGHT, 1);
|
||||
break;
|
||||
case 48:
|
||||
SetWindowTextW(history, L"programmatic history sentinel");
|
||||
PostMessageW(history, WM_KEYDOWN, VK_DOWN, 1);
|
||||
break;
|
||||
case 49:
|
||||
PostMessageW(history, WM_KEYDOWN, VK_DOWN, 1); // no history change
|
||||
break;
|
||||
case 50:
|
||||
SendMessageW(history, EM_SETPASSWORDCHAR, L'*', 0);
|
||||
PostMessageW(history, WM_KEYDOWN, VK_UP, 1);
|
||||
break;
|
||||
case 51:
|
||||
SetFocus(password);
|
||||
SendMessageW(history, EM_SETPASSWORDCHAR, 0, 0);
|
||||
PostMessageW(history, WM_KEYDOWN, VK_UP, 1); // background recall
|
||||
break;
|
||||
default:
|
||||
DestroyWindow(window); break;
|
||||
}
|
||||
@@ -245,6 +298,7 @@ int WINAPI WinMain(HINSTANCE instance, HINSTANCE previous, LPSTR args, int show)
|
||||
SetTimer(window, 1, 1500, NULL);
|
||||
MSG message;
|
||||
while (GetMessageW(&message, NULL, 0, 0) > 0) {
|
||||
if (history_input(&message)) continue;
|
||||
TranslateMessage(&message); DispatchMessageW(&message);
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -312,6 +312,13 @@ with tempfile.TemporaryDirectory(prefix="wine-access-menus-") as temporary:
|
||||
typed = [e[2] for e in text_events if e[1] == "text" and "kind=8" in e[5]]
|
||||
assert typed == ["z", "z", "space", "\u00e9", "\U0001f600", "new line", "tab", "q", "L", "\U0001f600"], f"typing echo missing or incorrect: {typed!r}"
|
||||
assert not any(e[1] == "text" and e[2] in ("!", "@", "~", "%") for e in events), "rejected, password or background typing leaked"
|
||||
history_focus = next(e[0] for e in text_events
|
||||
if e[1] == "focus" and e[4] == "blank")
|
||||
history_actions = [e[2] for e in text_events
|
||||
if e[0] == history_focus and e[1] == "text"]
|
||||
assert history_actions == ["history north", "history south", "history north", "blank",
|
||||
"history north", "history south", "history north", "h", "blank", "blank"], \
|
||||
f"command history missing, reordered, duplicated or leaked: {history_actions!r}"
|
||||
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"
|
||||
|
||||
Reference in new issue
Block a user