shell: fix matrix invertible bug in rotation handler
authorRafal Mielniczuk <rafal.mielniczuk2@gmail.com>
Thu, 22 Mar 2012 21:22:04 +0000 (22:22 +0100)
committerKristian Høgsberg <krh@bitplanet.net>
Fri, 23 Mar 2012 02:34:11 +0000 (22:34 -0400)
While activating and deactivating rotation mechanism without moving
the pointer, rotation matrix from rotate_grab object is not being
initialised and damage shell surface rotation matrix in
rotate_grab_button handler, making it invertible.

This patch initialise rotate matrix in rotate_binding
and moves surface position check to rotate_grab_motion handler.

src/shell.c

index b26cbf4..a262b4f 100644 (file)
@@ -1241,9 +1241,10 @@ rotate_grab_motion(struct wl_pointer_grab *grab,
                container_of(grab, struct rotate_grab, grab);
        struct wl_input_device *device = grab->input_device;
        struct shell_surface *surface = rotate->surface;
-       GLfloat cx = 0.5f * surface->surface->geometry.width;
-       GLfloat cy = 0.5f * surface->surface->geometry.height;
-       GLfloat dx, dy;
+       struct weston_surface *base_surface = surface->surface;
+       GLfloat cx = 0.5f * base_surface->geometry.width;
+       GLfloat cy = 0.5f * base_surface->geometry.height;
+       GLfloat dx, dy, cposx, cposy, dposx, dposy;
        GLfloat r;
 
        dx = device->x - rotate->center.x;
@@ -1278,6 +1279,18 @@ rotate_grab_motion(struct wl_pointer_grab *grab,
                weston_matrix_init(&rotate->rotation);
        }
 
+       /* We need to adjust the position of the surface
+        * in case it was resized in a rotated state before */
+       cposx = base_surface->geometry.x + cx;
+       cposy = base_surface->geometry.y + cy;
+       dposx = rotate->center.x - cposx;
+       dposy = rotate->center.y - cposy;
+       if (dposx != 0.0f || dposy != 0.0f) {
+               weston_surface_set_position(base_surface,
+                               base_surface->geometry.x + dposx,
+                               base_surface->geometry.y + dposy);
+       }
+
        /* Repaint implies weston_surface_update_transform(), which
         * lazily applies the damage due to rotation update.
         */
@@ -1315,7 +1328,7 @@ rotate_binding(struct wl_input_device *device, uint32_t time,
                (struct weston_surface *) device->pointer_focus;
        struct shell_surface *surface;
        struct rotate_grab *rotate;
-       GLfloat dx, dy, cx, cy, cposx, cposy, dposx, dposy;
+       GLfloat dx, dy;
        GLfloat r;
 
        if (base_surface == NULL)
@@ -1361,25 +1374,17 @@ rotate_binding(struct wl_input_device *device, uint32_t time,
                inverse.d[1] = -inverse.d[4];
                inverse.d[5] = inverse.d[0];
                weston_matrix_multiply(&surface->rotation.rotation, &inverse);
+
+               weston_matrix_init(&rotate->rotation);
+               rotate->rotation.d[0] = dx / r;
+               rotate->rotation.d[4] = -dy / r;
+               rotate->rotation.d[1] = -rotate->rotation.d[4];
+               rotate->rotation.d[5] = rotate->rotation.d[0];
        } else {
                weston_matrix_init(&surface->rotation.rotation);
                weston_matrix_init(&rotate->rotation);
        }
 
-       /* We need to adjust the position of the surface
-        * in case it was resized in a rotated state before */
-       cx = 0.5f * surface->surface->geometry.width;
-       cy = 0.5f * surface->surface->geometry.height;
-       cposx = surface->surface->geometry.x + cx;
-       cposy = surface->surface->geometry.y + cy;
-       dposx = rotate->center.x - cposx;
-       dposy = rotate->center.y - cposy;
-       if (dposx != 0 || dposy != 0) {
-               weston_surface_set_position(base_surface,
-                               base_surface->geometry.x + dposx,
-                               base_surface->geometry.y + dposy);
-       }
-
        wl_input_device_set_pointer_focus(device, NULL, time, 0, 0);
 }