OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |