user32/tests: Add some clipboard viewer tests.
This commit is contained in:
parent
1a5db69019
commit
4807fd99a7
|
@ -11724,6 +11724,171 @@ static void test_defwinproc(void)
|
|||
DestroyWindow( hwnd);
|
||||
}
|
||||
|
||||
#define clear_clipboard(hwnd) clear_clipboard_(__LINE__, (hwnd))
|
||||
static void clear_clipboard_(int line, HWND hWnd)
|
||||
{
|
||||
BOOL succ;
|
||||
succ = OpenClipboard(hWnd);
|
||||
ok_(__FILE__, line)(succ, "OpenClipboard failed, err=%u\n", GetLastError());
|
||||
succ = EmptyClipboard();
|
||||
ok_(__FILE__, line)(succ, "EmptyClipboard failed, err=%u\n", GetLastError());
|
||||
succ = CloseClipboard();
|
||||
ok_(__FILE__, line)(succ, "CloseClipboard failed, err=%u\n", GetLastError());
|
||||
}
|
||||
|
||||
#define expect_HWND(expected, got) expect_HWND_(__LINE__, (expected), (got))
|
||||
static void expect_HWND_(int line, HWND expected, HWND got)
|
||||
{
|
||||
ok_(__FILE__, line)(got==expected, "Expected %p, got %p\n", expected, got);
|
||||
}
|
||||
|
||||
static WNDPROC pOldViewerProc;
|
||||
|
||||
static LRESULT CALLBACK recursive_viewer_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static BOOL recursion_guard;
|
||||
|
||||
if (message == WM_DRAWCLIPBOARD && !recursion_guard)
|
||||
{
|
||||
recursion_guard = TRUE;
|
||||
clear_clipboard(hWnd);
|
||||
recursion_guard = FALSE;
|
||||
}
|
||||
return CallWindowProcA(pOldViewerProc, hWnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
static void test_clipboard_viewers(void)
|
||||
{
|
||||
static struct message wm_change_cb_chain[] =
|
||||
{
|
||||
{ WM_CHANGECBCHAIN, sent|wparam|lparam, 0, 0 },
|
||||
{ 0 }
|
||||
};
|
||||
static const struct message wm_clipboard_destroyed[] =
|
||||
{
|
||||
{ WM_DESTROYCLIPBOARD, sent|wparam|lparam, 0, 0 },
|
||||
{ 0 }
|
||||
};
|
||||
static struct message wm_clipboard_changed[] =
|
||||
{
|
||||
{ WM_DRAWCLIPBOARD, sent|wparam|lparam, 0, 0 },
|
||||
{ 0 }
|
||||
};
|
||||
static struct message wm_clipboard_changed_and_owned[] =
|
||||
{
|
||||
{ WM_DESTROYCLIPBOARD, sent|wparam|lparam, 0, 0 },
|
||||
{ WM_DRAWCLIPBOARD, sent|wparam|lparam, 0, 0 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
HINSTANCE hInst = GetModuleHandleA(NULL);
|
||||
HWND hWnd1, hWnd2, hWnd3;
|
||||
HWND hOrigViewer;
|
||||
HWND hRet;
|
||||
|
||||
hWnd1 = CreateWindowExA(0, "TestWindowClass", "Clipboard viewer test wnd 1",
|
||||
WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
GetDesktopWindow(), NULL, hInst, NULL);
|
||||
hWnd2 = CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 2",
|
||||
WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
GetDesktopWindow(), NULL, hInst, NULL);
|
||||
hWnd3 = CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 3",
|
||||
WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
GetDesktopWindow(), NULL, hInst, NULL);
|
||||
trace("clipbd viewers: hWnd1=%p, hWnd2=%p, hWnd3=%p\n", hWnd1, hWnd2, hWnd3);
|
||||
assert(hWnd1 && hWnd2 && hWnd3);
|
||||
|
||||
flush_sequence();
|
||||
|
||||
/* Test getting the clipboard viewer and setting the viewer to NULL. */
|
||||
hOrigViewer = GetClipboardViewer();
|
||||
hRet = SetClipboardViewer(NULL);
|
||||
ok_sequence(WmEmptySeq, "set viewer to NULL", FALSE);
|
||||
expect_HWND(hOrigViewer, hRet);
|
||||
expect_HWND(NULL, GetClipboardViewer());
|
||||
|
||||
/* Test registering hWnd1 as a viewer. */
|
||||
hRet = SetClipboardViewer(hWnd1);
|
||||
wm_clipboard_changed[0].wParam = (WPARAM) GetClipboardOwner();
|
||||
ok_sequence(wm_clipboard_changed, "set viewer NULL->1", TRUE);
|
||||
expect_HWND(NULL, hRet);
|
||||
expect_HWND(hWnd1, GetClipboardViewer());
|
||||
|
||||
/* Test that changing the clipboard actually refreshes the registered viewer. */
|
||||
clear_clipboard(hWnd1);
|
||||
wm_clipboard_changed[0].wParam = (WPARAM) GetClipboardOwner();
|
||||
ok_sequence(wm_clipboard_changed, "clear clipbd (viewer=owner=1)", TRUE);
|
||||
|
||||
/* Again, but with different owner. */
|
||||
clear_clipboard(hWnd2);
|
||||
wm_clipboard_changed_and_owned[1].wParam = (WPARAM) GetClipboardOwner();
|
||||
ok_sequence(wm_clipboard_changed_and_owned, "clear clipbd (viewer=1, owner=2)", TRUE);
|
||||
|
||||
/* Test re-registering same window. */
|
||||
hRet = SetClipboardViewer(hWnd1);
|
||||
wm_clipboard_changed[0].wParam = (WPARAM) GetClipboardOwner();
|
||||
ok_sequence(wm_clipboard_changed, "set viewer 1->1", TRUE);
|
||||
expect_HWND(hWnd1, hRet);
|
||||
expect_HWND(hWnd1, GetClipboardViewer());
|
||||
|
||||
/* Test ChangeClipboardChain. */
|
||||
ChangeClipboardChain(hWnd2, hWnd3);
|
||||
wm_change_cb_chain[0].wParam = (WPARAM) hWnd2;
|
||||
wm_change_cb_chain[0].lParam = (LPARAM) hWnd3;
|
||||
ok_sequence(wm_change_cb_chain, "change chain (viewer=1, remove=2, next=3)", FALSE);
|
||||
expect_HWND(hWnd1, GetClipboardViewer());
|
||||
|
||||
ChangeClipboardChain(hWnd2, NULL);
|
||||
wm_change_cb_chain[0].wParam = (WPARAM) hWnd2;
|
||||
wm_change_cb_chain[0].lParam = 0;
|
||||
ok_sequence(wm_change_cb_chain, "change chain (viewer=1, remove=2, next=NULL)", FALSE);
|
||||
expect_HWND(hWnd1, GetClipboardViewer());
|
||||
|
||||
ChangeClipboardChain(NULL, hWnd2);
|
||||
ok_sequence(WmEmptySeq, "change chain (viewer=1, remove=NULL, next=2)", TRUE);
|
||||
expect_HWND(hWnd1, GetClipboardViewer());
|
||||
|
||||
/* Actually change clipboard viewer with ChangeClipboardChain. */
|
||||
ChangeClipboardChain(hWnd1, hWnd2);
|
||||
ok_sequence(WmEmptySeq, "change chain (viewer=remove=1, next=2)", FALSE);
|
||||
expect_HWND(hWnd2, GetClipboardViewer());
|
||||
|
||||
/* Test that no refresh messages are sent when viewer has unregistered. */
|
||||
clear_clipboard(hWnd2);
|
||||
ok_sequence(WmEmptySeq, "clear clipd (viewer=2, owner=1)", FALSE);
|
||||
|
||||
/* Register hWnd1 again. */
|
||||
ChangeClipboardChain(hWnd2, hWnd1);
|
||||
ok_sequence(WmEmptySeq, "change chain (viewer=remove=2, next=1)", FALSE);
|
||||
expect_HWND(hWnd1, GetClipboardViewer());
|
||||
|
||||
/* Subclass hWnd1 so that when it receives a WM_DRAWCLIPBOARD message, it
|
||||
* changes the clipboard. When this happens, the system shouldn't send
|
||||
* another WM_DRAWCLIPBOARD (as this could cause an infinite loop).
|
||||
*/
|
||||
pOldViewerProc = (WNDPROC) SetWindowLongPtrA(hWnd1, GWLP_WNDPROC, (LONG_PTR) recursive_viewer_proc);
|
||||
clear_clipboard(hWnd2);
|
||||
/* The clipboard owner is changed in recursive_viewer_proc: */
|
||||
wm_clipboard_changed[0].wParam = (WPARAM) hWnd2;
|
||||
ok_sequence(wm_clipboard_changed, "recursive clear clipbd (viewer=1, owner=2)", TRUE);
|
||||
|
||||
/* Test unregistering. */
|
||||
ChangeClipboardChain(hWnd1, NULL);
|
||||
ok_sequence(WmEmptySeq, "change chain (viewer=remove=1, next=NULL)", FALSE);
|
||||
expect_HWND(NULL, GetClipboardViewer());
|
||||
|
||||
clear_clipboard(hWnd1);
|
||||
ok_sequence(wm_clipboard_destroyed, "clear clipbd (no viewer, owner=1)", FALSE);
|
||||
|
||||
DestroyWindow(hWnd1);
|
||||
DestroyWindow(hWnd2);
|
||||
DestroyWindow(hWnd3);
|
||||
SetClipboardViewer(hOrigViewer);
|
||||
}
|
||||
|
||||
static void test_PostMessage(void)
|
||||
{
|
||||
static const struct
|
||||
|
@ -11867,6 +12032,7 @@ START_TEST(msg)
|
|||
test_menu_messages();
|
||||
test_paintingloop();
|
||||
test_defwinproc();
|
||||
test_clipboard_viewers();
|
||||
/* keep it the last test, under Windows it tends to break the tests
|
||||
* which rely on active/foreground windows being correct.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue