/
main_message_loop_external_pump_win.cc
152 lines (122 loc) · 4.41 KB
/
main_message_loop_external_pump_win.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// 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