/* demo-Gtk.c --- implements the interactive demo-mode and options dialogs.
- * xscreensaver, Copyright (c) 1993-2003 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 */
#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"
/* 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)))
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 *);
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);
-# if 0
- gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (widget),
- path, NULL, FALSE, 0.0, 0.0);
-# else
gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), path, NULL, FALSE);
-# endif
+
+ gtk_tree_path_free (path);
+
#else /* !HAVE_GTK2 */
GtkScrolledWindow *scroller = 0;
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;
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);
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];
{
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 ();
}
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);
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);
}
"\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"
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);
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;
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
{
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)
{
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;
}
pref_changed_cb (widget, user_data);
-
- if (old_selected != p->selected_hack)
- abort(); /* dammit, not again... */
}
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);
Atom type;
int format;
unsigned long nitems, bytesafter;
- CARD32 *data = 0;
+ unsigned char *dataP = 0;
Display *dpy = GDK_DISPLAY();
int hack_number = -1;
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;
}
# 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) \
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);
}
}
+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)
{
static void
-kill_preview_subproc (state *s)
+kill_preview_subproc (state *s, Bool reset_p)
{
s->running_preview_error_p = False;
}
reap_zombies (s);
+
+ if (reset_p)
+ {
+ reset_preview_window (s);
+ clear_preview_window (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;
}
(unsigned int) id);
}
- kill_preview_subproc (s);
+ kill_preview_subproc (s, False);
if (! new_cmd)
{
s->running_preview_error_p = True;
{
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
}
+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.
{
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);
Atom type;
int format;
unsigned long nitems, bytesafter;
- CARD32 *data = 0;
+ unsigned char *dataP = 0;
Display *dpy = GDK_DISPLAY();
Bool blanked_p = False;
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;
}
{
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 */
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;
}
}
+#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
Widget toplevel_shell;
char *real_progname = argv[0];
char *window_title;
+ char *geom = 0;
Bool crapplet_p = False;
char *str;
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] &&
;
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);
}
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. */
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' */
# endif /* HAVE_CRAPPLET */
gtk_main ();
- kill_preview_subproc (s);
+ kill_preview_subproc (s, False);
exit (0);
}