~sircmpwn/casa

2234ef6b939b68087261483ad917b1de929d351d — Drew DeVault 3 months ago f04415a gl-refactor
Set minimum animation duration

This throttles user input to make things feel a bit better, and
finishes the animation if the user finishes their gesture before it
completes.
3 files changed, 79 insertions(+), 29 deletions(-)

M include/surface.h
M src/input.c
M src/surface.c
M include/surface.h => include/surface.h +4 -1
@@ 40,10 40,12 @@ struct casa_surface {
	struct casa_buffer buffer_pool[3];
	struct wl_callback *frame_callback;
	uint32_t last_frame;
	int32_t anim_due;

	struct wl_list outputs; // casa_surface_output::link

	enum casa_surface_state state;
	enum casa_surface_state next_state;
};

struct casa_surface_output {


@@ 58,6 60,7 @@ void casa_surface_schedule_frame(struct casa_surface *surf);

double casa_surface_state_progress(struct casa_surface *surf, int32_t time);

void casa_surface_touch_up(struct casa_surface *surf, int32_t time);
void casa_surface_touch_up(struct casa_surface *surf,
		struct casa_touchpoint *tp, int32_t time);

#endif

M src/input.c => src/input.c +1 -1
@@ 62,7 62,7 @@ wl_touch_up(void *data, struct wl_touch *wl_touch,
	}
	struct casa_surface *surf = tp->surface;
	tp->cur_time = time;
	casa_surface_touch_up(surf, time);
	casa_surface_touch_up(surf, tp, time);
	tp->surface = NULL;
	tp->id = -1;
}

M src/surface.c => src/surface.c +74 -27
@@ 1,6 1,5 @@
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <wayland-client.h>
#include "buffers.h"


@@ 166,19 165,13 @@ casa_surface_schedule_frame(struct casa_surface *surf)
	wl_surface_commit(surf->surface);
}

double
casa_surface_state_progress(struct casa_surface *surf, int32_t time)
{
	struct casa_touchpoint *tp = NULL;
	struct casa_state *state = surf->casa;
	for (size_t i = 0;
			i < sizeof(state->touchpoints) / sizeof(state->touchpoints[0]); ++i) {
		if (state->touchpoints[i].surface == surf) {
			tp = &state->touchpoints[i];
			break;
		}
	}
/* The minimum number of milliseconds an animation will complete in */
const int32_t anim_target_duration = 200;

static double
casa_surface_state_raw_progress(struct casa_surface *surf, int32_t time,
		struct casa_touchpoint *tp, double *raw)
{
	int height = surf->height * surf->scale;
	int32_t diff_px = 0, diff_ms = 0;
	float extra_px = 0;


@@ 192,43 185,97 @@ casa_surface_state_progress(struct casa_surface *surf, int32_t time)
		}
	}

	int32_t elapsed = tp ? time - tp->init_time : 0;
	if (elapsed > anim_target_duration) {
		elapsed = anim_target_duration;
	}

	double progress = 0;
	if (surf->anim_due > 0) {
		progress = 1.0 - (surf->anim_due - time) / (float)anim_target_duration;
		elapsed = anim_target_duration;
		if (progress >= 1.0) {
			progress = 1.0;
			surf->anim_due = 0;
			surf->state = surf->next_state;
		}
	}

	switch (surf->state) {
	case CASA_SURFACE_IDLE:
		if (!tp) {
			progress = 0;
		} else {
		if (tp) {
			progress = (tp->init_y - tp->cur_y - extra_px) * 4.0 / height;
		}
		progress = progress > 0 ? progress < 1 ? progress : 1 : 0;
		return progress;
		break;
	case CASA_SURFACE_BROWSE:
		if (!tp) {
			progress = 0;
		} else {
		if (tp) {
			progress = (tp->cur_y - tp->init_y - extra_px) * 4.0 / height;
		}
		return progress;
		break;
	default:
		assert(0);
	}

	if (raw) {
		*raw = progress;
	}

	double max_progress = elapsed / (float)anim_target_duration;
	if (progress > max_progress) {
		progress = max_progress;
	}

	return progress;
}

double
casa_surface_state_progress(struct casa_surface *surf, int32_t time)
{
	struct casa_touchpoint *tp = NULL;
	struct casa_state *state = surf->casa;
	for (size_t i = 0;
			i < sizeof(state->touchpoints) / sizeof(state->touchpoints[0]); ++i) {
		if (state->touchpoints[i].surface == surf) {
			tp = &state->touchpoints[i];
			break;
		}
	}

	double progress = casa_surface_state_raw_progress(surf, time, tp, NULL);
	if (progress != 0) {
		casa_surface_schedule_frame(surf);
	}
	return progress;
}

void
casa_surface_touch_up(struct casa_surface *surf, int32_t time)
casa_surface_touch_up(struct casa_surface *surf,
		struct casa_touchpoint *tp, int32_t time)
{
	double progress = casa_surface_state_progress(surf, time);
	if (progress > 0.5) {
	double raw;
	double progress = casa_surface_state_raw_progress(surf, time, tp, &raw);
	enum casa_surface_state next_state = surf->state;
	if (raw > 0.5) {
		switch (surf->state) {
		case CASA_SURFACE_IDLE:
			surf->state = CASA_SURFACE_BROWSE;
			next_state = CASA_SURFACE_BROWSE;
			break;
		case CASA_SURFACE_BROWSE:
			surf->state = CASA_SURFACE_IDLE;
			next_state = CASA_SURFACE_IDLE;
			break;
		}
	}

	if (progress >= 1.0) {
		surf->state = next_state;
	} else if (raw > 0.5) {
		surf->anim_due = time +
			(int32_t)(anim_target_duration * (1.0 - progress));
		surf->next_state = next_state;
	} else {
		/* TODO: Animate back to base state */
		/* Animate back to previous state? */
	}

	casa_surface_schedule_frame(surf);
}