From 8dacaaba1b0cae3f9a0d49867452ee14797ac4bd Mon Sep 17 00:00:00 2001 From: Scott Moreau Date: Sun, 17 Jun 2012 18:10:58 -0600 Subject: [PATCH] Animate transitions for zoom focus point change. Handle the transition when focus changes from text cursor to mouse pointer or vice versa. --- src/compositor.c | 198 +++++++++++++++++++++++++++++++++++++++++++------------ src/compositor.h | 15 +++-- src/shell.c | 5 +- 3 files changed, 167 insertions(+), 51 deletions(-) diff --git a/src/compositor.c b/src/compositor.c index 55b0efc..e550926 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -1633,7 +1633,7 @@ notify_motion(struct wl_seat *seat, uint32_t time, wl_fixed_t x, wl_fixed_t y) if (output->zoom.active && pixman_region32_contains_point(&output->region, ix, iy, NULL)) - weston_output_update_zoom(output, x, y, ZOOM_FOCUS_POINTER); + weston_output_update_zoom(output, ZOOM_FOCUS_POINTER); weston_device_repick(seat); interface = seat->pointer->grab->interface; @@ -2783,9 +2783,11 @@ weston_text_cursor_position_notify(struct weston_surface *surface, pixman_region32_contains_point(&output->region, wl_fixed_to_int(global_x), wl_fixed_to_int(global_y), - NULL)) - weston_output_update_zoom(output, global_x, global_y, - ZOOM_FOCUS_TEXT); + NULL)) { + output->zoom.text_cursor.x = global_x; + output->zoom.text_cursor.y = global_y; + weston_output_update_zoom(output, ZOOM_FOCUS_TEXT); + } } static void @@ -2815,71 +2817,178 @@ weston_zoom_frame_z(struct weston_animation *animation, } static void -weston_zoom_transition(struct weston_output *output) +weston_zoom_frame_xy(struct weston_animation *animation, + struct weston_output *output, uint32_t msecs) { - if (output->zoom.level != output->zoom.spring_z.current) { - output->zoom.spring_z.target = output->zoom.level; - if (wl_list_empty(&output->zoom.animation_z.link)) { - output->zoom.animation_z.frame_counter = 0; - wl_list_insert(output->animation_list.prev, - &output->zoom.animation_z.link); - } + wl_fixed_t x, y; + if (animation->frame_counter <= 1) + output->zoom.spring_xy.timestamp = msecs; + + weston_spring_update(&output->zoom.spring_xy, msecs); + + x = output->zoom.from.x - ((output->zoom.from.x - output->zoom.to.x) * + output->zoom.spring_xy.current); + y = output->zoom.from.y - ((output->zoom.from.y - output->zoom.to.y) * + output->zoom.spring_xy.current); + + output->zoom.current.x = x; + output->zoom.current.y = y; + + if (weston_spring_done(&output->zoom.spring_xy)) { + output->zoom.spring_xy.current = output->zoom.spring_xy.target; + output->zoom.current.x = + (output->zoom.type == ZOOM_FOCUS_POINTER) ? + output->compositor->seat->pointer.x : + output->zoom.text_cursor.x; + output->zoom.current.y = + (output->zoom.type == ZOOM_FOCUS_POINTER) ? + output->compositor->seat->pointer.y : + output->zoom.text_cursor.y; + wl_list_remove(&animation->link); + wl_list_init(&animation->link); } output->dirty = 1; weston_output_damage(output); } -WL_EXPORT void -weston_output_update_zoom(struct weston_output *output, - wl_fixed_t x, - wl_fixed_t y, - uint32_t type) +static void +zoom_area_center_from_pointer(struct weston_output *output, + wl_fixed_t *x, wl_fixed_t *y) +{ + float level = output->zoom.spring_z.current; + wl_fixed_t offset_x = wl_fixed_from_int(output->x); + wl_fixed_t offset_y = wl_fixed_from_int(output->y); + wl_fixed_t w = wl_fixed_from_int(output->current->width); + wl_fixed_t h = wl_fixed_from_int(output->current->height); + + *x -= ((((*x - offset_x) / (float) w) - 0.5) * (w * (1.0 - level))); + *y -= ((((*y - offset_y) / (float) h) - 0.5) * (h * (1.0 - level))); +} + +static void +weston_output_update_zoom_transform(struct weston_output *output) { + uint32_t type = output->zoom.type; float global_x, global_y; + wl_fixed_t x = output->zoom.current.x; + wl_fixed_t y = output->zoom.current.y; float trans_min, trans_max; float ratio, level; level = output->zoom.spring_z.current; + ratio = 1 / level; if (!output->zoom.active || level > output->zoom.max_level) return; - output->zoom.type = type; - - output->zoom.fx = x; - output->zoom.fy = y; + if (type == ZOOM_FOCUS_POINTER && + wl_list_empty(&output->zoom.animation_xy.link)) + zoom_area_center_from_pointer(output, &x, &y); global_x = wl_fixed_to_double(x); global_y = wl_fixed_to_double(y); output->zoom.trans_x = - (((global_x - output->x) / output->current->width) * - (level * 2)) - level; + ((((global_x - output->x) / output->current->width) * + (level * 2)) - level) * ratio; output->zoom.trans_y = - (((global_y - output->y) / output->current->height) * - (level * 2)) - level; + ((((global_y - output->y) / output->current->height) * + (level * 2)) - level) * ratio; - if (type == ZOOM_FOCUS_TEXT) { - ratio = 1 / level; + trans_max = level * 2 - level; + trans_min = -trans_max; - output->zoom.trans_x *= ratio; - output->zoom.trans_y *= ratio; + /* Clip zoom area to output */ + if (output->zoom.trans_x > trans_max) + output->zoom.trans_x = trans_max; + else if (output->zoom.trans_x < trans_min) + output->zoom.trans_x = trans_min; + if (output->zoom.trans_y > trans_max) + output->zoom.trans_y = trans_max; + else if (output->zoom.trans_y < trans_min) + output->zoom.trans_y = trans_min; +} - trans_max = level * 2 - level; - trans_min = -trans_max; +static void +weston_zoom_transition(struct weston_output *output, uint32_t type, + wl_fixed_t x, wl_fixed_t y) +{ + if (output->zoom.type != type) { + /* Set from/to points and start animation */ + output->zoom.spring_xy.current = 0.0; + output->zoom.spring_xy.previous = 0.0; + output->zoom.spring_xy.target = 1.0; - if (output->zoom.trans_x > trans_max) - output->zoom.trans_x = trans_max; - else if (output->zoom.trans_x < trans_min) - output->zoom.trans_x = trans_min; - if (output->zoom.trans_y > trans_max) - output->zoom.trans_y = trans_max; - else if (output->zoom.trans_y < trans_min) - output->zoom.trans_y = trans_min; + if (wl_list_empty(&output->zoom.animation_xy.link)) { + output->zoom.animation_xy.frame_counter = 0; + wl_list_insert(output->animation_list.prev, + &output->zoom.animation_xy.link); + + output->zoom.from.x = (type == ZOOM_FOCUS_TEXT) ? + x : output->zoom.text_cursor.x; + output->zoom.from.y = (type == ZOOM_FOCUS_TEXT) ? + y : output->zoom.text_cursor.y; + } else { + output->zoom.from.x = output->zoom.current.x; + output->zoom.from.y = output->zoom.current.y; + } + + output->zoom.to.x = (type == ZOOM_FOCUS_POINTER) ? + x : output->zoom.text_cursor.x; + output->zoom.to.y = (type == ZOOM_FOCUS_POINTER) ? + y : output->zoom.text_cursor.y; + output->zoom.current.x = output->zoom.from.x; + output->zoom.current.y = output->zoom.from.y; + + output->zoom.type = type; + } + + if (output->zoom.level != output->zoom.spring_z.current) { + output->zoom.spring_z.target = output->zoom.level; + if (wl_list_empty(&output->zoom.animation_z.link)) { + output->zoom.animation_z.frame_counter = 0; + wl_list_insert(output->animation_list.prev, + &output->zoom.animation_z.link); + } + } + + output->dirty = 1; + weston_output_damage(output); +} + +WL_EXPORT void +weston_output_update_zoom(struct weston_output *output, uint32_t type) +{ + wl_fixed_t x = output->compositor->seat->pointer.x; + wl_fixed_t y = output->compositor->seat->pointer.y; + + zoom_area_center_from_pointer(output, &x, &y); + + if (type == ZOOM_FOCUS_POINTER) { + if (wl_list_empty(&output->zoom.animation_xy.link)) { + output->zoom.current.x = + output->compositor->seat->pointer.x; + output->zoom.current.y = + output->compositor->seat->pointer.y; + } else { + output->zoom.to.x = x; + output->zoom.to.y = y; + } + } + + if (type == ZOOM_FOCUS_TEXT) { + if (wl_list_empty(&output->zoom.animation_xy.link)) { + output->zoom.current.x = output->zoom.text_cursor.x; + output->zoom.current.y = output->zoom.text_cursor.y; + } else { + output->zoom.to.x = output->zoom.text_cursor.x; + output->zoom.to.y = output->zoom.text_cursor.y; + } } - weston_zoom_transition(output); + weston_zoom_transition(output, type, x, y); + weston_output_update_zoom_transform(output); } WL_EXPORT void @@ -2904,9 +3013,7 @@ weston_output_update_matrix(struct weston_output *output) magnification = 1 / (1 - output->zoom.spring_z.current); weston_matrix_init(&camera); weston_matrix_init(&modelview); - weston_output_update_zoom(output, output->zoom.fx, - output->zoom.fy, - output->zoom.type); + weston_output_update_zoom(output, output->zoom.type); weston_matrix_translate(&camera, output->zoom.trans_x, flip * output->zoom.trans_y, 0); weston_matrix_invert(&modelview, &camera); @@ -2951,10 +3058,15 @@ weston_output_init(struct weston_output *output, struct weston_compositor *c, output->zoom.level = 0.0; output->zoom.trans_x = 0.0; output->zoom.trans_y = 0.0; + output->zoom.type = ZOOM_FOCUS_POINTER; weston_spring_init(&output->zoom.spring_z, 250.0, 0.0, 0.0); output->zoom.spring_z.friction = 1000; output->zoom.animation_z.frame = weston_zoom_frame_z; wl_list_init(&output->zoom.animation_z.link); + weston_spring_init(&output->zoom.spring_xy, 250.0, 0.0, 0.0); + output->zoom.spring_xy.friction = 1000; + output->zoom.animation_xy.frame = weston_zoom_frame_xy; + wl_list_init(&output->zoom.animation_xy.link); output->flags = flags; weston_output_move(output, x, y); diff --git a/src/compositor.h b/src/compositor.h index 4147811..5a52e60 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -115,16 +115,25 @@ enum { ZOOM_FOCUS_TEXT }; +struct weston_fixed_point { + wl_fixed_t x, y; +}; + struct weston_output_zoom { int active; uint32_t type; float increment; float level; float max_level; - wl_fixed_t fx, fy; float trans_x, trans_y; struct weston_animation animation_z; struct weston_spring spring_z; + struct weston_animation animation_xy; + struct weston_spring spring_xy; + struct weston_fixed_point from; + struct weston_fixed_point to; + struct weston_fixed_point current; + struct weston_fixed_point text_cursor; }; /* bit compatible with drm definitions. */ @@ -633,9 +642,7 @@ void weston_text_cursor_position_notify(struct weston_surface *surface, wl_fixed_t x, wl_fixed_t y); void -weston_output_update_zoom(struct weston_output *output, - wl_fixed_t x, wl_fixed_t y, - uint32_t type); +weston_output_update_zoom(struct weston_output *output, uint32_t type); void weston_output_update_matrix(struct weston_output *output); void diff --git a/src/shell.c b/src/shell.c index bc2a987..9186bdb 100644 --- a/src/shell.c +++ b/src/shell.c @@ -2185,10 +2185,7 @@ do_zoom(struct wl_seat *seat, uint32_t time, uint32_t key, uint32_t axis, output->zoom.spring_z.target = output->zoom.level; - weston_output_update_zoom(output, - seat->pointer->x, - seat->pointer->y, - ZOOM_FOCUS_POINTER); + weston_output_update_zoom(output, output->zoom.type); } } } -- 2.7.4