From dc483d01e1493b319aecd409ce4e65223c18b5bd Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Thu, 19 Mar 2015 01:32:51 +0100
Subject: user32: Get rid of wineserver call for GetInputState.

---
 dlls/user32/input.c | 14 +++++++++++++-
 server/protocol.def |  2 +-
 server/queue.c      | 14 ++++++++++++++
 3 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/dlls/user32/input.c b/dlls/user32/input.c
index 130aacc..4cf6b61 100644
--- a/dlls/user32/input.c
+++ b/dlls/user32/input.c
@@ -454,17 +454,29 @@ DWORD WINAPI GetQueueStatus( UINT flags )
  */
 BOOL WINAPI GetInputState(void)
 {
+    shmlocal_t *shm = wine_get_shmlocal();
     DWORD ret;
 
     check_for_events( QS_INPUT );
 
+    /* req->clear is not set, so we can safely get the
+     * wineserver status without an additional call. */
+    if (shm)
+    {
+        ret = shm->queue_bits;
+        goto done;
+    }
+
     SERVER_START_REQ( get_queue_status )
     {
         req->clear_bits = 0;
         wine_server_call( req );
-        ret = reply->wake_bits & (QS_KEY | QS_MOUSEBUTTON);
+        ret = reply->wake_bits;
     }
     SERVER_END_REQ;
+
+done:
+    ret &= (QS_KEY | QS_MOUSEBUTTON);
     return ret;
 }
 
diff --git a/server/protocol.def b/server/protocol.def
index ea2e231..4872251 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -76,7 +76,7 @@ typedef struct
 
 typedef struct
 {
-    int dummy;
+    int queue_bits;     /* queue wake bits */
 } shmlocal_t;
 
 /* debug event data */
diff --git a/server/queue.c b/server/queue.c
index c318fc3..3a1d2b7 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -118,6 +118,7 @@ struct thread_input
 struct msg_queue
 {
     struct object          obj;             /* object header */
+    struct thread         *thread;          /* reference to the thread owning the queue */
     struct fd             *fd;              /* optional file descriptor to poll */
     unsigned int           wake_bits;       /* wakeup bits */
     unsigned int           wake_mask;       /* wakeup mask */
@@ -282,6 +283,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
     if ((queue = alloc_object( &msg_queue_ops )))
     {
         queue->fd              = NULL;
+        queue->thread          = thread;
         queue->wake_bits       = 0;
         queue->wake_mask       = 0;
         queue->changed_bits    = 0;
@@ -315,6 +317,7 @@ void free_msg_queue( struct thread *thread )
 {
     remove_thread_hooks( thread );
     if (!thread->queue) return;
+    thread->queue->thread = NULL;
     release_object( thread->queue );
     thread->queue = NULL;
 }
@@ -427,11 +430,21 @@ static inline int is_signaled( struct msg_queue *queue )
     return ((queue->wake_bits & queue->wake_mask) || (queue->changed_bits & queue->changed_mask));
 }
 
+/* synchronize the queue state with the shared memory */
+static inline void update_shm_queue_bits( struct msg_queue *queue )
+{
+    shmlocal_t *shm;
+    if (!queue->thread) return;
+    if ((shm = queue->thread->shm))
+        shm->queue_bits = queue->wake_bits;
+}
+
 /* set some queue bits */
 static inline void set_queue_bits( struct msg_queue *queue, unsigned int bits )
 {
     queue->wake_bits |= bits;
     queue->changed_bits |= bits;
+    update_shm_queue_bits( queue );
     if (is_signaled( queue )) wake_up( &queue->obj, 0 );
 }
 
@@ -440,6 +453,7 @@ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits
 {
     queue->wake_bits &= ~bits;
     queue->changed_bits &= ~bits;
+    update_shm_queue_bits( queue );
 }
 
 /* check whether msg is a keyboard message */
-- 
2.3.5

