http://packetstorm.tacticalflex.com/UNIX/admin/xscreensaver-3.27.tar.gz
[xscreensaver] / driver / demo-Gtk.c
index 11c64d8985de896a76f8c47856559f4da3c80aae..0ff66e9382ae0a7bcbb721edff8ad66b1cb439c4 100644 (file)
@@ -109,6 +109,7 @@ static void populate_demo_window (GtkWidget *toplevel,
 static void populate_prefs_page (GtkWidget *top, prefs_pair *pair);
 static int apply_changes_and_save (GtkWidget *widget);
 static int maybe_reload_init_file (GtkWidget *widget, prefs_pair *pair);
+static void await_xscreensaver (GtkWidget *widget);
 
 \f
 /* Some random utility functions
@@ -171,7 +172,7 @@ ensure_selected_item_visible (GtkWidget *widget)
        kids; kids = kids->next)
     nkids++;
 
-  adj = gtk_scrolled_window_get_vadjustment (scroller);                        
+  adj = gtk_scrolled_window_get_vadjustment (scroller);
 
   gdk_window_get_geometry (GTK_WIDGET(vp)->window,
                            &ignore, &ignore, &ignore, &parent_h, &ignore);
@@ -257,12 +258,16 @@ warning_dialog (GtkWidget *parent, const char *message,
       sprintf (name, "label%d", i++);
 
       {
+#if 0
         char buf[255];
+#endif
         label = gtk_label_new (head);
+#if 0
         sprintf (buf, "warning_dialog.%s.font", name);
         GTK_WIDGET (label)->style = gtk_style_copy (GTK_WIDGET (label)->style);
         GTK_WIDGET (label)->style->font =
           gdk_font_load (get_string_resource (buf, "Dialog.Label.Font"));
+#endif
         if (center <= 0)
           gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
@@ -497,6 +502,69 @@ restart_menu_cb (GtkWidget *widget, gpointer user_data)
   sleep (1);
   system ("xscreensaver -nosplash &");
 #endif
+
+  await_xscreensaver (GTK_WIDGET (widget));
+}
+
+static void
+await_xscreensaver (GtkWidget *widget)
+{
+  int countdown = 5;
+
+  Display *dpy = gdk_display;
+  /*  GtkWidget *dialog = 0;*/
+  char *rversion = 0;
+
+  while (!rversion && (--countdown > 0))
+    {
+      /* Check for the version of the running xscreensaver... */
+      server_xscreensaver_version (dpy, &rversion, 0, 0);
+
+      /* If it's not there yet, wait a second... */
+      sleep (1);
+    }
+
+/*  if (dialog) gtk_widget_destroy (dialog);*/
+
+  if (rversion)
+    {
+      /* Got it. */
+      free (rversion);
+    }
+  else
+    {
+      /* Timed out, no screensaver running. */
+
+      char buf [1024];
+      Bool root_p = (geteuid () == 0);
+      
+      strcpy (buf, 
+              "Error:\n\n"
+              "The xscreensaver daemon did not start up properly.\n"
+              "\n");
+
+      if (root_p)
+        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"
+            "turned on.  Try running this command:\n"
+            "\n"
+            "                        xhost +localhost\n"
+            "\n"
+            "and then selecting `File / Restart Daemon'.\n"
+            "\n"
+            "Note that turning off access control will allow anyone logged\n"
+            "on to this machine to access your screen, which might be\n"
+            "considered a security problem.  Please read the xscreensaver\n"
+            "manual and FAQ for more information.\n"
+            "\n"
+            "You shouldn't run X as root. Instead, you should log in as a\n"
+            "normal user, and `su' as necessary.");
+      else
+        strcat (buf, "Please check your $PATH and permissions.");
+
+      warning_dialog (widget, buf, False, 1);
+    }
 }
 
 
@@ -915,6 +983,80 @@ list_unselect_cb (GtkList *list, GtkWidget *child)
   populate_demo_window (GTK_WIDGET (list), -1, pair);
 }
 
+
+static int updating_enabled_cb = 0;  /* kludge to make sure that enabled_cb
+                                        is only run by user action, not by
+                                        program action. */
+
+/* Called when the checkboxes that are in the left column of the
+   scrolling list are clicked.  This both populates the right pane
+   (just as clicking on the label (really, listitem) does) and
+   also syncs this checkbox with  the right pane Enabled checkbox.
+ */
+static void
+list_checkbox_cb (GtkWidget *cb, gpointer client_data)
+{
+  prefs_pair *pair = (prefs_pair *) client_data;
+
+  GtkWidget *line_hbox = GTK_WIDGET (cb)->parent;
+  GtkWidget *line = GTK_WIDGET (line_hbox)->parent;
+
+  GtkList *list = GTK_LIST (GTK_WIDGET (line)->parent);
+  GtkViewport *vp = GTK_VIEWPORT (GTK_WIDGET (list)->parent);
+  GtkScrolledWindow *scroller = GTK_SCROLLED_WINDOW (GTK_WIDGET (vp)->parent);
+  GtkAdjustment *adj;
+  double scroll_top;
+
+  GtkToggleButton *enabled =
+    GTK_TOGGLE_BUTTON (name_to_widget (cb, "enabled"));
+
+  int which = gtk_list_child_position (list, line);
+
+  /* remember previous scroll position of the top of the list */
+  adj = gtk_scrolled_window_get_vadjustment (scroller);
+  scroll_top = adj->value;
+
+  apply_changes_and_save (GTK_WIDGET (list));
+  gtk_list_select_item (list, which);
+  /* ensure_selected_item_visible (GTK_WIDGET (list)); */
+  populate_demo_window (GTK_WIDGET (list), which, pair);
+  
+  updating_enabled_cb++;
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (enabled),
+                                GTK_TOGGLE_BUTTON (cb)->active);
+  updating_enabled_cb--;
+
+  /* restore the previous scroll position of the top of the list.
+     this is weak, but I don't really know why it's moving... */
+  gtk_adjustment_set_value (adj, scroll_top);
+}
+
+
+/* Called when the right pane Enabled checkbox is clicked.  This syncs
+   the corresponding checkbox inside the scrolling list to the state
+   of this checkbox.
+ */
+void
+enabled_cb (GtkWidget *cb, gpointer client_data)
+{
+  int which = selected_hack_number (cb);
+  
+  if (updating_enabled_cb) return;
+
+  if (which != -1)
+    {
+      GtkList *list = GTK_LIST (name_to_widget (cb, "list"));
+      GList *kids = GTK_LIST (list)->children;
+      GtkWidget *line = GTK_WIDGET (g_list_nth_data (kids, which));
+      GtkWidget *line_hbox = GTK_WIDGET (GTK_BIN (line)->child);
+      GtkWidget *line_check =
+        GTK_WIDGET (gtk_container_children (GTK_CONTAINER (line_hbox))->data);
+
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (line_check),
+                                    GTK_TOGGLE_BUTTON (cb)->active);
+    }
+}
+
 \f
 /* Populating the various widgets
  */
@@ -1036,18 +1178,50 @@ populate_hack_list (GtkWidget *toplevel, prefs_pair *pair)
 
   for (h = hacks; h && *h; h++)
     {
+      /* A GtkList must contain only GtkListItems, but those can contain
+         an arbitrary widget.  We add an Hbox, and inside that, a Checkbox
+         and a Label.  We handle single and double click events on the
+         line itself, for clicking on the text, but the interior checkbox
+         also handles its own events.
+       */
       GtkWidget *line;
+      GtkWidget *line_hbox;
+      GtkWidget *line_check;
+      GtkWidget *line_label;
+
       char *pretty_name = (h[0]->name
                            ? strdup (h[0]->name)
                            : make_pretty_name (h[0]->command));
 
-      line = gtk_list_item_new_with_label (pretty_name);
+      line = gtk_list_item_new ();
+      line_hbox = gtk_hbox_new (FALSE, 0);
+      line_check = gtk_check_button_new ();
+      line_label = gtk_label_new (pretty_name);
+
+      gtk_container_add (GTK_CONTAINER (line), line_hbox);
+      gtk_box_pack_start (GTK_BOX (line_hbox), line_check, FALSE, FALSE, 0);
+      gtk_box_pack_start (GTK_BOX (line_hbox), line_label, FALSE, FALSE, 0);
+
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (line_check),
+                                    h[0]->enabled_p);
+      gtk_label_set_justify (GTK_LABEL (line_label), GTK_JUSTIFY_LEFT);
+
+      gtk_widget_show (line_check);
+      gtk_widget_show (line_label);
+      gtk_widget_show (line_hbox);
+      gtk_widget_show (line);
+
       free (pretty_name);
 
       gtk_container_add (GTK_CONTAINER (list), line);
       gtk_signal_connect (GTK_OBJECT (line), "button_press_event",
                           GTK_SIGNAL_FUNC (list_doubleclick_cb),
                           (gpointer) pair);
+
+      gtk_signal_connect (GTK_OBJECT (line_check), "toggled",
+                          GTK_SIGNAL_FUNC (list_checkbox_cb),
+                          (gpointer) pair);
+
 #if 0 /* #### */
       GTK_WIDGET (GTK_BIN(line)->child)->style =
         gtk_style_copy (GTK_WIDGET (text_line)->style);
@@ -1268,7 +1442,7 @@ static char *down_arrow_xpm[] = {
 };
 
 static void
-pixmapify_buttons (GtkWidget *toplevel)
+pixmapify_button (GtkWidget *toplevel, int down_p)
 {
   GdkPixmap *pixmap;
   GdkBitmap *mask;
@@ -1276,27 +1450,31 @@ pixmapify_buttons (GtkWidget *toplevel)
   GtkStyle *style;
   GtkWidget *w;
 
-  w = GTK_WIDGET (name_to_widget (GTK_WIDGET (toplevel), "next"));
+  w = GTK_WIDGET (name_to_widget (GTK_WIDGET (toplevel),
+                                  (down_p ? "next" : "prev")));
   style = gtk_widget_get_style (w);
   mask = 0;
   pixmap = gdk_pixmap_create_from_xpm_d (w->window, &mask,
                                          &style->bg[GTK_STATE_NORMAL],
-                                         (gchar **) down_arrow_xpm);
+                                         (down_p
+                                          ? (gchar **) down_arrow_xpm
+                                          : (gchar **) up_arrow_xpm));
   pixmapwid = gtk_pixmap_new (pixmap, mask);
   gtk_widget_show (pixmapwid);
   gtk_container_remove (GTK_CONTAINER (w), GTK_BIN (w)->child);
   gtk_container_add (GTK_CONTAINER (w), pixmapwid);
+}
 
-  w = GTK_WIDGET (name_to_widget (GTK_WIDGET (toplevel), "prev"));
-  style = gtk_widget_get_style (w);
-  mask = 0;
-  pixmap = gdk_pixmap_create_from_xpm_d (w->window, &mask,
-                                         &style->bg[GTK_STATE_NORMAL],
-                                         (gchar **) up_arrow_xpm);
-  pixmapwid = gtk_pixmap_new (pixmap, mask);
-  gtk_widget_show (pixmapwid);
-  gtk_container_remove (GTK_CONTAINER (w), GTK_BIN (w)->child);
-  gtk_container_add (GTK_CONTAINER (w), pixmapwid);
+static void
+map_next_button_cb (GtkWidget *w, gpointer user_data)
+{
+  pixmapify_button (w, 1);
+}
+
+static void
+map_prev_button_cb (GtkWidget *w, gpointer user_data)
+{
+  pixmapify_button (w, 0);
 }
 
 
@@ -1466,7 +1644,11 @@ populate_demo_window (GtkWidget *toplevel, int which, prefs_pair *pair)
   gtk_label_set_text (doc, (doc_string ? doc_string : ""));
   gtk_entry_set_text (cmd, (hack ? hack->command : ""));
   gtk_entry_set_position (cmd, 0);
+
+  updating_enabled_cb++;
   gtk_toggle_button_set_active (enabled, (hack ? hack->enabled_p : False));
+  updating_enabled_cb--;
+
   gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (vis)->entry),
                       (hack
                        ? (hack->visual && *hack->visual
@@ -1764,7 +1946,6 @@ map_window_cb (GtkWidget *w, gpointer user_data)
 {
   Boolean oi = initializing_p;
   initializing_p = True;
-  pixmapify_buttons (w);
   eschew_gtk_lossage (w);
   ensure_selected_item_visible (GTK_WIDGET(name_to_widget(w, "list")));
   initializing_p = oi;
@@ -1775,11 +1956,6 @@ int
 main (int argc, char **argv)
 {
   XtAppContext app;
-# ifdef HAVE_CRAPPLET
-  GnomeClient *client;
-  GnomeClientFlags flags;
-  int init_results;
-# endif /* HAVE_CRAPPLET */
   prefs_pair Pair, *pair;
   saver_preferences P, P2, *p, *p2;
   Bool prefs = False;
@@ -1858,9 +2034,21 @@ main (int argc, char **argv)
 # ifdef HAVE_CRAPPLET
   if (crapplet_p)
     {
-      init_results = gnome_capplet_init ("screensaver-properties",
-                                         short_version,
-                                         argc, argv, NULL, 0, NULL);
+      GnomeClient *client;
+      GnomeClientFlags flags = 0;
+
+      int init_results = gnome_capplet_init ("screensaver-properties",
+                                             short_version,
+                                             argc, argv, NULL, 0, NULL);
+      /* init_results is:
+         0 upon successful initialization;
+         1 if --init-session-settings was passed on the cmdline;
+         2 if --ignore was passed on the cmdline;
+        -1 on error.
+
+         So the 1 signifies just to init the settings, and quit, basically.
+         (Meaning launch the xscreensaver daemon.)
+       */
 
       if (init_results < 0)
         {
@@ -1878,14 +2066,38 @@ main (int argc, char **argv)
 
       if (client)
         flags = gnome_client_get_flags (client);
-      else
-        flags = 0;
 
       if (flags & GNOME_CLIENT_IS_CONNECTED)
         {
-          gnome_client_set_restart_style (client, GNOME_RESTART_NEVER);
+          int token =
+            gnome_startup_acquire_token ("GNOME_SCREENSAVER_PROPERTIES",
+                                         gnome_client_get_id (client));
+          if (token)
+            {
+              char *session_args[20];
+              int i = 0;
+              session_args[i++] = real_progname;
+              session_args[i++] = "--capplet";
+              session_args[i++] = "--init-session-settings";
+              session_args[i] = 0;
+              gnome_client_set_priority (client, 20);
+              gnome_client_set_restart_style (client, GNOME_RESTART_ANYWAY);
+              gnome_client_set_restart_command (client, i, session_args);
+            }
+          else
+            {
+              gnome_client_set_restart_style (client, GNOME_RESTART_NEVER);
+            }
+
           gnome_client_flush (client);
         }
+
+      if (init_results == 1)
+       {
+         system ("xscreensaver -nosplash &");
+         return 0;
+       }
+
     }
   else
 # endif /* HAVE_CRAPPLET */
@@ -2022,6 +2234,12 @@ main (int argc, char **argv)
   gtk_signal_connect (
               GTK_OBJECT (name_to_widget (GTK_WIDGET (gtk_window), "list")),
               "map", GTK_SIGNAL_FUNC(map_window_cb), 0);
+  gtk_signal_connect (
+              GTK_OBJECT (name_to_widget (GTK_WIDGET (gtk_window), "prev")),
+              "map", GTK_SIGNAL_FUNC(map_prev_button_cb), 0);
+  gtk_signal_connect (
+              GTK_OBJECT (name_to_widget (GTK_WIDGET (gtk_window), "next")),
+              "map", GTK_SIGNAL_FUNC(map_next_button_cb), 0);
 
 
   /* Handle the -prefs command-line argument. */
@@ -2046,10 +2264,6 @@ main (int argc, char **argv)
       gtk_container_remove (GTK_CONTAINER (gtk_window), top_vbox);
       GTK_OBJECT_SET_FLAGS (top_vbox, GTK_FLOATING);
 
-      /* This is a crock, but otherwise, the Control Center expands to
-         be as tall as the screen. */
-      gtk_window_set_default_size (GTK_WINDOW (top_vbox), 600, 400);
-
       /* In crapplet-mode, take off the menubar. */
       gtk_widget_hide (name_to_widget (gtk_window, "menubar"));