diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c index 0a9a89560de..6f2359de2ff 100644 --- a/dlls/user32/cursoricon.c +++ b/dlls/user32/cursoricon.c @@ -54,9 +54,10 @@ #include "wine/winbase16.h" #include "wine/winuser16.h" #include "wine/exception.h" -#include "wine/debug.h" +#include "wine/server.h" #include "controls.h" #include "user_private.h" +#include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(cursor); WINE_DECLARE_DEBUG_CHANNEL(icon); @@ -1587,7 +1588,7 @@ BOOL WINAPI DestroyIcon( HICON hIcon ) */ BOOL WINAPI DestroyCursor( HCURSOR hCursor ) { - if (get_user_thread_info()->cursor == hCursor) + if (GetCursor() == hCursor) { WARN_(cursor)("Destroying active cursor!\n" ); return FALSE; @@ -1762,15 +1763,28 @@ BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon ) */ HCURSOR WINAPI DECLSPEC_HOTPATCH SetCursor( HCURSOR hCursor /* [in] Handle of cursor to show */ ) { - struct user_thread_info *thread_info = get_user_thread_info(); HCURSOR hOldCursor; + int show_count; + BOOL ret; - if (hCursor == thread_info->cursor) return hCursor; /* No change */ TRACE("%p\n", hCursor); - hOldCursor = thread_info->cursor; - thread_info->cursor = hCursor; + + SERVER_START_REQ( set_cursor ) + { + req->flags = SET_CURSOR_HANDLE; + req->handle = wine_server_user_handle( hCursor ); + if ((ret = !wine_server_call_err( req ))) + { + hOldCursor = wine_server_ptr_handle( reply->prev_handle ); + show_count = reply->prev_count; + } + } + SERVER_END_REQ; + + if (!ret) return 0; + /* Change the cursor shape only if it is visible */ - if (thread_info->cursor_count >= 0) + if (show_count >= 0) { CURSORICONINFO *info = get_icon_ptr( hCursor ); /* release before calling driver (FIXME) */ @@ -1785,26 +1799,34 @@ HCURSOR WINAPI DECLSPEC_HOTPATCH SetCursor( HCURSOR hCursor /* [in] Handle of cu */ INT WINAPI DECLSPEC_HOTPATCH ShowCursor( BOOL bShow ) { - struct user_thread_info *thread_info = get_user_thread_info(); + HCURSOR cursor; + int increment = bShow ? 1 : -1; + int prev_count; - TRACE("%d, count=%d\n", bShow, thread_info->cursor_count ); - - if (bShow) + SERVER_START_REQ( set_cursor ) { - if (++thread_info->cursor_count == 0) /* Show it */ + req->flags = SET_CURSOR_COUNT; + req->show_count = increment; + wine_server_call( req ); + cursor = wine_server_ptr_handle( reply->prev_handle ); + prev_count = reply->prev_count; + } + SERVER_END_REQ; + + TRACE("%d, count=%d\n", bShow, prev_count + increment ); + + if (!prev_count) + { + if (bShow) { - CURSORICONINFO *info = get_icon_ptr( thread_info->cursor ); + CURSORICONINFO *info = get_icon_ptr( cursor ); /* release before calling driver (FIXME) */ - if (info) release_icon_ptr( thread_info->cursor, info ); + if (info) release_icon_ptr( cursor, info ); USER_Driver->pSetCursor( info ); } + else USER_Driver->pSetCursor( NULL ); } - else - { - if (--thread_info->cursor_count == -1) /* Hide it */ - USER_Driver->pSetCursor( NULL ); - } - return thread_info->cursor_count; + return prev_count + increment; } /*********************************************************************** @@ -1812,7 +1834,16 @@ INT WINAPI DECLSPEC_HOTPATCH ShowCursor( BOOL bShow ) */ HCURSOR WINAPI GetCursor(void) { - return get_user_thread_info()->cursor; + HCURSOR ret; + + SERVER_START_REQ( set_cursor ) + { + req->flags = 0; + wine_server_call( req ); + ret = wine_server_ptr_handle( reply->prev_handle ); + } + SERVER_END_REQ; + return ret; } diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c index 650e5fcaffd..11d11cfd079 100644 --- a/dlls/user32/tests/cursoricon.c +++ b/dlls/user32/tests/cursoricon.c @@ -1445,7 +1445,7 @@ static void test_SetCursor(void) WaitForSingleObject( thread, 1000 ); GetExitCodeThread( thread, &result ); ok( result == (DWORD_PTR)old_cursor, "wrong thread cursor %x/%p\n", result, old_cursor ); - todo_wine ok( GetCursor() == cursor, "wrong cursor %p/0\n", cursor ); + ok( GetCursor() == cursor, "wrong cursor %p/0\n", cursor ); if (pGetCursorInfo) { @@ -1461,7 +1461,7 @@ static void test_SetCursor(void) cursor = SetCursor( (HCURSOR)0xbadbad ); error = GetLastError(); ok( cursor == 0, "wrong cursor %p/0\n", cursor ); - todo_wine ok( error == ERROR_INVALID_CURSOR_HANDLE || broken( error == 0xdeadbeef ), /* win9x */ + ok( error == ERROR_INVALID_CURSOR_HANDLE || broken( error == 0xdeadbeef ), /* win9x */ "wrong error %u\n", error ); if (pGetCursorInfo) @@ -1559,22 +1559,22 @@ static void test_ShowCursor(void) thread = CreateThread( NULL, 0, show_cursor_thread, NULL, 0, &id ); WaitForSingleObject( event_start, 1000 ); count = ShowCursor( TRUE ); - todo_wine ok( count == -2, "wrong count %d\n", count ); + ok( count == -2, "wrong count %d\n", count ); SetEvent( event_next ); WaitForSingleObject( thread, 1000 ); GetExitCodeThread( thread, &result ); - todo_wine ok( result == -3, "wrong thread count %d\n", result ); + ok( result == -3, "wrong thread count %d\n", result ); count = ShowCursor( FALSE ); ok( count == -2, "wrong count %d\n", count ); thread = CreateThread( NULL, 0, show_cursor_thread, (void *)3, 0, &id ); WaitForSingleObject( event_start, 1000 ); count = ShowCursor( TRUE ); - todo_wine ok( count == 2, "wrong count %d\n", count ); + ok( count == 2, "wrong count %d\n", count ); SetEvent( event_next ); WaitForSingleObject( thread, 1000 ); GetExitCodeThread( thread, &result ); - todo_wine ok( result == 1, "wrong thread count %d\n", result ); + ok( result == 1, "wrong thread count %d\n", result ); count = ShowCursor( FALSE ); ok( count == -2, "wrong count %d\n", count ); diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index 893d4b59494..eb6bdc9147d 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -175,13 +175,11 @@ struct user_thread_info DWORD GetMessageTimeVal; /* Value for GetMessageTime */ DWORD GetMessagePosVal; /* Value for GetMessagePos */ ULONG_PTR GetMessageExtraInfoVal; /* Value for GetMessageExtraInfo */ - HCURSOR cursor; /* Current cursor */ - INT cursor_count; /* Cursor show count */ UINT active_hooks; /* Bitmap of active hooks */ HWND top_window; /* Desktop window */ HWND msg_window; /* HWND_MESSAGE parent window */ - ULONG pad[9]; /* Available for more data */ + ULONG pad[11]; /* Available for more data */ }; struct hook_extra_info