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

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

Issue 1283913002: Improve scroll performance on Windows 10 with high precision touchpads. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 4 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
« no previous file with comments | « content/browser/renderer_host/legacy_render_widget_host_win.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <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
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
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
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
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
OLDNEW
« no previous file with comments | « content/browser/renderer_host/legacy_render_widget_host_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698