Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / content / browser / renderer_host / legacy_render_widget_host_win.cc
blobe4f603f0feb475c100332a997c237ef4be2fdb9e
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/internal_constants.h"
16 #include "ui/base/win/window_event_target.h"
17 #include "ui/gfx/geometry/rect.h"
19 namespace content {
21 LegacyRenderWidgetHostHWND::~LegacyRenderWidgetHostHWND() {
22 ::DestroyWindow(hwnd());
25 // static
26 scoped_ptr<LegacyRenderWidgetHostHWND> LegacyRenderWidgetHostHWND::Create(
27 HWND parent) {
28 // content_unittests passes in the desktop window as the parent. We allow
29 // the LegacyRenderWidgetHostHWND instance to be created in this case for
30 // these tests to pass.
31 if (CommandLine::ForCurrentProcess()->HasSwitch(
32 switches::kDisableLegacyIntermediateWindow) ||
33 (!GetWindowEventTarget(parent) && parent != ::GetDesktopWindow()))
34 return scoped_ptr<LegacyRenderWidgetHostHWND>();
36 scoped_ptr<LegacyRenderWidgetHostHWND> legacy_window_instance;
37 legacy_window_instance.reset(new LegacyRenderWidgetHostHWND(parent));
38 // If we failed to create the child, or if the switch to disable the legacy
39 // window is passed in, then return NULL.
40 if (!::IsWindow(legacy_window_instance->hwnd()))
41 return scoped_ptr<LegacyRenderWidgetHostHWND>();
43 legacy_window_instance->Init();
44 return legacy_window_instance.Pass();
47 void LegacyRenderWidgetHostHWND::UpdateParent(HWND parent) {
48 ::SetParent(hwnd(), parent);
49 // If the new parent is the desktop Window, then we disable the child window
50 // to ensure that it does not receive any input events. It should not because
51 // of WS_EX_TRANSPARENT. This is only for safety.
52 if (parent == ::GetDesktopWindow()) {
53 ::EnableWindow(hwnd(), FALSE);
54 } else {
55 ::EnableWindow(hwnd(), TRUE);
59 HWND LegacyRenderWidgetHostHWND::GetParent() {
60 return ::GetParent(hwnd());
63 void LegacyRenderWidgetHostHWND::OnManagerDeleted() {
64 manager_ = NULL;
67 void LegacyRenderWidgetHostHWND::Show() {
68 ::ShowWindow(hwnd(), SW_SHOW);
71 void LegacyRenderWidgetHostHWND::Hide() {
72 ::ShowWindow(hwnd(), SW_HIDE);
75 void LegacyRenderWidgetHostHWND::SetBounds(const gfx::Rect& bounds) {
76 ::SetWindowPos(hwnd(), NULL, bounds.x(), bounds.y(), bounds.width(),
77 bounds.height(), 0);
80 void LegacyRenderWidgetHostHWND::OnFinalMessage(HWND hwnd) {
81 if (manager_)
82 manager_->OnAccessibleHwndDeleted();
85 LegacyRenderWidgetHostHWND::LegacyRenderWidgetHostHWND(HWND parent)
86 : manager_(NULL),
87 mouse_tracking_enabled_(false) {
88 RECT rect = {0};
89 Base::Create(parent, rect, L"Chrome Legacy Window",
90 WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
91 WS_EX_TRANSPARENT);
94 bool LegacyRenderWidgetHostHWND::Init() {
95 if (base::win::GetVersion() >= base::win::VERSION_WIN7 &&
96 ui::AreTouchEventsEnabled())
97 RegisterTouchWindow(hwnd(), TWF_WANTPALM);
99 HRESULT hr = ::CreateStdAccessibleObject(
100 hwnd(), OBJID_WINDOW, IID_IAccessible,
101 reinterpret_cast<void **>(window_accessible_.Receive()));
102 DCHECK(SUCCEEDED(hr));
103 return !!SUCCEEDED(hr);
106 // static
107 ui::WindowEventTarget* LegacyRenderWidgetHostHWND::GetWindowEventTarget(
108 HWND parent) {
109 return reinterpret_cast<ui::WindowEventTarget*>(ui::ViewProp::GetValue(
110 parent, ui::WindowEventTarget::kWin32InputEventTarget));
113 LRESULT LegacyRenderWidgetHostHWND::OnEraseBkGnd(UINT message,
114 WPARAM w_param,
115 LPARAM l_param) {
116 return 1;
119 LRESULT LegacyRenderWidgetHostHWND::OnGetObject(UINT message,
120 WPARAM w_param,
121 LPARAM l_param) {
122 if (OBJID_CLIENT != l_param || !manager_)
123 return static_cast<LRESULT>(0L);
125 base::win::ScopedComPtr<IAccessible> root(
126 manager_->GetRoot()->ToBrowserAccessibilityWin());
127 return LresultFromObject(IID_IAccessible, w_param,
128 static_cast<IAccessible*>(root.Detach()));
131 // We send keyboard/mouse/touch messages to the parent window via SendMessage.
132 // While this works, this has the side effect of converting input messages into
133 // sent messages which changes their priority and could technically result
134 // in these messages starving other messages in the queue. Additionally
135 // keyboard/mouse hooks would not see these messages. The alternative approach
136 // is to set and release capture as needed on the parent to ensure that it
137 // receives all mouse events. However that was shelved due to possible issues
138 // with capture changes.
139 LRESULT LegacyRenderWidgetHostHWND::OnKeyboardRange(UINT message,
140 WPARAM w_param,
141 LPARAM l_param,
142 BOOL& handled) {
143 if (GetWindowEventTarget(GetParent())) {
144 return GetWindowEventTarget(GetParent())->HandleKeyboardMessage(
145 message, w_param, l_param);
147 return 0;
150 LRESULT LegacyRenderWidgetHostHWND::OnMouseRange(UINT message,
151 WPARAM w_param,
152 LPARAM l_param,
153 BOOL& handled) {
154 if (message == WM_MOUSEMOVE) {
155 if (!mouse_tracking_enabled_) {
156 mouse_tracking_enabled_ = true;
157 TRACKMOUSEEVENT tme;
158 tme.cbSize = sizeof(tme);
159 tme.dwFlags = TME_LEAVE;
160 tme.hwndTrack = hwnd();
161 tme.dwHoverTime = 0;
162 TrackMouseEvent(&tme);
165 // The offsets for WM_NCXXX and WM_MOUSEWHEEL and WM_MOUSEHWHEEL messages are
166 // in screen coordinates. We should not be converting them to parent
167 // coordinates.
168 if ((message >= WM_MOUSEFIRST && message <= WM_MOUSELAST) &&
169 (message != WM_MOUSEWHEEL && message != WM_MOUSEHWHEEL)) {
170 POINT mouse_coords;
171 mouse_coords.x = GET_X_LPARAM(l_param);
172 mouse_coords.y = GET_Y_LPARAM(l_param);
173 ::MapWindowPoints(hwnd(), GetParent(), &mouse_coords, 1);
174 l_param = MAKELPARAM(mouse_coords.x, mouse_coords.y);
176 if (GetWindowEventTarget(GetParent())) {
177 return GetWindowEventTarget(GetParent())->HandleMouseMessage(
178 message, w_param, l_param);
180 return 0;
183 LRESULT LegacyRenderWidgetHostHWND::OnMouseLeave(UINT message,
184 WPARAM w_param,
185 LPARAM l_param) {
186 mouse_tracking_enabled_ = false;
187 if ((::GetCapture() != GetParent()) && GetWindowEventTarget(GetParent())) {
188 // We should send a WM_MOUSELEAVE to the parent window only if the mouse
189 // has moved outside the bounds of the parent.
190 POINT cursor_pos;
191 ::GetCursorPos(&cursor_pos);
192 if (::WindowFromPoint(cursor_pos) != GetParent()) {
193 return GetWindowEventTarget(GetParent())->HandleMouseMessage(
194 message, w_param, l_param);
197 return 0;
200 LRESULT LegacyRenderWidgetHostHWND::OnMouseActivate(UINT message,
201 WPARAM w_param,
202 LPARAM l_param) {
203 // Don't pass this to DefWindowProc. That results in the WM_MOUSEACTIVATE
204 // message going all the way to the parent which then messes up state
205 // related to focused views, etc. This is because it treats this as if
206 // it lost activation.
207 // Our dummy window should not interfere with focus and activation in
208 // the parent. Return MA_ACTIVATE here ensures that focus state in the parent
209 // is preserved. The only exception is if the parent was created with the
210 // WS_EX_NOACTIVATE style.
211 if (::GetWindowLong(GetParent(), GWL_EXSTYLE) & WS_EX_NOACTIVATE)
212 return MA_NOACTIVATE;
213 // On Windows, if we select the menu item by touch and if the window at the
214 // location is another window on the same thread, that window gets a
215 // WM_MOUSEACTIVATE message and ends up activating itself, which is not
216 // correct. We workaround this by setting a property on the window at the
217 // current cursor location. We check for this property in our
218 // WM_MOUSEACTIVATE handler and don't activate the window if the property is
219 // set.
220 if (::GetProp(hwnd(), ui::kIgnoreTouchMouseActivateForWindow)) {
221 ::RemoveProp(hwnd(), ui::kIgnoreTouchMouseActivateForWindow);
222 return MA_NOACTIVATE;
224 return MA_ACTIVATE;
227 LRESULT LegacyRenderWidgetHostHWND::OnTouch(UINT message,
228 WPARAM w_param,
229 LPARAM l_param) {
230 if (GetWindowEventTarget(GetParent())) {
231 return GetWindowEventTarget(GetParent())->HandleTouchMessage(
232 message, w_param, l_param);
234 return 0;
237 LRESULT LegacyRenderWidgetHostHWND::OnScroll(UINT message,
238 WPARAM w_param,
239 LPARAM l_param) {
240 if (GetWindowEventTarget(GetParent())) {
241 return GetWindowEventTarget(GetParent())->HandleScrollMessage(
242 message, w_param, l_param);
244 return 0;
247 LRESULT LegacyRenderWidgetHostHWND::OnNCHitTest(UINT message,
248 WPARAM w_param,
249 LPARAM l_param) {
250 if (GetWindowEventTarget(GetParent())) {
251 LRESULT hit_test = GetWindowEventTarget(
252 GetParent())->HandleNcHitTestMessage(message, w_param, l_param);
253 // If the parent returns HTNOWHERE which can happen for popup windows, etc
254 // we return HTCLIENT.
255 if (hit_test == HTNOWHERE)
256 hit_test = HTCLIENT;
257 return hit_test;
259 return HTNOWHERE;
262 LRESULT LegacyRenderWidgetHostHWND::OnNCPaint(UINT message,
263 WPARAM w_param,
264 LPARAM l_param) {
265 return 0;
268 LRESULT LegacyRenderWidgetHostHWND::OnPaint(UINT message,
269 WPARAM w_param,
270 LPARAM l_param) {
271 PAINTSTRUCT ps = {0};
272 ::BeginPaint(hwnd(), &ps);
273 ::EndPaint(hwnd(), &ps);
274 return 0;
277 LRESULT LegacyRenderWidgetHostHWND::OnSetCursor(UINT message,
278 WPARAM w_param,
279 LPARAM l_param) {
280 return 0;
283 LRESULT LegacyRenderWidgetHostHWND::OnNCCalcSize(UINT message,
284 WPARAM w_param,
285 LPARAM l_param) {
286 // Prevent scrollbars, etc from drawing.
287 return 0;
290 LRESULT LegacyRenderWidgetHostHWND::OnSize(UINT message,
291 WPARAM w_param,
292 LPARAM l_param) {
293 // Certain trackpad drivers on Windows have bugs where in they don't generate
294 // WM_MOUSEWHEEL messages for the trackpoint and trackpad scrolling gestures
295 // unless there is an entry for Chrome with the class name of the Window.
296 // Additionally others check if the window WS_VSCROLL/WS_HSCROLL styles and
297 // generate the legacy WM_VSCROLL/WM_HSCROLL messages.
298 // We add these styles to ensure that trackpad/trackpoint scrolling
299 // work.
300 long current_style = ::GetWindowLong(hwnd(), GWL_STYLE);
301 ::SetWindowLong(hwnd(), GWL_STYLE,
302 current_style | WS_VSCROLL | WS_HSCROLL);
303 return 0;
306 } // namespace content