Bug 1072752: Make Chromium UI message loops for Windows call into WinUtils::WaitForMessage; r=jimm

This commit is contained in:
Aaron Klotz 2014-09-25 12:39:15 -06:00
parent 1fe0a415bd
commit f7fb1297c2
3 changed files with 17 additions and 28 deletions

View File

@ -9,6 +9,7 @@
#include "base/message_loop.h" #include "base/message_loop.h"
#include "base/histogram.h" #include "base/histogram.h"
#include "base/win_util.h" #include "base/win_util.h"
#include "WinUtils.h"
using base::Time; using base::Time;
@ -263,31 +264,7 @@ void MessagePumpForUI::WaitForWork() {
if (delay < 0) // Negative value means no timers waiting. if (delay < 0) // Negative value means no timers waiting.
delay = INFINITE; delay = INFINITE;
DWORD result; mozilla::widget::WinUtils::WaitForMessage(delay);
result = MsgWaitForMultipleObjectsEx(0, NULL, delay, QS_ALLINPUT,
MWMO_INPUTAVAILABLE);
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();
} }
void MessagePumpForUI::HandleWorkMessage() { void MessagePumpForUI::HandleWorkMessage() {

View File

@ -622,13 +622,24 @@ WinUtils::GetMessage(LPMSG aMsg, HWND aWnd, UINT aFirstMessage,
/* static */ /* static */
void void
WinUtils::WaitForMessage() WinUtils::WaitForMessage(DWORD aTimeoutMs)
{ {
const DWORD waitStart = ::GetTickCount();
DWORD elapsed = 0;
while (true) { while (true) {
DWORD result = ::MsgWaitForMultipleObjectsEx(0, NULL, INFINITE, if (aTimeoutMs != INFINITE) {
elapsed = ::GetTickCount() - waitStart;
}
if (elapsed >= aTimeoutMs) {
break;
}
DWORD result = ::MsgWaitForMultipleObjectsEx(0, NULL, aTimeoutMs - elapsed,
MOZ_QS_ALLEVENT, MOZ_QS_ALLEVENT,
MWMO_INPUTAVAILABLE); MWMO_INPUTAVAILABLE);
NS_WARN_IF_FALSE(result != WAIT_FAILED, "Wait failed"); NS_WARN_IF_FALSE(result != WAIT_FAILED, "Wait failed");
if (result == WAIT_TIMEOUT) {
break;
}
// Sent messages (via SendMessage and friends) are processed differently // Sent messages (via SendMessage and friends) are processed differently
// than queued messages (via PostMessage); the destination window procedure // than queued messages (via PostMessage); the destination window procedure

View File

@ -153,8 +153,9 @@ public:
* not aware of (e.g., from a different thread). * not aware of (e.g., from a different thread).
* Note that this method may cause sync dispatch of sent (as opposed to * Note that this method may cause sync dispatch of sent (as opposed to
* posted) messages. * posted) messages.
* @param aTimeoutMs Timeout for waiting in ms, defaults to INFINITE
*/ */
static void WaitForMessage(); static void WaitForMessage(DWORD aTimeoutMs = INFINITE);
/** /**
* Gets the value of a string-typed registry value. * Gets the value of a string-typed registry value.