Cast: Skip receiver log messages with time delta that can't be encoded.
[chromium-blink-merge.git] / content / browser / renderer_host / legacy_render_widget_host_win.cc
blob67f450c5476da57e94034ac8eb8474405a89fd9c
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/renderer_host/legacy_render_widget_host_win.h"
7 #include "base/command_line.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/win/windows_version.h"
10 #include "content/browser/accessibility/browser_accessibility_manager_win.h"
11 #include "content/browser/accessibility/browser_accessibility_win.h"
12 #include "content/public/common/content_switches.h"
13 #include "ui/base/touch/touch_enabled.h"
14 #include "ui/base/view_prop.h"
15 #include "ui/base/win/window_event_target.h"
16 #include "ui/gfx/geometry/rect.h"
18 namespace content {
20 LegacyRenderWidgetHostHWND::~LegacyRenderWidgetHostHWND() {
21 ::DestroyWindow(hwnd());
24 // static
25 scoped_ptr<LegacyRenderWidgetHostHWND> LegacyRenderWidgetHostHWND::Create(
26 HWND parent) {
27 // content_unittests passes in the desktop window as the parent. We allow
28 // the LegacyRenderWidgetHostHWND instance to be created in this case for
29 // these tests to pass.
30 if (CommandLine::ForCurrentProcess()->HasSwitch(
31 switches::kDisableLegacyIntermediateWindow) ||
32 (!GetWindowEventTarget(parent) && parent != ::GetDesktopWindow()))
33 return scoped_ptr<LegacyRenderWidgetHostHWND>();
35 scoped_ptr<LegacyRenderWidgetHostHWND> legacy_window_instance;
36 legacy_window_instance.reset(new LegacyRenderWidgetHostHWND(parent));
37 // If we failed to create the child, or if the switch to disable the legacy
38 // window is passed in, then return NULL.
39 if (!::IsWindow(legacy_window_instance->hwnd()))
40 return scoped_ptr<LegacyRenderWidgetHostHWND>();
42 legacy_window_instance->Init();
43 return legacy_window_instance.Pass();
46 void LegacyRenderWidgetHostHWND::UpdateParent(HWND parent) {
47 ::SetParent(hwnd(), parent);
48 // If the new parent is the desktop Window, then we disable the child window
49 // to ensure that it does not receive any input events. It should not because
50 // of WS_EX_TRANSPARENT. This is only for safety.
51 if (parent == ::GetDesktopWindow()) {
52 ::EnableWindow(hwnd(), FALSE);
53 } else {
54 ::EnableWindow(hwnd(), TRUE);
58 HWND LegacyRenderWidgetHostHWND::GetParent() {
59 return ::GetParent(hwnd());
62 void LegacyRenderWidgetHostHWND::OnManagerDeleted() {
63 manager_ = NULL;
66 void LegacyRenderWidgetHostHWND::Show() {
67 ::ShowWindow(hwnd(), SW_SHOW);
70 void LegacyRenderWidgetHostHWND::Hide() {
71 ::ShowWindow(hwnd(), SW_HIDE);
74 void LegacyRenderWidgetHostHWND::SetBounds(const gfx::Rect& bounds) {
75 ::SetWindowPos(hwnd(), NULL, bounds.x(), bounds.y(), bounds.width(),
76 bounds.height(), 0);
79 void LegacyRenderWidgetHostHWND::OnFinalMessage(HWND hwnd) {
80 if (manager_)
81 manager_->OnAccessibleHwndDeleted();
84 LegacyRenderWidgetHostHWND::LegacyRenderWidgetHostHWND(HWND parent)
85 : manager_(NULL),
86 mouse_tracking_enabled_(false) {
87 RECT rect = {0};
88 Base::Create(parent, rect, L"Chrome Legacy Window",
89 WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
90 WS_EX_TRANSPARENT);
93 bool LegacyRenderWidgetHostHWND::Init() {
94 if (base::win::GetVersion() >= base::win::VERSION_WIN7 &&
95 ui::AreTouchEventsEnabled())
96 RegisterTouchWindow(hwnd(), TWF_WANTPALM);
98 HRESULT hr = ::CreateStdAccessibleObject(
99 hwnd(), OBJID_WINDOW, IID_IAccessible,
100 reinterpret_cast<void **>(window_accessible_.Receive()));
101 DCHECK(SUCCEEDED(hr));
102 return !!SUCCEEDED(hr);
105 // static
106 ui::WindowEventTarget* LegacyRenderWidgetHostHWND::GetWindowEventTarget(
107 HWND parent) {
108 return reinterpret_cast<ui::WindowEventTarget*>(ui::ViewProp::GetValue(
109 parent, ui::WindowEventTarget::kWin32InputEventTarget));
112 LRESULT LegacyRenderWidgetHostHWND::OnEraseBkGnd(UINT message,
113 WPARAM w_param,
114 LPARAM l_param) {
115 return 1;
118 LRESULT LegacyRenderWidgetHostHWND::OnGetObject(UINT message,
119 WPARAM w_param,
120 LPARAM l_param) {
121 if (OBJID_CLIENT != l_param || !manager_)
122 return static_cast<LRESULT>(0L);
124 base::win::ScopedComPtr<IAccessible> root(
125 manager_->GetRoot()->ToBrowserAccessibilityWin());
126 return LresultFromObject(IID_IAccessible, w_param,
127 static_cast<IAccessible*>(root.Detach()));
130 // We send keyboard/mouse/touch messages to the parent window via SendMessage.
131 // While this works, this has the side effect of converting input messages into
132 // sent messages which changes their priority and could technically result
133 // in these messages starving other messages in the queue. Additionally
134 // keyboard/mouse hooks would not see these messages. The alternative approach
135 // is to set and release capture as needed on the parent to ensure that it
136 // receives all mouse events. However that was shelved due to possible issues
137 // with capture changes.
138 LRESULT LegacyRenderWidgetHostHWND::OnKeyboardRange(UINT message,
139 WPARAM w_param,
140 LPARAM l_param,
141 BOOL& handled) {
142 if (GetWindowEventTarget(GetParent())) {
143 return GetWindowEventTarget(GetParent())->HandleKeyboardMessage(
144 message, w_param, l_param);
146 return 0;
149 LRESULT LegacyRenderWidgetHostHWND::OnMouseRange(UINT message,
150 WPARAM w_param,
151 LPARAM l_param,
152 BOOL& handled) {
153 if (message == WM_MOUSEMOVE) {
154 if (!mouse_tracking_enabled_) {
155 mouse_tracking_enabled_ = true;
156 TRACKMOUSEEVENT tme;
157 tme.cbSize = sizeof(tme);
158 tme.dwFlags = TME_LEAVE;
159 tme.hwndTrack = hwnd();
160 tme.dwHoverTime = 0;
161 TrackMouseEvent(&tme);
164 // The offsets for WM_NCXXX and WM_MOUSEWHEEL and WM_MOUSEHWHEEL messages are
165 // in screen coordinates. We should not be converting them to parent
166 // coordinates.
167 if ((message >= WM_MOUSEFIRST && message <= WM_MOUSELAST) &&
168 (message != WM_MOUSEWHEEL && message != WM_MOUSEHWHEEL)) {
169 POINT mouse_coords;
170 mouse_coords.x = GET_X_LPARAM(l_param);
171 mouse_coords.y = GET_Y_LPARAM(l_param);
172 ::MapWindowPoints(hwnd(), GetParent(), &mouse_coords, 1);
173 l_param = MAKELPARAM(mouse_coords.x, mouse_coords.y);
175 if (GetWindowEventTarget(GetParent())) {
176 return GetWindowEventTarget(GetParent())->HandleMouseMessage(
177 message, w_param, l_param);
179 return 0;
182 LRESULT LegacyRenderWidgetHostHWND::OnMouseLeave(UINT message,
183 WPARAM w_param,
184 LPARAM l_param) {
185 mouse_tracking_enabled_ = false;
186 if ((::GetCapture() != GetParent()) && GetWindowEventTarget(GetParent())) {
187 // We should send a WM_MOUSELEAVE to the parent window only if the mouse
188 // has moved outside the bounds of the parent.
189 POINT cursor_pos;
190 ::GetCursorPos(&cursor_pos);
191 if (::WindowFromPoint(cursor_pos) != GetParent()) {
192 return GetWindowEventTarget(GetParent())->HandleMouseMessage(
193 message, w_param, l_param);
196 return 0;
199 LRESULT LegacyRenderWidgetHostHWND::OnMouseActivate(UINT message,
200 WPARAM w_param,
201 LPARAM l_param) {
202 // Don't pass this to DefWindowProc. That results in the WM_MOUSEACTIVATE
203 // message going all the way to the parent which then messes up state
204 // related to focused views, etc. This is because it treats this as if
205 // it lost activation.
206 // Our dummy window should not interfere with focus and activation in
207 // the parent. Return MA_ACTIVATE here ensures that focus state in the parent
208 // is preserved. The only exception is if the parent was created with the
209 // WS_EX_NOACTIVATE style.
210 if (::GetWindowLong(GetParent(), GWL_EXSTYLE) & WS_EX_NOACTIVATE)
211 return MA_NOACTIVATE;
212 return MA_ACTIVATE;
215 LRESULT LegacyRenderWidgetHostHWND::OnTouch(UINT message,
216 WPARAM w_param,
217 LPARAM l_param) {
218 if (GetWindowEventTarget(GetParent())) {
219 return GetWindowEventTarget(GetParent())->HandleTouchMessage(
220 message, w_param, l_param);
222 return 0;
225 LRESULT LegacyRenderWidgetHostHWND::OnScroll(UINT message,
226 WPARAM w_param,
227 LPARAM l_param) {
228 if (GetWindowEventTarget(GetParent())) {
229 return GetWindowEventTarget(GetParent())->HandleScrollMessage(
230 message, w_param, l_param);
232 return 0;
235 LRESULT LegacyRenderWidgetHostHWND::OnNCHitTest(UINT message,
236 WPARAM w_param,
237 LPARAM l_param) {
238 if (GetWindowEventTarget(GetParent())) {
239 LRESULT hit_test = GetWindowEventTarget(
240 GetParent())->HandleNcHitTestMessage(message, w_param, l_param);
241 // If the parent returns HTNOWHERE which can happen for popup windows, etc
242 // we return HTCLIENT.
243 if (hit_test == HTNOWHERE)
244 hit_test = HTCLIENT;
245 return hit_test;
247 return HTNOWHERE;
250 LRESULT LegacyRenderWidgetHostHWND::OnNCPaint(UINT message,
251 WPARAM w_param,
252 LPARAM l_param) {
253 return 0;
256 LRESULT LegacyRenderWidgetHostHWND::OnPaint(UINT message,
257 WPARAM w_param,
258 LPARAM l_param) {
259 PAINTSTRUCT ps = {0};
260 ::BeginPaint(hwnd(), &ps);
261 ::EndPaint(hwnd(), &ps);
262 return 0;
265 LRESULT LegacyRenderWidgetHostHWND::OnSetCursor(UINT message,
266 WPARAM w_param,
267 LPARAM l_param) {
268 return 0;
271 LRESULT LegacyRenderWidgetHostHWND::OnNCCalcSize(UINT message,
272 WPARAM w_param,
273 LPARAM l_param) {
274 // Prevent scrollbars, etc from drawing.
275 return 0;
278 LRESULT LegacyRenderWidgetHostHWND::OnSize(UINT message,
279 WPARAM w_param,
280 LPARAM l_param) {
281 // Certain trackpad drivers on Windows have bugs where in they don't generate
282 // WM_MOUSEWHEEL messages for the trackpoint and trackpad scrolling gestures
283 // unless there is an entry for Chrome with the class name of the Window.
284 // Additionally others check if the window WS_VSCROLL/WS_HSCROLL styles and
285 // generate the legacy WM_VSCROLL/WM_HSCROLL messages.
286 // We add these styles to ensure that trackpad/trackpoint scrolling
287 // work.
288 long current_style = ::GetWindowLong(hwnd(), GWL_STYLE);
289 ::SetWindowLong(hwnd(), GWL_STYLE,
290 current_style | WS_VSCROLL | WS_HSCROLL);
291 return 0;
294 } // namespace content