| // Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights |
| // reserved. Use of this source code is governed by a BSD-style license that |
| // can be found in the LICENSE file. |
| |
| #include "tests/shared/browser/main_message_loop_external_pump.h" |
| |
| #include <CommCtrl.h> |
| |
| #include "include/cef_app.h" |
| #include "tests/shared/browser/util_win.h" |
| |
| namespace client { |
| |
| namespace { |
| |
| // 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; |
| |
| class MainMessageLoopExternalPumpWin : public MainMessageLoopExternalPump { |
| public: |
| MainMessageLoopExternalPumpWin(); |
| ~MainMessageLoopExternalPumpWin(); |
| |
| // MainMessageLoopStd methods: |
| void Quit() OVERRIDE; |
| int Run() OVERRIDE; |
| |
| // MainMessageLoopExternalPump methods: |
| void OnScheduleMessagePumpWork(int64 delay_ms) OVERRIDE; |
| |
| protected: |
| // MainMessageLoopExternalPump methods: |
| void SetTimer(int64 delay_ms) OVERRIDE; |
| void KillTimer() OVERRIDE; |
| bool IsTimerPending() OVERRIDE { return timer_pending_; } |
| |
| private: |
| static LRESULT CALLBACK WndProc(HWND hwnd, |
| UINT msg, |
| WPARAM wparam, |
| LPARAM lparam); |
| |
| // True if a timer event is currently pending. |
| bool timer_pending_; |
| |
| // HWND owned by the thread that CefDoMessageLoopWork should be invoked on. |
| HWND main_thread_target_; |
| }; |
| |
| MainMessageLoopExternalPumpWin::MainMessageLoopExternalPumpWin() |
| : timer_pending_(false), main_thread_target_(NULL) { |
| HINSTANCE hInstance = GetModuleHandle(NULL); |
| const wchar_t* const kClassName = L"CEFMainTargetHWND"; |
| |
| WNDCLASSEX wcex = {}; |
| wcex.cbSize = sizeof(WNDCLASSEX); |
| wcex.lpfnWndProc = WndProc; |
| wcex.hInstance = hInstance; |
| wcex.lpszClassName = kClassName; |
| RegisterClassEx(&wcex); |
| |
| // Create the message handling window. |
| main_thread_target_ = |
| CreateWindowW(kClassName, NULL, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, |
| HWND_MESSAGE, NULL, hInstance, NULL); |
| DCHECK(main_thread_target_); |
| SetUserDataPtr(main_thread_target_, this); |
| } |
| |
| MainMessageLoopExternalPumpWin::~MainMessageLoopExternalPumpWin() { |
| KillTimer(); |
| if (main_thread_target_) |
| DestroyWindow(main_thread_target_); |
| } |
| |
| void MainMessageLoopExternalPumpWin::Quit() { |
| PostMessage(NULL, WM_QUIT, 0, 0); |
| } |
| |
| int MainMessageLoopExternalPumpWin::Run() { |
| // Run the message loop. |
| MSG msg; |
| while (GetMessage(&msg, NULL, 0, 0)) { |
| TranslateMessage(&msg); |
| DispatchMessage(&msg); |
| } |
| |
| KillTimer(); |
| |
| // We need to run the message pump until it is idle. However we don't have |
| // that information here so we run the message loop "for a while". |
| for (int i = 0; i < 10; ++i) { |
| // Do some work. |
| CefDoMessageLoopWork(); |
| |
| // Sleep to allow the CEF proc to do work. |
| Sleep(50); |
| } |
| |
| return 0; |
| } |
| |
| void MainMessageLoopExternalPumpWin::OnScheduleMessagePumpWork(int64 delay_ms) { |
| // This method may be called on any thread. |
| PostMessage(main_thread_target_, kMsgHaveWork, 0, |
| static_cast<LPARAM>(delay_ms)); |
| } |
| |
| void MainMessageLoopExternalPumpWin::SetTimer(int64 delay_ms) { |
| DCHECK(!timer_pending_); |
| DCHECK_GT(delay_ms, 0); |
| timer_pending_ = true; |
| ::SetTimer(main_thread_target_, 1, static_cast<UINT>(delay_ms), NULL); |
| } |
| |
| void MainMessageLoopExternalPumpWin::KillTimer() { |
| if (timer_pending_) { |
| ::KillTimer(main_thread_target_, 1); |
| timer_pending_ = false; |
| } |
| } |
| |
| // static |
| LRESULT CALLBACK MainMessageLoopExternalPumpWin::WndProc(HWND hwnd, |
| UINT msg, |
| WPARAM wparam, |
| LPARAM lparam) { |
| if (msg == WM_TIMER || msg == kMsgHaveWork) { |
| MainMessageLoopExternalPumpWin* message_loop = |
| GetUserDataPtr<MainMessageLoopExternalPumpWin*>(hwnd); |
| if (msg == kMsgHaveWork) { |
| // OnScheduleMessagePumpWork() request. |
| const int64 delay_ms = static_cast<int64>(lparam); |
| message_loop->OnScheduleWork(delay_ms); |
| } else { |
| // Timer timed out. |
| message_loop->OnTimerTimeout(); |
| } |
| } |
| return DefWindowProc(hwnd, msg, wparam, lparam); |
| } |
| |
| } // namespace |
| |
| // static |
| scoped_ptr<MainMessageLoopExternalPump> MainMessageLoopExternalPump::Create() { |
| return scoped_ptr<MainMessageLoopExternalPump>( |
| new MainMessageLoopExternalPumpWin()); |
| } |
| |
| } // namespace client |