X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Fdemo-Gtk.c;h=f9c066c3d81dc0c280350e8c1aeb42025ad49e3b;hb=2d04c4f22466851aedb6ed0f2919d148f726b889;hp=715ca3934f55a472ed8a2b8300177e391a65d9b3;hpb=6a1da724858673ac40aa13a9612340d8bed8c7b9;p=xscreensaver diff --git a/driver/demo-Gtk.c b/driver/demo-Gtk.c index 715ca393..f9c066c3 100644 --- a/driver/demo-Gtk.c +++ b/driver/demo-Gtk.c @@ -1,5 +1,5 @@ /* demo-Gtk.c --- implements the interactive demo-mode and options dialogs. - * xscreensaver, Copyright (c) 1993-2003 Jamie Zawinski + * xscreensaver, Copyright (c) 1993-2005 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -88,8 +88,11 @@ #include #ifdef HAVE_GTK2 -#include -#endif /* HAVE_GTK2 */ +# include +# include +#else /* !HAVE_GTK2 */ +# define G_MODULE_EXPORT /**/ +#endif /* !HAVE_GTK2 */ #if defined(DEFAULT_ICONDIR) && !defined(GLADE_DIR) # define GLADE_DIR DEFAULT_ICONDIR @@ -116,6 +119,9 @@ #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" @@ -135,6 +141,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))) @@ -211,7 +219,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 *); @@ -572,6 +580,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]; @@ -608,14 +621,18 @@ run_hack (state *s, int list_elt, Bool report_errors_p) /* Button callbacks + + According to Eric Lassauge, this G_MODULE_EXPORT crud is needed to make + libglade work on Cygwin; apparently all Glade callbacks need this magic + extra declaration. I do not pretend to understand. */ -void +G_MODULE_EXPORT void 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 (); } @@ -629,7 +646,7 @@ wm_toplevel_close_cb (GtkWidget *widget, GdkEvent *event, gpointer data) } -void +G_MODULE_EXPORT void about_menu_cb (GtkMenuItem *menuitem, gpointer user_data) { char msg [2048]; @@ -648,9 +665,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-2003 %s"), s); + sprintf(copy, ("Copyright \xC2\xA9 1991-2005 %s"), s); #else /* !HAVE_GTK2 */ - sprintf(copy, ("Copyright \251 1991-2003 %s"), s); + sprintf(copy, ("Copyright \251 1991-2005 %s"), s); #endif /* !HAVE_GTK2 */ sprintf (msg, "%s\n\n%s", copy, desc); @@ -756,7 +773,7 @@ about_menu_cb (GtkMenuItem *menuitem, gpointer user_data) } -void +G_MODULE_EXPORT void doc_menu_cb (GtkMenuItem *menuitem, gpointer user_data) { state *s = global_state_kludge; /* I hate C so much... */ @@ -772,17 +789,18 @@ doc_menu_cb (GtkMenuItem *menuitem, gpointer user_data) } help_command = (char *) malloc (strlen (p->load_url_command) + - (strlen (p->help_url) * 2) + 20); + (strlen (p->help_url) * 4) + 20); strcpy (help_command, "( "); sprintf (help_command + strlen(help_command), - p->load_url_command, p->help_url, p->help_url); + p->load_url_command, + p->help_url, p->help_url, p->help_url, p->help_url); strcat (help_command, " ) &"); system (help_command); free (help_command); } -void +G_MODULE_EXPORT void activate_menu_cb (GtkMenuItem *menuitem, gpointer user_data) { state *s = global_state_kludge; /* I hate C so much... */ @@ -790,7 +808,7 @@ activate_menu_cb (GtkMenuItem *menuitem, gpointer user_data) } -void +G_MODULE_EXPORT void lock_menu_cb (GtkMenuItem *menuitem, gpointer user_data) { state *s = global_state_kludge; /* I hate C so much... */ @@ -798,7 +816,7 @@ lock_menu_cb (GtkMenuItem *menuitem, gpointer user_data) } -void +G_MODULE_EXPORT void kill_menu_cb (GtkMenuItem *menuitem, gpointer user_data) { state *s = global_state_kludge; /* I hate C so much... */ @@ -806,7 +824,7 @@ kill_menu_cb (GtkMenuItem *menuitem, gpointer user_data) } -void +G_MODULE_EXPORT void restart_menu_cb (GtkWidget *widget, gpointer user_data) { state *s = global_state_kludge; /* I hate C so much... */ @@ -929,7 +947,7 @@ demo_write_init_file (state *s, saver_preferences *p) } -void +G_MODULE_EXPORT void run_this_cb (GtkButton *button, gpointer user_data) { state *s = global_state_kludge; /* I hate C so much... */ @@ -940,7 +958,7 @@ run_this_cb (GtkButton *button, gpointer user_data) } -void +G_MODULE_EXPORT void manual_cb (GtkButton *button, gpointer user_data) { state *s = global_state_kludge; /* I hate C so much... */ @@ -967,7 +985,7 @@ manual_cb (GtkButton *button, gpointer user_data) cmd = get_string_resource ("manualCommand", "ManualCommand"); if (cmd) { - char *cmd2 = (char *) malloc (strlen (cmd) + strlen (name2) + 100); + char *cmd2 = (char *) malloc (strlen (cmd) + (strlen (name2) * 4) + 100); strcpy (cmd2, "( "); sprintf (cmd2 + strlen (cmd2), cmd, @@ -1013,7 +1031,7 @@ force_list_select_item (state *s, GtkWidget *list, int list_elt, Bool scroll_p) } -void +G_MODULE_EXPORT void run_next_cb (GtkButton *button, gpointer user_data) { state *s = global_state_kludge; /* I hate C so much... */ @@ -1042,7 +1060,7 @@ run_next_cb (GtkButton *button, gpointer user_data) } -void +G_MODULE_EXPORT void run_prev_cb (GtkButton *button, gpointer user_data) { state *s = global_state_kludge; /* I hate C so much... */ @@ -1544,7 +1562,7 @@ flush_popup_changes_and_save (state *s) } -void +G_MODULE_EXPORT void pref_changed_cb (GtkWidget *widget, gpointer user_data) { state *s = global_state_kludge; /* I hate C so much... */ @@ -1556,7 +1574,7 @@ pref_changed_cb (GtkWidget *widget, gpointer user_data) } } -gboolean +G_MODULE_EXPORT gboolean pref_changed_event_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data) { pref_changed_cb (widget, user_data); @@ -1576,7 +1594,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) { @@ -1590,17 +1607,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; @@ -1611,13 +1623,10 @@ 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... */ } -void +G_MODULE_EXPORT void switch_page_cb (GtkNotebook *notebook, GtkNotebookPage *page, gint page_num, gpointer user_data) { @@ -1860,7 +1869,7 @@ browse_image_dir_close (GtkWidget *widget, GdkEvent *event, gpointer user_data) } -void +G_MODULE_EXPORT void browse_image_dir_cb (GtkButton *button, gpointer user_data) { state *s = global_state_kludge; /* I hate C so much... */ @@ -1896,7 +1905,7 @@ browse_image_dir_cb (GtkButton *button, gpointer user_data) } -void +G_MODULE_EXPORT void settings_cb (GtkButton *button, gpointer user_data) { state *s = global_state_kludge; /* I hate C so much... */ @@ -1919,7 +1928,7 @@ settings_sync_cmd_text (state *s) # endif /* HAVE_XML */ } -void +G_MODULE_EXPORT void settings_adv_cb (GtkButton *button, gpointer user_data) { state *s = global_state_kludge; /* I hate C so much... */ @@ -1930,7 +1939,7 @@ settings_adv_cb (GtkButton *button, gpointer user_data) gtk_notebook_set_page (notebook, 1); } -void +G_MODULE_EXPORT void settings_std_cb (GtkButton *button, gpointer user_data) { state *s = global_state_kludge; /* I hate C so much... */ @@ -1943,7 +1952,7 @@ settings_std_cb (GtkButton *button, gpointer user_data) gtk_notebook_set_page (notebook, 0); } -void +G_MODULE_EXPORT void settings_switch_page_cb (GtkNotebook *notebook, GtkNotebookPage *page, gint page_num, gpointer user_data) { @@ -1967,14 +1976,14 @@ settings_switch_page_cb (GtkNotebook *notebook, GtkNotebookPage *page, -void +G_MODULE_EXPORT void settings_cancel_cb (GtkButton *button, gpointer user_data) { state *s = global_state_kludge; /* I hate C so much... */ gtk_widget_hide (s->popup_widget); } -void +G_MODULE_EXPORT void settings_ok_cb (GtkButton *button, gpointer user_data) { state *s = global_state_kludge; /* I hate C so much... */ @@ -2013,7 +2022,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; @@ -2021,14 +2030,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; } @@ -2372,7 +2384,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) \ @@ -2431,6 +2443,7 @@ populate_prefs_page (state *s) { Bool found_any_writable_cells = False; + Bool fading_possible = False; Bool dpms_supported = False; Display *dpy = GDK_DISPLAY(); @@ -2446,8 +2459,9 @@ populate_prefs_page (state *s) } } + fading_possible = found_any_writable_cells; #ifdef HAVE_XF86VMODE_GAMMA - found_any_writable_cells = True; /* if we can gamma fade, go for it */ + fading_possible = True; #endif #ifdef HAVE_DPMS_EXTENSION @@ -2484,14 +2498,14 @@ populate_prefs_page (state *s) /* Colormaps */ - SENSITIZE ("cmap_frame", found_any_writable_cells); + SENSITIZE ("cmap_frame", found_any_writable_cells || fading_possible); SENSITIZE ("install_button", found_any_writable_cells); - SENSITIZE ("fade_button", found_any_writable_cells); - SENSITIZE ("unfade_button", found_any_writable_cells); + SENSITIZE ("fade_button", fading_possible); + SENSITIZE ("unfade_button", fading_possible); - SENSITIZE ("fade_label", (found_any_writable_cells && + SENSITIZE ("fade_label", (fading_possible && (p->fade_p || p->unfade_p))); - SENSITIZE ("fade_spinbutton", (found_any_writable_cells && + SENSITIZE ("fade_spinbutton", (fading_possible && (p->fade_p || p->unfade_p))); # undef SENSITIZE @@ -2840,15 +2854,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); } @@ -3114,6 +3128,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) { @@ -3328,7 +3368,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; @@ -3374,6 +3414,12 @@ kill_preview_subproc (state *s) } reap_zombies (s); + + if (reset_p) + { + reset_preview_window (s); + clear_preview_window (s); + } } @@ -3390,13 +3436,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; } @@ -3416,7 +3466,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; @@ -3439,6 +3489,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 @@ -3529,6 +3581,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. @@ -3538,7 +3613,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); @@ -3661,7 +3736,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; @@ -3669,14 +3744,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; } @@ -3694,7 +3772,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 */ @@ -3875,7 +3953,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; } @@ -4034,6 +4112,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; @@ -4128,6 +4207,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] && @@ -4285,7 +4379,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); } @@ -4496,6 +4591,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' */ @@ -4555,7 +4655,7 @@ main (int argc, char **argv) # endif /* HAVE_CRAPPLET */ gtk_main (); - kill_preview_subproc (s); + kill_preview_subproc (s, False); exit (0); }