Chromium Code Reviews| 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 <directmanipulation.h> | |
| 8 | |
| 7 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 8 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| 11 #include "base/win/scoped_comptr.h" | |
| 9 #include "base/win/windows_version.h" | 12 #include "base/win/windows_version.h" |
| 10 #include "content/browser/accessibility/browser_accessibility_manager_win.h" | 13 #include "content/browser/accessibility/browser_accessibility_manager_win.h" |
| 11 #include "content/browser/accessibility/browser_accessibility_win.h" | 14 #include "content/browser/accessibility/browser_accessibility_win.h" |
| 12 #include "content/browser/renderer_host/render_widget_host_impl.h" | 15 #include "content/browser/renderer_host/render_widget_host_impl.h" |
| 13 #include "content/browser/renderer_host/render_widget_host_view_aura.h" | 16 #include "content/browser/renderer_host/render_widget_host_view_aura.h" |
| 14 #include "content/public/browser/browser_accessibility_state.h" | 17 #include "content/public/browser/browser_accessibility_state.h" |
| 15 #include "content/public/common/content_switches.h" | 18 #include "content/public/common/content_switches.h" |
| 16 #include "ui/base/touch/touch_enabled.h" | 19 #include "ui/base/touch/touch_enabled.h" |
| 17 #include "ui/base/view_prop.h" | 20 #include "ui/base/view_prop.h" |
| 18 #include "ui/base/win/internal_constants.h" | 21 #include "ui/base/win/internal_constants.h" |
| 19 #include "ui/base/win/window_event_target.h" | 22 #include "ui/base/win/window_event_target.h" |
| 20 #include "ui/gfx/geometry/rect.h" | 23 #include "ui/gfx/geometry/rect.h" |
| 21 #include "ui/gfx/win/dpi.h" | 24 #include "ui/gfx/win/dpi.h" |
| 22 | 25 |
| 23 namespace content { | 26 namespace content { |
| 24 | 27 |
| 28 // Windows 10 provides a new API called Direct Manipulation which generates | |
| 29 // smooth scroll events via WM_MOUSEWHEEL messages with predictable deltas | |
| 30 // on high precision touch pads. This basically requires the application window | |
| 31 // to register as a Direct Manipulation consumer. The way mouse wheel messages | |
| 32 // are dispatched is | |
| 33 // 1. The foreground window is checked to see if it is a Direct Manipulation | |
| 34 // consumer. | |
| 35 // 2. If it is then Direct Manipulation takes over and sends the following | |
| 36 // messages. WM_POINTERACTIVATE, WM_POINTERDOWN and DM_POINTERHITTEST. | |
| 37 // 3. It then posts WM_MOUSEWHEEL messages with precision deltas which vary | |
| 38 // based on the amount of the scroll. | |
| 39 // 4. If the foreground window is not a Direct Manipulation consumer, it | |
| 40 // then takes a fallback route where it posts WM_MOUSEWHEEL messages | |
| 41 // with precision but varying deltas to the window. There is a also | |
| 42 // a slight delay in receiving the first set of mouse wheel messages. | |
| 43 // This causes scrolling in Chrome to appear janky and jumpy. | |
| 44 // Our approach for addressing this is to do the absolute minimum to | |
| 45 // register our window as a Direct Manipulation consumer. This class | |
| 46 // provides the necessary functionality to register the legacy HWND as a | |
| 47 // Direct Manipulation consumer. We don't rely on Direct manipulation | |
| 48 // to do the smooth scrolling in the background thread as documented on | |
| 49 // msdn. | |
| 50 class DirectManipulationHelper { | |
|
sky
2015/08/11 15:43:12
Would it make more sense to do this in views so th
ananta
2015/08/11 20:52:08
I guess so. I moved the DirectManipulationHelper c
| |
| 51 public: | |
| 52 DirectManipulationHelper() {} | |
| 53 | |
| 54 // This function instantiates Direct Manipulation and creates a viewport for | |
| 55 // the passed in |window|. | |
| 56 // consumer. Most of the code is boiler plate and is based on the sample. | |
| 57 bool Initialize(HWND window) { | |
| 58 DCHECK(::IsWindow(window)); | |
| 59 | |
| 60 HRESULT hr = manager_.CreateInstance(CLSID_DirectManipulationManager, | |
| 61 nullptr, CLSCTX_INPROC_SERVER); | |
| 62 CHECK(SUCCEEDED(hr)); | |
|
sky
2015/08/11 15:43:12
Do these all need to be CHECKs, if any of these fa
ananta
2015/08/11 20:52:08
Added a TODO to remove the CHECKs once this stabli
| |
| 63 | |
| 64 hr = compositor_.CreateInstance(CLSID_DCompManipulationCompositor, | |
| 65 nullptr, CLSCTX_INPROC_SERVER); | |
| 66 CHECK(SUCCEEDED(hr)); | |
| 67 | |
| 68 hr = manager_->GetUpdateManager(IID_PPV_ARGS(update_manager_.Receive())); | |
| 69 CHECK(SUCCEEDED(hr)); | |
| 70 | |
| 71 hr = compositor_->SetUpdateManager(update_manager_.get()); | |
| 72 CHECK(SUCCEEDED(hr)); | |
| 73 | |
| 74 hr = frame_info_.QueryFrom(compositor_.get()); | |
| 75 CHECK(SUCCEEDED(hr)); | |
| 76 | |
| 77 hr = manager_->CreateViewport(frame_info_.get(), window, | |
| 78 IID_PPV_ARGS(view_port_outer_.Receive())); | |
| 79 CHECK(SUCCEEDED(hr)); | |
| 80 | |
| 81 // | |
| 82 // Enable the desired configuration for each viewport. | |
| 83 // | |
| 84 DIRECTMANIPULATION_CONFIGURATION configuration = | |
| 85 DIRECTMANIPULATION_CONFIGURATION_INTERACTION | |
| 86 | DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_X | |
| 87 | DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_Y | |
| 88 | DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_INERTIA | |
| 89 | DIRECTMANIPULATION_CONFIGURATION_RAILS_X | |
| 90 | DIRECTMANIPULATION_CONFIGURATION_RAILS_Y | |
| 91 | DIRECTMANIPULATION_CONFIGURATION_SCALING | |
| 92 | DIRECTMANIPULATION_CONFIGURATION_SCALING_INERTIA; | |
| 93 | |
| 94 hr = view_port_outer_->ActivateConfiguration(configuration); | |
| 95 CHECK(SUCCEEDED(hr)); | |
| 96 return true; | |
|
sky
2015/08/11 15:43:12
Seems like you always return true.
ananta
2015/08/11 20:52:08
Changed the type to void
| |
| 97 } | |
| 98 | |
| 99 // Sets the bounds of the fake Direct manipulation viewport to match those | |
| 100 // of the legacy window. | |
| 101 void SetBounds(const gfx::Rect& bounds) { | |
| 102 base::win::ScopedComPtr<IDirectManipulationPrimaryContent> | |
| 103 primary_content_outer; | |
| 104 HRESULT hr = view_port_outer_->GetPrimaryContent( | |
| 105 IID_PPV_ARGS(primary_content_outer.Receive())); | |
| 106 CHECK(SUCCEEDED(hr)); | |
| 107 | |
| 108 base::win::ScopedComPtr<IDirectManipulationContent> content_outer; | |
| 109 hr = content_outer.QueryFrom(primary_content_outer.get()); | |
| 110 CHECK(SUCCEEDED(hr)); | |
| 111 | |
| 112 RECT rect = bounds.ToRECT(); | |
| 113 | |
| 114 hr = view_port_outer_->SetViewportRect(&rect); | |
| 115 CHECK(SUCCEEDED(hr)); | |
| 116 | |
| 117 hr = content_outer->SetContentRect(&rect); | |
| 118 CHECK(SUCCEEDED(hr)); | |
| 119 } | |
| 120 | |
| 121 // Registers the passed in |window| as a Direct Manipulation consumer. | |
| 122 void Activate(HWND window) { | |
| 123 DCHECK(::IsWindow(window)); | |
| 124 HRESULT hr = manager_->Activate(window); | |
| 125 CHECK(SUCCEEDED(hr)); | |
| 126 } | |
| 127 | |
| 128 // Passes the WM_MOUSEWHEEL messages to Direct Manipulation. This is for | |
| 129 // logistics purposes. | |
| 130 void HandleMouseWheel(HWND window, UINT message, WPARAM w_param, | |
| 131 LPARAM l_param) { | |
| 132 MSG msg = { window, message, w_param, l_param}; | |
| 133 | |
| 134 HRESULT hr = view_port_outer_->SetContact(DIRECTMANIPULATION_MOUSEFOCUS); | |
| 135 if (SUCCEEDED(hr)) { | |
| 136 BOOL handled = FALSE; | |
| 137 manager_->ProcessInput(&msg, &handled); | |
| 138 view_port_outer_->ReleaseContact(DIRECTMANIPULATION_MOUSEFOCUS); | |
| 139 } | |
| 140 } | |
| 141 | |
| 142 private: | |
| 143 base::win::ScopedComPtr<IDirectManipulationManager2> manager_; | |
| 144 base::win::ScopedComPtr<IDirectManipulationCompositor> compositor_; | |
| 145 base::win::ScopedComPtr<IDirectManipulationUpdateManager> update_manager_; | |
| 146 base::win::ScopedComPtr<IDirectManipulationFrameInfoProvider> frame_info_; | |
| 147 base::win::ScopedComPtr<IDirectManipulationViewport2> view_port_outer_; | |
| 148 }; | |
|
sky
2015/08/11 15:43:12
DISALLOW...
ananta
2015/08/11 20:52:08
Done.
| |
| 149 | |
| 25 // A custom MSAA object id used to determine if a screen reader or some | 150 // A custom MSAA object id used to determine if a screen reader or some |
| 26 // other client is listening on MSAA events - if so, we enable full web | 151 // other client is listening on MSAA events - if so, we enable full web |
| 27 // accessibility support. | 152 // accessibility support. |
| 28 const int kIdScreenReaderHoneyPot = 1; | 153 const int kIdScreenReaderHoneyPot = 1; |
| 29 | 154 |
| 30 // static | 155 // static |
| 31 LegacyRenderWidgetHostHWND* LegacyRenderWidgetHostHWND::Create( | 156 LegacyRenderWidgetHostHWND* LegacyRenderWidgetHostHWND::Create( |
| 32 HWND parent) { | 157 HWND parent) { |
| 33 // content_unittests passes in the desktop window as the parent. We allow | 158 // content_unittests passes in the desktop window as the parent. We allow |
| 34 // the LegacyRenderWidgetHostHWND instance to be created in this case for | 159 // the LegacyRenderWidgetHostHWND instance to be created in this case for |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 68 ::EnableWindow(hwnd(), TRUE); | 193 ::EnableWindow(hwnd(), TRUE); |
| 69 } | 194 } |
| 70 } | 195 } |
| 71 | 196 |
| 72 HWND LegacyRenderWidgetHostHWND::GetParent() { | 197 HWND LegacyRenderWidgetHostHWND::GetParent() { |
| 73 return ::GetParent(hwnd()); | 198 return ::GetParent(hwnd()); |
| 74 } | 199 } |
| 75 | 200 |
| 76 void LegacyRenderWidgetHostHWND::Show() { | 201 void LegacyRenderWidgetHostHWND::Show() { |
| 77 ::ShowWindow(hwnd(), SW_SHOW); | 202 ::ShowWindow(hwnd(), SW_SHOW); |
| 203 if (direct_manipulation_helper_) | |
| 204 direct_manipulation_helper_->Activate(hwnd()); | |
| 78 } | 205 } |
| 79 | 206 |
| 80 void LegacyRenderWidgetHostHWND::Hide() { | 207 void LegacyRenderWidgetHostHWND::Hide() { |
| 81 ::ShowWindow(hwnd(), SW_HIDE); | 208 ::ShowWindow(hwnd(), SW_HIDE); |
| 82 } | 209 } |
| 83 | 210 |
| 84 void LegacyRenderWidgetHostHWND::SetBounds(const gfx::Rect& bounds) { | 211 void LegacyRenderWidgetHostHWND::SetBounds(const gfx::Rect& bounds) { |
| 85 gfx::Rect bounds_in_pixel = gfx::win::DIPToScreenRect(bounds); | 212 gfx::Rect bounds_in_pixel = gfx::win::DIPToScreenRect(bounds); |
| 86 ::SetWindowPos(hwnd(), NULL, bounds_in_pixel.x(), bounds_in_pixel.y(), | 213 ::SetWindowPos(hwnd(), NULL, bounds_in_pixel.x(), bounds_in_pixel.y(), |
| 87 bounds_in_pixel.width(), bounds_in_pixel.height(), | 214 bounds_in_pixel.width(), bounds_in_pixel.height(), |
| 88 SWP_NOREDRAW); | 215 SWP_NOREDRAW); |
| 216 if (direct_manipulation_helper_) | |
| 217 direct_manipulation_helper_->SetBounds(bounds_in_pixel); | |
| 89 } | 218 } |
| 90 | 219 |
| 91 void LegacyRenderWidgetHostHWND::OnFinalMessage(HWND hwnd) { | 220 void LegacyRenderWidgetHostHWND::OnFinalMessage(HWND hwnd) { |
| 92 if (host_) { | 221 if (host_) { |
| 93 host_->OnLegacyWindowDestroyed(); | 222 host_->OnLegacyWindowDestroyed(); |
| 94 host_ = NULL; | 223 host_ = NULL; |
| 95 } | 224 } |
| 96 delete this; | 225 delete this; |
| 97 } | 226 } |
| 98 | 227 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 119 reinterpret_cast<void **>(window_accessible_.Receive())); | 248 reinterpret_cast<void **>(window_accessible_.Receive())); |
| 120 DCHECK(SUCCEEDED(hr)); | 249 DCHECK(SUCCEEDED(hr)); |
| 121 | 250 |
| 122 if (!BrowserAccessibilityState::GetInstance()->IsAccessibleBrowser()) { | 251 if (!BrowserAccessibilityState::GetInstance()->IsAccessibleBrowser()) { |
| 123 // Attempt to detect screen readers or other clients who want full | 252 // Attempt to detect screen readers or other clients who want full |
| 124 // accessibility support, by seeing if they respond to this event. | 253 // accessibility support, by seeing if they respond to this event. |
| 125 NotifyWinEvent(EVENT_SYSTEM_ALERT, hwnd(), kIdScreenReaderHoneyPot, | 254 NotifyWinEvent(EVENT_SYSTEM_ALERT, hwnd(), kIdScreenReaderHoneyPot, |
| 126 CHILDID_SELF); | 255 CHILDID_SELF); |
| 127 } | 256 } |
| 128 | 257 |
| 258 if (base::win::GetVersion() >= base::win::VERSION_WIN10) { | |
| 259 direct_manipulation_helper_.reset(new DirectManipulationHelper); | |
| 260 direct_manipulation_helper_->Initialize(hwnd()); | |
| 261 } | |
| 262 | |
| 129 return !!SUCCEEDED(hr); | 263 return !!SUCCEEDED(hr); |
| 130 } | 264 } |
| 131 | 265 |
| 132 // static | 266 // static |
| 133 ui::WindowEventTarget* LegacyRenderWidgetHostHWND::GetWindowEventTarget( | 267 ui::WindowEventTarget* LegacyRenderWidgetHostHWND::GetWindowEventTarget( |
| 134 HWND parent) { | 268 HWND parent) { |
| 135 return reinterpret_cast<ui::WindowEventTarget*>(ui::ViewProp::GetValue( | 269 return reinterpret_cast<ui::WindowEventTarget*>(ui::ViewProp::GetValue( |
| 136 parent, ui::WindowEventTarget::kWin32InputEventTarget)); | 270 parent, ui::WindowEventTarget::kWin32InputEventTarget)); |
| 137 } | 271 } |
| 138 | 272 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 235 // If the parent did not handle non client mouse messages, we call | 369 // If the parent did not handle non client mouse messages, we call |
| 236 // DefWindowProc on the message with the parent window handle. This | 370 // DefWindowProc on the message with the parent window handle. This |
| 237 // ensures that WM_SYSCOMMAND is generated for the parent and we are | 371 // ensures that WM_SYSCOMMAND is generated for the parent and we are |
| 238 // out of the picture. | 372 // out of the picture. |
| 239 if (!handled && | 373 if (!handled && |
| 240 (message >= WM_NCMOUSEMOVE && message <= WM_NCXBUTTONDBLCLK)) { | 374 (message >= WM_NCMOUSEMOVE && message <= WM_NCXBUTTONDBLCLK)) { |
| 241 ret = ::DefWindowProc(GetParent(), message, w_param, l_param); | 375 ret = ::DefWindowProc(GetParent(), message, w_param, l_param); |
| 242 handled = TRUE; | 376 handled = TRUE; |
| 243 } | 377 } |
| 244 } | 378 } |
| 379 | |
| 380 if (direct_manipulation_helper_ && | |
| 381 (message == WM_MOUSEWHEEL || message == WM_MOUSEHWHEEL)) { | |
| 382 direct_manipulation_helper_->HandleMouseWheel(hwnd(), message, w_param, | |
| 383 l_param); | |
| 384 } | |
| 245 return ret; | 385 return ret; |
| 246 } | 386 } |
| 247 | 387 |
| 248 LRESULT LegacyRenderWidgetHostHWND::OnMouseLeave(UINT message, | 388 LRESULT LegacyRenderWidgetHostHWND::OnMouseLeave(UINT message, |
| 249 WPARAM w_param, | 389 WPARAM w_param, |
| 250 LPARAM l_param) { | 390 LPARAM l_param) { |
| 251 mouse_tracking_enabled_ = false; | 391 mouse_tracking_enabled_ = false; |
| 252 LRESULT ret = 0; | 392 LRESULT ret = 0; |
| 253 if ((::GetCapture() != GetParent()) && GetWindowEventTarget(GetParent())) { | 393 if ((::GetCapture() != GetParent()) && GetWindowEventTarget(GetParent())) { |
| 254 // We should send a WM_MOUSELEAVE to the parent window only if the mouse | 394 // We should send a WM_MOUSELEAVE to the parent window only if the mouse |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 373 // generate the legacy WM_VSCROLL/WM_HSCROLL messages. | 513 // generate the legacy WM_VSCROLL/WM_HSCROLL messages. |
| 374 // We add these styles to ensure that trackpad/trackpoint scrolling | 514 // We add these styles to ensure that trackpad/trackpoint scrolling |
| 375 // work. | 515 // work. |
| 376 long current_style = ::GetWindowLong(hwnd(), GWL_STYLE); | 516 long current_style = ::GetWindowLong(hwnd(), GWL_STYLE); |
| 377 ::SetWindowLong(hwnd(), GWL_STYLE, | 517 ::SetWindowLong(hwnd(), GWL_STYLE, |
| 378 current_style | WS_VSCROLL | WS_HSCROLL); | 518 current_style | WS_VSCROLL | WS_HSCROLL); |
| 379 return 0; | 519 return 0; |
| 380 } | 520 } |
| 381 | 521 |
| 382 } // namespace content | 522 } // namespace content |
| OLD | NEW |