From a18943341e17fef24e9b7f8dd85458a2e33bedab Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Thu, 19 Mar 2015 02:07:24 +0100
Subject: [PATCH] user32: Avoid unnecessary wineserver calls in
 PeekMessage/GetMessage.

---
 dlls/user32/message.c      | 14 ++++++++++++++
 dlls/user32/user_private.h |  5 +++++
 2 files changed, 19 insertions(+)

diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index cbe9920384f..cdb8f4047a1 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -2756,6 +2756,18 @@ static int peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags,
     unsigned int hw_id = 0;  /* id of previous hardware message */
     void *buffer;
     size_t buffer_size = 256;
+    shmlocal_t *shm = wine_get_shmlocal();
+
+    /* From time to time we are forced to do a wineserver call in
+     * order to update last_msg_time stored for each server thread. */
+    if (shm && GetTickCount() - thread_info->last_get_msg < 500)
+    {
+        int filter = flags >> 16;
+        if (!filter) filter = QS_ALLINPUT;
+        filter |= QS_SENDMESSAGE;
+        if (filter & QS_INPUT) filter |= QS_INPUT;
+        if (!(shm->queue_bits & filter)) return FALSE;
+    }
 
     if (!(buffer = HeapAlloc( GetProcessHeap(), 0, buffer_size ))) return -1;
 
@@ -2770,6 +2782,8 @@ static int peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags,
 
         thread_info->msg_source = prev_source;
 
+        if (shm) thread_info->last_get_msg = GetTickCount();
+
         SERVER_START_REQ( get_message )
         {
             req->flags     = flags;
diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h
index c11aae707c9..74f56925211 100644
--- a/dlls/user32/user_private.h
+++ b/dlls/user32/user_private.h
@@ -169,6 +169,8 @@ struct wm_char_mapping_data
     MSG  get_msg;
 };
 
+#include <pshpack1.h>
+
 /* this is the structure stored in TEB->Win32ClientInfo */
 /* no attempt is made to keep the layout compatible with the Windows one */
 struct user_thread_info
@@ -189,6 +191,7 @@ struct user_thread_info
     DWORD                         GetMessageTimeVal;      /* Value for GetMessageTime */
     DWORD                         GetMessagePosVal;       /* Value for GetMessagePos */
     ULONG_PTR                     GetMessageExtraInfoVal; /* Value for GetMessageExtraInfo */
+    DWORD                         last_get_msg;           /* Last time of Get/PeekMessage call */
     struct user_key_state_info   *key_state;              /* Cache of global key state */
     HWND                          top_window;             /* Desktop window */
     HWND                          msg_window;             /* HWND_MESSAGE parent window */
@@ -197,6 +200,8 @@ struct user_thread_info
 
 C_ASSERT( sizeof(struct user_thread_info) <= sizeof(((TEB *)0)->Win32ClientInfo) );
 
+#include <poppack.h>
+
 extern INT global_key_state_counter DECLSPEC_HIDDEN;
 extern BOOL (WINAPI *imm_register_window)(HWND) DECLSPEC_HIDDEN;
 extern void (WINAPI *imm_unregister_window)(HWND) DECLSPEC_HIDDEN;
-- 
2.17.1

