119 lines
4.3 KiB
C
119 lines
4.3 KiB
C
// SPDX-License-Identifier: LGPL-2.1-or-later
|
|
// Drive Wine's actual Notepad; the standard-control fixture covers edge cases.
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
|
|
static DWORD notepad_pid;
|
|
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) {
|
|
(void)unused;
|
|
DWORD pid;
|
|
GetWindowThreadProcessId(window, &pid);
|
|
if (pid == notepad_pid && IsWindowVisible(window) &&
|
|
FindWindowExW(window, NULL, L"Edit", NULL)) {
|
|
notepad = window;
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static void key(WORD vk, BOOL control, BOOL shift) {
|
|
INPUT input[6] = {0};
|
|
UINT count = 0;
|
|
if (control) { input[count].ki.wVk = VK_CONTROL; ++count; }
|
|
if (shift) { input[count].ki.wVk = VK_SHIFT; ++count; }
|
|
input[count].ki.wVk = vk; ++count;
|
|
input[count].ki.wVk = vk; input[count].ki.dwFlags = KEYEVENTF_KEYUP; ++count;
|
|
if (shift) { input[count].ki.wVk = VK_SHIFT; input[count].ki.dwFlags = KEYEVENTF_KEYUP; ++count; }
|
|
if (control) { input[count].ki.wVk = VK_CONTROL; input[count].ki.dwFlags = KEYEVENTF_KEYUP; ++count; }
|
|
for (UINT i = 0; i < count; ++i) input[i].type = INPUT_KEYBOARD;
|
|
if (SendInput(count, input, sizeof(INPUT)) != count) ExitProcess(3);
|
|
Sleep(200);
|
|
}
|
|
|
|
int WINAPI WinMain(HINSTANCE instance, HINSTANCE previous, LPSTR args, int show) {
|
|
(void)instance; (void)previous; (void)args; (void)show;
|
|
STARTUPINFOW startup = {0};
|
|
PROCESS_INFORMATION process = {0};
|
|
startup.cb = sizeof(startup);
|
|
WCHAR command[] = L"notepad.exe";
|
|
if (!CreateProcessW(NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &process)) return 2;
|
|
notepad_pid = process.dwProcessId;
|
|
for (int i = 0; i < 100 && !notepad; ++i) {
|
|
EnumWindows(find_notepad, 0);
|
|
Sleep(50);
|
|
}
|
|
int result = 2;
|
|
if (notepad) {
|
|
HWND edit = FindWindowExW(notepad, NULL, L"Edit", NULL);
|
|
SetForegroundWindow(notepad);
|
|
Sleep(400);
|
|
key('Z', FALSE, FALSE);
|
|
key('Z', FALSE, FALSE);
|
|
key(VK_SPACE, FALSE, FALSE);
|
|
key(VK_RETURN, FALSE, FALSE);
|
|
WCHAR typed[16] = {0};
|
|
SendMessageW(edit, WM_GETTEXT, 16, (LPARAM)typed);
|
|
if (lstrcmpW(typed, L"zz \r\n")) {
|
|
fprintf(stderr, "Notepad typing did not reach its edit: units=%d first=%04x foreground=%p expected=%p\n",
|
|
lstrlenW(typed), (unsigned)typed[0], (void *)GetForegroundWindow(), (void *)notepad);
|
|
ExitProcess(2);
|
|
}
|
|
SendMessageW(edit, WM_SETTEXT, 0, (LPARAM)L"hello beta\r\nNotepad second line");
|
|
SendMessageW(edit, EM_SETSEL, 0, 0);
|
|
Sleep(400);
|
|
key(VK_RIGHT, FALSE, FALSE); // e
|
|
key(VK_RIGHT, FALSE, FALSE); // l
|
|
key(VK_RIGHT, FALSE, FALSE); // l
|
|
key(VK_RIGHT, TRUE, FALSE); // beta
|
|
key(VK_DOWN, FALSE, FALSE); // second line
|
|
key(VK_HOME, FALSE, FALSE);
|
|
key(VK_RIGHT, FALSE, TRUE); // N selected
|
|
key(VK_LEFT, FALSE, TRUE); // N unselected
|
|
key(VK_DELETE, FALSE, FALSE);// N deleted
|
|
key(VK_MENU, FALSE, FALSE);
|
|
key(VK_ESCAPE, FALSE, FALSE);
|
|
key(VK_ESCAPE, FALSE, FALSE);
|
|
WCHAR text[80] = {0};
|
|
SendMessageW(edit, WM_GETTEXT, 80, (LPARAM)text);
|
|
if (!lstrcmpW(text, L"hello beta\r\notepad second line")) result = 0;
|
|
else fprintf(stderr, "Notepad final document mismatch: units=%d\n", lstrlenW(text));
|
|
PostMessageW(notepad, WM_CLOSE, 0, 0);
|
|
for (int i = 0; i < 100 && !saveDialog; ++i) {
|
|
EnumWindows(find_save_dialog, 0);
|
|
Sleep(50);
|
|
}
|
|
if (!saveDialog) { fprintf(stderr, "Notepad save dialog missing\n"); 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.
|
|
SendMessageW(edit, EM_SETMODIFY, FALSE, 0);
|
|
PostMessageW(notepad, WM_CLOSE, 0, 0);
|
|
if (WaitForSingleObject(process.hProcess, 3000) != WAIT_OBJECT_0) result = 2;
|
|
}
|
|
CloseHandle(process.hThread);
|
|
CloseHandle(process.hProcess);
|
|
return result;
|
|
}
|