blob: 449518edaca8b42186962643fe2f3255fc449dec [file] [log] [blame]
// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <gtest/gtest.h> // For FRIEND_TEST
#include "gestures/include/gestures.h"
#include "gestures/include/interpreter.h"
#include "gestures/include/prop_registry.h"
#include "gestures/include/tracer.h"
#ifndef GESTURES_MOUSE_INTERPRETER_H_
#define GESTURES_MOUSE_INTERPRETER_H_
namespace gestures {
class MouseInterpreter : public Interpreter, public PropertyDelegate {
FRIEND_TEST(MouseInterpreterTest, SimpleTest);
FRIEND_TEST(MouseInterpreterTest, HighResolutionVerticalScrollTest);
public:
MouseInterpreter(PropRegistry* prop_reg, Tracer* tracer);
virtual ~MouseInterpreter() {};
protected:
virtual void SyncInterpretImpl(HardwareState* hwstate, stime_t* timeout);
// These functions interpret mouse events, which include button clicking and
// mouse movement. This function needs two consecutive HardwareState. If no
// mouse events are presented, result object is not modified. Scroll wheel
// events are not interpreted as they are handled differently for normal
// mice and multi-touch mice (ignored for multi-touch mice and accelerated
// for normal mice).
void InterpretMouseButtonEvent(const HardwareState& prev_state,
const HardwareState& hwstate);
void InterpretMouseMotionEvent(const HardwareState& prev_state,
const HardwareState& hwstate);
// Check for scroll wheel events and produce scroll gestures.
void InterpretScrollWheelEvent(const HardwareState& hwstate,
bool is_vertical);
bool EmulateScrollWheel(const HardwareState& hwstate);
private:
struct WheelRecord {
WheelRecord(float v, stime_t t): value(v), timestamp(t) {}
WheelRecord(): value(0), timestamp(0) {}
float value;
stime_t timestamp;
};
// Accelerate mouse scroll offsets so that it is larger when the user scroll
// the mouse wheel faster.
double ComputeScrollAccelFactor(double input_speed);
HardwareState prev_state_;
// Records last scroll wheel event.
WheelRecord last_wheel_, last_hwheel_;
// Accumulators to measure scroll distance while doing scroll wheel emulation
double wheel_emulation_accu_x_;
double wheel_emulation_accu_y_;
// True while wheel emulation is locked in.
bool wheel_emulation_active_;
// Reverse wheel scrolling.
BoolProperty reverse_scrolling_;
// Enable high-resolution scrolling.
BoolProperty hi_res_scrolling_;
// We use normal CDF to simulate scroll wheel acceleration curve. Use the
// following method to generate the coefficients of a degree-4 polynomial
// regression for a specific normal cdf in Python.
//
// Note: x for wheel value, v for velocity, y for scroll pixels (offset),
// and v = x / dt.
//
// The offset is computed as x * f(v) where f() outputs the acceleration
// factor for the given input speed. The formula allows us to produce similar
// offsets regardless of the mouse scrolling resolution. Since we want y to
// follow the normal CDF, we need to attenuate the case where x >= 1. This can
// happen when the user scrolls really fast, e.g., more than 1 unit within 8ms
// for a common, low-resolution mouse.
//
// In reality, v ranges from 1 to 120+ for an Apple Mighty Mouse, use range
// greater than that to minimize approximation error at the end points.
// In our case, the range is [-50, 200].
//
// Python (3) code:
// import numpy as np
// from scipy.stats import norm
// v = np.arange(-50, 201)
// f = (580 * norm.cdf(v, 100, 40) + 20) / np.maximum(v / 125.0, 1)
// coeff = np.flip(np.polyfit(v, f, 4), 0)
// f_approximated = a0 + a1*v + a2*v^2 + a3*v^3 + a4*v^4
double scroll_accel_curve_[5];
// Adjust the scroll acceleration curve
DoubleArrayProperty scroll_accel_curve_prop_;
// when x is 177, the polynomial curve gives 450, the max pixels to scroll.
DoubleProperty scroll_max_allowed_input_speed_;
// Force scroll wheel emulation for any devices
BoolProperty force_scroll_wheel_emulation_;
// Multiplication factor to translate cursor motion into scrolling
DoubleProperty scroll_wheel_emulation_speed_;
// Movement distance after which to start scroll wheel emulation [in mm]
DoubleProperty scroll_wheel_emulation_thresh_;
};
} // namespace gestures
#endif // GESTURES_MOUSE_INTERPRETER_H_