From 5bfd73ad3ec48deae92927e8116fce81ac31cf66 Mon Sep 17 00:00:00 2001
From: Christopher Thielen <cthielen@gmail.com>
Date: Mon, 23 Nov 2015 21:48:26 -0800
Subject: user32: Also send WM_CAPTURECHANGE when capture has not changed.

Fixes https://bugs.winehq.org/show_bug.cgi?id=13683

A window may be notified with WM_CAPTURECHANGED about itself
gaining mouse capture if it calls SetCapture() twice.

Signed-off-by: Christopher Thielen <cthielen@gmail.com>
Signed-off-by: Sebastian Lackner <sebastian@fds-team.de>
---
 dlls/comctl32/toolbar.c  |  1 +
 dlls/comctl32/trackbar.c |  1 +
 dlls/user32/button.c     |  1 +
 dlls/user32/input.c      |  2 +-
 dlls/user32/tests/msg.c  | 27 +++++++++++++++++++++++++++
 5 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/dlls/comctl32/toolbar.c b/dlls/comctl32/toolbar.c
index 890c18e..3251682 100644
--- a/dlls/comctl32/toolbar.c
+++ b/dlls/comctl32/toolbar.c
@@ -6807,6 +6807,7 @@ ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 	    return TOOLBAR_MouseLeave (infoPtr);
 
 	case WM_CAPTURECHANGED:
+            if (lParam == (LPARAM)hwnd) return 0;
 	    return TOOLBAR_CaptureChanged(infoPtr);
 
 	case WM_NCACTIVATE:
diff --git a/dlls/comctl32/trackbar.c b/dlls/comctl32/trackbar.c
index 6d092a3..4d19a70 100644
--- a/dlls/comctl32/trackbar.c
+++ b/dlls/comctl32/trackbar.c
@@ -1976,6 +1976,7 @@ TRACKBAR_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 
 
     case WM_CAPTURECHANGED:
+        if (lParam == (LPARAM)hwnd) return 0;
         return TRACKBAR_CaptureChanged (infoPtr);
 
     case WM_CREATE:
diff --git a/dlls/user32/button.c b/dlls/user32/button.c
index 890d154..2fee3c8 100644
--- a/dlls/user32/button.c
+++ b/dlls/user32/button.c
@@ -364,6 +364,7 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
 
     case WM_CAPTURECHANGED:
         TRACE("WM_CAPTURECHANGED %p\n", hWnd);
+        if (lParam == (LPARAM)hWnd) break;
         state = get_button_state( hWnd );
         if (state & BUTTON_BTNPRESSED)
         {
diff --git a/dlls/user32/input.c b/dlls/user32/input.c
index 40e35a9..63fae67 100644
--- a/dlls/user32/input.c
+++ b/dlls/user32/input.c
@@ -108,7 +108,7 @@ BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret )
     {
         USER_Driver->pSetCapture( hwnd, gui_flags );
 
-        if (previous && previous != hwnd)
+        if (previous)
             SendMessageW( previous, WM_CAPTURECHANGED, 0, (LPARAM)hwnd );
 
         if (prev_ret) *prev_ret = previous;
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
index b90f8d0..151b77a 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -14906,6 +14906,32 @@ else
     flush_sequence();
 }
 
+static const struct message DoubleSetCaptureSeq[] =
+{
+    { WM_CAPTURECHANGED, sent },
+    { 0 }
+};
+
+static void test_DoubleSetCapture(void)
+{
+    HWND hwnd;
+
+    hwnd = CreateWindowExA(0, "TestWindowClass", "Test DoubleSetCapture",
+                           WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+                           100, 100, 200, 200, 0, 0, 0, NULL);
+    ok(hwnd != 0, "Failed to create overlapped window\n");
+
+    ShowWindow( hwnd, SW_SHOW );
+    flush_sequence();
+
+    SetCapture(hwnd);
+    ok_sequence(WmEmptySeq, "SetCapture(hwnd) empty sequence", FALSE);
+    SetCapture(hwnd);
+    ok_sequence(DoubleSetCaptureSeq, "SetCapture(hwnd) twice", FALSE);
+
+    DestroyWindow(hwnd);
+}
+
 static void init_funcs(void)
 {
     HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
@@ -15045,6 +15071,7 @@ START_TEST(msg)
     test_layered_window();
     test_TrackPopupMenu();
     test_TrackPopupMenuEmpty();
+    test_DoubleSetCapture();
     /* keep it the last test, under Windows it tends to break the tests
      * which rely on active/foreground windows being correct.
      */
-- 
2.6.2

