diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 147bb5b2..a1264db1 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -1022,6 +1022,9 @@ if test "$enable_server_Shared_Memory" -eq 1; then if test "$enable_ntdll_Threading" -gt 1; then abort "Patchset ntdll-Threading disabled, but server-Shared_Memory depends on that." fi + if test "$enable_server_ClipCursor" -gt 1; then + abort "Patchset server-ClipCursor disabled, but server-Shared_Memory depends on that." + fi if test "$enable_server_Key_State" -gt 1; then abort "Patchset server-Key_State disabled, but server-Shared_Memory depends on that." fi @@ -1033,6 +1036,7 @@ if test "$enable_server_Shared_Memory" -eq 1; then fi enable_dinput_Events=1 enable_ntdll_Threading=1 + enable_server_ClipCursor=1 enable_server_Key_State=1 enable_server_PeekMessage=1 enable_user32_Key_State=1 @@ -3876,6 +3880,7 @@ if test "$enable_server_Shared_Memory" -eq 1; then patch_apply server-Shared_Memory/0007-user32-Move-key_state-cache-into-separate-structure.patch patch_apply server-Shared_Memory/0008-server-Store-a-list-of-associated-queues-for-each-th.patch patch_apply server-Shared_Memory/0009-user32-Get-rid-of-wineserver-call-for-GetActiveWindo.patch + patch_apply server-Shared_Memory/0010-user32-Cache-the-result-of-GetForegroundWindow.patch ( echo '+ { "Sebastian Lackner", "ntdll: Implement virtual_map_shared_memory.", 1 },'; echo '+ { "Michael Müller", "server: Implement support for global and local shared memory blocks based on memfd.", 1 },'; @@ -3886,6 +3891,7 @@ if test "$enable_server_Shared_Memory" -eq 1; then echo '+ { "Sebastian Lackner", "user32: Move key_state cache into separate structure.", 1 },'; echo '+ { "Sebastian Lackner", "server: Store a list of associated queues for each thread input.", 1 },'; echo '+ { "Sebastian Lackner", "user32: Get rid of wineserver call for GetActiveWindow, GetFocus, GetCapture.", 1 },'; + echo '+ { "Sebastian Lackner", "user32: Cache the result of GetForegroundWindow.", 1 },'; ) >> "$patchlist" fi diff --git a/patches/server-Shared_Memory/0010-user32-Cache-the-result-of-GetForegroundWindow.patch b/patches/server-Shared_Memory/0010-user32-Cache-the-result-of-GetForegroundWindow.patch new file mode 100644 index 00000000..ef17460d --- /dev/null +++ b/patches/server-Shared_Memory/0010-user32-Cache-the-result-of-GetForegroundWindow.patch @@ -0,0 +1,123 @@ +From 8d67b53668f39c8684ddc8be8937f70eb50774df Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Sat, 21 Mar 2015 22:35:24 +0100 +Subject: user32: Cache the result of GetForegroundWindow. + +--- + dlls/user32/focus.c | 21 ++++++++++++++++++++- + dlls/user32/user_private.h | 4 +++- + server/protocol.def | 5 ++++- + server/queue.c | 10 +++++++++- + 4 files changed, 36 insertions(+), 4 deletions(-) + +diff --git a/dlls/user32/focus.c b/dlls/user32/focus.c +index 35fe89b..8b17d1f 100644 +--- a/dlls/user32/focus.c ++++ b/dlls/user32/focus.c +@@ -367,12 +367,31 @@ HWND WINAPI GetFocus(void) + */ + HWND WINAPI GetForegroundWindow(void) + { ++ struct user_thread_info *thread_info = get_user_thread_info(); ++ shmglobal_t *shm = wine_get_shmglobal(); + HWND ret = 0; ++ DWORD epoch; ++ ++ if (shm) ++ { ++ epoch = shm->foreground_wnd_epoch; ++ ++ if (epoch == thread_info->foreground_wnd_epoch) ++ return thread_info->foreground_wnd; ++ } + + SERVER_START_REQ( get_thread_input ) + { + req->tid = 0; +- if (!wine_server_call_err( req )) ret = wine_server_ptr_handle( reply->foreground ); ++ if (!wine_server_call_err( req )) ++ { ++ ret = wine_server_ptr_handle( reply->foreground ); ++ if (shm) ++ { ++ thread_info->foreground_wnd = ret; ++ thread_info->foreground_wnd_epoch = epoch; ++ } ++ } + } + SERVER_END_REQ; + return ret; +diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h +index a35ebf3..7752416 100644 +--- a/dlls/user32/user_private.h ++++ b/dlls/user32/user_private.h +@@ -190,8 +190,10 @@ struct user_thread_info + struct user_key_state_info *key_state; /* Cache of global key state */ + UINT active_hooks; /* Bitmap of active hooks */ + DWORD last_get_msg; /* Last message time */ ++ HWND foreground_wnd; /* Cache of the foreground window */ ++ DWORD foreground_wnd_epoch; /* Counter to invalidate foreground window */ + +- ULONG pad[5]; /* Available for more data */ ++ ULONG pad[2]; /* Available for more data */ + }; + #include + +diff --git a/server/protocol.def b/server/protocol.def +index 7eaa6cd..c770644 100644 +--- a/server/protocol.def ++++ b/server/protocol.def +@@ -69,11 +69,14 @@ struct request_max_size + #define FIRST_USER_HANDLE 0x0020 /* first possible value for low word of user handle */ + #define LAST_USER_HANDLE 0xffef /* last possible value for low word of user handle */ + ++/* wineserver global shared memory block */ + typedef struct + { +- unsigned int last_input_time; /* last input time */ ++ unsigned int last_input_time; /* last input time */ ++ unsigned int foreground_wnd_epoch; /* counter to invalidate foreground window */ + } shmglobal_t; + ++/* wineserver local shared memory block */ + typedef struct + { + int queue_bits; /* queue wake bits */ +diff --git a/server/queue.c b/server/queue.c +index 6fa076d..764ba11 100644 +--- a/server/queue.c ++++ b/server/queue.c +@@ -436,6 +436,7 @@ static void set_foreground_input( struct desktop *desktop, struct thread_input * + if (desktop->foreground_input == input) return; + set_clip_rectangle( desktop, NULL, 1 ); + desktop->foreground_input = input; ++ if (shmglobal) interlocked_xchg_add( (int *)&shmglobal->foreground_wnd_epoch, 1 ); + } + + /* get the hook table for a given thread */ +@@ -1076,7 +1077,12 @@ static inline void thread_input_cleanup_window( struct msg_queue *queue, user_ha + + if (window == input->focus) input->focus = 0; + if (window == input->capture) input->capture = 0; +- if (window == input->active) input->active = 0; ++ if (window == input->active) ++ { ++ input->active = 0; ++ if (shmglobal && input->desktop->foreground_input == input) ++ interlocked_xchg_add( (int *)&shmglobal->foreground_wnd_epoch, 1 ); ++ } + if (window == input->menu_owner) input->menu_owner = 0; + if (window == input->move_size) input->move_size = 0; + if (window == input->caret) set_caret_window( input, 0 ); +@@ -3018,6 +3024,8 @@ DECL_HANDLER(set_active_window) + reply->previous = queue->input->active; + queue->input->active = get_user_full_handle( req->handle ); + update_shm_thread_input( queue->input ); ++ if (shmglobal && queue->input->desktop->foreground_input == queue->input) ++ interlocked_xchg_add( (int *)&shmglobal->foreground_wnd_epoch, 1 ); + } + else set_error( STATUS_INVALID_HANDLE ); + } +-- +2.3.2 + diff --git a/patches/server-Shared_Memory/definition b/patches/server-Shared_Memory/definition index 1c71ed97..72cc7a94 100644 --- a/patches/server-Shared_Memory/definition +++ b/patches/server-Shared_Memory/definition @@ -3,3 +3,4 @@ Depends: user32-Key_State Depends: dinput-Events Depends: server-Key_State Depends: server-PeekMessage +Depends: server-ClipCursor