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

Unified 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/renderer_host/legacy_render_widget_host_win.cc
diff --git a/content/browser/renderer_host/legacy_render_widget_host_win.cc b/content/browser/renderer_host/legacy_render_widget_host_win.cc
index 5126ad2bc2da97d1c829ad9f6913ecaeb5de0424..1b814bbd908f94ad3a5b994f1c17eef6f564513a 100644
--- a/content/browser/renderer_host/legacy_render_widget_host_win.cc
+++ b/content/browser/renderer_host/legacy_render_widget_host_win.cc
@@ -4,8 +4,11 @@
#include "content/browser/renderer_host/legacy_render_widget_host_win.h"
+#include <directmanipulation.h>
+
#include "base/command_line.h"
#include "base/memory/scoped_ptr.h"
+#include "base/win/scoped_comptr.h"
#include "base/win/windows_version.h"
#include "content/browser/accessibility/browser_accessibility_manager_win.h"
#include "content/browser/accessibility/browser_accessibility_win.h"
@@ -22,6 +25,128 @@
namespace content {
+// Windows 10 provides a new API called Direct Manipulation which generates
+// smooth scroll events via WM_MOUSEWHEEL messages with predictable deltas
+// on high precision touch pads. This basically requires the application window
+// to register as a Direct Manipulation consumer. The way mouse wheel messages
+// are dispatched is
+// 1. The foreground window is checked to see if it is a Direct Manipulation
+// consumer.
+// 2. If it is then Direct Manipulation takes over and sends the following
+// messages. WM_POINTERACTIVATE, WM_POINTERDOWN and DM_POINTERHITTEST.
+// 3. It then posts WM_MOUSEWHEEL messages with precision deltas which vary
+// based on the amount of the scroll.
+// 4. If the foreground window is not a Direct Manipulation consumer, it
+// then takes a fallback route where it posts WM_MOUSEWHEEL messages
+// with precision but varying deltas to the window. There is a also
+// a slight delay in receiving the first set of mouse wheel messages.
+// This causes scrolling in Chrome to appear janky and jumpy.
+// Our approach for addressing this is to do the absolute minimum to
+// register our window as a Direct Manipulation consumer. This class
+// provides the necessary functionality to register the legacy HWND as a
+// Direct Manipulation consumer. We don't rely on Direct manipulation
+// to do the smooth scrolling in the background thread as documented on
+// msdn.
+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
+ public:
+ DirectManipulationHelper() {}
+
+ // This function instantiates Direct Manipulation and creates a viewport for
+ // the passed in |window|.
+ // consumer. Most of the code is boiler plate and is based on the sample.
+ bool Initialize(HWND window) {
+ DCHECK(::IsWindow(window));
+
+ HRESULT hr = manager_.CreateInstance(CLSID_DirectManipulationManager,
+ nullptr, CLSCTX_INPROC_SERVER);
+ 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
+
+ hr = compositor_.CreateInstance(CLSID_DCompManipulationCompositor,
+ nullptr, CLSCTX_INPROC_SERVER);
+ CHECK(SUCCEEDED(hr));
+
+ hr = manager_->GetUpdateManager(IID_PPV_ARGS(update_manager_.Receive()));
+ CHECK(SUCCEEDED(hr));
+
+ hr = compositor_->SetUpdateManager(update_manager_.get());
+ CHECK(SUCCEEDED(hr));
+
+ hr = frame_info_.QueryFrom(compositor_.get());
+ CHECK(SUCCEEDED(hr));
+
+ hr = manager_->CreateViewport(frame_info_.get(), window,
+ IID_PPV_ARGS(view_port_outer_.Receive()));
+ CHECK(SUCCEEDED(hr));
+
+ //
+ // Enable the desired configuration for each viewport.
+ //
+ DIRECTMANIPULATION_CONFIGURATION configuration =
+ DIRECTMANIPULATION_CONFIGURATION_INTERACTION
+ | DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_X
+ | DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_Y
+ | DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_INERTIA
+ | DIRECTMANIPULATION_CONFIGURATION_RAILS_X
+ | DIRECTMANIPULATION_CONFIGURATION_RAILS_Y
+ | DIRECTMANIPULATION_CONFIGURATION_SCALING
+ | DIRECTMANIPULATION_CONFIGURATION_SCALING_INERTIA;
+
+ hr = view_port_outer_->ActivateConfiguration(configuration);
+ CHECK(SUCCEEDED(hr));
+ 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
+ }
+
+ // Sets the bounds of the fake Direct manipulation viewport to match those
+ // of the legacy window.
+ void SetBounds(const gfx::Rect& bounds) {
+ base::win::ScopedComPtr<IDirectManipulationPrimaryContent>
+ primary_content_outer;
+ HRESULT hr = view_port_outer_->GetPrimaryContent(
+ IID_PPV_ARGS(primary_content_outer.Receive()));
+ CHECK(SUCCEEDED(hr));
+
+ base::win::ScopedComPtr<IDirectManipulationContent> content_outer;
+ hr = content_outer.QueryFrom(primary_content_outer.get());
+ CHECK(SUCCEEDED(hr));
+
+ RECT rect = bounds.ToRECT();
+
+ hr = view_port_outer_->SetViewportRect(&rect);
+ CHECK(SUCCEEDED(hr));
+
+ hr = content_outer->SetContentRect(&rect);
+ CHECK(SUCCEEDED(hr));
+ }
+
+ // Registers the passed in |window| as a Direct Manipulation consumer.
+ void Activate(HWND window) {
+ DCHECK(::IsWindow(window));
+ HRESULT hr = manager_->Activate(window);
+ CHECK(SUCCEEDED(hr));
+ }
+
+ // Passes the WM_MOUSEWHEEL messages to Direct Manipulation. This is for
+ // logistics purposes.
+ void HandleMouseWheel(HWND window, UINT message, WPARAM w_param,
+ LPARAM l_param) {
+ MSG msg = { window, message, w_param, l_param};
+
+ HRESULT hr = view_port_outer_->SetContact(DIRECTMANIPULATION_MOUSEFOCUS);
+ if (SUCCEEDED(hr)) {
+ BOOL handled = FALSE;
+ manager_->ProcessInput(&msg, &handled);
+ view_port_outer_->ReleaseContact(DIRECTMANIPULATION_MOUSEFOCUS);
+ }
+ }
+
+ private:
+ base::win::ScopedComPtr<IDirectManipulationManager2> manager_;
+ base::win::ScopedComPtr<IDirectManipulationCompositor> compositor_;
+ base::win::ScopedComPtr<IDirectManipulationUpdateManager> update_manager_;
+ base::win::ScopedComPtr<IDirectManipulationFrameInfoProvider> frame_info_;
+ base::win::ScopedComPtr<IDirectManipulationViewport2> view_port_outer_;
+};
sky 2015/08/11 15:43:12 DISALLOW...
ananta 2015/08/11 20:52:08 Done.
+
// A custom MSAA object id used to determine if a screen reader or some
// other client is listening on MSAA events - if so, we enable full web
// accessibility support.
@@ -75,6 +200,8 @@ HWND LegacyRenderWidgetHostHWND::GetParent() {
void LegacyRenderWidgetHostHWND::Show() {
::ShowWindow(hwnd(), SW_SHOW);
+ if (direct_manipulation_helper_)
+ direct_manipulation_helper_->Activate(hwnd());
}
void LegacyRenderWidgetHostHWND::Hide() {
@@ -86,6 +213,8 @@ void LegacyRenderWidgetHostHWND::SetBounds(const gfx::Rect& bounds) {
::SetWindowPos(hwnd(), NULL, bounds_in_pixel.x(), bounds_in_pixel.y(),
bounds_in_pixel.width(), bounds_in_pixel.height(),
SWP_NOREDRAW);
+ if (direct_manipulation_helper_)
+ direct_manipulation_helper_->SetBounds(bounds_in_pixel);
}
void LegacyRenderWidgetHostHWND::OnFinalMessage(HWND hwnd) {
@@ -126,6 +255,11 @@ bool LegacyRenderWidgetHostHWND::Init() {
CHILDID_SELF);
}
+ if (base::win::GetVersion() >= base::win::VERSION_WIN10) {
+ direct_manipulation_helper_.reset(new DirectManipulationHelper);
+ direct_manipulation_helper_->Initialize(hwnd());
+ }
+
return !!SUCCEEDED(hr);
}
@@ -242,6 +376,12 @@ LRESULT LegacyRenderWidgetHostHWND::OnMouseRange(UINT message,
handled = TRUE;
}
}
+
+ if (direct_manipulation_helper_ &&
+ (message == WM_MOUSEWHEEL || message == WM_MOUSEHWHEEL)) {
+ direct_manipulation_helper_->HandleMouseWheel(hwnd(), message, w_param,
+ l_param);
+ }
return ret;
}
« 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