Index: base/message_pump_win.cc |
=================================================================== |
--- base/message_pump_win.cc (revision 2630) |
+++ base/message_pump_win.cc (working copy) |
@@ -213,10 +213,20 @@ |
} |
bool MessagePumpWin::ProcessNextWindowsMessage() { |
+ // If there are sent messages in the queue then PeekMessage internally |
+ // dispatches the message and returns false. We return true in this |
+ // case to ensure that the message loop peeks again instead of calling |
+ // MsgWaitForMultipleObjectsEx again. |
+ bool sent_messages_in_queue = false; |
+ DWORD queue_status = GetQueueStatus(QS_SENDMESSAGE); |
+ if (HIWORD(queue_status) & QS_SENDMESSAGE) |
+ sent_messages_in_queue = true; |
+ |
MSG msg; |
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) |
return ProcessMessageHelper(msg); |
- return false; |
+ |
+ return sent_messages_in_queue; |
} |
bool MessagePumpWin::ProcessMessageHelper(const MSG& msg) { |
@@ -358,8 +368,25 @@ |
result = MsgWaitForMultipleObjectsEx(0, NULL, delay, QS_ALLINPUT, |
MWMO_INPUTAVAILABLE); |
- if (WAIT_OBJECT_0 == result) |
- return; // A WM_* message is available. |
+ if (WAIT_OBJECT_0 == result) { |
+ // A WM_* message is available. |
+ // If a parent child relationship exists between windows across threads |
+ // then their thread inputs are implicitly attached. |
+ // This causes the MsgWaitForMultipleObjectsEx API to return indicating |
+ // that messages are ready for processing (specifically mouse messages |
+ // intended for the child window. Occurs if the child window has capture) |
+ // The subsequent PeekMessages call fails to return any messages thus |
+ // causing us to enter a tight loop at times. |
+ // The WaitMessage call below is a workaround to give the child window |
+ // sometime to process its input messages. |
+ MSG msg = {0}; |
+ DWORD queue_status = GetQueueStatus(QS_MOUSE); |
+ if (HIWORD(queue_status) & QS_MOUSE && |
+ !PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE)) { |
+ WaitMessage(); |
+ } |
+ return; |
+ } |
DCHECK_NE(WAIT_FAILED, result) << GetLastError(); |
} |