Commit 397923a7 authored by Jamie Walch's avatar Jamie Walch Committed by Commit Bot

Improve host-side wheel-tick detection algorithm.

Change-Id: I25172eeb7f589d1dea3480d322d4ed73f2213fe4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1633969Reviewed-by: default avatarJamie Walch <jamiewalch@chromium.org>
Reviewed-by: default avatarJoe Downing <joedow@chromium.org>
Auto-Submit: Jamie Walch <jamiewalch@chromium.org>
Commit-Queue: Joe Downing <joedow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#664103}
parent 22bbb760
......@@ -17,6 +17,7 @@
#include "base/optional.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversion_utils.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "remoting/base/logging.h"
#include "remoting/host/clipboard.h"
......@@ -44,6 +45,10 @@ using protocol::TextEvent;
using protocol::MouseEvent;
using protocol::TouchEvent;
int sign(float num) {
return (num > 0) ? 1 : (num < 0) ? -1 : 0;
}
bool IsDomModifierKey(ui::DomCode dom_code) {
return dom_code == ui::DomCode::CONTROL_LEFT ||
dom_code == ui::DomCode::SHIFT_LEFT ||
......@@ -59,6 +64,10 @@ bool IsDomModifierKey(ui::DomCode dom_code) {
// From third_party/WebKit/Source/web/gtk/WebInputEventFactory.cpp .
const float kWheelTicksPerPixel = 3.0f / 160.0f;
// When the user is scrolling, generate at least one tick per time period.
const base::TimeDelta kContinuousScrollTimeout =
base::TimeDelta::FromMilliseconds(500);
// A class to generate events on X11.
class InputInjectorX11 : public InputInjector {
public:
......@@ -138,6 +147,8 @@ class InputInjectorX11 : public InputInjector {
webrtc::DesktopVector latest_mouse_position_;
float wheel_ticks_x_;
float wheel_ticks_y_;
base::Time latest_tick_y_event_;
int latest_tick_y_direction_;
// X11 graphics context.
Display* display_;
......@@ -211,10 +222,10 @@ InputInjectorX11::Core::Core(
latest_mouse_position_(-1, -1),
wheel_ticks_x_(0.0f),
wheel_ticks_y_(0.0f),
latest_tick_y_direction_(0),
display_(XOpenDisplay(nullptr)),
root_window_(BadValue),
saved_auto_repeat_enabled_(false) {
}
saved_auto_repeat_enabled_(false) {}
bool InputInjectorX11::Core::Init() {
CHECK(display_);
......@@ -477,11 +488,8 @@ void InputInjectorX11::Core::InjectMouseEvent(const MouseEvent& event) {
x11::CurrentTime);
}
// Older client plugins always send scroll events in pixels, which
// must be accumulated host-side. Recent client plugins send both
// pixels and ticks with every scroll event, allowing the host to
// choose the best model on a per-platform basis. Since we can only
// inject ticks on Linux, use them if available.
// remotedesktop.google.com currently sends scroll events in pixels, which
// are accumulated host-side.
int ticks_y = 0;
if (event.has_wheel_ticks_y()) {
ticks_y = event.wheel_ticks_y();
......@@ -490,7 +498,44 @@ void InputInjectorX11::Core::InjectMouseEvent(const MouseEvent& event) {
ticks_y = static_cast<int>(wheel_ticks_y_);
wheel_ticks_y_ -= ticks_y;
}
if (ticks_y == 0 && event.has_wheel_delta_y()) {
// For the y-direction only (the common case), try to ensure that a tick is
// injected when the user would expect one, regardless of how many pixels
// the client sends per tick (even if it accelerates wheel events). To do
// this, generate a tick if one has not occurred recently in the current
// scroll direction. The accumulated pixels are not reset in this case.
//
// The effect when a physical mouse is used is as follows:
//
// Client sends slightly too few pixels per tick (e.g. Linux):
// * First scroll in either direction synthesizes a tick.
// * Subsequent scrolls in the same direction are unaffected (their
// accumulated pixel deltas mostly meet the threshold for a regular
// tick; occasionally a tick will be dropped if the user is scrolling
// quickly).
//
// Client sends far too few pixels per tick, but applies acceleration
// (e.g. macOs, ChromeOS):
// * First scroll in either direction synthesizes a tick.
// * Slow scrolling will synthesize a tick a few times per second.
// * Fast scrolling is unaffected (acceleration means that enough pixels
// are accumulated naturally).
//
// Client sends too many pixels per tick (e.g. Windows):
// * Scrolling is unaffected (most scroll events generate one tick; every
// so often one generates two ticks).
//
// The effect when a trackpad is used is that the first tick in either
// direction occurs sooner; subsequent ticks are mostly unaffected.
const int current_tick_y_direction = sign(event.wheel_delta_y());
if ((base::Time::Now() - latest_tick_y_event_ > kContinuousScrollTimeout) ||
latest_tick_y_direction_ != current_tick_y_direction) {
ticks_y = current_tick_y_direction;
}
}
if (ticks_y != 0) {
latest_tick_y_direction_ = sign(ticks_y);
latest_tick_y_event_ = base::Time::Now();
InjectScrollWheelClicks(VerticalScrollWheelToX11ButtonNumber(ticks_y),
abs(ticks_y));
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment