M include/casa.h => include/casa.h +5 -4
@@ 12,16 12,17 @@
struct casa_touchpoint {
int32_t id;
struct casa_surface *surface;
- int init_x, init_y;
+
+ float init[2];
int32_t init_time;
- int cur_x, cur_y;
+ float cur[2];
int32_t cur_time;
- int last_x, last_y;
+ float last[2];
int32_t last_time;
- double vel_x, vel_y; // moving average of velocity (pixel / msec)
+ float vel[2]; // moving average of velocity (pixel / msec)
};
struct casa_state {
M include/matrix.h => include/matrix.h +8 -0
@@ 16,4 16,12 @@ void matrix_projection(float mat[static 9], int width, int height);
void matrix_project_box(float mat[static 9], const struct box *box,
float rotation, const float projection[static 9]);
+void vec2_zero(float vec[static 2]);
+void vec2_add(float vec[static 2],
+ const float a[static 2], const float b[static 2]);
+void vec2_sub(float vec[static 2],
+ const float a[static 2], const float b[static 2]);
+void vec2_mul(float vec[static 2], const float a[static 2], float b);
+float vec2_dot(const float a[static 2], const float b[static 2]);
+
#endif
M include/surface.h => include/surface.h +10 -9
@@ 30,7 30,7 @@ enum casa_surface_state {
struct casa_drag_integrator {
uint32_t touchpoints;
- double int_x, int_y;
+ float integ[2];
};
enum casa_animation_kind {
@@ 44,13 44,13 @@ struct casa_animation {
enum casa_animation_kind kind;
union {
struct {
- double s_0, s_1;
+ float s_0, s_1;
} linear;
struct {
// s(t) = s_0 + v_0*t + (1/2)*a*t^2
- double s_0; // pixel
- double v_0; // pixel / msec
- double a; // pixel / msec^2
+ float s_0; // pixel
+ float v_0; // pixel / msec
+ float a; // pixel / msec^2
} quadratic;
};
};
@@ 71,8 71,8 @@ struct casa_surface {
struct wl_list outputs; // casa_surface_output::link
enum casa_surface_state state;
- double idle_offset;
- double scroll_offset; // (-infinity, idle_offset]
+ float idle_offset;
+ float scroll_offset; // (-infinity, idle_offset]
struct casa_drag_integrator drag_integrator;
struct casa_animation scroll_offset_anim;
};
@@ 88,9 88,10 @@ struct casa_surface *casa_surface_create(
void casa_surface_schedule_frame(struct casa_surface *surf);
void casa_surface_state_progress(struct casa_surface *surf, int32_t time,
- double *progress, double *y_offs);
+ float *progress, float *y_offs);
void casa_surface_touch_down(struct casa_surface *surf, int32_t time);
-void casa_surface_touch_up(struct casa_surface *surf, int32_t time, double vel_y);
+void casa_surface_touch_up(struct casa_surface *surf, int32_t time,
+ const float vel[static 2]);
#endif
M src/input.c => src/input.c +18 -14
@@ 1,6 1,7 @@
#include <stdio.h>
#include <wayland-client.h>
#include "casa.h"
+#include "matrix.h"
#include "surface.h"
#include "render.h"
@@ 43,12 44,12 @@ wl_touch_down(void *data, struct wl_touch *wl_touch,
}
tp->id = id;
tp->surface = surf;
- tp->last_x = tp->cur_x = tp->init_x =
+ tp->last[0] = tp->cur[0] = tp->init[0] =
(int)(wl_fixed_to_double(x) * surf->scale);
- tp->last_y = tp->cur_y = tp->init_y =
+ tp->last[1] = tp->cur[1] = tp->init[1] =
(int)(wl_fixed_to_double(y) * surf->scale);
tp->last_time = tp->cur_time = tp->init_time = time;
- tp->vel_x = tp->vel_y = 0;
+ vec2_zero(tp->vel);
surf->drag_integrator.touchpoints++;
@@ 70,12 71,13 @@ wl_touch_up(void *data, struct wl_touch *wl_touch,
tp->id = -1;
struct casa_drag_integrator *di = &surf->drag_integrator;
- di->int_x += tp->cur_x - tp->init_x;
- di->int_y += tp->cur_y - tp->init_y;
+ float delta[2];
+ vec2_sub(delta, tp->cur, tp->init);
+ vec2_add(di->integ, di->integ, delta);
if (--di->touchpoints == 0) {
// last touchpoint gone from this surface
- casa_surface_touch_up(surf, time, tp->vel_y);
+ casa_surface_touch_up(surf, time, tp->vel);
}
}
@@ 89,19 91,21 @@ wl_touch_motion(void *data, struct wl_touch *wl_touch,
return;
}
struct casa_surface *surf = tp->surface;
- tp->last_x = tp->cur_x, tp->last_y = tp->cur_y;
+ tp->last[0] = tp->cur[0], tp->last[1] = tp->cur[1];
tp->last_time = tp->cur_time, tp->last_time = tp->cur_time;
- tp->cur_x = (int)(wl_fixed_to_double(x) * surf->scale);
- tp->cur_y = (int)(wl_fixed_to_double(y) * surf->scale);
+ tp->cur[0] = (int)(wl_fixed_to_double(x) * surf->scale);
+ tp->cur[1] = (int)(wl_fixed_to_double(y) * surf->scale);
tp->cur_time = time;
- double dt = tp->cur_time - tp->last_time;
- double vel_x = (tp->cur_x - tp->last_x) / dt;
- double vel_y = (tp->cur_y - tp->last_y) / dt;
+ float dt = tp->cur_time - tp->last_time;
+ float vel[2];
+ vec2_sub(vel, tp->cur, tp->last);
+ vec2_mul(vel, vel, 1/dt);
// moving average filter
- tp->vel_x = 0.7 * tp->vel_x + 0.3 * vel_x;
- tp->vel_y = 0.7 * tp->vel_y + 0.3 * vel_y;
+ vec2_mul(tp->vel, tp->vel, 0.7);
+ vec2_mul(vel, vel, 0.3);
+ vec2_add(tp->vel, tp->vel, vel);
casa_surface_schedule_frame(surf);
}
M src/matrix.c => src/matrix.c +37 -0
@@ 112,3 112,40 @@ void matrix_project_box(float mat[static 9], const struct box *box,
matrix_scale(mat, width, height);
matrix_multiply(mat, projection, mat);
}
+
+void vec2_zero(float vec[static 2])
+{
+ vec[0] = 0;
+ vec[1] = 0;
+}
+
+void vec2_add(float vec[static 2],
+ const float a[static 2], const float b[static 2])
+{
+ float sum[2];
+ sum[0] = a[0] + b[0];
+ sum[1] = a[1] + b[1];
+ memcpy(vec, sum, sizeof(sum));
+}
+
+void vec2_sub(float vec[static 2],
+ const float a[static 2], const float b[static 2])
+{
+ float sum[2];
+ sum[0] = a[0] - b[0];
+ sum[1] = a[1] - b[1];
+ memcpy(vec, sum, sizeof(sum));
+}
+
+void vec2_mul(float vec[static 2], const float a[static 2], float b)
+{
+ float product[2];
+ product[0] = a[0] * b;
+ product[1] = a[1] * b;
+ memcpy(vec, product, sizeof(product));
+}
+
+float vec2_dot(const float a[static 2], const float b[static 2])
+{
+ return a[0] * b[0] + a[1] * b[1];
+}
M src/render.c => src/render.c +2 -2
@@ 15,7 15,7 @@
*/
static void
render_icons(struct casa_surface *surface,
- struct casa_buffer *buffer, double progress, int y_offs)
+ struct casa_buffer *buffer, float progress, int y_offs)
{
const int width = 128, height = 128;
const int nrows = 16, ncols = 4;
@@ 87,7 87,7 @@ casa_render(struct casa_surface *surface, uint32_t time)
surface->height * surface->scale);
assert(buffer);
- double y_offs, progress;
+ float y_offs, progress;
casa_surface_state_progress(surface, time, &progress, &y_offs);
glClearColor(0.0f, 0.0f, 0.0f, progress * 0.75);
M src/surface.c => src/surface.c +28 -26
@@ 4,6 4,7 @@
#include <wayland-client.h>
#include "buffers.h"
#include "casa.h"
+#include "matrix.h"
#include "output.h"
#include "render.h"
#include "surface.h"
@@ 11,22 12,23 @@
/* TODO: Move animation/state into its own file */
/* The minimum number of milliseconds an animation will complete in */
const int32_t anim_target_duration = 200;
-const double gesture_completion_threshold = 0.25;
-const double kinetic_scrolling_friction = 0.01; // pixel / msec^2
-const double kinetic_scrolling_max_v = 5.0; // pixel / msec
+const float gesture_completion_threshold = 0.25;
+const float kinetic_scrolling_friction = 0.01; // pixel / msec^2
+const float kinetic_scrolling_max_v = 5.0; // pixel / msec
static void
-casa_surface_drag_get(const struct casa_surface *surf, double *x, double *y)
+casa_surface_drag_get(const struct casa_surface *surf, float off[static 2])
{
const struct casa_state *state = surf->casa;
- *x = surf->drag_integrator.int_x;
- *y = surf->drag_integrator.int_y;
+ off[0] = surf->drag_integrator.integ[0];
+ off[1] = surf->drag_integrator.integ[1];
for (size_t i = 0;
i < sizeof(state->touchpoints) / sizeof(state->touchpoints[0]); ++i) {
const struct casa_touchpoint *point = &state->touchpoints[i];
if (point->id != -1 && point->surface == surf) {
- *x += point->cur_x - point->init_x;
- *y += point->cur_y - point->init_y;
+ float delta[2];
+ vec2_sub(delta, point->cur, point->init);
+ vec2_add(off, off, delta);
}
}
}
@@ 145,7 147,7 @@ casa_surface_create(struct casa_state *state, struct wl_output *output)
surf->scroll_offset = surf->idle_offset;
surf->state = CASA_SURFACE_IDLE;
surf->drag_integrator = (struct casa_drag_integrator){
- .touchpoints = 0, .int_x = 0, .int_y = 0 };
+ .touchpoints = 0, .integ = { 0, 0 } };
surf->scroll_offset_anim.time_end = -1;
surf->surface = wl_compositor_create_surface(state->compositor);
@@ 196,18 198,18 @@ casa_surface_schedule_frame(struct casa_surface *surf)
}
static void
-casa_surface_set_scroll_offset(struct casa_surface *surf, double offs) {
+casa_surface_set_scroll_offset(struct casa_surface *surf, float offs) {
offs = fmin(offs, surf->idle_offset);
surf->scroll_offset = offs;
}
-double
+static float
casa_animation_val(const struct casa_animation *anim, int32_t time)
{
- double t, val;
+ float t, val;
switch (anim->kind) {
case CASA_ANIMATION_LINEAR:
- t = (time - anim->time_start) / (double)(anim->time_end - anim->time_start);
+ t = (time - anim->time_start) / (float)(anim->time_end - anim->time_start);
val = (1.0 - t) * anim->linear.s_0 + t * anim->linear.s_1;
break;
case CASA_ANIMATION_QUADRATIC:
@@ 222,14 224,14 @@ casa_animation_val(const struct casa_animation *anim, int32_t time)
void
casa_surface_state_progress(struct casa_surface *surf, int32_t time,
- double *progress, double *y_offs)
+ float *progress, float *y_offs)
{
struct casa_animation *anim = &surf->scroll_offset_anim;
if (surf->drag_integrator.touchpoints > 0) {
- double off_x, off_y;
- casa_surface_drag_get(surf, &off_x, &off_y);
- *y_offs = fmin(surf->scroll_offset + off_y, surf->idle_offset);
+ float off[2];
+ casa_surface_drag_get(surf, off);
+ *y_offs = fmin(surf->scroll_offset + off[1], surf->idle_offset);
} else if (anim->kind != CASA_ANIMATION_NONE) {
if (anim->time_end > time) {
*y_offs = casa_animation_val(anim, time);
@@ 267,16 269,16 @@ casa_surface_touch_down(struct casa_surface *surf, int32_t time)
}
void
-casa_surface_touch_up(struct casa_surface *surf, int32_t time, double vel_y)
+casa_surface_touch_up(struct casa_surface *surf, int32_t time,
+ const float vel[static 2])
{
- surf->scroll_offset += surf->drag_integrator.int_y;
+ surf->scroll_offset += surf->drag_integrator.integ[1];
surf->scroll_offset = fmin(surf->scroll_offset, surf->idle_offset);
// reset integrator
- surf->drag_integrator.int_x = 0;
- surf->drag_integrator.int_y = 0;
+ vec2_zero(surf->drag_integrator.integ);
- double progress = 1.0 - surf->scroll_offset / surf->idle_offset;
+ float progress = 1.0 - surf->scroll_offset / surf->idle_offset;
enum casa_surface_state next_state = surf->state;
switch (surf->state) {
@@ 299,17 301,17 @@ casa_surface_touch_up(struct casa_surface *surf, int32_t time, double vel_y)
anim->linear.s_0 = surf->scroll_offset;
anim->linear.s_1 = next_state == CASA_SURFACE_BROWSE
? 0.0 : surf->idle_offset;
- double diff = fabs(anim->linear.s_1 - anim->linear.s_0);
+ float diff = fabs(anim->linear.s_1 - anim->linear.s_0);
anim->time_end = anim->time_start +
(int32_t)(anim_target_duration * (diff / surf->idle_offset));
} else if (progress >= 1.0) {
anim->kind = CASA_ANIMATION_QUADRATIC;
anim->time_start = time;
anim->quadratic.s_0 = surf->scroll_offset;
- if (fabs(vel_y) > kinetic_scrolling_max_v) {
- anim->quadratic.v_0 = copysign(kinetic_scrolling_max_v, vel_y);
+ if (fabs(vel[1]) > kinetic_scrolling_max_v) {
+ anim->quadratic.v_0 = copysign(kinetic_scrolling_max_v, vel[1]);
} else {
- anim->quadratic.v_0 = vel_y;
+ anim->quadratic.v_0 = vel[1];
}
anim->quadratic.a = copysign(kinetic_scrolling_friction, -anim->quadratic.v_0);
anim->time_end = anim->time_start - anim->quadratic.v_0 / anim->quadratic.a;