Split motion tracking out into separate handlers so we can have one per touch.
Signed-off-by: Daniel Stone <[email protected]> --- clients/smoke.c | 155 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 110 insertions(+), 45 deletions(-) diff --git a/clients/smoke.c b/clients/smoke.c index 80b8c58..42540d0 100644 --- a/clients/smoke.c +++ b/clients/smoke.c @@ -37,9 +37,18 @@ struct smoke { struct window *window; struct widget *widget; int width, height; - int current; uint32_t time; + struct wl_list motion_list; +}; + +struct motion { + struct smoke *smoke; + int is_pointer; + uint32_t touch_id; + int current; + int active; struct { float *d, *u, *v; } b[2]; + struct wl_list link; }; static void diffuse(struct smoke *smoke, uint32_t time, @@ -142,12 +151,14 @@ static void project(struct smoke *smoke, uint32_t time, } } -static void render(struct smoke *smoke, cairo_surface_t *surface) +static int render(struct smoke *smoke, struct motion *motion, + cairo_surface_t *surface) { unsigned char *dest; int x, y, width, height, stride; float *s; uint32_t *d, c, a; + int ret = 0; dest = cairo_image_surface_get_data(surface); width = cairo_image_surface_get_width(surface); @@ -155,7 +166,7 @@ static void render(struct smoke *smoke, cairo_surface_t *surface) stride = cairo_image_surface_get_stride(surface); for (y = 1; y < height - 1; y++) { - s = smoke->b[smoke->current].d + y * smoke->height; + s = motion->b[motion->current].d + y * smoke->height; d = (uint32_t *) (dest + y * stride); for (x = 1; x < width - 1; x++) { c = (int) (s[x] * 800); @@ -165,8 +176,12 @@ static void render(struct smoke *smoke, cairo_surface_t *surface) if (a < 0x33) a = 0x33; d[x] = (a << 24) | (c << 16) | (c << 8) | c; + if (c != 0) + ret = 1; } } + + return ret; } static void @@ -185,60 +200,78 @@ static const struct wl_callback_listener listener = { frame_callback, }; -static void -redraw_handler(struct widget *widget, void *data) +static int +do_redraw(struct motion *motion, cairo_surface_t *surface) { - struct smoke *smoke = data; + struct smoke *smoke = motion->smoke; uint32_t time = smoke->time; - struct wl_callback *callback; - cairo_surface_t *surface; - diffuse(smoke, time / 30, smoke->b[0].u, smoke->b[1].u); - diffuse(smoke, time / 30, smoke->b[0].v, smoke->b[1].v); + diffuse(smoke, time / 30, motion->b[0].u, motion->b[1].u); + diffuse(smoke, time / 30, motion->b[0].v, motion->b[1].v); project(smoke, time / 30, - smoke->b[1].u, smoke->b[1].v, - smoke->b[0].u, smoke->b[0].v); + motion->b[1].u, motion->b[1].v, + motion->b[0].u, motion->b[0].v); advect(smoke, time / 30, - smoke->b[1].u, smoke->b[1].v, - smoke->b[1].u, smoke->b[0].u); + motion->b[1].u, motion->b[1].v, + motion->b[1].u, motion->b[0].u); advect(smoke, time / 30, - smoke->b[1].u, smoke->b[1].v, - smoke->b[1].v, smoke->b[0].v); + motion->b[1].u, motion->b[1].v, + motion->b[1].v, motion->b[0].v); project(smoke, time / 30, - smoke->b[0].u, smoke->b[0].v, - smoke->b[1].u, smoke->b[1].v); + motion->b[0].u, motion->b[0].v, + motion->b[1].u, motion->b[1].v); - diffuse(smoke, time / 30, smoke->b[0].d, smoke->b[1].d); + diffuse(smoke, time / 30, motion->b[0].d, motion->b[1].d); advect(smoke, time / 30, - smoke->b[0].u, smoke->b[0].v, - smoke->b[1].d, smoke->b[0].d); + motion->b[0].u, motion->b[0].v, + motion->b[1].d, motion->b[0].d); - surface = window_get_surface(smoke->window); + return render(smoke, motion, surface); +} - render(smoke, surface); +static void +redraw_handler(struct widget *widget, void *data) +{ + struct wl_callback *callback; + struct smoke *smoke = data; + struct motion *motion, *tmp; + cairo_surface_t *surface = window_get_surface(smoke->window); + int did_redraw = 0; + + wl_list_for_each_safe(motion, tmp, &smoke->motion_list, link) { + if (do_redraw(motion, surface)) { + did_redraw = 1; + continue; + } - window_damage(smoke->window, 0, 0, smoke->width, smoke->height); + if (motion->active == 0) { + wl_list_remove(&motion->link); + free(motion); + } + } cairo_surface_destroy(surface); + if (!did_redraw) + return; + + window_damage(smoke->window, 0, 0, smoke->width, smoke->height); callback = wl_surface_frame(window_get_wl_surface(smoke->window)); wl_callback_add_listener(callback, &listener, smoke); wl_surface_commit(window_get_wl_surface(smoke->window)); } -static int -smoke_motion_handler(struct widget *widget, struct input *input, - uint32_t time, float x, float y, void *data) +static void +handle_motion(struct motion *motion, float x, float y) { - struct smoke *smoke = data; int i, i0, i1, j, j0, j1, k, d = 5; if (x - d < 1) i0 = 1; else i0 = x - d; - if (i0 + 2 * d > smoke->width - 1) - i1 = smoke->width - 1; + if (i0 + 2 * d > motion->smoke->width - 1) + i1 = motion->smoke->width - 1; else i1 = i0 + 2 * d; @@ -246,18 +279,35 @@ smoke_motion_handler(struct widget *widget, struct input *input, j0 = 1; else j0 = y - d; - if (j0 + 2 * d > smoke->height - 1) - j1 = smoke->height - 1; + if (j0 + 2 * d > motion->smoke->height - 1) + j1 = motion->smoke->height - 1; else j1 = j0 + 2 * d; for (i = i0; i < i1; i++) for (j = j0; j < j1; j++) { - k = j * smoke->width + i; - smoke->b[0].u[k] += 256 - (random() & 512); - smoke->b[0].v[k] += 256 - (random() & 512); - smoke->b[0].d[k] += 1; + k = j * motion->smoke->width + i; + motion->b[0].u[k] += 256 - (random() & 512); + motion->b[0].v[k] += 256 - (random() & 512); + motion->b[0].d[k] += 1; + } + + window_schedule_redraw(motion->smoke->window); +} + +static int +smoke_motion_handler(struct widget *widget, struct input *input, + uint32_t time, float x, float y, void *data) +{ + struct smoke *smoke = data; + struct motion *motion; + + wl_list_for_each(motion, &smoke->motion_list, link) { + if (motion->is_pointer) { + handle_motion(motion, x, y); + break; } + } return CURSOR_HAND1; } @@ -272,12 +322,29 @@ resize_handler(struct widget *widget, widget_set_size(smoke->widget, smoke->width, smoke->height); } +static void +init_motion(struct smoke *smoke, struct motion *motion) +{ + int size; + + motion->current = 0; + size = smoke->height * smoke->width; + motion->b[0].d = calloc(size, sizeof(float)); + motion->b[0].u = calloc(size, sizeof(float)); + motion->b[0].v = calloc(size, sizeof(float)); + motion->b[1].d = calloc(size, sizeof(float)); + motion->b[1].u = calloc(size, sizeof(float)); + motion->b[1].v = calloc(size, sizeof(float)); + motion->smoke = smoke; + wl_list_insert(&smoke->motion_list, &motion->link); +} + int main(int argc, char *argv[]) { struct timespec ts; struct smoke smoke; + struct motion pointer_motion; struct display *d; - int size; d = display_create(argc, argv); if (d == NULL) { @@ -290,20 +357,18 @@ int main(int argc, char *argv[]) smoke.display = d; smoke.window = window_create(d); smoke.widget = window_add_widget(smoke.window, &smoke); + wl_list_init(&smoke.motion_list); window_set_title(smoke.window, "smoke"); window_set_buffer_type(smoke.window, WINDOW_BUFFER_TYPE_SHM); clock_gettime(CLOCK_MONOTONIC, &ts); srandom(ts.tv_nsec); - smoke.current = 0; - size = smoke.height * smoke.width; - smoke.b[0].d = calloc(size, sizeof(float)); - smoke.b[0].u = calloc(size, sizeof(float)); - smoke.b[0].v = calloc(size, sizeof(float)); - smoke.b[1].d = calloc(size, sizeof(float)); - smoke.b[1].u = calloc(size, sizeof(float)); - smoke.b[1].v = calloc(size, sizeof(float)); + wl_list_init(&pointer_motion.link); + pointer_motion.is_pointer = 1; + pointer_motion.touch_id = 0; + pointer_motion.active = 1; + init_motion(&smoke, &pointer_motion); widget_set_motion_handler(smoke.widget, smoke_motion_handler); widget_set_resize_handler(smoke.widget, resize_handler); -- 1.7.10.4 _______________________________________________ wayland-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/wayland-devel
