From http://www.jwz.org/xscreensaver/xscreensaver-5.18.tar.gz
[xscreensaver] / hacks / glx / crackberg.c
index c4e925c73670fdcc389bce8954db781cad9f0004..2d8acbd47db7afad3a7e1281ec90d37d380d8949 100644 (file)
@@ -131,6 +131,10 @@ struct _cberg_state {
 
     double vs0r,vs0g,vs0b, vs1r, vs1g, vs1b,
            vf0r,vf0g,vf0b, vf1r, vf1g, vf1b;
+
+    Bool button_down_p;
+    int mouse_x, mouse_y;
+    struct timeval paused;
 };
 
 
@@ -1297,6 +1301,38 @@ ENTRYPOINT Bool crackberg_handle_event (ModeInfo *mi, XEvent *ev)
                 break;
             default:            return False;
         }
+    } else if (ev->xany.type == ButtonPress &&
+               ev->xbutton.button == Button1) {
+      cberg->button_down_p = True;
+      cberg->mouse_x = ev->xbutton.x;
+      cberg->mouse_y = ev->xbutton.y;
+      cberg->motion_state = MOTION_MANUAL;
+      cberg->paused.tv_sec = 0;
+    } else if (ev->xany.type == ButtonRelease &&
+               ev->xbutton.button == Button1) {
+      cberg->button_down_p = False;
+      cberg->motion_state = MOTION_AUTO;
+      /* After mouse-up, don't go back into auto-motion mode for a second, so
+         that repeated click-and-drag gestures don't fight with auto-motion. */
+      gettimeofday(&cberg->paused, NULL);
+    } else if (ev->xany.type == MotionNotify &&
+               cberg->button_down_p) {
+      int dx = ev->xmotion.x - cberg->mouse_x;
+      int dy = ev->xmotion.y - cberg->mouse_y;
+      cberg->mouse_x = ev->xmotion.x;
+      cberg->mouse_y = ev->xmotion.y;
+      cberg->motion_state = MOTION_MANUAL;
+
+      /* Take the larger dimension, since motion_state doesn't scale */
+      if (dx > 0 && dx > dy) dy = 0;
+      if (dx < 0 && dx < dy) dy = 0;
+      if (dy > 0 && dy > dx) dx = 0;
+      if (dy < 0 && dy < dx) dx = 0;
+
+      if      (dx > 0) cberg->motion_state |= MOTION_LEFT;
+      else if (dx < 0) cberg->motion_state |= MOTION_RIGHT;
+      else if (dy > 0) cberg->motion_state |= MOTION_FORW;
+      else if (dy < 0) cberg->motion_state |= MOTION_BACK;
     } else
         return False;
     return True;
@@ -1320,7 +1356,8 @@ ENTRYPOINT void draw_crackberg (ModeInfo *mi)
 
         cberg->elapsed = cur_frame - cberg->prev_frame;
 
-        if (cberg->motion_state == MOTION_AUTO) {
+        if (cberg->motion_state == MOTION_AUTO &&
+            cberg->paused.tv_sec < cur_frame_t.tv_sec) {
             cberg->x += cberg->dx * cberg->elapsed;
             cberg->y += cberg->dy * cberg->elapsed;
             /* cberg->z */