diff options
-rw-r--r-- | base/message_loop/message_pump_win.cc | 95 | ||||
-rw-r--r-- | base/message_loop/message_pump_win.h | 24 |
2 files changed, 35 insertions, 84 deletions
diff --git a/base/message_loop/message_pump_win.cc b/base/message_loop/message_pump_win.cc index 6d9863a..14384d1 100644 --- a/base/message_loop/message_pump_win.cc +++ b/base/message_loop/message_pump_win.cc @@ -6,12 +6,11 @@ #include <math.h> +#include "base/bind.h" #include "base/debug/trace_event.h" #include "base/message_loop/message_loop.h" #include "base/metrics/histogram.h" #include "base/process_util.h" -#include "base/strings/stringprintf.h" -#include "base/win/wrapped_window_proc.h" namespace base { @@ -26,11 +25,13 @@ enum MessageLoopProblems { } // namespace -static const wchar_t kWndClassFormat[] = L"Chrome_MessagePumpWindow_%p"; - // Message sent to get an additional time slice for pumping (processing) another // task (a series of such messages creates a continuous task pump). -static const int kMsgHaveWork = WM_USER + 1; +const int kMsgHaveWork = WM_USER + 1; + +// Identifies the timer used to wake up the UI message pump to run delayed +// tasks. +const int kMessageTimerId = 1; //----------------------------------------------------------------------------- // MessagePumpWin public: @@ -97,15 +98,12 @@ int MessagePumpWin::GetCurrentDelay() const { // MessagePumpForUI public: MessagePumpForUI::MessagePumpForUI() - : atom_(0), - message_filter_(new MessageFilter) { - InitMessageWnd(); + : message_filter_(new MessageFilter) { + CHECK(message_window_.Create(base::Bind(&MessagePumpForUI::HandleMessage, + base::Unretained(this)))); } MessagePumpForUI::~MessagePumpForUI() { - DestroyWindow(message_hwnd_); - UnregisterClass(MAKEINTATOM(atom_), - GetModuleFromAddress(&WndProcThunk)); } void MessagePumpForUI::ScheduleWork() { @@ -113,9 +111,7 @@ void MessagePumpForUI::ScheduleWork() { return; // Someone else continued the pumping. // Make sure the MessagePump does some work for us. - BOOL ret = PostMessage(message_hwnd_, kMsgHaveWork, - reinterpret_cast<WPARAM>(this), 0); - if (ret) + if (PostMessage(message_window_.hwnd(), kMsgHaveWork, 0, 0)) return; // There was room in the Window Message queue. // We have failed to insert a have-work message, so there is a chance that we @@ -132,6 +128,8 @@ void MessagePumpForUI::ScheduleWork() { } void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { + DCHECK(message_window_.CalledOnValidThread()); + // // We would *like* to provide high resolution timers. Windows timers using // SetTimer() have a 10ms granularity. We have to use WM_TIMER as a wakeup @@ -161,9 +159,7 @@ void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { // Create a WM_TIMER event that will wake us up to check for any pending // timers (in case we are running within a nested, external sub-pump). - BOOL ret = SetTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this), - delay_msec, NULL); - if (ret) + if (SetTimer(message_window_.hwnd(), kMessageTimerId, delay_msec, NULL)) return; // If we can't set timers, we are in big trouble... but cross our fingers for // now. @@ -172,48 +168,27 @@ void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { MESSAGE_LOOP_PROBLEM_MAX); } -void MessagePumpForUI::PumpOutPendingPaintMessages() { - // If we are being called outside of the context of Run, then don't try to do - // any work. - if (!state_) - return; - - // Create a mini-message-pump to force immediate processing of only Windows - // WM_PAINT messages. Don't provide an infinite loop, but do enough peeking - // to get the job done. Actual common max is 4 peeks, but we'll be a little - // safe here. - const int kMaxPeekCount = 20; - int peek_count; - for (peek_count = 0; peek_count < kMaxPeekCount; ++peek_count) { - MSG msg; - if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_QS_PAINT)) - break; - ProcessMessageHelper(msg); - if (state_->should_quit) // Handle WM_QUIT. - break; - } - // Histogram what was really being used, to help to adjust kMaxPeekCount. - DHISTOGRAM_COUNTS("Loop.PumpOutPendingPaintMessages Peeks", peek_count); -} - //----------------------------------------------------------------------------- // MessagePumpForUI private: -// static -LRESULT CALLBACK MessagePumpForUI::WndProcThunk( - HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { +bool MessagePumpForUI::HandleMessage(UINT message, + WPARAM wparam, + LPARAM lparam, + LRESULT* result) { switch (message) { case kMsgHaveWork: - reinterpret_cast<MessagePumpForUI*>(wparam)->HandleWorkMessage(); + HandleWorkMessage(); break; case WM_TIMER: - reinterpret_cast<MessagePumpForUI*>(wparam)->HandleTimerMessage(); + HandleTimerMessage(); break; } - return DefWindowProc(hwnd, message, wparam, lparam); + return false; } void MessagePumpForUI::DoRunLoop() { + DCHECK(message_window_.CalledOnValidThread()); + // IF this was just a simple PeekMessage() loop (servicing all possible work // queues), then Windows would try to achieve the following order according // to MSDN documentation about PeekMessage with no filter): @@ -251,7 +226,7 @@ void MessagePumpForUI::DoRunLoop() { // don't want to disturb that timer if it is already in flight. However, // if we did do all remaining delayed work, then lets kill the WM_TIMER. if (more_work_is_plausible && delayed_work_time_.is_null()) - KillTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this)); + KillTimer(message_window_.hwnd(), kMessageTimerId); if (state_->should_quit) break; @@ -269,24 +244,6 @@ void MessagePumpForUI::DoRunLoop() { } } -void MessagePumpForUI::InitMessageWnd() { - // Generate a unique window class name. - string16 class_name = StringPrintf(kWndClassFormat, this); - - HINSTANCE instance = GetModuleFromAddress(&WndProcThunk); - WNDCLASSEX wc = {0}; - wc.cbSize = sizeof(wc); - wc.lpfnWndProc = base::win::WrappedWindowProc<WndProcThunk>; - wc.hInstance = instance; - wc.lpszClassName = class_name.c_str(); - atom_ = RegisterClassEx(&wc); - DCHECK(atom_); - - message_hwnd_ = CreateWindow(MAKEINTATOM(atom_), 0, 0, 0, 0, 0, 0, - HWND_MESSAGE, 0, instance, 0); - DCHECK(message_hwnd_); -} - void MessagePumpForUI::WaitForWork() { // Wait until a message is available, up to the time needed by the timer // manager to fire the next set of timers. @@ -344,7 +301,7 @@ void MessagePumpForUI::HandleWorkMessage() { } void MessagePumpForUI::HandleTimerMessage() { - KillTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this)); + KillTimer(message_window_.hwnd(), kMessageTimerId); // If we are being called outside of the context of Run, then don't do // anything. This could correspond to a MessageBox call or something of @@ -388,7 +345,7 @@ bool MessagePumpForUI::ProcessMessageHelper(const MSG& msg) { } // While running our main message pump, we discard kMsgHaveWork messages. - if (msg.message == kMsgHaveWork && msg.hwnd == message_hwnd_) + if (msg.message == kMsgHaveWork && msg.hwnd == message_window_.hwnd()) return ProcessPumpReplacementMessage(); if (CallMsgFilter(const_cast<MSG*>(&msg), kMessageFilterCode)) @@ -435,7 +392,7 @@ bool MessagePumpForUI::ProcessPumpReplacementMessage() { } DCHECK(!have_message || kMsgHaveWork != msg.message || - msg.hwnd != message_hwnd_); + msg.hwnd != message_window_.hwnd()); // Since we discarded a kMsgHaveWork message, we must update the flag. int old_have_work = InterlockedExchange(&have_work_, 0); diff --git a/base/message_loop/message_pump_win.h b/base/message_loop/message_pump_win.h index 2d83354..5cc8805 100644 --- a/base/message_loop/message_pump_win.h +++ b/base/message_loop/message_pump_win.h @@ -17,6 +17,7 @@ #include "base/message_loop/message_pump_observer.h" #include "base/observer_list.h" #include "base/time/time.h" +#include "base/win/message_window.h" #include "base/win/scoped_handle.h" namespace base { @@ -169,18 +170,14 @@ class BASE_EXPORT MessagePumpForUI : public MessagePumpWin { virtual void ScheduleWork(); virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time); - // Applications can call this to encourage us to process all pending WM_PAINT - // messages. This method will process all paint messages the Windows Message - // queue can provide, up to some fixed number (to avoid any infinite loops). - void PumpOutPendingPaintMessages(); - private: - static LRESULT CALLBACK WndProcThunk(HWND window_handle, - UINT message, - WPARAM wparam, - LPARAM lparam); + // Handles messages received by |message_window_|. + bool HandleMessage(UINT message, + WPARAM wparam, + LPARAM lparam, + LRESULT* result); + virtual void DoRunLoop(); - void InitMessageWnd(); void WaitForWork(); void HandleWorkMessage(); void HandleTimerMessage(); @@ -188,13 +185,10 @@ class BASE_EXPORT MessagePumpForUI : public MessagePumpWin { bool ProcessMessageHelper(const MSG& msg); bool ProcessPumpReplacementMessage(); - // Atom representing the registered window class. - ATOM atom_; + scoped_ptr<MessageFilter> message_filter_; // A hidden message-only window. - HWND message_hwnd_; - - scoped_ptr<MessageFilter> message_filter_; + win::MessageWindow message_window_; }; //----------------------------------------------------------------------------- |