Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(174)

Side by Side Diff: content/browser/renderer_host/legacy_render_widget_host_win.cc

Issue 159713012: Don't track mouse events in HWNDMessageHandler when they are forwarded by the LegacyRenderWidgetHost (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/renderer_host/legacy_render_widget_host_win.h" 5 #include "content/browser/renderer_host/legacy_render_widget_host_win.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
9 #include "base/win/windows_version.h" 9 #include "base/win/windows_version.h"
10 #include "content/browser/accessibility/browser_accessibility_manager_win.h" 10 #include "content/browser/accessibility/browser_accessibility_manager_win.h"
11 #include "content/browser/accessibility/browser_accessibility_win.h" 11 #include "content/browser/accessibility/browser_accessibility_win.h"
12 #include "content/public/common/content_switches.h" 12 #include "content/public/common/content_switches.h"
13 #include "ui/base/touch/touch_enabled.h" 13 #include "ui/base/touch/touch_enabled.h"
14 #include "ui/gfx/geometry/rect.h" 14 #include "ui/gfx/geometry/rect.h"
15 15
16 namespace {
17
18 // This property is set on the parent window when we set capture on it. This
19 // is used to retrieve the child window whose bounds we are tracking.
20 const wchar_t kCaptureForcedOnParentByTrackingWindow[] =
21 L"CaptureForcedByTrackingWindow";
22
23 } // namespace
24
16 namespace content { 25 namespace content {
17 26
27 WNDPROC LegacyRenderWidgetHostHWND::g_parent_original_class_proc = NULL;
28
18 LegacyRenderWidgetHostHWND::~LegacyRenderWidgetHostHWND() { 29 LegacyRenderWidgetHostHWND::~LegacyRenderWidgetHostHWND() {
19 ::DestroyWindow(hwnd()); 30 ::DestroyWindow(hwnd());
20 } 31 }
21 32
22 // static 33 // static
23 scoped_ptr<LegacyRenderWidgetHostHWND> LegacyRenderWidgetHostHWND::Create( 34 scoped_ptr<LegacyRenderWidgetHostHWND> LegacyRenderWidgetHostHWND::Create(
24 HWND parent) { 35 HWND parent) {
36 if (CommandLine::ForCurrentProcess()->HasSwitch(
37 switches::kDisableLegacyIntermediateWindow))
38 return scoped_ptr<LegacyRenderWidgetHostHWND>();
39
25 scoped_ptr<LegacyRenderWidgetHostHWND> legacy_window_instance; 40 scoped_ptr<LegacyRenderWidgetHostHWND> legacy_window_instance;
26 legacy_window_instance.reset(new LegacyRenderWidgetHostHWND(parent)); 41 legacy_window_instance.reset(new LegacyRenderWidgetHostHWND(parent));
27 // If we failed to create the child, or if the switch to disable the legacy 42 // If we failed to create the child, or if the switch to disable the legacy
28 // window is passed in, then return NULL. 43 // window is passed in, then return NULL.
29 if (!::IsWindow(legacy_window_instance->hwnd()) || 44 if (!::IsWindow(legacy_window_instance->hwnd()))
30 CommandLine::ForCurrentProcess()->HasSwitch(
31 switches::kDisableLegacyIntermediateWindow))
32 return scoped_ptr<LegacyRenderWidgetHostHWND>(); 45 return scoped_ptr<LegacyRenderWidgetHostHWND>();
33 46
34 legacy_window_instance->Init(); 47 legacy_window_instance->Init();
35 return legacy_window_instance.Pass(); 48 return legacy_window_instance.Pass();
36 } 49 }
37 50
38 void LegacyRenderWidgetHostHWND::UpdateParent(HWND parent) { 51 void LegacyRenderWidgetHostHWND::UpdateParent(HWND parent) {
39 ::SetParent(hwnd(), parent); 52 ::SetParent(hwnd(), parent);
40 // If the new parent is the desktop Window, then we disable the child window 53 // If the new parent is the desktop Window, then we disable the child window
41 // to ensure that it does not receive any input events. It should not because 54 // to ensure that it does not receive any input events. It should not because
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 Base::Create(parent, rect, L"Chrome Legacy Window", 92 Base::Create(parent, rect, L"Chrome Legacy Window",
80 WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 93 WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
81 WS_EX_TRANSPARENT); 94 WS_EX_TRANSPARENT);
82 } 95 }
83 96
84 bool LegacyRenderWidgetHostHWND::Init() { 97 bool LegacyRenderWidgetHostHWND::Init() {
85 if (base::win::GetVersion() >= base::win::VERSION_WIN7 && 98 if (base::win::GetVersion() >= base::win::VERSION_WIN7 &&
86 ui::AreTouchEventsEnabled()) 99 ui::AreTouchEventsEnabled())
87 RegisterTouchWindow(hwnd(), TWF_WANTPALM); 100 RegisterTouchWindow(hwnd(), TWF_WANTPALM);
88 101
102 // We superclass the parent window class. This is to ensure that we avoid
103 // messy code tracking if the window was subclassed or not. Superclassing
104 // the parent ensures that we can windows subsequently created.
105 // Note: We never unsubclass. This should be safe.
106 if (!g_parent_original_class_proc) {
sky 2014/02/12 14:36:31 Doesn't this assume the legacy hwnd always has a p
107 g_parent_original_class_proc = reinterpret_cast<WNDPROC>(
108 ::SetClassLong(GetParent(), GCL_WNDPROC,
109 reinterpret_cast<long>(ParentWindowSuperClassProc)));
110 DCHECK(g_parent_original_class_proc);
111 // We need to subclass the first window as the super class does not take
112 // effect until a new window is created.
113 ::SetWindowLong(GetParent(), GWL_WNDPROC,
114 reinterpret_cast<long>(ParentWindowSuperClassProc));
115 }
116
89 HRESULT hr = ::CreateStdAccessibleObject( 117 HRESULT hr = ::CreateStdAccessibleObject(
90 hwnd(), OBJID_WINDOW, IID_IAccessible, 118 hwnd(), OBJID_WINDOW, IID_IAccessible,
91 reinterpret_cast<void **>(window_accessible_.Receive())); 119 reinterpret_cast<void **>(window_accessible_.Receive()));
92 DCHECK(SUCCEEDED(hr)); 120 DCHECK(SUCCEEDED(hr));
93 return !!SUCCEEDED(hr); 121 return !!SUCCEEDED(hr);
94 } 122 }
95 123
96 LRESULT LegacyRenderWidgetHostHWND::OnEraseBkGnd(UINT message, 124 LRESULT LegacyRenderWidgetHostHWND::OnEraseBkGnd(UINT message,
97 WPARAM w_param, 125 WPARAM w_param,
98 LPARAM l_param) { 126 LPARAM l_param) {
(...skipping 24 matching lines...) Expand all
123 WPARAM w_param, 151 WPARAM w_param,
124 LPARAM l_param, 152 LPARAM l_param,
125 BOOL& handled) { 153 BOOL& handled) {
126 return ::SendMessage(GetParent(), message, w_param, l_param); 154 return ::SendMessage(GetParent(), message, w_param, l_param);
127 } 155 }
128 156
129 LRESULT LegacyRenderWidgetHostHWND::OnMouseRange(UINT message, 157 LRESULT LegacyRenderWidgetHostHWND::OnMouseRange(UINT message,
130 WPARAM w_param, 158 WPARAM w_param,
131 LPARAM l_param, 159 LPARAM l_param,
132 BOOL& handled) { 160 BOOL& handled) {
133 POINT mouse_coords; 161 // We won't receive mouse messages when capture is with the parent window.
134 mouse_coords.x = GET_X_LPARAM(l_param); 162 // If we receive a mouse move then it means that parent capture was released.
135 mouse_coords.y = GET_Y_LPARAM(l_param); 163 // This would happen if we lost focus or if the mouse left our window bounds
136 ::MapWindowPoints(hwnd(), GetParent(), &mouse_coords, 1); 164 // and we released capture.
137 return ::SendMessage(GetParent(), message, w_param, 165 if (message == WM_MOUSEMOVE) {
138 MAKELPARAM(mouse_coords.x, mouse_coords.y)); 166 if (::GetCapture() != GetParent()) {
167 ::SetCapture(GetParent());
168 ::SetProp(GetParent(), kCaptureForcedOnParentByTrackingWindow, hwnd());
169 }
170 } else if (message == WM_MOUSEWHEEL || message == WM_MOUSEHWHEEL) {
171 return ::SendMessage(GetParent(), message, w_param, l_param);
172 } else {
173 NOTREACHED() << "Unexpected mouse message received: " << message;
174 }
175 return 0;
139 } 176 }
140 177
141 LRESULT LegacyRenderWidgetHostHWND::OnMouseActivate(UINT message, 178 LRESULT LegacyRenderWidgetHostHWND::OnMouseActivate(UINT message,
142 WPARAM w_param, 179 WPARAM w_param,
143 LPARAM l_param) { 180 LPARAM l_param) {
144 // Don't pass this to DefWindowProc. That results in the WM_MOUSEACTIVATE 181 // Don't pass this to DefWindowProc. That results in the WM_MOUSEACTIVATE
145 // message going all the way to the parent which then messes up state 182 // message going all the way to the parent which then messes up state
146 // related to focused views, etc. This is because it treats this as if 183 // related to focused views, etc. This is because it treats this as if
147 // it lost activation. 184 // it lost activation.
148 // Our dummy window should not interfere with focus and activation in 185 // Our dummy window should not interfere with focus and activation in
(...skipping 25 matching lines...) Expand all
174 ::EndPaint(hwnd(), &ps); 211 ::EndPaint(hwnd(), &ps);
175 return 0; 212 return 0;
176 } 213 }
177 214
178 LRESULT LegacyRenderWidgetHostHWND::OnSetCursor(UINT message, 215 LRESULT LegacyRenderWidgetHostHWND::OnSetCursor(UINT message,
179 WPARAM w_param, 216 WPARAM w_param,
180 LPARAM l_param) { 217 LPARAM l_param) {
181 return 0; 218 return 0;
182 } 219 }
183 220
221 // static
222 LRESULT CALLBACK LegacyRenderWidgetHostHWND::ParentWindowSuperClassProc(
223 HWND window, UINT message, WPARAM w_param, LPARAM l_param) {
224 // To ensure that the LegacyRenderWidgetHostHWND is as less intrusive as
225 // possible, we set capture on the parent window when we receive a
226 // mouse move message for the LegacyRenderWidgetHostHWND hwnd. This ensures
227 // that subsequent mouse messages go to the parent. We need to release this
228 // forced capture on the parent when the mouse cursor leaves the bounds of
229 // the LegacyRenderWidgetHostHWND window which is identified by the
230 // tracking_window local variable below. We only do this when no mouse
231 // buttons are down as in that case capture is released by code in the
232 // default parent mouse event handling.
233 const int mouse_down_flags =
234 MK_LBUTTON | MK_MBUTTON | MK_RBUTTON | MK_XBUTTON1 | MK_XBUTTON2;
235 if (message == WM_MOUSEMOVE && ::GetCapture() == window &&
236 !(w_param & mouse_down_flags)) {
237 HWND tracking_window = reinterpret_cast<HWND>(::GetProp(window,
238 kCaptureForcedOnParentByTrackingWindow));
239 if (::IsWindow(tracking_window)) {
240 POINT pt = {0};
241 pt.x = GET_X_LPARAM(l_param);
242 pt.y = GET_Y_LPARAM(l_param);
243 ::ClientToScreen(window, &pt);
244
245 RECT window_rect = {0};
246 ::GetWindowRect(tracking_window, &window_rect);
247 if (!::PtInRect(&window_rect, pt) ||
248 ::WindowFromPoint(pt) != tracking_window) {
249 ::ReleaseCapture();
250 ::RemoveProp(window, kCaptureForcedOnParentByTrackingWindow);
251 }
252 }
253 }
254 DCHECK(g_parent_original_class_proc);
255 return ::CallWindowProc(g_parent_original_class_proc, window, message,
256 w_param, l_param);
257 }
258
184 } // namespace content 259 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698