~sircmpwn/public-inbox

casa: Fix upside-down icons, implement scaling. v1 PROPOSED

György Kurucz
György Kurucz: 4
 Fix upside-down icons, implement scaling.
 Fix bad logic in wl_seat_capabilities.
 Change everything to use float, add vec2 functions.
 Implement tap gesture.

 14 files changed, 186 insertions(+), 78 deletions(-)
Thanks!

To git@git.sr.ht:~sircmpwn/casa
   fa510a6..01cafa6  master -> master
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~sircmpwn/public-inbox/patches/11564/mbox | git am -3
Learn more about email & git
View this thread in the archives

[PATCH casa 1/4] Fix upside-down icons, implement scaling. Export this patch

György Kurucz
---
 src/prerender.c | 7 ++++---
 src/render.c    | 8 ++++----
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/src/prerender.c b/src/prerender.c
index 6ec0f93..eb1e862 100644
--- a/src/prerender.c
+++ b/src/prerender.c
@@ -21,7 +21,7 @@ casa_get_icon_texture(struct fd_icon_database *database,
	struct fd_icon *icon =
		fd_icon_database_get_icon_criteria(database, &criteria);
	if (!icon) {
		fprintf(stderr, "Found no suitable icon for %s at %xx%d@%d\n",
		fprintf(stderr, "Found no suitable icon for %s at %dx%d@%d\n",
				name, size, size, scale);
		return 1;
	}
@@ -29,11 +29,12 @@ casa_get_icon_texture(struct fd_icon_database *database,
	cairo_surface_t *source =
		cairo_image_surface_create_from_png(icon->path);

	/* TODO: Scale as necessary for icons which don't match our expected size or
	 * scale. */
	cairo_surface_t *surface = cairo_image_surface_create(
			CAIRO_FORMAT_ARGB32, size, size);
	cairo_t *cairo = cairo_create(surface);
	// TODO: consider scale too!
	double s = size / (double)cairo_image_surface_get_height(source);
	cairo_scale(cairo, s, s);
	cairo_set_source_surface(cairo, source, 0, 0);
	cairo_paint(cairo);

diff --git a/src/render.c b/src/render.c
index de1ba3a..6bd8bd2 100644
--- a/src/render.c
+++ b/src/render.c
@@ -33,10 +33,10 @@ render_icons(struct casa_surface *surface,

	matrix_projection(projection, buffer->width, buffer->height);
	GLfloat verts[] = {
		1, 0, // top right
		0, 0, // top left
		1, 1, // bottom right
		0, 1, // bottom left
		1, 1, // top right
		0, 1, // top left
		1, 0, // bottom right
		0, 0, // bottom left
	};
	GLfloat texcoord[] = {
		1, 0, // top right
-- 
2.27.0

[PATCH casa 2/4] Fix bad logic in wl_seat_capabilities. Export this patch

György Kurucz
---
 src/input.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/input.c b/src/input.c
index 49cbefc..336a392 100644
--- a/src/input.c
+++ b/src/input.c
@@ -147,9 +147,12 @@ static void
wl_seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities)
{
	struct casa_state *state = data;
	if ((capabilities & WL_SEAT_CAPABILITY_TOUCH) && !state->touch) {
		state->touch = wl_seat_get_touch(wl_seat);
		wl_touch_add_listener(state->touch, &wl_touch_listener, state);
	if (capabilities & WL_SEAT_CAPABILITY_TOUCH) {
		if (!state->touch) {
			state->touch = wl_seat_get_touch(wl_seat);
			wl_touch_add_listener(state->touch,
					&wl_touch_listener, state);
		}
	} else if (state->touch) {
		wl_touch_release(state->touch);
		state->touch = NULL;
-- 
2.27.0

[PATCH casa 3/4] Change everything to use float, add vec2 functions. Export this patch

György Kurucz
---
I tried to mimic the way matrices were implemented.

 include/casa.h    |  9 ++++----
 include/matrix.h  |  8 +++++++
 include/surface.h | 19 +++++++++--------
 src/input.c       | 32 ++++++++++++++++------------
 src/matrix.c      | 37 ++++++++++++++++++++++++++++++++
 src/render.c      |  4 ++--
 src/surface.c     | 54 ++++++++++++++++++++++++-----------------------
 7 files changed, 108 insertions(+), 55 deletions(-)

diff --git a/include/casa.h b/include/casa.h
index 6c7d496..b44193a 100644
--- a/include/casa.h
+++ b/include/casa.h
@@ -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 {
diff --git a/include/matrix.h b/include/matrix.h
index 57469ce..c447f70 100644
--- a/include/matrix.h
+++ b/include/matrix.h
@@ -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
diff --git a/include/surface.h b/include/surface.h
index 30b4730..4c4b889 100644
--- a/include/surface.h
+++ b/include/surface.h
@@ -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
diff --git a/src/input.c b/src/input.c
index 336a392..9ca752d 100644
--- a/src/input.c
+++ b/src/input.c
@@ -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);
}
diff --git a/src/matrix.c b/src/matrix.c
index 98166b2..6c30da4 100644
--- a/src/matrix.c
+++ b/src/matrix.c
@@ -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];
}
diff --git a/src/render.c b/src/render.c
index 6bd8bd2..c311609 100644
--- a/src/render.c
+++ b/src/render.c
@@ -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);
diff --git a/src/surface.c b/src/surface.c
index e2adfe1..29f25e4 100644
--- a/src/surface.c
+++ b/src/surface.c
@@ -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;
-- 
2.27.0

[PATCH casa 4/4] Implement tap gesture. Export this patch

György Kurucz
---
Not too useful on its own, since we don't read desktop files yet. It
just prints to stderr the grid coordinates of the tapped icon.

 include/surface.h |  7 ++++++-
 src/input.c       |  6 +++++-
 src/render.c      | 16 ++++++----------
 src/surface.c     | 48 ++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 64 insertions(+), 13 deletions(-)

diff --git a/include/surface.h b/include/surface.h
index 4c4b889..49993a4 100644
--- a/include/surface.h
+++ b/include/surface.h
@@ -30,7 +30,7 @@ enum casa_surface_state {

struct casa_drag_integrator {
	uint32_t touchpoints;
	float integ[2];
	float integ[2], start[2];
};

enum casa_animation_kind {
@@ -75,6 +75,8 @@ struct casa_surface {
	float scroll_offset; // (-infinity, idle_offset]
	struct casa_drag_integrator drag_integrator;
	struct casa_animation scroll_offset_anim;

	int icon_size;
};

struct casa_surface_output {
@@ -94,4 +96,7 @@ void casa_surface_touch_down(struct casa_surface *surf, int32_t time);
void casa_surface_touch_up(struct casa_surface *surf, int32_t time,
		const float vel[static 2]);

void casa_surface_get_icon_pos(const struct casa_surface *surf,
		int row, int col, float pos[static 2]);

#endif
diff --git a/src/input.c b/src/input.c
index 9ca752d..72ee514 100644
--- a/src/input.c
+++ b/src/input.c
@@ -53,7 +53,11 @@ wl_touch_down(void *data, struct wl_touch *wl_touch,

	surf->drag_integrator.touchpoints++;

	casa_surface_touch_down(surf, time);
	if (surf->drag_integrator.touchpoints == 1) {
		surf->drag_integrator.start[0] = tp->cur[0];
		surf->drag_integrator.start[1] = tp->cur[1];
		casa_surface_touch_down(surf, time);
	}
	casa_surface_schedule_frame(surf);
}

diff --git a/src/render.c b/src/render.c
index c311609..f2e3eeb 100644
--- a/src/render.c
+++ b/src/render.c
@@ -17,11 +17,7 @@ static void
render_icons(struct casa_surface *surface,
		struct casa_buffer *buffer, float progress, int y_offs)
{
	const int width = 128, height = 128;
	const int nrows = 16, ncols = 4;
	const int gutter = 32;
	int x_margin = (((buffer->width - gutter * 2) / ncols) - width) / 2;
	int y_margin = 32;

	float projection[9], matrix[9], transposition[9];
	const struct casa_shaders *shaders = &surface->casa->shaders;
@@ -53,13 +49,13 @@ render_icons(struct casa_surface *surface,

	for (int row = 0; row < nrows; ++row) {
		for (int col = 0; col < ncols; ++col) {
			int x = gutter + x_margin + col * (width + x_margin * 2);
			int y = gutter * 2 + row * (height + y_margin);
			float icon_pos[2];
			casa_surface_get_icon_pos(surface, row, col, icon_pos);
			struct box box = {
				.x = x,
				.y = buffer->height - height - (y + y_offs),
				.width = width,
				.height = height,
				.x = icon_pos[0],
				.y = buffer->height - surface->icon_size - (icon_pos[1] + y_offs),
				.width = surface->icon_size,
				.height = surface->icon_size,
			};
			matrix_project_box(matrix, &box, 0, projection);
			matrix_transpose(transposition, matrix);
diff --git a/src/surface.c b/src/surface.c
index 29f25e4..a0aad95 100644
--- a/src/surface.c
+++ b/src/surface.c
@@ -1,5 +1,6 @@
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <wayland-client.h>
#include "buffers.h"
@@ -15,6 +16,7 @@ const int32_t anim_target_duration = 200;
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
const float gesture_tap_max_distance_squared = 10.0 * 10.0; // pixel^2

static void
casa_surface_drag_get(const struct casa_surface *surf, float off[static 2])
@@ -33,6 +35,34 @@ casa_surface_drag_get(const struct casa_surface *surf, float off[static 2])
	}
}

void
casa_surface_get_icon_pos(const struct casa_surface *surf,
		int row, int col, float pos[static 2])
{
	const int width = surf->icon_size, height = surf->icon_size;
	const int ncols = 4;
	const int gutter = 32;
	int x_margin = (((surf->width * surf->scale - gutter * 2) / ncols) - width) / 2;
	int y_margin = 32;

	pos[0] = gutter + x_margin + col * (width + x_margin * 2);
	pos[1] = gutter * 2 + row * (height + y_margin);
}

static void
casa_surface_get_icon_at(const struct casa_surface *surf,
		const float pos[static 2], int *row, int *col)
{
	const int width = surf->icon_size, height = surf->icon_size;
	const int ncols = 4;
	const int gutter = 32;
	int x_margin = (((surf->width * surf->scale - gutter * 2) / ncols) - width) / 2;
	int y_margin = 32;

	*col = (pos[0] - gutter - x_margin) / (width + x_margin * 2);
	*row = (pos[1] - gutter * 2) / (height + y_margin);
}

static void
wl_surface_enter(void *data,
		struct wl_surface *wl_surface,
@@ -143,6 +173,8 @@ casa_surface_create(struct casa_state *state, struct wl_output *output)
	surf->casa = state;
	wl_list_init(&surf->outputs);

	surf->icon_size = 128; // TODO: scale this based on something...

	surf->idle_offset = 256; // TODO: scale this based on something...
	surf->scroll_offset = surf->idle_offset;
	surf->state = CASA_SURFACE_IDLE;
@@ -231,7 +263,11 @@ casa_surface_state_progress(struct casa_surface *surf, int32_t time,
	if (surf->drag_integrator.touchpoints > 0) {
		float off[2];
		casa_surface_drag_get(surf, off);
		*y_offs = fmin(surf->scroll_offset + off[1], surf->idle_offset);
		if (vec2_dot(off, off) > gesture_tap_max_distance_squared) {
			*y_offs = fmin(surf->scroll_offset + off[1], surf->idle_offset);
		} else {
			*y_offs = surf->scroll_offset;
		}
	} else if (anim->kind != CASA_ANIMATION_NONE) {
		if (anim->time_end > time) {
			*y_offs = casa_animation_val(anim, time);
@@ -272,6 +308,16 @@ void
casa_surface_touch_up(struct casa_surface *surf, int32_t time,
		const float vel[static 2])
{
	struct casa_drag_integrator *di = &surf->drag_integrator;
	if (vec2_dot(di->integ, di->integ) <= gesture_tap_max_distance_squared) {
		// tap gesture
		float tap[2] = { di->start[0], di->start[1] - surf->scroll_offset };
		int row, col;
		casa_surface_get_icon_at(surf, tap, &row, &col);
		fprintf(stderr, "tap gesture @(%f %f) @(%d %d)\n", tap[0], tap[1], row, col);
		return;
	}

	surf->scroll_offset += surf->drag_integrator.integ[1];
	surf->scroll_offset = fmin(surf->scroll_offset, surf->idle_offset);

-- 
2.27.0
Thanks!

To git@git.sr.ht:~sircmpwn/casa
   fa510a6..01cafa6  master -> master