diff options
author | iyengar@google.com <iyengar@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-10-01 00:26:59 +0000 |
---|---|---|
committer | iyengar@google.com <iyengar@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-10-01 00:26:59 +0000 |
commit | d5b7f1658e3ce35e28492e4d873bf73400930a30 (patch) | |
tree | 2ae0a028a3a31777265698d358e9d2d9437904eb /base/message_pump_win.cc | |
parent | 266eb6ff422cf97eef1e56e78d0a9e73e9aef34a (diff) | |
download | chromium_src-d5b7f1658e3ce35e28492e4d873bf73400930a30.zip chromium_src-d5b7f1658e3ce35e28492e4d873bf73400930a30.tar.gz chromium_src-d5b7f1658e3ce35e28492e4d873bf73400930a30.tar.bz2 |
This fixes http://code.google.com/p/chromium/issues/detail?id=772,
which was an issue with the browser UI thread entering a tight loop
at times. The thread inputs of the browser UI thread and the plugin thread
are attached due to the parent child relationship between the windows.
As a result at times the MsgWaitForMultipleObjectsEx API returns the
fact that there are messages in the queue (mouse messages). The subsequent
peek fails to return any messages causing us to enter a loop for a while.
This also happens when the plugin has capture and just before it releases capture, some mousemoves end up in the browser ui thread causing a tight loop.
The fix is to check if there are mouse messages in the queue by invoking
GetQueueStatus and attempting to peek them out with PM_NOREMOVE. If this
fails we call WaitMessage to block until the next message.
The other fix is to return true from ProcessNextWindowsMessage if PeekMessage returns false and there were sent messages in the queue, as
this is as expected. This will ensure that we go back up and peek again
instead of calling MsgWaitForMultipleObjectsEx again.
Bug=772
R=darin
Review URL: http://codereview.chromium.org/6021
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@2740 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/message_pump_win.cc')
-rw-r--r-- | base/message_pump_win.cc | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/base/message_pump_win.cc b/base/message_pump_win.cc index 9c96475..4fff9d7 100644 --- a/base/message_pump_win.cc +++ b/base/message_pump_win.cc @@ -213,10 +213,20 @@ void MessagePumpWin::HandleTimerMessage() { } 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 @@ void MessagePumpForUI::WaitForWork() { 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(); } |