From http://www.jwz.org/xscreensaver/xscreensaver-5.22.tar.gz
[xscreensaver] / hacks / fluidballs.c
index f0954fc2a55022e842f72298a5782d5a1f750536..6bab228740d4c38266dfa2fec6fe9b2691c60fbd 100644 (file)
@@ -94,10 +94,11 @@ static void
 draw_fps_string (b_state *state)
 {  
   XFillRectangle (state->dpy, state->b, state->erase_gc,
-                 0, state->xgwa.height - state->font_height,
-                 state->xgwa.width, state->font_height);
+                 0, state->xgwa.height - state->font_height*3 - 20,
+                 state->xgwa.width, state->font_height*3 + 20);
   XDrawImageString (state->dpy, state->b, state->font_gc,
-                   0, state->xgwa.height - state->font_baseline,
+                   10, state->xgwa.height - state->font_height*2 -
+                    state->font_baseline - 10,
                    state->fps_str, strlen(state->fps_str));
 }
 
@@ -132,7 +133,8 @@ check_window_moved (b_state *state)
   state->xmin = wx;
   state->ymin = wy;
   state->xmax = state->xmin + state->xgwa.width;
-  state->ymax = state->ymin + state->xgwa.height - state->font_height;
+  state->ymax = state->ymin + state->xgwa.height - (state->font_height*3) -
+    (state->font_height ? 22 : 0);
 
   if (state->dbuf && (state->ba))
     {
@@ -154,8 +156,8 @@ check_window_moved (b_state *state)
        XClearWindow (state->dpy, state->window);
       else if (state->fps_p && oymax != state->ymax)
        XFillRectangle (state->dpy, state->b, state->erase_gc,
-                       0, state->xgwa.height - state->font_height,
-                       state->xgwa.width, state->font_height);
+                       0, state->xgwa.height - state->font_height*3,
+                       state->xgwa.width, state->font_height*3);
     }
 }
 
@@ -326,16 +328,21 @@ fluidballs_init (Display *dpy, Window window)
   state->shake_p = get_boolean_resource (dpy, "shake", "Shake");
   state->shake_threshold = get_float_resource (dpy, "shakeThreshold",
                                                "ShakeThreshold");
+  state->time_tick = 999999;
+
+# ifdef USE_IPHONE     /* Always obey real-world gravity */
+  state->shake_p = False;
+# endif
+
 
   state->fps_p = get_boolean_resource (dpy, "doFPS", "DoFPS");
   if (state->fps_p)
     {
       XFontStruct *font;
-      char *fontname = get_string_resource (dpy, "font", "Font");
-      const char *def_font = "fixed";
-      if (!fontname || !*fontname) fontname = (char *)def_font;
+      char *fontname = get_string_resource (dpy, "fpsFont", "Font");
+      if (!fontname) fontname = "-*-courier-bold-r-normal-*-180-*";
       font = XLoadQueryFont (dpy, fontname);
-      if (!font) font = XLoadQueryFont (dpy, def_font);
+      if (!font) font = XLoadQueryFont (dpy, "fixed");
       if (!font) exit(-1);
       gcv.font = font->fid;
       gcv.foreground = get_pixel_resource(state->dpy, state->xgwa.colormap,
@@ -442,6 +449,20 @@ check_wall_clock (b_state *state, float max_d)
 
       state->time_since_shake += (now.tv_sec - state->last_time.tv_sec);
 
+# ifdef USE_IPHONE     /* Always obey real-world gravity */
+      {
+        float a = fabs (fabs(state->accx) > fabs(state->accy)
+                        ? state->accx : state->accy);
+        switch ((int) current_device_rotation ()) {
+        case    0: case  360: state->accx =  0; state->accy =  a; break;
+        case  -90:            state->accx = -a; state->accy =  0; break;
+        case   90:            state->accx =  a; state->accy =  0; break;
+        case  180: case -180: state->accx =  0; state->accy = -a; break;
+        default: break;
+        }
+      }
+# endif /* USE_IPHONE */
+
       if (state->fps_p) 
        {
          float elapsed = ((now.tv_sec  + (now.tv_usec  / 1000000.0)) -
@@ -449,9 +470,8 @@ check_wall_clock (b_state *state, float max_d)
          float fps = state->frame_count / elapsed;
          float cps = state->collision_count / elapsed;
          
-         sprintf (state->fps_str, 
-                  " FPS: %.2f  Collisions: %.3f/frame  Max motion: %.3f",
-                  fps, cps/fps, max_d);
+         sprintf (state->fps_str, "Collisions: %.3f/frame  Max motion: %.3f",
+                  cps/fps, max_d);
          
          draw_fps_string(state);
        }
@@ -715,17 +735,29 @@ fluidballs_event (Display *dpy, Window window, void *closure, XEvent *event)
           return True;
         }
       else
-        for (i=1; i <= state->count; i++)
-          {
-            float d = ((state->px[i] - rx) * (state->px[i] - rx) +
-                       (state->py[i] - ry) * (state->py[i] - ry));
-            float r = state->r[i];
-            if (d < r*r)
+        {
+          /* When trying to pick up a ball, first look for a click directly
+             inside the ball; but if we don't find it, expand the radius
+             outward until we find something nearby.
+           */
+          float max = state->max_radius * 4;
+          float step = max / 10;
+          float r2;
+          for (r2 = step; r2 < max; r2 += step) {
+            for (i = 1; i <= state->count; i++)
               {
-                state->mouse_ball = i;
-                return True;
+                float d = ((state->px[i] - rx) * (state->px[i] - rx) +
+                           (state->py[i] - ry) * (state->py[i] - ry));
+                float r = state->r[i];
+                if (r2 > r) r = r2;
+                if (d < r*r)
+                  {
+                    state->mouse_ball = i;
+                    return True;
+                  }
               }
           }
+        }
       return True;
     }
   else if (event->xany.type == ButtonRelease)   /* drop the ball */
@@ -763,9 +795,8 @@ fluidballs_free (Display *dpy, Window window, void *closure)
 static const char *fluidballs_defaults [] = {
   ".background:                black",
   ".foreground:                yellow",
-  ".textColor:         yellow",
+  ".textColor:         white",
   "*mouseForeground:   white",
-  ".font:              -*-helvetica-*-r-*-*-*-180-*-*-p-*-*-*",
   "*delay:             10000",
   "*count:             300",
   "*size:              25",
@@ -774,7 +805,6 @@ static const char *fluidballs_defaults [] = {
   "*wind:              0.00",
   "*elasticity:                0.97",
   "*timeScale:         1.0",
-  "*doFPS:             False",
   "*shake:             True",
   "*shakeThreshold:    0.015",
   "*doubleBuffer:      True",
@@ -782,6 +812,9 @@ static const char *fluidballs_defaults [] = {
   "*useDBE:            True",
   "*useDBEClear:       True",
 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+#ifdef USE_IPHONE
+  "*ignoreRotation:    True",
+#endif
   0
 };
 
@@ -793,8 +826,6 @@ static XrmOptionDescRec fluidballs_options [] = {
   { "-gravity",                ".gravity",     XrmoptionSepArg, 0 },
   { "-wind",           ".wind",        XrmoptionSepArg, 0 },
   { "-elasticity",     ".elasticity",  XrmoptionSepArg, 0 },
-  { "-fps",            ".doFPS",       XrmoptionNoArg, "True" },
-  { "-no-fps",         ".doFPS",       XrmoptionNoArg, "False" },
   { "-shake",          ".shake",       XrmoptionNoArg, "True" },
   { "-no-shake",       ".shake",       XrmoptionNoArg, "False" },
   { "-random",         ".random",      XrmoptionNoArg, "True" },
@@ -806,4 +837,4 @@ static XrmOptionDescRec fluidballs_options [] = {
 };
 
 
-XSCREENSAVER_MODULE ("Fluidballs", fluidballs)
+XSCREENSAVER_MODULE ("FluidBalls", fluidballs)