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 <memory> | 7 #include <memory> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/win/win_util.h" | 10 #include "base/win/win_util.h" |
11 #include "base/win/windows_version.h" | 11 #include "base/win/windows_version.h" |
12 #include "content/browser/accessibility/browser_accessibility_manager_win.h" | 12 #include "content/browser/renderer_host/legacy_render_widget_host_win_delegate.h
" |
13 #include "content/browser/accessibility/browser_accessibility_win.h" | |
14 #include "content/browser/renderer_host/render_widget_host_impl.h" | 13 #include "content/browser/renderer_host/render_widget_host_impl.h" |
15 #include "content/browser/renderer_host/render_widget_host_view_aura.h" | 14 #include "content/browser/renderer_host/render_widget_host_view_aura.h" |
16 #include "content/public/browser/browser_accessibility_state.h" | 15 #include "content/public/browser/browser_accessibility_state.h" |
17 #include "content/public/common/content_switches.h" | 16 #include "content/public/common/content_switches.h" |
18 #include "ui/base/touch/touch_enabled.h" | 17 #include "ui/base/touch/touch_enabled.h" |
19 #include "ui/base/view_prop.h" | 18 #include "ui/base/view_prop.h" |
20 #include "ui/base/win/internal_constants.h" | 19 #include "ui/base/win/internal_constants.h" |
21 #include "ui/base/win/window_event_target.h" | 20 #include "ui/base/win/window_event_target.h" |
22 #include "ui/display/win/screen_win.h" | 21 #include "ui/display/win/screen_win.h" |
23 #include "ui/gfx/geometry/rect.h" | 22 #include "ui/gfx/geometry/rect.h" |
24 #include "ui/gfx/win/direct_manipulation.h" | 23 #include "ui/gfx/win/direct_manipulation.h" |
25 | 24 |
26 namespace content { | 25 namespace content { |
27 | 26 |
| 27 namespace { |
| 28 |
28 // A custom MSAA object id used to determine if a screen reader or some | 29 // A custom MSAA object id used to determine if a screen reader or some |
29 // other client is listening on MSAA events - if so, we enable full web | 30 // other client is listening on MSAA events - if so, we enable full web |
30 // accessibility support. | 31 // accessibility support. |
31 const int kIdScreenReaderHoneyPot = 1; | 32 const int kIdScreenReaderHoneyPot = 1; |
32 | 33 |
| 34 } // namespace |
| 35 |
| 36 LegacyRenderWidgetHostHWND::~LegacyRenderWidgetHostHWND() { |
| 37 // Re-enable flicks for just a moment |
| 38 base::win::EnableFlicks(hwnd()); |
| 39 |
| 40 if (::IsWindow(hwnd())) |
| 41 ::DestroyWindow(hwnd()); |
| 42 } |
| 43 |
33 // static | 44 // static |
34 LegacyRenderWidgetHostHWND* LegacyRenderWidgetHostHWND::Create( | 45 LegacyRenderWidgetHostHWND* LegacyRenderWidgetHostHWND::Create( |
35 HWND parent) { | 46 HWND parent, |
| 47 LegacyRenderWidgetHostHWNDDelegate* delegate) { |
36 // content_unittests passes in the desktop window as the parent. We allow | 48 // content_unittests passes in the desktop window as the parent. We allow |
37 // the LegacyRenderWidgetHostHWND instance to be created in this case for | 49 // the LegacyRenderWidgetHostHWND instance to be created in this case for |
38 // these tests to pass. | 50 // these tests to pass. |
39 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 51 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
40 switches::kDisableLegacyIntermediateWindow) || | 52 switches::kDisableLegacyIntermediateWindow) || |
41 (!GetWindowEventTarget(parent) && parent != ::GetDesktopWindow())) | 53 (!GetWindowEventTarget(parent) && parent != ::GetDesktopWindow())) |
42 return nullptr; | 54 return nullptr; |
43 | 55 |
44 LegacyRenderWidgetHostHWND* legacy_window_instance = | 56 LegacyRenderWidgetHostHWND* legacy_window_instance = |
45 new LegacyRenderWidgetHostHWND(parent); | 57 new LegacyRenderWidgetHostHWND(parent, delegate); |
46 // If we failed to create the child, or if the switch to disable the legacy | 58 |
47 // window is passed in, then return NULL. | 59 // If we failed to create the child, return nullptr. |
48 if (!::IsWindow(legacy_window_instance->hwnd())) { | 60 if (!::IsWindow(legacy_window_instance->hwnd())) { |
49 delete legacy_window_instance; | 61 delete legacy_window_instance; |
50 return NULL; | 62 return nullptr; |
51 } | 63 } |
52 legacy_window_instance->Init(); | 64 legacy_window_instance->Init(); |
53 return legacy_window_instance; | 65 return legacy_window_instance; |
54 } | 66 } |
55 | 67 |
56 void LegacyRenderWidgetHostHWND::Destroy() { | |
57 if (::IsWindow(hwnd())) | |
58 ::DestroyWindow(hwnd()); | |
59 } | |
60 | |
61 void LegacyRenderWidgetHostHWND::UpdateParent(HWND parent) { | 68 void LegacyRenderWidgetHostHWND::UpdateParent(HWND parent) { |
62 if (GetWindowEventTarget(GetParent())) | 69 if (GetWindowEventTarget(GetParent())) |
63 GetWindowEventTarget(GetParent())->HandleParentChanged(); | 70 GetWindowEventTarget(GetParent())->HandleParentChanged(); |
| 71 |
| 72 if (!::IsWindow(hwnd())) |
| 73 return; |
| 74 |
64 ::SetParent(hwnd(), parent); | 75 ::SetParent(hwnd(), parent); |
65 // If the new parent is the desktop Window, then we disable the child window | 76 // If the new parent is the desktop Window, then we disable the child window |
66 // to ensure that it does not receive any input events. It should not because | 77 // to ensure that it does not receive any input events. It should not because |
67 // of WS_EX_TRANSPARENT. This is only for safety. | 78 // of WS_EX_TRANSPARENT. This is only for safety. |
68 if (parent == ::GetDesktopWindow()) { | 79 if (parent == ::GetDesktopWindow()) { |
69 ::EnableWindow(hwnd(), FALSE); | 80 ::EnableWindow(hwnd(), FALSE); |
70 } else { | 81 } else { |
71 ::EnableWindow(hwnd(), TRUE); | 82 ::EnableWindow(hwnd(), TRUE); |
72 } | 83 } |
73 } | 84 } |
74 | 85 |
75 HWND LegacyRenderWidgetHostHWND::GetParent() { | 86 HWND LegacyRenderWidgetHostHWND::GetParent() { |
| 87 if (!::IsWindow(hwnd())) |
| 88 return NULL; |
| 89 |
76 return ::GetParent(hwnd()); | 90 return ::GetParent(hwnd()); |
77 } | 91 } |
78 | 92 |
79 void LegacyRenderWidgetHostHWND::Show() { | 93 void LegacyRenderWidgetHostHWND::Show() { |
80 ::ShowWindow(hwnd(), SW_SHOW); | 94 if (::IsWindow(hwnd())) |
| 95 ::ShowWindow(hwnd(), SW_SHOW); |
81 } | 96 } |
82 | 97 |
83 void LegacyRenderWidgetHostHWND::Hide() { | 98 void LegacyRenderWidgetHostHWND::Hide() { |
84 ::ShowWindow(hwnd(), SW_HIDE); | 99 if (::IsWindow(hwnd())) |
| 100 ::ShowWindow(hwnd(), SW_HIDE); |
85 } | 101 } |
86 | 102 |
87 void LegacyRenderWidgetHostHWND::SetBounds(const gfx::Rect& bounds) { | 103 void LegacyRenderWidgetHostHWND::SetBounds(const gfx::Rect& bounds) { |
| 104 if (!::IsWindow(hwnd())) |
| 105 return; |
| 106 |
88 gfx::Rect bounds_in_pixel = display::win::ScreenWin::DIPToClientRect(hwnd(), | 107 gfx::Rect bounds_in_pixel = display::win::ScreenWin::DIPToClientRect(hwnd(), |
89 bounds); | 108 bounds); |
90 ::SetWindowPos(hwnd(), NULL, bounds_in_pixel.x(), bounds_in_pixel.y(), | 109 ::SetWindowPos(hwnd(), NULL, bounds_in_pixel.x(), bounds_in_pixel.y(), |
91 bounds_in_pixel.width(), bounds_in_pixel.height(), | 110 bounds_in_pixel.width(), bounds_in_pixel.height(), |
92 SWP_NOREDRAW); | 111 SWP_NOREDRAW); |
93 if (direct_manipulation_helper_) | 112 if (direct_manipulation_helper_) |
94 direct_manipulation_helper_->SetBounds(bounds_in_pixel); | 113 direct_manipulation_helper_->SetBounds(bounds_in_pixel); |
95 } | 114 } |
96 | 115 |
97 void LegacyRenderWidgetHostHWND::OnFinalMessage(HWND hwnd) { | 116 LegacyRenderWidgetHostHWND::LegacyRenderWidgetHostHWND( |
98 if (host_) { | 117 HWND parent, |
99 host_->OnLegacyWindowDestroyed(); | 118 LegacyRenderWidgetHostHWNDDelegate* delegate) |
100 host_ = NULL; | |
101 } | |
102 | |
103 // Re-enable flicks for just a moment | |
104 base::win::EnableFlicks(hwnd); | |
105 | |
106 delete this; | |
107 } | |
108 | |
109 LegacyRenderWidgetHostHWND::LegacyRenderWidgetHostHWND(HWND parent) | |
110 : mouse_tracking_enabled_(false), | 119 : mouse_tracking_enabled_(false), |
111 host_(NULL) { | 120 delegate_(delegate) { |
| 121 DCHECK(delegate_); |
112 RECT rect = {0}; | 122 RECT rect = {0}; |
113 Base::Create(parent, rect, L"Chrome Legacy Window", | 123 Base::Create(parent, rect, L"Chrome Legacy Window", |
114 WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, | 124 WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, |
115 WS_EX_TRANSPARENT); | 125 WS_EX_TRANSPARENT); |
116 } | 126 } |
117 | 127 |
118 LegacyRenderWidgetHostHWND::~LegacyRenderWidgetHostHWND() { | |
119 DCHECK(!::IsWindow(hwnd())); | |
120 } | |
121 | |
122 bool LegacyRenderWidgetHostHWND::Init() { | 128 bool LegacyRenderWidgetHostHWND::Init() { |
123 if (base::win::GetVersion() >= base::win::VERSION_WIN7 && | 129 if (base::win::GetVersion() >= base::win::VERSION_WIN7 && |
124 ui::AreTouchEventsEnabled()) | 130 ui::AreTouchEventsEnabled()) |
125 RegisterTouchWindow(hwnd(), TWF_WANTPALM); | 131 RegisterTouchWindow(hwnd(), TWF_WANTPALM); |
126 | 132 |
127 HRESULT hr = ::CreateStdAccessibleObject( | 133 HRESULT hr = ::CreateStdAccessibleObject( |
128 hwnd(), OBJID_WINDOW, IID_IAccessible, | 134 hwnd(), OBJID_WINDOW, IID_IAccessible, |
129 reinterpret_cast<void **>(window_accessible_.Receive())); | 135 reinterpret_cast<void **>(window_accessible_.Receive())); |
130 DCHECK(SUCCEEDED(hr)); | 136 DCHECK(SUCCEEDED(hr)); |
131 | 137 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 // because it sometimes gets sign-extended incorrectly (but not always). | 175 // because it sometimes gets sign-extended incorrectly (but not always). |
170 DWORD obj_id = static_cast<DWORD>(static_cast<DWORD_PTR>(l_param)); | 176 DWORD obj_id = static_cast<DWORD>(static_cast<DWORD_PTR>(l_param)); |
171 | 177 |
172 if (kIdScreenReaderHoneyPot == obj_id) { | 178 if (kIdScreenReaderHoneyPot == obj_id) { |
173 // When an MSAA client has responded to our fake event on this id, | 179 // When an MSAA client has responded to our fake event on this id, |
174 // enable screen reader support. | 180 // enable screen reader support. |
175 BrowserAccessibilityState::GetInstance()->OnScreenReaderDetected(); | 181 BrowserAccessibilityState::GetInstance()->OnScreenReaderDetected(); |
176 return static_cast<LRESULT>(0L); | 182 return static_cast<LRESULT>(0L); |
177 } | 183 } |
178 | 184 |
179 if (static_cast<DWORD>(OBJID_CLIENT) != obj_id || !host_) | 185 if (static_cast<DWORD>(OBJID_CLIENT) != obj_id) |
180 return static_cast<LRESULT>(0L); | 186 return static_cast<LRESULT>(0L); |
181 | 187 |
182 RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From( | 188 base::win::ScopedComPtr<IAccessible> native_accessible( |
183 host_->GetRenderWidgetHost()); | 189 delegate_->GetNativeViewAccessible()); |
184 if (!rwhi) | 190 if (!native_accessible) |
185 return static_cast<LRESULT>(0L); | 191 return static_cast<LRESULT>(0L); |
186 | 192 |
187 BrowserAccessibilityManagerWin* manager = | |
188 static_cast<BrowserAccessibilityManagerWin*>( | |
189 rwhi->GetRootBrowserAccessibilityManager()); | |
190 if (!manager) | |
191 return static_cast<LRESULT>(0L); | |
192 | |
193 base::win::ScopedComPtr<IAccessible> root( | |
194 ToBrowserAccessibilityWin(manager->GetRoot())); | |
195 return LresultFromObject(IID_IAccessible, w_param, | 193 return LresultFromObject(IID_IAccessible, w_param, |
196 static_cast<IAccessible*>(root.Detach())); | 194 static_cast<IAccessible*>(native_accessible.Detach())); |
197 } | 195 } |
198 | 196 |
199 // We send keyboard/mouse/touch messages to the parent window via SendMessage. | 197 // We send keyboard/mouse/touch messages to the parent window via SendMessage. |
200 // While this works, this has the side effect of converting input messages into | 198 // While this works, this has the side effect of converting input messages into |
201 // sent messages which changes their priority and could technically result | 199 // sent messages which changes their priority and could technically result |
202 // in these messages starving other messages in the queue. Additionally | 200 // in these messages starving other messages in the queue. Additionally |
203 // keyboard/mouse hooks would not see these messages. The alternative approach | 201 // keyboard/mouse hooks would not see these messages. The alternative approach |
204 // is to set and release capture as needed on the parent to ensure that it | 202 // is to set and release capture as needed on the parent to ensure that it |
205 // receives all mouse events. However that was shelved due to possible issues | 203 // receives all mouse events. However that was shelved due to possible issues |
206 // with capture changes. | 204 // with capture changes. |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 direct_manipulation_helper_->Activate(hwnd()); | 412 direct_manipulation_helper_->Activate(hwnd()); |
415 } else if (window_pos->flags & SWP_HIDEWINDOW) { | 413 } else if (window_pos->flags & SWP_HIDEWINDOW) { |
416 direct_manipulation_helper_->Deactivate(hwnd()); | 414 direct_manipulation_helper_->Deactivate(hwnd()); |
417 } | 415 } |
418 } | 416 } |
419 SetMsgHandled(FALSE); | 417 SetMsgHandled(FALSE); |
420 return 0; | 418 return 0; |
421 } | 419 } |
422 | 420 |
423 } // namespace content | 421 } // namespace content |
OLD | NEW |