From 452f8d47d7cd63f0fe5270d8ec6a7062544d3903 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 21 Mar 2015 09:45:54 +0100
Subject: user32: Get rid of wineserver call for GetActiveWindow, GetFocus,
 GetCapture.

---
 dlls/user32/focus.c |  4 ++++
 dlls/user32/input.c |  2 ++
 server/protocol.def |  5 ++++-
 server/queue.c      | 30 +++++++++++++++++++++++++++++-
 4 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/dlls/user32/focus.c b/dlls/user32/focus.c
index c47a82d..35fe89b 100644
--- a/dlls/user32/focus.c
+++ b/dlls/user32/focus.c
@@ -329,8 +329,10 @@ BOOL WINAPI SetForegroundWindow( HWND hwnd )
  */
 HWND WINAPI GetActiveWindow(void)
 {
+    shmlocal_t *shm = wine_get_shmlocal();
     HWND ret = 0;
 
+    if (shm) return wine_server_ptr_handle( shm->input_active );
     SERVER_START_REQ( get_thread_input )
     {
         req->tid = GetCurrentThreadId();
@@ -346,8 +348,10 @@ HWND WINAPI GetActiveWindow(void)
  */
 HWND WINAPI GetFocus(void)
 {
+    shmlocal_t *shm = wine_get_shmlocal();
     HWND ret = 0;
 
+    if (shm) return wine_server_ptr_handle( shm->input_focus );
     SERVER_START_REQ( get_thread_input )
     {
         req->tid = GetCurrentThreadId();
diff --git a/dlls/user32/input.c b/dlls/user32/input.c
index e63c8cf..0943d01 100644
--- a/dlls/user32/input.c
+++ b/dlls/user32/input.c
@@ -342,8 +342,10 @@ BOOL WINAPI DECLSPEC_HOTPATCH ReleaseCapture(void)
  */
 HWND WINAPI GetCapture(void)
 {
+    shmlocal_t *shm = wine_get_shmlocal();
     HWND ret = 0;
 
+    if (shm) return wine_server_ptr_handle( shm->input_capture );
     SERVER_START_REQ( get_thread_input )
     {
         req->tid = GetCurrentThreadId();
diff --git a/server/protocol.def b/server/protocol.def
index f12109f..5ec2485 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -76,7 +76,10 @@ typedef struct
 
 typedef struct
 {
-    int queue_bits;                 /* queue wake bits */
+    int             queue_bits;     /* queue wake bits */
+    user_handle_t   input_focus;    /* focus window */
+    user_handle_t   input_capture;  /* capture window */
+    user_handle_t   input_active;   /* active window */
 } shmlocal_t;
 
 /* debug event data */
diff --git a/server/queue.c b/server/queue.c
index 3f52656..33c2758 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -270,6 +270,25 @@ static struct thread_input *create_thread_input( struct thread *thread )
     return input;
 }
 
+/* synchronize the input state with the shared memory */
+static void update_shm_thread_input( struct thread_input *input )
+{
+    struct msg_queue *queue;
+
+    /* the loop doesn't matter, usually it should only have one or a few entries */
+    LIST_FOR_EACH_ENTRY( queue, &input->queues, struct msg_queue, input_entry )
+    {
+        shmlocal_t *shm;
+        if (!queue->thread) continue;
+        if ((shm = queue->thread->shm))
+        {
+            shm->input_active  = input->active;
+            shm->input_focus   = input->focus;
+            shm->input_capture = input->capture;
+        }
+    }
+}
+
 /* create a message queue object */
 static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_input *input )
 {
@@ -312,7 +331,11 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
 
         thread->queue = queue;
     }
-    if (new_input) release_object( new_input );
+    if (new_input)
+    {
+        update_shm_thread_input( new_input );
+        release_object( new_input );
+    }
     return queue;
 }
 
@@ -347,6 +370,7 @@ static int assign_thread_input( struct thread *thread, struct thread_input *new_
     queue->input = (struct thread_input *)grab_object( new_input );
     list_add_tail( &new_input->queues, &queue->input_entry );
     new_input->cursor_count += queue->cursor_count;
+    update_shm_thread_input( new_input );
     return 1;
 }
 
@@ -1056,6 +1080,7 @@ static inline void thread_input_cleanup_window( struct msg_queue *queue, user_ha
     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 );
+    update_shm_thread_input( input );
 }
 
 /* check if the specified window can be set in the input data of a given queue */
@@ -2985,6 +3010,7 @@ DECL_HANDLER(set_focus_window)
     {
         reply->previous = queue->input->focus;
         queue->input->focus = get_user_full_handle( req->handle );
+        update_shm_thread_input( queue->input );
     }
 }
 
@@ -3001,6 +3027,7 @@ 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 );
         }
         else set_error( STATUS_INVALID_HANDLE );
     }
@@ -3027,6 +3054,7 @@ DECL_HANDLER(set_capture_window)
         input->capture = get_user_full_handle( req->handle );
         input->menu_owner = (req->flags & CAPTURE_MENU) ? input->capture : 0;
         input->move_size = (req->flags & CAPTURE_MOVESIZE) ? input->capture : 0;
+        update_shm_thread_input( input );
         reply->full_handle = input->capture;
     }
 }
-- 
2.3.5

