blob: f278c557e7e048483329952e53e7702f3f24ebc1 [file]
// 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.
#ifndef GESTURES_GESTURES_H__
#define GESTURES_GESTURES_H__
#include <stdint.h>
#include <sys/time.h>
#ifdef __cplusplus
#include <string>
#include <base/basictypes.h>
#include <base/memory/scoped_ptr.h>
extern "C" {
#endif
// C API:
// external logging interface
#define GESTURES_LOG_ERROR 0
#define GESTURES_LOG_INFO 1
// this function has to be provided by the user of the library.
void gestures_log(int verb, const char* format, ...);
typedef double stime_t; // seconds
stime_t StimeFromTimeval(const struct timeval*);
stime_t StimeFromTimespec(const struct timespec*);
struct HardwareProperties {
float left, top, right, bottom;
float res_x; // pixels/mm
float res_y; // pixels/mm
float screen_x_dpi; // read from X server and passed to library
float screen_y_dpi; // read from X server and passed to library
unsigned short max_finger_cnt; // Max finger slots in one report
unsigned short max_touch_cnt; // Max fingers that can be detected at once
unsigned supports_t5r2:1;
unsigned support_semi_mt:1;
unsigned is_button_pad:1;
#ifdef __cplusplus
std::string String() const;
#endif // __cplusplus
};
// position is the (x,y) cartesian coord of the finger on the trackpad.
// touch_major/minor are the large/small radii of the ellipse of the touching
// finger. width_major/minor are also radii, but of the finger itself,
// including a little bit that isn't touching. So, width* is generally a tad
// larger than touch*.
// tracking_id: If a finger is the same physical finger across two
// consecutive frames, it must have the same tracking id; if it's a different
// finger, it may (should) have a different tracking id.
// Warp: If a finger has the 'warp' flag set for an axis, it means that while
// the finger may have moved, it should not cause any motion in that direction.
// This may occur is some situations where we thought a finger was in one place,
// but then we realized later it was actually in another place.
#define GESTURES_FINGER_WARP_X (1 << 0)
#define GESTURES_FINGER_WARP_Y (1 << 1)
// If a finger has notap set, it shouldn't begin a tap gesture.
#define GESTURES_FINGER_NO_TAP (1 << 2)
#define GESTURES_FINGER_POSSIBLE_PALM (1 << 3)
#define GESTURES_FINGER_PALM (1 << 4)
struct FingerState {
float touch_major, touch_minor;
float width_major, width_minor;
float pressure;
float orientation;
float position_x;
float position_y;
short tracking_id;
unsigned flags;
#ifdef __cplusplus
bool operator==(const FingerState& that) const {
return touch_major == that.touch_major &&
touch_minor == that.touch_minor &&
width_major == that.width_major &&
width_minor == that.width_minor &&
pressure == that.pressure &&
orientation == that.orientation &&
position_x == that.position_x &&
position_y == that.position_y &&
tracking_id == that.tracking_id &&
flags == that.flags;
}
bool operator!=(const FingerState& that) const { return !(*this == that); }
std::string String() const;
#endif
};
#define GESTURES_BUTTON_LEFT 1
#define GESTURES_BUTTON_MIDDLE 2
#define GESTURES_BUTTON_RIGHT 4
// One frame of trackpad data
struct HardwareState {
#ifdef __cplusplus
FingerState* GetFingerState(short tracking_id);
const FingerState* GetFingerState(short tracking_id) const;
bool SameFingersAs(const HardwareState& that) const;
std::string String() const;
#endif // __cplusplus
stime_t timestamp; // 64-bit Wall clock time in microseconds (10^-6 s)
int buttons_down; // bit field, use GESTURES_BUTTON_*
unsigned short finger_cnt; // Number of valid finger slots
unsigned short touch_cnt; // Number of fingers touching pad
struct FingerState* fingers;
};
#define GESTURES_FLING_START 0 // Scroll end/fling begin
#define GESTURES_FLING_TAP_DOWN 1 // Finger touched down/fling end
// Gesture sub-structs
typedef struct {
float dx, dy;
} GestureMove;
typedef struct{
float dx, dy;
// If set, stop_fling means that this scroll should stop flinging, thus
// if an interpreter suppresses it for any reason (e.g., rounds the size
// down to 0, thus making it a noop), it will replace it with a Fling
// TAP_DOWN gesture
unsigned stop_fling:1;
} GestureScroll;
typedef struct {
// If a bit is set in both down and up, client should process down first
unsigned down; // bit field, use GESTURES_BUTTON_*
unsigned up; // bit field, use GESTURES_BUTTON_*
} GestureButtonsChange;
typedef struct {
// fling velocity (valid when fling_state is GESTURES_FLING_START):
float vx, vy;
unsigned fling_state:1; // GESTURES_FLING_START or GESTURES_FLING_TAP_DOWN
} GestureFling;
typedef struct {
float dx;
} GestureSwipe;
typedef struct {
// Relative pinch factor starting with 1.0 = no pinch
// <1.0 for outwards pinch
// >1.0 for inwards pinch
float dz;
} GesturePinch;
enum GestureType {
#ifdef GESTURES_INTERNAL
kGestureTypeNull = -1, // internal to Gestures library only
#endif // GESTURES_INTERNAL
kGestureTypeContactInitiated = 0,
kGestureTypeMove,
kGestureTypeScroll,
kGestureTypeButtonsChange,
kGestureTypeFling,
kGestureTypeSwipe,
kGestureTypePinch
};
#ifdef __cplusplus
// Pass these into Gesture() ctor as first arg
extern const GestureMove kGestureMove;
extern const GestureScroll kGestureScroll;
extern const GestureButtonsChange kGestureButtonsChange;
extern const GestureFling kGestureFling;
extern const GestureSwipe kGestureSwipe;
extern const GesturePinch kGesturePinch;
#endif // __cplusplus
struct Gesture {
#ifdef __cplusplus
// Create Move/Scroll gesture
#ifdef GESTURES_INTERNAL
Gesture() : start_time(0), end_time(0), type(kGestureTypeNull) {}
std::string String() const;
bool operator==(const Gesture& that) const;
bool operator!=(const Gesture& that) const { return !(*this == that); };
#endif // GESTURES_INTERNAL
Gesture(const GestureMove&, stime_t start, stime_t end, float dx, float dy)
: start_time(start), end_time(end), type(kGestureTypeMove) {
details.move.dx = dx;
details.move.dy = dy;
}
Gesture(const GestureScroll&,
stime_t start, stime_t end, float dx, float dy)
: start_time(start), end_time(end), type(kGestureTypeScroll) {
details.scroll.dx = dx;
details.scroll.dy = dy;
details.scroll.stop_fling = 0;
}
Gesture(const GestureButtonsChange&,
stime_t start, stime_t end, unsigned down, unsigned up)
: start_time(start), end_time(end), type(kGestureTypeButtonsChange) {
details.buttons.down = down;
details.buttons.up = up;
}
Gesture(const GestureFling&,
stime_t start, stime_t end, float vx, float vy, unsigned state)
: start_time(start), end_time(end), type(kGestureTypeFling) {
details.fling.vx = vx;
details.fling.vy = vy;
details.fling.fling_state = state;
}
Gesture(const GestureSwipe&,
stime_t start, stime_t end, float dx)
: start_time(start),
end_time(end),
type(kGestureTypeSwipe) {
details.swipe.dx = dx;
}
Gesture(const GesturePinch&,
stime_t start, stime_t end, float dz)
: start_time(start),
end_time(end),
type(kGestureTypePinch) {
details.pinch.dz = dz;
}
#endif // __cplusplus
stime_t start_time, end_time;
enum GestureType type;
union {
GestureMove move;
GestureScroll scroll;
GestureButtonsChange buttons;
GestureFling fling;
GestureSwipe swipe;
GesturePinch pinch;
} details;
};
typedef void (*GestureReadyFunction)(void* client_data,
const struct Gesture* gesture);
// Gestures Timer Provider Interface
struct GesturesTimer;
typedef struct GesturesTimer GesturesTimer;
// If this returns < 0, the timer should be freed. If it returns >= 0.0, it
// should be called again after that amount of delay.
typedef stime_t (*GesturesTimerCallback)(stime_t now,
void* callback_data);
// Allocate and return a new timer, or NULL if error.
typedef GesturesTimer* (*GesturesTimerCreate)(void* data);
// Set a timer:
typedef void (*GesturesTimerSet)(void* data,
GesturesTimer* timer,
stime_t delay,
GesturesTimerCallback callback,
void* callback_data);
// Cancel a set timer:
typedef void (*GesturesTimerCancel)(void* data, GesturesTimer* timer);
// Free the timer. Will not be called from within a timer callback.
typedef void (*GesturesTimerFree)(void* data, GesturesTimer* timer);
typedef struct {
GesturesTimerCreate create_fn;
GesturesTimerSet set_fn;
GesturesTimerCancel cancel_fn;
GesturesTimerFree free_fn;
} GesturesTimerProvider;
// Gestures Property Provider Interface
struct GesturesProp;
typedef struct GesturesProp GesturesProp;
typedef int GesturesPropBool;
// These functions create a named property of given type.
// data - data used by PropProvider
// loc - location of a variable to be updated by PropProvider.
// Set to NULL to create a ReadOnly property
// init - initial value for the property.
// If the PropProvider has an alternate configuration source, it may
// override this initial value, in which case *loc returns the
// value from the configuration source.
typedef GesturesProp* (*GesturesPropCreateInt)(void* data, const char* name,
int* loc, const int init);
typedef GesturesProp* (*GesturesPropCreateShort)(void* data, const char* name,
short* loc, const short init);
typedef GesturesProp* (*GesturesPropCreateBool)(void* data, const char* name,
GesturesPropBool* loc,
const GesturesPropBool init);
typedef GesturesProp* (*GesturesPropCreateString)(void* data, const char* name,
const char** loc,
const char* const init);
typedef GesturesProp* (*GesturesPropCreateReal)(void* data, const char* name,
double* loc, const double init);
// A function to call just before a property is to be read.
// |handler_data| is a local context pointer that can be used by the handler.
// Handler should return non-zero if it modifies the property's value.
typedef GesturesPropBool (*GesturesPropGetHandler)(void* handler_data);
// A function to call just after a property's value is updated.
// |handler_data| is a local context pointer that can be used by the handler.
typedef void (*GesturesPropSetHandler)(void* handler_data);
// Register handlers to be called when a GesturesProp is accessed.
// The get handler, if not NULL, is called immediately before the property's
// value is to be read. This gives the library a chance to update its value.
// The set handler, if not NULL, is called immediately after the property's
// value is updated. This can be used to create a property that is used to
// trigger an action, or to force an update to multiple properties atomically.
// Note: the handlers are called from non-signal/interrupt context
typedef void (*GesturesPropRegisterHandlers)(void* data, GesturesProp* prop,
void* handler_data,
GesturesPropGetHandler getter,
GesturesPropSetHandler setter);
// Free a property.
typedef void (*GesturesPropFree)(void* data, GesturesProp* prop);
typedef struct GesturesPropProvider {
GesturesPropCreateInt create_int_fn;
GesturesPropCreateShort create_short_fn;
GesturesPropCreateBool create_bool_fn;
GesturesPropCreateString create_string_fn;
GesturesPropCreateReal create_real_fn;
GesturesPropRegisterHandlers register_handlers_fn;
GesturesPropFree free_fn;
} GesturesPropProvider;
#ifdef __cplusplus
// C++ API:
namespace gestures {
class FingerMetrics;
class Interpreter;
class PropRegistry;
class LoggingFilterInterpreter;
struct GestureInterpreter {
public:
explicit GestureInterpreter(int version);
~GestureInterpreter();
void PushHardwareState(HardwareState* hwstate);
void SetHardwareProperties(const HardwareProperties& hwprops);
void TimerCallback(stime_t now, stime_t* timeout);
void set_callback(GestureReadyFunction callback,
void* client_data) {
callback_ = callback;
callback_data_ = client_data;
}
void SetTimerProvider(GesturesTimerProvider* tp, void* data);
void SetPropProvider(GesturesPropProvider* pp, void* data);
Interpreter* interpreter() const { return interpreter_.get(); }
PropRegistry* prop_reg() const { return prop_reg_.get(); }
std::string EncodeActivityLog();
private:
GestureReadyFunction callback_;
void* callback_data_;
scoped_ptr<PropRegistry> prop_reg_;
scoped_ptr<FingerMetrics> finger_metrics_;
scoped_ptr<Interpreter> interpreter_;
GesturesTimerProvider* timer_provider_;
void* timer_provider_data_;
GesturesTimer* interpret_timer_;
GesturesPropProvider* prop_provider_;
void* prop_provider_data_;
LoggingFilterInterpreter* loggingFilter_;
DISALLOW_COPY_AND_ASSIGN(GestureInterpreter);
};
} // namespace gestures
typedef gestures::GestureInterpreter GestureInterpreter;
#else
struct GestureInterpreter;
typedef struct GestureInterpreter GestureInterpreter;
#endif // __cplusplus
#define GESTURES_VERSION 1
GestureInterpreter* NewGestureInterpreterImpl(int);
#define NewGestureInterpreter() NewGestureInterpreterImpl(GESTURES_VERSION)
void DeleteGestureInterpreter(GestureInterpreter*);
void GestureInterpreterSetHardwareProperties(GestureInterpreter*,
const struct HardwareProperties*);
void GestureInterpreterPushHardwareState(GestureInterpreter*,
struct HardwareState*);
void GestureInterpreterSetCallback(GestureInterpreter*,
GestureReadyFunction,
void*);
// Gestures will hold a reference to passed provider. Pass NULL to tell
// Gestures to stop holding a reference.
void GestureInterpreterSetTimerProvider(GestureInterpreter*,
GesturesTimerProvider*,
void*);
void GestureInterpreterSetPropProvider(GestureInterpreter*,
GesturesPropProvider*,
void*);
#ifdef __cplusplus
}
#endif
#endif // GESTURES_GESTURES_H__