diff --git a/src/compositor.c b/src/compositor.c index 3330ffba4..cc77747a0 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -258,6 +258,65 @@ weston_surface_update_transform(struct weston_surface *surface) } } +WL_EXPORT void +weston_surface_to_global(struct weston_surface *surface, + int32_t sx, int32_t sy, int32_t *x, int32_t *y) +{ + weston_surface_update_transform(surface); + + if (surface->transform.enabled) { + struct weston_vector v = { { sx, sy, 0.0f, 1.0f } }; + + v.f[0] += surface->x; + v.f[1] += surface->y; + + weston_matrix_transform(&surface->transform.matrix, &v); + + if (fabsf(v.f[3]) < 1e-6) { + fprintf(stderr, "warning: numerical instability in " + "weston_surface_to_global(), divisor = %g\n", + v.f[3]); + *x = 0; + *y = 0; + return; + } + + *x = floorf(v.f[0] / v.f[3]); + *y = floorf(v.f[1] / v.f[3]); + } else { + *x = sx + surface->x; + *y = sy + surface->y; + } +} + +WL_EXPORT void +weston_surface_from_global(struct weston_surface *surface, + int32_t x, int32_t y, int32_t *sx, int32_t *sy) +{ + weston_surface_update_transform(surface); + + if (surface->transform.enabled) { + struct weston_vector v = { { x, y, 0.0f, 1.0f } }; + + weston_matrix_transform(&surface->transform.inverse, &v); + + if (fabsf(v.f[3]) < 1e-6) { + fprintf(stderr, "warning: numerical instability in " + "weston_surface_from_global(), divisor = %g\n", + v.f[3]); + *sx = 0; + *sy = 0; + return; + } + + *sx = floorf(v.f[0] / v.f[3] - surface->x); + *sy = floorf(v.f[1] / v.f[3] - surface->y); + } else { + *sx = x - surface->x; + *sy = y - surface->y; + } +} + WL_EXPORT void weston_surface_damage_rectangle(struct weston_surface *surface, int32_t x, int32_t y, @@ -337,23 +396,6 @@ weston_surface_configure(struct weston_surface *surface, pixman_region32_init(&surface->opaque); } -static void -weston_surface_transform(struct weston_surface *surface, - int32_t x, int32_t y, int32_t *sx, int32_t *sy) -{ - weston_surface_update_transform(surface); - - if (surface->transform.enabled) { - struct weston_vector v = { { x, y, 0.0f, 1.0f } }; - weston_matrix_transform(&surface->transform.inverse, &v); - x = floorf(v.f[0] / v.f[3]); - y = floorf(v.f[1] / v.f[3]); - } - - *sx = x - surface->x; - *sy = y - surface->y; -} - WL_EXPORT uint32_t weston_compositor_get_time(void) { @@ -385,8 +427,8 @@ weston_device_repick(struct wl_input_device *device, uint32_t time) focus = (struct weston_surface *) device->grab->focus; if (focus) - weston_surface_transform(focus, device->x, device->y, - &device->grab->x, &device->grab->y); + weston_surface_from_global(focus, device->x, device->y, + &device->grab->x, &device->grab->y); } WL_EXPORT void @@ -536,23 +578,27 @@ texture_region(struct weston_surface *es, pixman_region32_t *region) static void transform_vertex(struct weston_surface *surface, - GLfloat x, GLfloat y, GLfloat u, GLfloat v, GLfloat *r) + GLfloat sx, GLfloat sy, + GLfloat tex_x, GLfloat tex_y, GLfloat *r) { - struct weston_vector t; + /* surface->transform.enabled must always be 1 here. */ - t.f[0] = x; - t.f[1] = y; - t.f[2] = 0.0; - t.f[3] = 1.0; + struct weston_vector v = { { sx, sy, 0.0f, 1.0f } }; - weston_matrix_transform(&surface->transform.matrix, &t); + v.f[0] += surface->x; + v.f[1] += surface->y; - /* XXX: assumes last row of matrix is [0 0 * 1] */ + weston_matrix_transform(&surface->transform.matrix, &v); - r[ 0] = t.f[0]; - r[ 1] = t.f[1]; - r[ 2] = u; - r[ 3] = v; + if (fabsf(v.f[3]) < 1e-6) { + fprintf(stderr, "warning: numerical instability in " + "transform_vertex(), divisor = %g\n", v.f[3]); + } + + r[ 0] = v.f[0] / v.f[3]; + r[ 1] = v.f[1] / v.f[3]; + r[ 2] = tex_x; + r[ 3] = tex_y; } static int @@ -565,11 +611,10 @@ texture_transformed_surface(struct weston_surface *es) v = wl_array_add(&ec->vertices, 16 * sizeof *v); p = wl_array_add(&ec->indices, 6 * sizeof *p); - transform_vertex(es, es->x, es->y, 0.0, 0.0, &v[0]); - transform_vertex(es, es->x, es->y + es->height, 0.0, 1.0, &v[4]); - transform_vertex(es, es->x + es->width, es->y, 1.0, 0.0, &v[8]); - transform_vertex(es, es->x + es->width, es->y + es->height, - 1.0, 1.0, &v[12]); + transform_vertex(es, 0, 0, 0.0, 0.0, &v[0]); + transform_vertex(es, 0, es->height, 0.0, 1.0, &v[4]); + transform_vertex(es, es->width, 0, 1.0, 0.0, &v[8]); + transform_vertex(es, es->width, es->height, 1.0, 1.0, &v[12]); p[0] = 0; p[1] = 1; @@ -1096,7 +1141,7 @@ weston_compositor_pick_surface(struct weston_compositor *compositor, wl_list_for_each(surface, &compositor->surface_list, link) { if (surface->surface.resource.client == NULL) continue; - weston_surface_transform(surface, x, y, sx, sy); + weston_surface_from_global(surface, x, y, sx, sy); if (0 <= *sx && *sx < surface->width && 0 <= *sy && *sy < surface->height) return surface; @@ -1484,7 +1529,7 @@ notify_touch(struct wl_input_device *device, uint32_t time, int touch_id, touch_set_focus(wd, &es->surface, time); } else if (wd->touch_focus) { es = (struct weston_surface *) wd->touch_focus; - weston_surface_transform(es, x, y, &sx, &sy); + weston_surface_from_global(es, x, y, &sx, &sy); } if (wd->touch_focus_resource && wd->touch_focus) @@ -1498,7 +1543,7 @@ notify_touch(struct wl_input_device *device, uint32_t time, int touch_id, if (!es) break; - weston_surface_transform(es, x, y, &sx, &sy); + weston_surface_from_global(es, x, y, &sx, &sy); if (wd->touch_focus_resource) wl_resource_post_event(wd->touch_focus_resource, touch_type, time, diff --git a/src/compositor.h b/src/compositor.h index 7555e8526..76239213c 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -266,6 +266,14 @@ struct weston_surface { void weston_surface_update_transform(struct weston_surface *surface); +void +weston_surface_to_global(struct weston_surface *surface, + int32_t sx, int32_t sy, int32_t *x, int32_t *y); + +void +weston_surface_from_global(struct weston_surface *surface, + int32_t x, int32_t y, int32_t *sx, int32_t *sy); + void weston_device_repick(struct wl_input_device *device, uint32_t time); diff --git a/src/shell.c b/src/shell.c index d6e0205de..d2b23794f 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1037,7 +1037,6 @@ rotate_binding(struct wl_input_device *device, uint32_t time, (struct weston_surface *) device->pointer_focus; struct shell_surface *surface; struct rotate_grab *rotate; - struct weston_vector center = { { 0.0f, 0.0f, 0.0f, 1.0f } }; if (base_surface == NULL) return; @@ -1056,21 +1055,17 @@ rotate_binding(struct wl_input_device *device, uint32_t time, break; } - center.f[0] = 0.5f * surface->surface->width; - center.f[1] = 0.5f * surface->surface->height; - weston_surface_update_transform(surface->surface); - weston_matrix_transform(&surface->surface->transform.matrix, ¢er); - if (fabsf(center.f[3]) < 1e-6) - return; - rotate = malloc(sizeof *rotate); if (!rotate) return; rotate->grab.interface = &rotate_grab_interface; rotate->surface = surface; - rotate->center.x = center.f[0] / center.f[3]; - rotate->center.y = center.f[1] / center.f[3]; + + weston_surface_to_global(surface->surface, + surface->surface->width / 2, + surface->surface->height / 2, + &rotate->center.x, &rotate->center.y); wl_input_device_start_grab(device, &rotate->grab, time); wl_input_device_set_pointer_focus(device, NULL, time, 0, 0, 0, 0);