X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Ffilter.c;h=5b0b87744666f648f04f6fcfc9c7e1a564f898b2;hb=468e6288082ee61ac6a4663726a2728e413804e1;hp=72ef9be973c5d77aa5ee036c696f71550bf235d6;hpb=bb25b2ad297891430606c367bfabc5a032f0359d;p=platform%2Fupstream%2Flibinput.git diff --git a/src/filter.c b/src/filter.c index 72ef9be..5b0b877 100644 --- a/src/filter.c +++ b/src/filter.c @@ -20,50 +20,65 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include +#include "config.h" + #include +#include #include #include #include -#include - -#include "compositor.h" #include "filter.h" void -weston_filter_dispatch(struct weston_motion_filter *filter, - struct weston_motion_params *motion, - void *data, uint32_t time) +filter_dispatch(struct motion_filter *filter, + struct motion_params *motion, + void *data, uint64_t time) { filter->interface->filter(filter, motion, data, time); } +void +filter_destroy(struct motion_filter *filter) +{ + if (!filter) + return; + + filter->interface->destroy(filter); +} + +/* + * Default parameters for pointer acceleration profiles. + */ + +#define DEFAULT_THRESHOLD 0.4 /* in units/ms */ +#define DEFAULT_ACCELERATION 2.0 /* unitless factor */ + /* - * Pointer acceleration filter + * Pointer acceleration filter constants */ -#define MAX_VELOCITY_DIFF 1.0 +#define MAX_VELOCITY_DIFF 1.0 /* units/ms */ #define MOTION_TIMEOUT 300 /* (ms) */ #define NUM_POINTER_TRACKERS 16 struct pointer_tracker { - double dx; - double dy; - uint32_t time; + double dx; /* delta to most recent event, in device units */ + double dy; /* delta to most recent event, in device units */ + uint64_t time; /* ms */ int dir; }; struct pointer_accelerator; struct pointer_accelerator { - struct weston_motion_filter base; + struct motion_filter base; accel_profile_func_t profile; - double velocity; - double last_velocity; - int last_dx; - int last_dy; + double velocity; /* units/ms */ + double last_velocity; /* units/ms */ + int last_dx; /* device units */ + int last_dy; /* device units */ struct pointer_tracker *trackers; int cur_tracker; @@ -98,15 +113,14 @@ get_direction(int dx, int dy) else if (dx < 0 && dy < 0) dir = N | NW | W; else if (dx > 0) - dir = NW | W | SW; - else if (dx < 0) dir = NE | E | SE; + else if (dx < 0) + dir = NW | W | SW; else if (dy > 0) dir = SE | S | SW; else if (dy < 0) dir = NE | N | NW; - } - else { + } else { /* Calculate r within the interval [0 to 8) * * r = [0 .. 2π] where 0 is North @@ -130,7 +144,7 @@ get_direction(int dx, int dy) static void feed_trackers(struct pointer_accelerator *accel, double dx, double dy, - uint32_t time) + uint64_t time) { int i, current; struct pointer_tracker *trackers = accel->trackers; @@ -159,7 +173,7 @@ tracker_by_offset(struct pointer_accelerator *accel, unsigned int offset) } static double -calculate_tracker_velocity(struct pointer_tracker *tracker, uint32_t time) +calculate_tracker_velocity(struct pointer_tracker *tracker, uint64_t time) { int dx; int dy; @@ -168,37 +182,24 @@ calculate_tracker_velocity(struct pointer_tracker *tracker, uint32_t time) dx = tracker->dx; dy = tracker->dy; distance = sqrt(dx*dx + dy*dy); - return distance / (double)(time - tracker->time); + return distance / (double)(time - tracker->time); /* units/ms */ } static double -calculate_velocity(struct pointer_accelerator *accel, uint32_t time) +calculate_velocity(struct pointer_accelerator *accel, uint64_t time) { struct pointer_tracker *tracker; double velocity; double result = 0.0; - double initial_velocity; + double initial_velocity = 0.0; double velocity_diff; unsigned int offset; unsigned int dir = tracker_by_offset(accel, 0)->dir; - /* Find first velocity */ - for (offset = 1; offset < NUM_POINTER_TRACKERS; offset++) { - tracker = tracker_by_offset(accel, offset); - - if (time <= tracker->time) - continue; - - result = initial_velocity = - calculate_tracker_velocity(tracker, time); - if (initial_velocity > 0.0) - break; - } - /* Find least recent vector within a timelimit, maximum velocity diff * and direction threshold. */ - for (; offset < NUM_POINTER_TRACKERS; offset++) { + for (offset = 1; offset < NUM_POINTER_TRACKERS; offset++) { tracker = tracker_by_offset(accel, offset); /* Stop if too far away in time */ @@ -213,27 +214,31 @@ calculate_velocity(struct pointer_accelerator *accel, uint32_t time) velocity = calculate_tracker_velocity(tracker, time); - /* Stop if velocity differs too much from initial */ - velocity_diff = fabs(initial_velocity - velocity); - if (velocity_diff > MAX_VELOCITY_DIFF) - break; + if (initial_velocity == 0.0) { + result = initial_velocity = velocity; + } else { + /* Stop if velocity differs too much from initial */ + velocity_diff = fabs(initial_velocity - velocity); + if (velocity_diff > MAX_VELOCITY_DIFF) + break; - result = velocity; + result = velocity; + } } - return result; + return result; /* units/ms */ } static double acceleration_profile(struct pointer_accelerator *accel, - void *data, double velocity, uint32_t time) + void *data, double velocity, uint64_t time) { return accel->profile(&accel->base, data, velocity, time); } static double calculate_acceleration(struct pointer_accelerator *accel, - void *data, double velocity, uint32_t time) + void *data, double velocity, uint64_t time) { double factor; @@ -248,39 +253,18 @@ calculate_acceleration(struct pointer_accelerator *accel, factor = factor / 6.0; - return factor; -} - -static double -soften_delta(double last_delta, double delta) -{ - if (delta < -1.0 || delta > 1.0) { - if (delta > last_delta) - return delta - 0.5; - else if (delta < last_delta) - return delta + 0.5; - } - - return delta; -} - -static void -apply_softening(struct pointer_accelerator *accel, - struct weston_motion_params *motion) -{ - motion->dx = soften_delta(accel->last_dx, motion->dx); - motion->dy = soften_delta(accel->last_dy, motion->dy); + return factor; /* unitless factor */ } static void -accelerator_filter(struct weston_motion_filter *filter, - struct weston_motion_params *motion, - void *data, uint32_t time) +accelerator_filter(struct motion_filter *filter, + struct motion_params *motion, + void *data, uint64_t time) { struct pointer_accelerator *accel = (struct pointer_accelerator *) filter; - double velocity; - double accel_value; + double velocity; /* units/ms */ + double accel_value; /* unitless factor */ feed_trackers(accel, motion->dx, motion->dy, time); velocity = calculate_velocity(accel, time); @@ -289,8 +273,6 @@ accelerator_filter(struct weston_motion_filter *filter, motion->dx = accel_value * motion->dx; motion->dy = accel_value * motion->dy; - apply_softening(accel, motion); - accel->last_dx = motion->dx; accel->last_dy = motion->dy; @@ -298,7 +280,7 @@ accelerator_filter(struct weston_motion_filter *filter, } static void -accelerator_destroy(struct weston_motion_filter *filter) +accelerator_destroy(struct motion_filter *filter) { struct pointer_accelerator *accel = (struct pointer_accelerator *) filter; @@ -307,12 +289,12 @@ accelerator_destroy(struct weston_motion_filter *filter) free(accel); } -struct weston_motion_filter_interface accelerator_interface = { +struct motion_filter_interface accelerator_interface = { accelerator_filter, accelerator_destroy }; -struct weston_motion_filter * +struct motion_filter * create_pointer_accelator_filter(accel_profile_func_t profile) { struct pointer_accelerator *filter; @@ -322,7 +304,6 @@ create_pointer_accelator_filter(accel_profile_func_t profile) return NULL; filter->base.interface = &accelerator_interface; - wl_list_init(&filter->base.link); filter->profile = profile; filter->last_velocity = 0.0; @@ -335,3 +316,44 @@ create_pointer_accelator_filter(accel_profile_func_t profile) return &filter->base; } + +static inline double +calc_penumbral_gradient(double x) +{ + x *= 2.0; + x -= 1.0; + return 0.5 + (x * sqrt(1.0 - x * x) + asin(x)) / M_PI; +} + +double +pointer_accel_profile_smooth_simple(struct motion_filter *filter, + void *data, + double velocity, /* units/ms */ + uint64_t time) +{ + double threshold = DEFAULT_THRESHOLD; /* units/ms */ + double accel = DEFAULT_ACCELERATION; /* unitless factor */ + double smooth_accel_coefficient; /* unitless factor */ + double factor; /* unitless factor */ + + if (threshold < 0.1) + threshold = 0.1; + if (accel < 1.0) + accel = 1.0; + + + if (velocity < (threshold / 2.0)) + return calc_penumbral_gradient(0.5 + velocity / threshold) * 2.0 - 1.0; + + if (velocity <= threshold) + return 1.0; + + factor = velocity/threshold; + if (factor >= accel) + return accel; + + /* factor is between 1.0 and accel, scale this to 0.0 - 1.0 */ + factor = (factor - 1.0) / (accel - 1.0); + smooth_accel_coefficient = calc_penumbral_gradient(factor); + return 1.0 + (smooth_accel_coefficient * (accel - 1.0)); +}