From http://www.jwz.org/xscreensaver/xscreensaver-5.35.tar.gz
[xscreensaver] / driver / demo-Gtk.c
index a62d0b77b79c86729757353cf4b617329e94b867..f5c483965a3a8ead6947abc473d9ea4a823f1c29 100644 (file)
@@ -1,5 +1,5 @@
 /* demo-Gtk.c --- implements the interactive demo-mode and options dialogs.
- * xscreensaver, Copyright (c) 1993-2008 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1993-2016 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 "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"
 
 #include <stdio.h>
@@ -142,6 +137,41 @@ enum {
 };
 #endif /* HAVE_GTK2 */
 
+/* Deal with deprecation of direct access to struct fields on the way to GTK3
+   See http://live.gnome.org/GnomeGoals/UseGseal
+ */
+#if GTK_CHECK_VERSION(2,14,0)
+# define GET_PARENT(w)          gtk_widget_get_parent (w)
+# define GET_WINDOW(w)          gtk_widget_get_window (w)
+# define GET_ACTION_AREA(d)     gtk_dialog_get_action_area (d)
+# define GET_CONTENT_AREA(d)    gtk_dialog_get_content_area (d)
+# define GET_ADJ_VALUE(a)       gtk_adjustment_get_value (a)
+# define SET_ADJ_VALUE(a,v)     gtk_adjustment_set_value (a, v)
+# define SET_ADJ_UPPER(a,v)     gtk_adjustment_set_upper (a, v)
+#else
+# define GET_PARENT(w)          ((w)->parent)
+# define GET_WINDOW(w)          ((w)->window)
+# define GET_ACTION_AREA(d)     ((d)->action_area)
+# define GET_CONTENT_AREA(d)    ((d)->vbox)
+# define GET_ADJ_VALUE(a)       ((a)->value)
+# define SET_ADJ_VALUE(a,v)     (a)->value = v
+# define SET_ADJ_UPPER(a,v)     (a)->upper = v
+#endif
+
+#if GTK_CHECK_VERSION(2,18,0)
+# define SET_CAN_DEFAULT(w)     gtk_widget_set_can_default ((w), TRUE)
+# define GET_SENSITIVE(w)       gtk_widget_get_sensitive (w)
+#else
+# define SET_CAN_DEFAULT(w)     GTK_WIDGET_SET_FLAGS ((w), GTK_CAN_DEFAULT)
+# define GET_SENSITIVE(w)       GTK_WIDGET_IS_SENSITIVE (w)
+#endif
+
+#if GTK_CHECK_VERSION(2,20,0)
+# define GET_REALIZED(w)        gtk_widget_get_realized (w)
+#else
+# define GET_REALIZED(w)        GTK_WIDGET_REALIZED (w)
+#endif
+
 /* from exec.c */
 extern void exec_command (const char *shell, const char *command, int nice);
 extern int on_path_p (const char *program);
@@ -427,9 +457,9 @@ ensure_selected_item_visible (GtkWidget *widget)
 
   adj = gtk_scrolled_window_get_vadjustment (scroller);
 
-  gdk_window_get_geometry (GTK_WIDGET(vp)->window,
+  gdk_window_get_geometry (GET_WINDOW (GTK_WIDGET (vp)),
                            &ignore, &ignore, &ignore, &parent_h, &ignore);
-  gdk_window_get_geometry (GTK_WIDGET(selected)->window,
+  gdk_window_get_geometry (GET_WINDOW (GTK_WIDGET (selected)),
                            &ignore, &child_y, &ignore, &child_h, &ignore);
   children_h = nkids * child_h;
 
@@ -472,8 +502,8 @@ static void
 warning_dialog_dismiss_cb (GtkWidget *widget, gpointer user_data)
 {
   GtkWidget *shell = GTK_WIDGET (user_data);
-  while (shell->parent)
-    shell = shell->parent;
+  while (GET_PARENT (shell))
+    shell = GET_PARENT (shell);
   gtk_widget_destroy (GTK_WIDGET (shell));
 }
 
@@ -500,7 +530,7 @@ static void warning_dialog_killk_cb (GtkWidget *widget, gpointer user_data)
 
 typedef enum { D_NONE, D_LAUNCH, D_GNOME, D_KDE } dialog_button;
 
-static void
+static Bool
 warning_dialog (GtkWidget *parent, const char *message,
                 dialog_button button_type, int center)
 {
@@ -513,14 +543,15 @@ warning_dialog (GtkWidget *parent, const char *message,
   GtkWidget *cancel = 0;
   int i = 0;
 
-  while (parent && !parent->window)
-    parent = parent->parent;
+  while (parent && !GET_WINDOW (parent))
+    parent = GET_PARENT (parent);
 
   if (!parent ||
-      !GTK_WIDGET (parent)->window) /* too early to pop up transient dialogs */
+      !GET_WINDOW (parent)) /* too early to pop up transient dialogs */
     {
       fprintf (stderr, "%s: too early for dialog?\n", progname);
-      return;
+      free(msg);
+      return False;
     }
 
   head = msg;
@@ -552,7 +583,7 @@ warning_dialog (GtkWidget *parent, const char *message,
 #endif /* !HAVE_GTK2 */
         if (center <= 0)
           gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
-        gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
+        gtk_box_pack_start (GTK_BOX (GET_CONTENT_AREA (GTK_DIALOG (dialog))),
                             label, TRUE, TRUE, 0);
         gtk_widget_show (label);
       }
@@ -566,12 +597,12 @@ warning_dialog (GtkWidget *parent, const char *message,
     }
 
   label = gtk_label_new ("");
-  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
+  gtk_box_pack_start (GTK_BOX (GET_CONTENT_AREA (GTK_DIALOG (dialog))),
                       label, TRUE, TRUE, 0);
   gtk_widget_show (label);
 
   label = gtk_hbutton_box_new ();
-  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
+  gtk_box_pack_start (GTK_BOX (GET_ACTION_AREA (GTK_DIALOG (dialog))),
                       label, TRUE, TRUE, 0);
 
 #ifdef HAVE_GTK2
@@ -600,13 +631,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);
+  SET_CAN_DEFAULT (ok);
   gtk_widget_show (ok);
   gtk_widget_grab_focus (ok);
 
   if (cancel)
     {
-      GTK_WIDGET_SET_FLAGS (cancel, GTK_CAN_DEFAULT); 
+      SET_CAN_DEFAULT (cancel);
       gtk_widget_show (cancel);
     }
   gtk_widget_show (label);
@@ -634,8 +665,8 @@ warning_dialog (GtkWidget *parent, const char *message,
                                  (gpointer) dialog);
     }
 
-  gdk_window_set_transient_for (GTK_WIDGET (dialog)->window,
-                                GTK_WIDGET (parent)->window);
+  gdk_window_set_transient_for (GET_WINDOW (GTK_WIDGET (dialog)),
+                                GET_WINDOW (GTK_WIDGET (parent)));
 
 #ifdef HAVE_GTK2
   gtk_window_present (GTK_WINDOW (dialog));
@@ -645,6 +676,7 @@ warning_dialog (GtkWidget *parent, const char *message,
 #endif /* !HAVE_GTK2 */
 
   free (msg);
+  return True;
 }
 
 
@@ -766,23 +798,30 @@ about_menu_cb (GtkMenuItem *menuitem, gpointer user_data)
 {
   char msg [2048];
   char *vers = strdup (screensaver_id + 4);
-  char *s;
+  char *s, *s2;
   char copy[1024];
-  char *desc = _("For updates, check http://www.jwz.org/xscreensaver/");
+  char year[5];
+  char *desc = _("For updates, check https://www.jwz.org/xscreensaver/");
 
   s = strchr (vers, ',');
   *s = 0;
   s += 2;
 
+  s2 = vers;
+  s2 = strrchr (vers, '-');
+  s2++;
+  strncpy (year, s2, 4);
+  year[4] = 0;
+
   /* Ole Laursen <olau@hardworking.dk> says "don't use _() here because
      non-ASCII characters aren't allowed in localizable string keys."
      (I don't want to just use (c) instead of © because that doesn't
      look as good in the plain-old default Latin1 "C" locale.)
    */
 #ifdef HAVE_GTK2
-  sprintf(copy, ("Copyright \xC2\xA9 1991-2008 %s"), s);
+  sprintf(copy, ("Copyright \xC2\xA9 1991-%s %s"), year, s);
 #else  /* !HAVE_GTK2 */
-  sprintf(copy, ("Copyright \251 1991-2008 %s"), s);
+  sprintf(copy, ("Copyright \251 1991-%s %s"), year, s);
 #endif /* !HAVE_GTK2 */
 
   sprintf (msg, "%s\n\n%s", copy, desc);
@@ -809,11 +848,11 @@ about_menu_cb (GtkMenuItem *menuitem, gpointer user_data)
     GtkWidget *dialog = gtk_dialog_new ();
     GtkWidget *hbox, *icon, *vbox, *label1, *label2, *hb, *ok;
     GtkWidget *parent = GTK_WIDGET (menuitem);
-    while (parent->parent)
-      parent = parent->parent;
+    while (GET_PARENT (parent))
+      parent = GET_PARENT (parent);
 
     hbox = gtk_hbox_new (FALSE, 20);
-    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
+    gtk_box_pack_start (GTK_BOX (GET_CONTENT_AREA (GTK_DIALOG (dialog))),
                         hbox, TRUE, TRUE, 0);
 
     colormap = gtk_widget_get_colormap (parent);
@@ -854,7 +893,7 @@ about_menu_cb (GtkMenuItem *menuitem, gpointer user_data)
 
     hb = gtk_hbutton_box_new ();
 
-    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
+    gtk_box_pack_start (GTK_BOX (GET_ACTION_AREA (GTK_DIALOG (dialog))),
                         hb, TRUE, TRUE, 0);
 
 #ifdef HAVE_GTK2
@@ -880,10 +919,10 @@ about_menu_cb (GtkMenuItem *menuitem, gpointer user_data)
     gtk_signal_connect_object (GTK_OBJECT (ok), "clicked",
                                GTK_SIGNAL_FUNC (warning_dialog_dismiss_cb),
                                (gpointer) dialog);
-    gdk_window_set_transient_for (GTK_WIDGET (dialog)->window,
-                                  GTK_WIDGET (parent)->window);
-    gdk_window_show (GTK_WIDGET (dialog)->window);
-    gdk_window_raise (GTK_WIDGET (dialog)->window);
+    gdk_window_set_transient_for (GET_WINDOW (GTK_WIDGET (dialog)),
+                                  GET_WINDOW (GTK_WIDGET (parent)));
+    gdk_window_show (GET_WINDOW (GTK_WIDGET (dialog)));
+    gdk_window_raise (GET_WINDOW (GTK_WIDGET (dialog)));
   }
 }
 
@@ -1141,7 +1180,7 @@ static void
 force_list_select_item (state *s, GtkWidget *list, int list_elt, Bool scroll_p)
 {
   GtkWidget *parent = name_to_widget (s, "scroller");
-  Bool was = GTK_WIDGET_IS_SENSITIVE (parent);
+  gboolean was = GET_SENSITIVE (parent);
 #ifdef HAVE_GTK2
   GtkTreeIter iter;
   GtkTreeModel *model;
@@ -1376,19 +1415,32 @@ normalize_directory (const char *path)
             {
               s0--;
               s += 3;
-              strcpy (s0, s);
+              /* strcpy (s0, s); */
+              memmove(s0, s, strlen(s) + 1);
               s = s0-1;
             }
         }
-      else if (*s == '/' && !strncmp (s, "/./", 3))    /* delete "/./" */
-        strcpy (s, s+2), s--;
+      else if (*s == '/' && !strncmp (s, "/./", 3)) {  /* delete "/./" */
+        /* strcpy (s, s+2), s--; */
+        memmove(s, s+2, strlen(s+2) + 1);
+        s--;
+       }
       else if (*s == '/' && !strncmp (s, "/.\000", 3)) /* delete "/.$" */
         *s = 0, s--;
     }
 
-  for (s = p2; s && *s; s++)           /* normalize consecutive slashes */
-    while (s[0] == '/' && s[1] == '/')
-      strcpy (s, s+1);
+  /*
+    Normalize consecutive slashes.
+    Ignore doubled slashes after ":" to avoid mangling URLs.
+  */
+
+  for (s = p2; s && *s; s++){
+    if (*s == ':') continue;
+    if (!s[1] || !s[2]) continue;
+    while (s[1] == '/' && s[2] == '/')
+      /* strcpy (s+1, s+2); */
+      memmove (s+1, s+2, strlen(s+2) + 1);
+  }
 
   /* and strip trailing whitespace for good measure. */
   L = strlen(p2);
@@ -1450,6 +1502,7 @@ flush_dialog_changes_and_save (state *s)
   GList *kids = gtk_container_children (GTK_CONTAINER (list_widget));
   int i;
 #endif /* !HAVE_GTK2 */
+  static Bool already_warned_about_missing_image_directory = False; /* very long name... */
 
   Bool changed = False;
   GtkWidget *w;
@@ -1504,14 +1557,15 @@ flush_dialog_changes_and_save (state *s)
 
 # define TEXT(FIELD,NAME) \
     w = name_to_widget (s, (NAME)); \
-    (FIELD) = (char *) gtk_entry_get_text (GTK_ENTRY (w))
+    (FIELD) = (char *) g_strdup(gtk_entry_get_text (GTK_ENTRY (w)))
 
   MINUTES  (&p2->timeout,         "timeout_spinbutton");
   MINUTES  (&p2->cycle,           "cycle_spinbutton");
   CHECKBOX (p2->lock_p,           "lock_button");
   MINUTES  (&p2->lock_timeout,    "lock_spinbutton");
 
-  CHECKBOX (p2->dpms_enabled_p,  "dpms_button");
+  CHECKBOX (p2->dpms_enabled_p,   "dpms_button");
+  CHECKBOX (p2->dpms_quickoff_p,  "dpms_quickoff_button");
   MINUTES  (&p2->dpms_standby,    "dpms_standby_spinbutton");
   MINUTES  (&p2->dpms_suspend,    "dpms_suspend_spinbutton");
   MINUTES  (&p2->dpms_off,        "dpms_off_spinbutton");
@@ -1552,16 +1606,28 @@ flush_dialog_changes_and_save (state *s)
 # undef PATHNAME
 # undef TEXT
 
-  /* Warn if the image directory doesn't exist.
+  /* Warn if the image directory doesn't exist, when:
+     - not being warned before
+     - image directory is changed and the directory doesn't exist
+     - image directory does not begin with http://
    */
   if (p2->image_directory &&
       *p2->image_directory &&
-      !directory_p (p2->image_directory))
+      !directory_p (p2->image_directory) &&
+       strncmp(p2->image_directory, "http://", 6) &&
+        ( !already_warned_about_missing_image_directory ||
+          ( p->image_directory &&
+            *p->image_directory &&
+            strcmp(p->image_directory, p2->image_directory)
+          )
+        )
+      )
     {
       char b[255];
-      sprintf (b, "Error:\n\n" "Directory does not exist: \"%s\"\n",
+      sprintf (b, "Warning:\n\n" "Directory does not exist: \"%s\"\n",
                p2->image_directory);
-      warning_dialog (s->toplevel_widget, b, D_NONE, 100);
+      if (warning_dialog (s->toplevel_widget, b, D_NONE, 100))
+        already_warned_about_missing_image_directory = True;
     }
 
 
@@ -1600,10 +1666,11 @@ flush_dialog_changes_and_save (state *s)
   COPY(lock_p,         "lock_p");
   COPY(lock_timeout,   "lock_timeout");
 
-  COPY(dpms_enabled_p, "dpms_enabled_p");
-  COPY(dpms_standby,   "dpms_standby");
-  COPY(dpms_suspend,   "dpms_suspend");
-  COPY(dpms_off,       "dpms_off");
+  COPY(dpms_enabled_p,  "dpms_enabled_p");
+  COPY(dpms_quickoff_p, "dpms_quickoff_enabled_p");
+  COPY(dpms_standby,    "dpms_standby");
+  COPY(dpms_suspend,    "dpms_suspend");
+  COPY(dpms_off,        "dpms_off");
 
 #if 0
   COPY(verbose_p,        "verbose_p");
@@ -1651,7 +1718,7 @@ flush_dialog_changes_and_save (state *s)
     {
       Display *dpy = GDK_DISPLAY();
       Bool enabled_p = (p->dpms_enabled_p && p->mode != DONT_BLANK);
-      sync_server_dpms_settings (dpy, enabled_p,
+      sync_server_dpms_settings (dpy, enabled_p, p->dpms_quickoff_p,
                                  p->dpms_standby / 1000,
                                  p->dpms_suspend / 1000,
                                  p->dpms_off / 1000,
@@ -1771,7 +1838,8 @@ mode_menu_item_cb (GtkWidget *widget, gpointer user_data)
   GtkWidget *list = name_to_widget (s, "list");
   int list_elt;
 
-  GList *menu_items = gtk_container_children (GTK_CONTAINER (widget->parent));
+  GList *menu_items =
+    gtk_container_children (GTK_CONTAINER (GET_PARENT (widget)));
   int menu_index = 0;
   saver_mode new_mode;
 
@@ -1984,7 +2052,7 @@ list_checkbox_cb (
 
   /* remember previous scroll position of the top of the list */
   adj = gtk_scrolled_window_get_vadjustment (scroller);
-  scroll_top = adj->value;
+  scroll_top = GET_ADJ_VALUE (adj);
 
   flush_dialog_changes_and_save (s);
   force_list_select_item (s, GTK_WIDGET (list), list_elt, False);
@@ -2016,7 +2084,8 @@ store_image_directory (GtkWidget *button, gpointer user_data)
   if (p->image_directory && !strcmp(p->image_directory, path))
     return;  /* no change */
 
-  if (!directory_p (path))
+  /* No warning for URLs. */
+  if ((!directory_p (path)) && strncmp(path, "http://", 6))
     {
       char b[255];
       sprintf (b, _("Error:\n\n" "Directory does not exist: \"%s\"\n"), path);
@@ -2509,7 +2578,7 @@ populate_hack_list (state *s)
              (but don't actually make it be insensitive, since we still
              want to be able to click on it.)
            */
-          GtkStyle *style = GTK_WIDGET (list)->style;
+          GtkStyle *style = gtk_widget_get_style (GTK_WIDGET (list));
           GdkColor *fg = &style->fg[GTK_STATE_INSENSITIVE];
        /* GdkColor *bg = &style->bg[GTK_STATE_INSENSITIVE]; */
           char *buf = (char *) malloc (strlen (pretty_name) + 100);
@@ -2747,6 +2816,7 @@ populate_prefs_page (state *s)
   TOGGLE_ACTIVE ("splash_button",     p->splash_p);
 #endif
   TOGGLE_ACTIVE ("dpms_button",       p->dpms_enabled_p);
+  TOGGLE_ACTIVE ("dpms_quickoff_button", p->dpms_quickoff_p);
   TOGGLE_ACTIVE ("grab_desk_button",  p->grab_desktop_p);
   TOGGLE_ACTIVE ("grab_video_button", p->grab_video_p);
   TOGGLE_ACTIVE ("grab_image_button", p->random_image_p);
@@ -2850,8 +2920,11 @@ populate_prefs_page (state *s)
 
     /* DPMS
      */
+dpms_supported=1;
     SENSITIZE ("dpms_frame",              dpms_supported);
     SENSITIZE ("dpms_button",             dpms_supported);
+    SENSITIZE ("dpms_quickoff_button",    dpms_supported);
+
     SENSITIZE ("dpms_standby_label",      dpms_supported && p->dpms_enabled_p);
     SENSITIZE ("dpms_standby_mlabel",     dpms_supported && p->dpms_enabled_p);
     SENSITIZE ("dpms_standby_spinbutton", dpms_supported && p->dpms_enabled_p);
@@ -2977,7 +3050,7 @@ force_dialog_repaint (state *s)
 #if 1
   /* Tell GDK to invalidate and repaint the whole window.
    */
-  GdkWindow *w = s->toplevel_widget->window;
+  GdkWindow *w = GET_WINDOW (s->toplevel_widget);
   GdkRegion *region = gdk_region_new ();
   GdkRectangle rect;
   rect.x = rect.y = 0;
@@ -3065,7 +3138,7 @@ fix_text_entry_sizes (state *s)
 #ifdef HAVE_GTK2
     PangoFontMetrics *pain =
       pango_context_get_metrics (gtk_widget_get_pango_context (w),
-                                 w->style->font_desc,
+                                 gtk_widget_get_style (w)->font_desc,
                                  gtk_get_default_language ());
     height = PANGO_PIXELS (pango_font_metrics_get_ascent (pain) +
                            pango_font_metrics_get_descent (pain));
@@ -3502,16 +3575,18 @@ clear_preview_window (state *s)
 {
   GtkWidget *p;
   GdkWindow *window;
+  GtkStyle  *style;
 
   if (!s->toplevel_widget) return;  /* very early */
   p = name_to_widget (s, "preview");
-  window = p->window;
+  window = GET_WINDOW (p);
 
   if (!window) return;
 
   /* Flush the widget background down into the window, in case a subproc
      has changed it. */
-  gdk_window_set_background (window, &p->style->bg[GTK_STATE_NORMAL]);
+  style = gtk_widget_get_style (p);
+  gdk_window_set_background (window, &style->bg[GTK_STATE_NORMAL]);
   gdk_window_clear (window);
 
   {
@@ -3572,15 +3647,16 @@ reset_preview_window (state *s)
      when changing hacks, instead of always trying to reuse the same one?
    */
   GtkWidget *pr = name_to_widget (s, "preview");
-  if (GTK_WIDGET_REALIZED (pr))
+  if (GET_REALIZED (pr))
     {
-      Window oid = (pr->window ? GDK_WINDOW_XWINDOW (pr->window) : 0);
+      GdkWindow *window = GET_WINDOW (pr);
+      Window oid = (window ? GDK_WINDOW_XWINDOW (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);
+      id = (window ? GDK_WINDOW_XWINDOW (window) : 0);
       if (s->debug_p)
         fprintf (stderr, "%s: window id 0x%X -> 0x%X\n", blurb(),
                  (unsigned int) oid,
@@ -3605,7 +3681,7 @@ fix_preview_visual (state *s)
              (visual == dvisual ? "default" : "non-default"),
              (xvisual ? (unsigned long) xvisual->visualid : 0L));
 
-  if (!GTK_WIDGET_REALIZED (widget) ||
+  if (!GET_REALIZED (widget) ||
       gtk_widget_get_visual (widget) != visual)
     {
       gtk_widget_unrealize (widget);
@@ -3616,8 +3692,8 @@ fix_preview_visual (state *s)
 
   /* Set the Widget colors to be white-on-black. */
   {
-    GdkWindow *window = widget->window;
-    GtkStyle *style = gtk_style_copy (widget->style);
+    GdkWindow *window = GET_WINDOW (widget);
+    GtkStyle *style = gtk_style_copy (gtk_widget_get_style (widget));
     GdkColormap *cmap = gtk_widget_get_colormap (widget);
     GdkColor *fg = &style->fg[GTK_STATE_NORMAL];
     GdkColor *bg = &style->bg[GTK_STATE_NORMAL];
@@ -3880,7 +3956,7 @@ launch_preview_subproc (state *s)
 
   reset_preview_window (s);
 
-  window = pr->window;
+  window = GET_WINDOW (pr);
 
   s->running_preview_error_p = False;
 
@@ -4256,9 +4332,8 @@ static void
 init_icon (GdkWindow *window)
 {
   GdkBitmap *mask = 0;
-  GdkColor transp;
   GdkPixmap *pixmap =
-    gdk_pixmap_create_from_xpm_d (window, &mask, &transp,
+    gdk_pixmap_create_from_xpm_d (window, &mask, 0,
                                   (gchar **) logo_50_xpm);
   if (pixmap)
     gdk_window_set_icon (window, 0, pixmap, mask);
@@ -4641,7 +4716,7 @@ delayed_scroll_kludge (gpointer data)
 
 #ifdef HAVE_GTK2
 
-GtkWidget *
+static GtkWidget *
 create_xscreensaver_demo (void)
 {
   GtkWidget *nb;
@@ -4652,7 +4727,7 @@ create_xscreensaver_demo (void)
   return name_to_widget (global_state_kludge, "xscreensaver_demo");
 }
 
-GtkWidget *
+static GtkWidget *
 create_xscreensaver_settings_dialog (void)
 {
   GtkWidget *w, *box;
@@ -5155,7 +5230,7 @@ main (int argc, char **argv)
       {
         GtkWidget *window = capplet;
         while (window && !GTK_IS_WINDOW (window))
-          window = window->parent;
+          window = GET_PARENT (window);
         if (window)
           {
             gtk_window_set_title (GTK_WINDOW (window), window_title);
@@ -5190,7 +5265,7 @@ main (int argc, char **argv)
 #endif
 
   gtk_widget_show (s->toplevel_widget);
-  init_icon (GTK_WIDGET (s->toplevel_widget)->window);  /* after `show' */
+  init_icon (GET_WINDOW (GTK_WIDGET (s->toplevel_widget)));  /* after `show' */
   fix_preview_visual (s);
 
   /* Realize page zero, so that we can diddle the scrollbar when the
@@ -5217,6 +5292,20 @@ main (int argc, char **argv)
     the_network_is_not_the_computer (s);
 
 
+  if (decrepit_p())
+    warning_dialog (s->toplevel_widget,
+      _("Warning:\n\n"
+        "This version of xscreensaver is VERY OLD!\n"
+        "Please upgrade!\n"
+        "\n"
+        "https://www.jwz.org/xscreensaver/\n"
+        "\n"
+        "(If this is the latest version that your distro ships, then\n"
+        "your distro is doing you a disservice. Build from source.)\n"
+        ),
+      D_NONE, 7);
+
+
   /* Run the Gtk event loop, and not the Xt event loop.  This means that
      if there were Xt timers or fds registered, they would never get serviced,
      and if there were any Xt widgets, they would never have events delivered.