From: Rémi Bernon rbernon@codeweavers.com
Based on a patch by Huw Davies huw@codeweavers.com. --- dlls/win32u/input.c | 20 +++++++-------- dlls/win32u/ntuser_private.h | 27 ++++++++++++++++++++ dlls/win32u/sysparams.c | 6 +++++ dlls/win32u/winstation.c | 49 ++++++++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+), 11 deletions(-)
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index ef8d564c264..4f78f450798 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -749,25 +749,23 @@ BOOL WINAPI NtUserSetCursorPos( INT x, INT y ) */ BOOL get_cursor_pos( POINT *pt ) { - BOOL ret; + const desktop_shm_t *shared = get_desktop_shared_memory(); DWORD last_change; + BOOL ret = TRUE; UINT dpi;
- if (!pt) return FALSE; + if (!pt || !shared) return FALSE;
- SERVER_START_REQ( set_cursor ) + SHARED_READ_BEGIN( shared, desktop_shm_t ) { - if ((ret = !wine_server_call( req ))) - { - pt->x = reply->new_x; - pt->y = reply->new_y; - last_change = reply->last_change; - } + pt->x = shared->cursor.x; + pt->y = shared->cursor.y; + last_change = shared->cursor.last_change; } - SERVER_END_REQ; + SHARED_READ_END;
/* query new position from graphics driver if we haven't updated recently */ - if (ret && NtGetTickCount() - last_change > 100) ret = user_driver->pGetCursorPos( pt ); + if (NtGetTickCount() - last_change > 100) ret = user_driver->pGetCursorPos( pt ); if (ret && (dpi = get_thread_dpi())) { HMONITOR monitor = monitor_from_point( *pt, MONITOR_DEFAULTTOPRIMARY, 0 ); diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 11bb7f4baf6..2efab7062ec 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -137,6 +137,7 @@ struct user_thread_info UINT spy_indent; /* Current spy indent */ BOOL clipping_cursor; /* thread is currently clipping */ DWORD clipping_reset; /* time when clipping was last reset */ + const desktop_shm_t *desktop_shm; /* Ptr to server's desktop shared memory */ };
C_ASSERT( sizeof(struct user_thread_info) <= sizeof(((TEB *)0)->Win32ClientInfo) ); @@ -261,6 +262,9 @@ void release_user_handle_ptr( void *ptr ); void *next_process_user_handle_ptr( HANDLE *handle, unsigned int type ); UINT win_set_flags( HWND hwnd, UINT set_mask, UINT clear_mask );
+/* winstation.c */ +extern const desktop_shm_t *get_desktop_shared_memory(void); + static inline UINT win_get_flags( HWND hwnd ) { return win_set_flags( hwnd, 0, 0 ); @@ -270,4 +274,27 @@ WND *get_win_ptr( HWND hwnd ); BOOL is_child( HWND parent, HWND child ); BOOL is_window( HWND hwnd );
+#if defined(__i386__) || defined(__x86_64__) +#define __SHARED_READ_SEQ( x ) (x) +#define __SHARED_READ_FENCE do {} while(0) +#else +#define __SHARED_READ_SEQ( x ) __atomic_load_n( &(x), __ATOMIC_RELAXED ) +#define __SHARED_READ_FENCE __atomic_thread_fence( __ATOMIC_ACQUIRE ) +#endif + +#define SHARED_READ_BEGIN( ptr, type ) \ + do { \ + const type *__shared = (ptr); \ + unsigned int __seq; \ + do { \ + while ((__seq = __SHARED_READ_SEQ( __shared->seq )) & 1) YieldProcessor(); \ + __SHARED_READ_FENCE; \ + do + +#define SHARED_READ_END \ + while (0); \ + __SHARED_READ_FENCE; \ + } while (__SHARED_READ_SEQ( __shared->seq ) != __seq); \ + } while(0) + #endif /* __WINE_NTUSER_PRIVATE_H */ diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index e2c5b10da9e..526f3286885 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -6205,6 +6205,12 @@ static void thread_detach(void) cleanup_imm_thread(); NtClose( thread_info->server_queue );
+ if (thread_info->desktop_shm) + { + NtUnmapViewOfSection( GetCurrentProcess(), (void *)thread_info->desktop_shm ); + thread_info->desktop_shm = NULL; + } + exiting_thread_id = 0; }
diff --git a/dlls/win32u/winstation.c b/dlls/win32u/winstation.c index b187b246941..01dbe2c0b67 100644 --- a/dlls/win32u/winstation.c +++ b/dlls/win32u/winstation.c @@ -265,6 +265,11 @@ BOOL WINAPI NtUserSetThreadDesktop( HDESK handle ) thread_info->client_info.msg_window = 0; if (key_state_info) key_state_info->time = 0; if (was_virtual_desktop != is_virtual_desktop()) update_display_cache( TRUE ); + if (thread_info->desktop_shm) + { + NtUnmapViewOfSection( GetCurrentProcess(), (void *)thread_info->desktop_shm ); + thread_info->desktop_shm = NULL; + } } return ret; } @@ -607,6 +612,50 @@ static const WCHAR *get_default_desktop( void *buf, size_t buf_size ) return defaultW; }
+static volatile void *map_object_shared_memory( HANDLE object, SIZE_T size ) +{ + static const WCHAR mapping_nameW[] = + { + '_','_','w','i','n','e','_','m','a','p','p','i','n','g',0 + }; + OBJECT_ATTRIBUTES attr; + UNICODE_STRING section_str; + HANDLE handle; + UINT status; + void *ptr; + + RtlInitUnicodeString( §ion_str, mapping_nameW ); + InitializeObjectAttributes( &attr, §ion_str, 0, object, NULL ); + if (!(status = NtOpenSection( &handle, SECTION_ALL_ACCESS, &attr ))) + { + ptr = NULL; + status = NtMapViewOfSection( handle, GetCurrentProcess(), &ptr, 0, 0, NULL, + &size, ViewUnmap, 0, PAGE_READONLY ); + NtClose( handle ); + } + + if (status) + { + ERR( "Failed to map object %p mapping, status %#x\n", object, status ); + return NULL; + } + + return ptr; +} + +const desktop_shm_t *get_desktop_shared_memory(void) +{ + struct user_thread_info *thread_info = get_user_thread_info(); + HANDLE desktop; + + if (thread_info->desktop_shm) return thread_info->desktop_shm; + + desktop = NtUserGetThreadDesktop( GetCurrentThreadId() ); + thread_info->desktop_shm = map_object_shared_memory( desktop, sizeof(*thread_info->desktop_shm) ); + + return thread_info->desktop_shm; +} + /*********************************************************************** * winstation_init *