[1/4] user32/tests: Add some clipboard viewer tests.

Alexander Scott-Johns alexander.scott.johns at googlemail.com
Tue Sep 22 20:16:03 CDT 2009


Tested in Windows 95, Windows XP and Wine.
-------------- next part --------------
From d3e0f51909de122a339d495e2dc7e6c853075504 Mon Sep 17 00:00:00 2001
From: Alexander Scott-Johns <alexander.scott.johns at googlemail.com>
Date: Sat, 19 Sep 2009 23:29:44 +0100
Subject: user32/tests: Add some clipboard viewer tests.

The clipboard viewer API is involves messages, which is why I have
added the tests to msg.c instead of clipboard.c.
---
 dlls/user32/tests/clipboard.c |    2 +
 dlls/user32/tests/msg.c       |  166 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 168 insertions(+), 0 deletions(-)

diff --git a/dlls/user32/tests/clipboard.c b/dlls/user32/tests/clipboard.c
index e2ba2f9..5049b0e 100644
--- a/dlls/user32/tests/clipboard.c
+++ b/dlls/user32/tests/clipboard.c
@@ -271,4 +271,6 @@ START_TEST(clipboard)
     test_RegisterClipboardFormatA();
     test_ClipboardOwner();
     test_synthesized();
+
+    /* Clipboard viewer tests are in msg.c */
 }
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
index 540b494..5c1a9d7 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -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.
      */
-- 
1.6.0.4


More information about the wine-patches mailing list