ftp://ftp.linux.ncsu.edu/mirror/ftp.redhat.com/pub/redhat/linux/enterprise/4/en/os...
[xscreensaver] / driver / demo-Gtk.c
index f0ca8e4aa96a784d6d0dd6bbf49acfffd4b8b9cc..298860a7e130a07dfb0cd4f4c0a9cd5435e8b27c 100644 (file)
@@ -1,5 +1,5 @@
 /* demo-Gtk.c --- implements the interactive demo-mode and options dialogs.
- * xscreensaver, Copyright (c) 1993-2002 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1993-2004 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
 # include <unistd.h>
 #endif
 
+# ifdef __GNUC__
+#  define STFU __extension__  /* ignore gcc -pendantic warnings in next sexp */
+# else
+#  define STFU /* */
+# endif
+
+
 #ifdef ENABLE_NLS
 # include <locale.h>
 #endif /* ENABLE_NLS */
 # define DEFAULT_ICONDIR GLADE_DIR
 #endif
 
+#ifndef HAVE_XML
+ /* Kludge: this is defined in demo-Gtk-conf.c when HAVE_XML.
+    It is unused otherwise, so in that case, stub it out. */
+ static const char *hack_configuration_path = 0;
+#endif
+
+
 
 #include "version.h"
 #include "prefs.h"
 #include "logo-50.xpm"
 #include "logo-180.xpm"
 
+#undef dgettext  /* else these are defined twice... */
+#undef dcgettext
+
 #include "demo-Gtk-widgets.h"
 #include "demo-Gtk-support.h"
 #include "demo-Gtk-conf.h"
@@ -121,6 +138,8 @@ enum {
 /* from exec.c */
 extern void exec_command (const char *shell, const char *command, int nice);
 
+static void hack_subproc_environment (Window preview_window_id, Bool debug_p);
+
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
 
@@ -197,7 +216,7 @@ static int maybe_reload_init_file (state *);
 static void await_xscreensaver (state *);
 
 static void schedule_preview (state *, const char *cmd);
-static void kill_preview_subproc (state *);
+static void kill_preview_subproc (state *, Bool reset_p);
 static void schedule_preview_check (state *);
 
 
@@ -293,12 +312,14 @@ ensure_selected_item_visible (GtkWidget *widget)
   
   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
   if (!gtk_tree_selection_get_selected (selection, &model, &iter))
-    return;
-
-  path = gtk_tree_model_get_path (model, &iter);
+       path = gtk_tree_path_new_first ();
+  else
+       path = gtk_tree_model_get_path (model, &iter);
   
-  gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (widget),
-                               path, NULL, FALSE, 0.0, 0.0);
+  gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), path, NULL, FALSE);
+
+  gtk_tree_path_free (path);
+
 #else /* !HAVE_GTK2 */
 
   GtkScrolledWindow *scroller = 0;
@@ -422,7 +443,8 @@ warning_dialog (GtkWidget *parent, const char *message,
   while (parent && !parent->window)
     parent = parent->parent;
 
-  if (!GTK_WIDGET (parent)->window) /* too early to pop up transient dialogs */
+  if (!parent ||
+      !GTK_WIDGET (parent)->window) /* too early to pop up transient dialogs */
     {
       fprintf (stderr, "%s: too early for dialog?\n", progname);
       return;
@@ -505,13 +527,13 @@ warning_dialog (GtkWidget *parent, const char *message,
   gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
   gtk_container_set_border_width (GTK_CONTAINER (dialog), 10);
   gtk_window_set_title (GTK_WINDOW (dialog), progclass);
-  GTK_WIDGET_SET_FLAGS (ok, GTK_CAN_DEFAULT);
+  STFU GTK_WIDGET_SET_FLAGS (ok, GTK_CAN_DEFAULT);
   gtk_widget_show (ok);
   gtk_widget_grab_focus (ok);
 
   if (cancel)
     {
-      GTK_WIDGET_SET_FLAGS (cancel, GTK_CAN_DEFAULT); 
+      STFU GTK_WIDGET_SET_FLAGS (cancel, GTK_CAN_DEFAULT); 
       gtk_widget_show (cancel);
     }
   gtk_widget_show (label);
@@ -555,6 +577,11 @@ run_cmd (state *s, Atom command, int arg)
 
   flush_dialog_changes_and_save (s);
   status = xscreensaver_command (GDK_DISPLAY(), command, arg, False, &err);
+
+  /* Kludge: ignore the spurious "window unexpectedly deleted" errors... */
+  if (status < 0 && err && strstr (err, "unexpectedly deleted"))
+    status = 0;
+
   if (status < 0)
     {
       char buf [255];
@@ -598,7 +625,7 @@ exit_menu_cb (GtkMenuItem *menuitem, gpointer user_data)
 {
   state *s = global_state_kludge;  /* I hate C so much... */
   flush_dialog_changes_and_save (s);
-  kill_preview_subproc (s);
+  kill_preview_subproc (s, False);
   gtk_main_quit ();
 }
 
@@ -631,9 +658,9 @@ about_menu_cb (GtkMenuItem *menuitem, gpointer user_data)
      look as good in the plain-old default Latin1 "C" locale.)
    */
 #ifdef HAVE_GTK2
-  sprintf(copy, ("Copyright \xC2\xA9 1991-2002 %s"), s);
+  sprintf(copy, ("Copyright \xC2\xA9 1991-2004 %s"), s);
 #else  /* !HAVE_GTK2 */
-  sprintf(copy, ("Copyright \251 1991-2002 %s"), s);
+  sprintf(copy, ("Copyright \251 1991-2004 %s"), s);
 #endif /* !HAVE_GTK2 */
 
   sprintf (msg, "%s\n\n%s", copy, desc);
@@ -760,7 +787,6 @@ doc_menu_cb (GtkMenuItem *menuitem, gpointer user_data)
   sprintf (help_command + strlen(help_command),
            p->load_url_command, p->help_url, p->help_url);
   strcat (help_command, " ) &");
-fprintf(stderr, "## %s\n", help_command);
   system (help_command);
   free (help_command);
 }
@@ -841,6 +867,12 @@ await_xscreensaver (state *s)
                "\n"));
 
       if (root_p)
+
+# ifdef __GNUC__
+        __extension__     /* don't warn about "string length is greater than
+                             the length ISO C89 compilers are required to
+                             support" in the following expression... */
+# endif
         strcat (buf,
          _("You are running as root.  This usually means that xscreensaver\n"
             "was unable to contact your X server because access control is\n"
@@ -979,7 +1011,7 @@ force_list_select_item (state *s, GtkWidget *list, int list_elt, Bool scroll_p)
   if (!was) gtk_widget_set_sensitive (parent, True);
 #ifdef HAVE_GTK2
   model = gtk_tree_view_get_model (GTK_TREE_VIEW (list));
-  g_assert (model);
+  STFU g_assert (model);
   gtk_tree_model_iter_nth_child (model, &iter, NULL, list_elt);
   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list));
   gtk_tree_selection_select_iter (selection, &iter);
@@ -1127,7 +1159,7 @@ hack_time_text (state *s, const char *line, Time *store, Bool sec_p)
       else
         {
           char c;
-          if (sscanf (line, "%u%c", &value, &c) != 1)
+          if (sscanf (line, "%d%c", &value, &c) != 1)
             value = -1;
           if (!sec_p)
             value *= 60;
@@ -1497,7 +1529,7 @@ flush_popup_changes_and_save (state *s)
   else if (!strcasecmp (visual, "greyscale"))          visual = "GrayScale";
   else if (!strcasecmp (visual, "pseudocolor"))        visual = "PseudoColor";
   else if (!strcasecmp (visual, "directcolor"))        visual = "DirectColor";
-  else if (1 == sscanf (visual, " %ld %c", &id, &c))   ;
+  else if (1 == sscanf (visual, " %lu %c", &id, &c))   ;
   else if (1 == sscanf (visual, " 0x%lx %c", &id, &c)) ;
   else
     {
@@ -1554,7 +1586,6 @@ mode_menu_item_cb (GtkWidget *widget, gpointer user_data)
   GList *menu_items = gtk_container_children (GTK_CONTAINER (widget->parent));
   int menu_index = 0;
   saver_mode new_mode;
-  int old_selected = p->selected_hack;
 
   while (menu_items)
     {
@@ -1568,17 +1599,12 @@ mode_menu_item_cb (GtkWidget *widget, gpointer user_data)
   new_mode = mode_menu_order[menu_index];
 
   /* Keep the same list element displayed as before; except if we're
-     switching *to* "one screensaver" mode from any other mode, scroll
-     to and select "the one".
+     switching *to* "one screensaver" mode from any other mode, set
+     "the one" to be that which is currently selected.
    */
-  list_elt = -1;
+  list_elt = selected_list_element (s);
   if (new_mode == ONE_HACK)
-    list_elt = (p->selected_hack >= 0
-                ? s->hack_number_to_list_elt[p->selected_hack]
-                : -1);
-
-  if (list_elt < 0)
-    list_elt = selected_list_element (s);
+    p->selected_hack = s->list_elt_to_hack_number[list_elt];
 
   {
     saver_mode old_mode = p->mode;
@@ -1589,9 +1615,6 @@ mode_menu_item_cb (GtkWidget *widget, gpointer user_data)
   }
 
   pref_changed_cb (widget, user_data);
-
-  if (old_selected != p->selected_hack)
-    abort();    /* dammit, not again... */
 }
 
 
@@ -1621,7 +1644,7 @@ list_activated_cb (GtkTreeView       *list,
   char *str;
   int list_elt;
 
-  g_return_if_fail (!gdk_pointer_is_grabbed ());
+  STFU g_return_if_fail (!gdk_pointer_is_grabbed ());
 
   str = gtk_tree_path_to_string (path);
   list_elt = strtol (str, NULL, 10);
@@ -1991,7 +2014,7 @@ server_current_hack (void)
   Atom type;
   int format;
   unsigned long nitems, bytesafter;
-  CARD32 *data = 0;
+  unsigned char *dataP = 0;
   Display *dpy = GDK_DISPLAY();
   int hack_number = -1;
 
@@ -1999,14 +2022,17 @@ server_current_hack (void)
                           XA_SCREENSAVER_STATUS,
                           0, 3, False, XA_INTEGER,
                           &type, &format, &nitems, &bytesafter,
-                          (unsigned char **) &data)
+                          &dataP)
       == Success
       && type == XA_INTEGER
       && nitems >= 3
-      && data)
-    hack_number = (int) data[2] - 1;
+      && dataP)
+    {
+      CARD32 *data = (CARD32 *) dataP;
+      hack_number = (int) data[2] - 1;
+    }
 
-  if (data) free (data);
+  if (dataP) XFree (dataP);
 
   return hack_number;
 }
@@ -2334,6 +2360,15 @@ populate_prefs_page (state *s)
 {
   saver_preferences *p = &s->prefs;
 
+  Bool can_lock_p = True;
+
+  /* Disable all the "lock" controls if locking support was not provided
+     at compile-time, or if running on MacOS. */
+# if defined(NO_LOCKING) || defined(__APPLE__)
+  can_lock_p = False;
+# endif
+
+
   /* The file supports timeouts of less than a minute, but the GUI does
      not, so throttle the values to be at least one minute (since "0" is
      a bad rounding choice...)
@@ -2341,7 +2376,7 @@ populate_prefs_page (state *s)
 # define THROTTLE(NAME) if (p->NAME != 0 && p->NAME < 60000) p->NAME = 60000
   THROTTLE (timeout);
   THROTTLE (cycle);
-  THROTTLE (passwd_timeout);
+  /* THROTTLE (passwd_timeout); */  /* GUI doesn't set this; leave it alone */
 # undef THROTTLE
 
 # define FMT_MINUTES(NAME,N) \
@@ -2433,8 +2468,9 @@ populate_prefs_page (state *s)
 
     /* Blanking and Locking
      */
-    SENSITIZE ("lock_spinbutton", p->lock_p);
-    SENSITIZE ("lock_mlabel",     p->lock_p);
+    SENSITIZE ("lock_button",     can_lock_p);
+    SENSITIZE ("lock_spinbutton", can_lock_p && p->lock_p);
+    SENSITIZE ("lock_mlabel",     can_lock_p && p->lock_p);
 
     /* DPMS
      */
@@ -2470,14 +2506,7 @@ populate_prefs_page (state *s)
 static void
 populate_popup_window (state *s)
 {
-  saver_preferences *p = &s->prefs;
-  GtkWidget *parent = name_to_widget (s, "settings_vbox");
   GtkLabel *doc = GTK_LABEL (name_to_widget (s, "doc"));
-  int list_elt = selected_list_element (s);
-  int hack_number = (list_elt >= 0 && list_elt < s->list_count
-                     ? s->list_elt_to_hack_number[list_elt]
-                     : -1);
-  screenhack *hack = (hack_number >= 0 ? p->screenhacks[hack_number] : 0);
   char *doc_string = 0;
 
   /* #### not in Gtk 1.2
@@ -2491,14 +2520,24 @@ populate_popup_window (state *s)
       s->cdata = 0;
     }
 
-  if (hack)
-    {
-      GtkWidget *cmd = GTK_WIDGET (name_to_widget (s, "cmd_text"));
-      const char *cmd_line = gtk_entry_get_text (GTK_ENTRY (cmd));
-      s->cdata = load_configurator (cmd_line, s->debug_p);
-      if (s->cdata && s->cdata->widget)
-        gtk_box_pack_start (GTK_BOX (parent), s->cdata->widget, TRUE, TRUE, 0);
-    }
+  {
+    saver_preferences *p = &s->prefs;
+    int list_elt = selected_list_element (s);
+    int hack_number = (list_elt >= 0 && list_elt < s->list_count
+                       ? s->list_elt_to_hack_number[list_elt]
+                       : -1);
+    screenhack *hack = (hack_number >= 0 ? p->screenhacks[hack_number] : 0);
+    if (hack)
+      {
+        GtkWidget *parent = name_to_widget (s, "settings_vbox");
+        GtkWidget *cmd = GTK_WIDGET (name_to_widget (s, "cmd_text"));
+        const char *cmd_line = gtk_entry_get_text (GTK_ENTRY (cmd));
+        s->cdata = load_configurator (cmd_line, s->debug_p);
+        if (s->cdata && s->cdata->widget)
+          gtk_box_pack_start (GTK_BOX (parent), s->cdata->widget,
+                              TRUE, TRUE, 0);
+      }
+  }
 
   doc_string = (s->cdata
                 ? s->cdata->description
@@ -2805,15 +2844,15 @@ populate_demo_window (state *s, int list_elt)
   if (!pretty_name)
     pretty_name = strdup (_("Preview"));
 
-  gtk_frame_set_label (frame1, pretty_name);
-  gtk_frame_set_label (frame2, pretty_name);
+  gtk_frame_set_label (frame1, _(pretty_name));
+  gtk_frame_set_label (frame2, _(pretty_name));
 
   gtk_entry_set_text (cmd, (hack ? hack->command : ""));
   gtk_entry_set_position (cmd, 0);
 
   {
     char title[255];
-    sprintf (title, "%s: %.100s Settings",
+    sprintf (title, _("%s: %.100s Settings"),
              progclass, (pretty_name ? pretty_name : "???"));
     gtk_window_set_title (GTK_WINDOW (s->popup_widget), title);
   }
@@ -3079,6 +3118,32 @@ clear_preview_window (state *s)
 }
 
 
+static void
+reset_preview_window (state *s)
+{
+  /* On some systems (most recently, MacOS X) OpenGL programs get confused
+     when you kill one and re-start another on the same window.  So maybe
+     it's best to just always destroy and recreate the preview window
+     when changing hacks, instead of always trying to reuse the same one?
+   */
+  GtkWidget *pr = name_to_widget (s, "preview");
+  if (GTK_WIDGET_REALIZED (pr))
+    {
+      Window oid = (pr->window ? GDK_WINDOW_XWINDOW (pr->window) : 0);
+      Window id;
+      gtk_widget_hide (pr);
+      gtk_widget_unrealize (pr);
+      gtk_widget_realize (pr);
+      gtk_widget_show (pr);
+      id = (pr->window ? GDK_WINDOW_XWINDOW (pr->window) : 0);
+      if (s->debug_p)
+        fprintf (stderr, "%s: window id 0x%X -> 0x%X\n", blurb(),
+                 (unsigned int) oid,
+                 (unsigned int) id);
+    }
+}
+
+
 static void
 fix_preview_visual (state *s)
 {
@@ -3238,7 +3303,14 @@ get_best_gl_visual (state *s)
             sprintf (buf, "%s: running %s", blurb(), av[0]);
             perror (buf);
           }
-        exit (1);                               /* exits fork */
+
+        /* Note that one must use _exit() instead of exit() in procs forked
+           off of Gtk programs -- Gtk installs an atexit handler that has a
+           copy of the X connection (which we've already closed, for safety.)
+           If one uses exit() instead of _exit(), then one sometimes gets a
+           spurious "Gdk-ERROR: Fatal IO error on X server" error message.
+        */
+        _exit (1);                              /* exits fork */
         break;
       }
     default:
@@ -3286,7 +3358,7 @@ get_best_gl_visual (state *s)
 
 
 static void
-kill_preview_subproc (state *s)
+kill_preview_subproc (state *s, Bool reset_p)
 {
   s->running_preview_error_p = False;
 
@@ -3332,6 +3404,12 @@ kill_preview_subproc (state *s)
     }
 
   reap_zombies (s);
+
+  if (reset_p)
+    {
+      reset_preview_window (s);
+      clear_preview_window (s);
+    }
 }
 
 
@@ -3348,13 +3426,17 @@ launch_preview_subproc (state *s)
   const char *cmd = s->desired_preview_cmd;
 
   GtkWidget *pr = name_to_widget (s, "preview");
-  GdkWindow *window = pr->window;
+  GdkWindow *window;
+
+  reset_preview_window (s);
+
+  window = pr->window;
 
   s->running_preview_error_p = False;
 
   if (s->preview_suppressed_p)
     {
-      kill_preview_subproc (s);
+      kill_preview_subproc (s, False);
       goto DONE;
     }
 
@@ -3374,7 +3456,7 @@ launch_preview_subproc (state *s)
                (unsigned int) id);
     }
 
-  kill_preview_subproc (s);
+  kill_preview_subproc (s, False);
   if (! new_cmd)
     {
       s->running_preview_error_p = True;
@@ -3397,6 +3479,8 @@ launch_preview_subproc (state *s)
       {
         close (ConnectionNumber (GDK_DISPLAY()));
 
+        hack_subproc_environment (id, s->debug_p);
+
         usleep (250000);  /* pause for 1/4th second before launching, to give
                              the previous program time to die and flush its X
                              buffer, so we don't get leftover turds on the
@@ -3404,8 +3488,15 @@ launch_preview_subproc (state *s)
 
         exec_command (p->shell, new_cmd, p->nice_inferior);
         /* Don't bother printing an error message when we are unable to
-           exec subprocesses; we handle that by polling the pid later. */
-        exit (1);  /* exits child fork */
+           exec subprocesses; we handle that by polling the pid later.
+
+           Note that one must use _exit() instead of exit() in procs forked
+           off of Gtk programs -- Gtk installs an atexit handler that has a
+           copy of the X connection (which we've already closed, for safety.)
+           If one uses exit() instead of _exit(), then one sometimes gets a
+           spurious "Gdk-ERROR: Fatal IO error on X server" error message.
+        */
+        _exit (1);  /* exits child fork */
         break;
 
       default:
@@ -3480,6 +3571,29 @@ hack_environment (state *s)
 }
 
 
+static void
+hack_subproc_environment (Window preview_window_id, Bool debug_p)
+{
+  /* Store a window ID in $XSCREENSAVER_WINDOW -- this isn't strictly
+     necessary yet, but it will make programs work if we had invoked
+     them with "-root" and not with "-window-id" -- which, of course,
+     doesn't happen.
+   */
+  char *nssw = (char *) malloc (40);
+  sprintf (nssw, "XSCREENSAVER_WINDOW=0x%X", (unsigned int) preview_window_id);
+
+  /* Allegedly, BSD 4.3 didn't have putenv(), but nobody runs such systems
+     any more, right?  It's not Posix, but everyone seems to have it. */
+  if (putenv (nssw))
+    abort ();
+
+  if (debug_p)
+    fprintf (stderr, "%s: %s\n", blurb(), nssw);
+
+  /* do not free(nssw) -- see above */
+}
+
+
 /* Called from a timer:
    Launches the currently-chosen subprocess, if it's not already running.
    If there's a different process running, kills it.
@@ -3489,7 +3603,7 @@ update_subproc_timer (gpointer data)
 {
   state *s = (state *) data;
   if (! s->desired_preview_cmd)
-    kill_preview_subproc (s);
+    kill_preview_subproc (s, True);
   else if (!s->running_preview_cmd ||
            !!strcmp (s->desired_preview_cmd, s->running_preview_cmd))
     launch_preview_subproc (s);
@@ -3612,7 +3726,7 @@ screen_blanked_p (void)
   Atom type;
   int format;
   unsigned long nitems, bytesafter;
-  CARD32 *data = 0;
+  unsigned char *dataP = 0;
   Display *dpy = GDK_DISPLAY();
   Bool blanked_p = False;
 
@@ -3620,14 +3734,17 @@ screen_blanked_p (void)
                           XA_SCREENSAVER_STATUS,
                           0, 3, False, XA_INTEGER,
                           &type, &format, &nitems, &bytesafter,
-                          (unsigned char **) &data)
+                          &dataP)
       == Success
       && type == XA_INTEGER
       && nitems >= 3
-      && data)
-    blanked_p = (data[0] == XA_BLANK || data[0] == XA_LOCK);
+      && dataP)
+    {
+      Atom *data = (Atom *) dataP;
+      blanked_p = (data[0] == XA_BLANK || data[0] == XA_LOCK);
+    }
 
-  if (data) free (data);
+  if (dataP) XFree (dataP);
 
   return blanked_p;
 }
@@ -3645,7 +3762,7 @@ check_blanked_timer (gpointer data)
     {
       if (s->debug_p)
         fprintf (stderr, "%s: screen is blanked: killing preview\n", blurb());
-      kill_preview_subproc (s);
+      kill_preview_subproc (s, True);
     }
 
   return True;  /* re-execute timer */
@@ -3826,7 +3943,7 @@ demo_ehandler (Display *dpy, XErrorEvent *error)
   state *s = global_state_kludge;  /* I hate C so much... */
   fprintf (stderr, "\nX error in %s:\n", blurb());
   XmuPrintDefaultErrorMessage (dpy, error, stderr);
-  kill_preview_subproc (s);
+  kill_preview_subproc (s, False);
   exit (-1);
   return 0;
 }
@@ -3863,6 +3980,12 @@ g_log_handler (const gchar *log_domain, GLogLevelFlags log_level,
 }
 
 
+#ifdef __GNUC__
+ __extension__     /* shut up about "string length is greater than the length
+                      ISO C89 compilers are required to support" when including
+                      the .ad file... */
+#endif
+
 static char *defaults[] = {
 #include "XScreenSaver_ad.h"
  0
@@ -3979,6 +4102,7 @@ main (int argc, char **argv)
   Widget toplevel_shell;
   char *real_progname = argv[0];
   char *window_title;
+  char *geom = 0;
   Bool crapplet_p = False;
   char *str;
 
@@ -4073,6 +4197,21 @@ main (int argc, char **argv)
           argc--;
           i--;
         }
+      else if (argv[i] &&
+               argc > i+1 &&
+               *argv[i+1] &&
+               (!strcmp(argv[i], "-geometry") ||
+                !strcmp(argv[i], "-geom") ||
+                !strcmp(argv[i], "-geo") ||
+                !strcmp(argv[i], "-g")))
+        {
+          int j;
+          geom = argv[i+1];
+          for (j = i; j < argc; j++)  /* remove them from the list */
+            argv[j] = argv[j+2];
+          argc -= 2;
+          i -= 2;
+        }
       else if (argv[i] &&
                argc > i+1 &&
                *argv[i+1] &&
@@ -4230,7 +4369,8 @@ main (int argc, char **argv)
         ;
       else
        {
-         fprintf (stderr, _("%s: unknown option: %s\n"), real_progname, argv[i]);
+         fprintf (stderr, _("%s: unknown option: %s\n"), real_progname,
+                   argv[i]);
           fprintf (stderr, "%s: %s\n", real_progname, usage);
           exit (1);
        }
@@ -4406,7 +4546,7 @@ main (int argc, char **argv)
       gtk_widget_ref (outer_vbox);
       gtk_container_remove (GTK_CONTAINER (s->toplevel_widget),
                             outer_vbox);
-      GTK_OBJECT_SET_FLAGS (outer_vbox, GTK_FLOATING);
+      STFU GTK_OBJECT_SET_FLAGS (outer_vbox, GTK_FLOATING);
       gtk_container_add (GTK_CONTAINER (capplet), outer_vbox);
 
       /* Find the window above us, and set the title and close handler. */
@@ -4441,6 +4581,11 @@ main (int argc, char **argv)
   free (window_title);
   window_title = 0;
 
+#ifdef HAVE_GTK2
+  /* After picking the default size, allow -geometry to override it. */
+  if (geom)
+    gtk_window_parse_geometry (GTK_WINDOW (s->toplevel_widget), geom);
+#endif
 
   gtk_widget_show (s->toplevel_widget);
   init_icon (GTK_WIDGET (s->toplevel_widget)->window);  /* after `show' */
@@ -4500,7 +4645,7 @@ main (int argc, char **argv)
 # endif /* HAVE_CRAPPLET */
     gtk_main ();
 
-  kill_preview_subproc (s);
+  kill_preview_subproc (s, False);
   exit (0);
 }