X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Fdemo.c;h=c7a12ba3eb4b4c5e458440768e9672a8ff6f287a;hb=2a991a811de4c7b22f812682b267b616a809fd9a;hp=b7823400dd5d200c4bd09d589049f2632cb7e7ef;hpb=ccbc9f87eb59497b23bd0424ee1ed20ad7c7db54;p=xscreensaver diff --git a/driver/demo.c b/driver/demo.c index b7823400..c7a12ba3 100644 --- a/driver/demo.c +++ b/driver/demo.c @@ -1,4 +1,5 @@ -/* xscreensaver, Copyright (c) 1993-1995 Jamie Zawinski +/* demo.c --- implements the interactive demo-mode and options dialogs. + * xscreensaver, Copyright (c) 1993-1998 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 @@ -9,40 +10,51 @@ * implied warranty. */ -#include - -#if !__STDC__ -# define _NO_PROTO +#ifdef HAVE_CONFIG_H +# include "config.h" #endif -#include -#include -#include -#include +#include +#include + +/* We don't actually use any widget internals, but these are included + so that gdb will have debug info for the widgets... */ +#include +#include + +#ifdef HAVE_MOTIF +# include +# include +# include +# include + +#else /* HAVE_ATHENA */ + /* Athena demo code contributed by Jon A. Christopher */ + /* Copyright 1997, with the same permissions as above. */ +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif /* HAVE_ATHENA */ #include "xscreensaver.h" +#include "resources.h" /* for parse_time() */ #include +#include +#include -#ifdef HAVE_SAVER_EXTENSION -extern int saver_ext_event_number; -extern Window server_saver_window; -#endif /* HAVE_SAVER_EXTENSION */ - -extern Time timeout, cycle, lock_timeout; -#ifndef NO_LOCKING -extern Time passwd_timeout; +#ifdef _VROOT_H_ +ERROR! You must not include vroot.h in this file. #endif -extern int fade_seconds, fade_ticks; -extern Bool verbose_p, install_cmap_p, fade_p, unfade_p; -extern Bool lock_p, locking_disabled_p; -static void demo_mode_hack P((char *)); -static void demo_mode_done P((void)); - -static void focus_fuckus P((Widget dialog)); -static void text_cb P((Widget button, XtPointer, XtPointer)); - -extern void demo_mode_restart_process (); +static void demo_mode_hack (saver_info *si, char *); +static void demo_mode_done (saver_info *si); extern Widget demo_dialog; extern Widget label1; @@ -59,61 +71,223 @@ extern Widget lock_time_text, passwd_time_text; extern Widget verbose_toggle, cmap_toggle, fade_toggle, unfade_toggle, lock_toggle; -extern create_demo_dialog (); -extern create_resources_dialog (); + +#ifdef HAVE_MOTIF + +# define set_toggle_button_state(toggle,state) \ + XmToggleButtonSetState ((toggle), (state), True) +# define set_text_string(text_widget,string) \ + XmTextSetString ((text_widget), (string)) +# define add_button_callback(button,cb,arg) \ + XtAddCallback ((button), XmNactivateCallback, (cb), (arg)) +# define add_toggle_callback(button,cb,arg) \ + XtAddCallback ((button), XmNvalueChangedCallback, (cb), (arg)) +# define add_text_callback add_toggle_callback + +#else /* HAVE_ATHENA */ + +# define set_toggle_button_state(toggle,state) \ + XtVaSetValues((toggle), XtNstate, (state), 0) +# define set_text_string(text_widget,string) \ + XtVaSetValues ((text_widget), XtNvalue, (string), 0) +# define add_button_callback(button,cb,arg) \ + XtAddCallback ((button), XtNcallback, (cb), (arg)) +# define add_toggle_callback add_button_callback +# define add_text_callback(b,c,a) ERROR! + +#endif /* HAVE_ATHENA */ + + +#define disable_widget(widget) \ + XtVaSetValues((widget), XtNsensitive, False, 0) + + +static char * +get_text_string (Widget text_widget) +{ +#ifdef HAVE_MOTIF + return XmTextGetString (text_widget); +#else /* HAVE_ATHENA */ + char *string = 0; + if (XtIsSubclass(text_widget, textWidgetClass)) + XtVaGetValues (text_widget, XtNstring, &string, 0); + else if (XtIsSubclass(text_widget, dialogWidgetClass)) + XtVaGetValues (text_widget, XtNvalue, &string, 0); + else + string = 0; + + return string; +#endif /* HAVE_ATHENA */ +} + +static char * +get_label_string (Widget label_widget) +{ +#ifdef HAVE_MOTIF + char *label = 0; + XmString xm_label = 0; + XtVaGetValues (label_widget, XmNlabelString, &xm_label, 0); + if (!xm_label) + return 0; + XmStringGetLtoR (xm_label, XmSTRING_DEFAULT_CHARSET, &label); + return label; +#else /* HAVE_ATHENA */ + char *label = 0; + XtVaGetValues (label_widget, XtNlabel, &label, 0); + return (label ? strdup(label) : 0); +#endif /* HAVE_ATHENA */ +} + static void -focus_fuckus (dialog) - Widget dialog; +set_label_string (Widget label_widget, char *string) { - XSetInputFocus (XtDisplay (dialog), XtWindow (dialog), - RevertToParent, CurrentTime); +#ifdef HAVE_MOTIF + XmString xm_string = XmStringCreate (string, XmSTRING_DEFAULT_CHARSET); + XtVaSetValues (label_widget, XmNlabelString, xm_string, 0); + XmStringFree (xm_string); +#else /* HAVE_ATHENA */ + XtVaSetValues (label_widget, XtNlabel, string, 0); +#endif /* HAVE_ATHENA */ +} + + +void +format_into_label (Widget label, const char *arg) +{ + char *text = get_label_string (label); + char *buf = (char *) malloc ((text ? strlen(text) : 100) + strlen(arg) + 10); + + if (!text || !strcmp (text, XtName (label))) + strcpy (buf, "ERROR: RESOURCES ARE NOT INSTALLED CORRECTLY"); + else + sprintf (buf, text, arg); + + set_label_string (label, buf); + free (buf); + XtFree (text); +} + + +void +steal_focus_and_colormap (Widget dialog) +{ + Display *dpy = XtDisplay (dialog); + Window window = XtWindow (dialog); + Colormap cmap = 0; + XSetInputFocus (dpy, window, RevertToParent, CurrentTime); + + XtVaGetValues (dialog, XtNcolormap, &cmap, 0); + if (cmap) + XInstallColormap (dpy, cmap); } static void -raise_screenhack_dialog () +raise_screenhack_dialog (void) { XMapRaised (XtDisplay (demo_dialog), XtWindow (demo_dialog)); if (resources_dialog) XMapRaised (XtDisplay (resources_dialog), XtWindow (resources_dialog)); - focus_fuckus (resources_dialog ? resources_dialog : demo_dialog); + steal_focus_and_colormap (resources_dialog ? resources_dialog : demo_dialog); } static void -destroy_screenhack_dialogs () +destroy_screenhack_dialogs (saver_info *si) { + saver_screen_info *ssi = si->default_screen; + if (demo_dialog) XtDestroyWidget (demo_dialog); if (resources_dialog) XtDestroyWidget (resources_dialog); demo_dialog = resources_dialog = 0; + + if (ssi->demo_cmap && + ssi->demo_cmap != ssi->cmap && + ssi->demo_cmap != DefaultColormapOfScreen (ssi->screen)) + { + XFreeColormap (si->dpy, ssi->demo_cmap); + ssi->demo_cmap = 0; + } + + /* Since we installed our colormap to display the dialogs properly, put + the old one back, so that the screensaver_window is now displayed + properly. */ + if (ssi->cmap) + XInstallColormap (si->dpy, ssi->cmap); } + static void -text_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +text_cb (Widget text_widget, XtPointer client_data, XtPointer call_data) +{ + saver_info *si = (saver_info *) client_data; + saver_preferences *p = &si->prefs; + char *line; + line = get_text_string (text_widget); + + if (p->verbose_p) + fprintf (stderr, "%s: processing text \"%s\".\n", blurb(), line); + + demo_mode_hack (si, line); +} + + +#ifdef HAVE_ATHENA +/* Bend over backwards to make hitting Return in the text field do the + right thing. + */ +extern saver_info *global_si_kludge; +static void text_enter (Widget w, XEvent *event, String *av, Cardinal *ac) { - char *line = XmTextGetString (button); - demo_mode_hack (line); + text_cb (w, global_si_kludge, 0); } +static XtActionsRec actions[] = {{"done", text_enter} + }; +static char translations[] = ("Return: done()\n" + "Linefeed: done()\n" + "CtrlM: done()\n" + "CtrlJ: done()\n"); +#endif /* HAVE_ATHENA */ + static void -select_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +select_cb (Widget button, XtPointer client_data, XtPointer call_data) { - char **hacks = (char **) client_data; + saver_info *si = (saver_info *) client_data; + +#ifdef HAVE_ATHENA + XawListReturnStruct *item = (XawListReturnStruct*)call_data; + XtVaSetValues(text_line, XtNstring, item->string, 0); + + demo_mode_hack (si, item->string); + if (item->list_index >= 0) + si->default_screen->current_hack = item->list_index; + +#else /* HAVE_MOTIF */ XmListCallbackStruct *lcb = (XmListCallbackStruct *) call_data; - XmTextSetString (text_line, hacks [lcb->item_position - 1]); - if (lcb->reason == XmCR_DEFAULT_ACTION) - text_cb (text_line, 0, 0); - focus_fuckus (demo_dialog); + char *string = 0; + if (lcb->item) + XmStringGetLtoR (lcb->item, XmSTRING_DEFAULT_CHARSET, &string); + set_text_string (text_line, (string ? string : "")); + if (lcb->reason == XmCR_DEFAULT_ACTION && string) + { + demo_mode_hack (si, string); + if (lcb->item_position > 0) + si->default_screen->current_hack = lcb->item_position - 1; + } + if (string) + XtFree (string); +#endif /* HAVE_MOTIF */ + steal_focus_and_colormap (demo_dialog); } + +/* Why this behavior isn't automatic in *either* toolkit, I'll never know. + */ static void -ensure_selected_item_visible (list) - Widget list; +ensure_selected_item_visible (Widget list) { +#ifdef HAVE_MOTIF int *pos_list = 0; int pos_count = 0; if (XmListGetSelectedPos (list, &pos_list, &pos_count) && pos_count > 0) @@ -137,86 +311,209 @@ ensure_selected_item_visible (list) } if (pos_list) XtFree ((char *) pos_list); + +#else /* HAVE_ATHENA */ +# ifdef HAVE_XawViewportSetCoordinates + + int margin = 16; /* should be line height or something. */ + int count = 0; + int pos; + Dimension list_h = 0, vp_h = 0; + Dimension top_margin = 4; /* I don't know where this value comes from */ + Position vp_x = 0, vp_y = 0, current_y; + double cratio; + Widget viewport = XtParent(demo_list); + Widget sb = (viewport ? XtNameToWidget(viewport, "*vertical") : 0); + float sb_top = 0, sb_size = 0; + XawListReturnStruct *current = XawListShowCurrent(demo_list); + if (!current || !sb) return; + + XtVaGetValues(demo_list, + XtNnumberStrings, &count, + XtNheight, &list_h, + 0); + if (count < 2 || list_h < 10) return; + + XtVaGetValues(viewport, XtNheight, &vp_h, XtNx, &vp_x, XtNy, &vp_y, 0); + if (vp_h < 10) return; + + XtVaGetValues(sb, XtNtopOfThumb, &sb_top, XtNshown, &sb_size, 0); + if (sb_size <= 0) return; + + pos = current->list_index; + cratio = ((double) pos) / ((double) count); + current_y = (cratio * list_h); + + if (cratio < sb_top || + cratio > sb_top + sb_size) + { + if (cratio < sb_top) + current_y -= (vp_h - margin - margin); + else + current_y -= margin; + + if ((long)current_y >= (long) list_h) + current_y = (Position) ((long)list_h - (long)vp_h); + + if ((long)current_y < (long)top_margin) + current_y = (Position)top_margin; + + XawViewportSetCoordinates (viewport, vp_x, current_y); + } +# endif /* HAVE_XawViewportSetCoordinates */ +#endif /* HAVE_ATHENA */ } + static void -next_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +next_cb (Widget button, XtPointer client_data, XtPointer call_data) { + saver_info *si = (saver_info *) client_data; + saver_preferences *p = &si->prefs; + + if (p->verbose_p) + fprintf (stderr, "%s: Run Next\n", blurb()); + + { +#ifdef HAVE_ATHENA + int cnt; + XawListReturnStruct *current = XawListShowCurrent(demo_list); + if (current->list_index == XAW_LIST_NONE) + XawListHighlight(demo_list, 0); + else + { + XtVaGetValues(demo_list, + XtNnumberStrings, &cnt, + NULL); + if (current->list_index + 1 < cnt) + { + current->list_index++; + XawListHighlight(demo_list, current->list_index); + } + } + + ensure_selected_item_visible (demo_list); + current = XawListShowCurrent(demo_list); + XtVaSetValues(text_line, XtNstring, current->string, 0); + demo_mode_hack (si, current->string); + +#else /* HAVE_MOTIF */ + int *pos_list; int pos_count; if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count)) - XmListSelectPos (demo_list, 1, True); + { + XmListDeselectAllItems(demo_list); /* LessTif lossage */ + XmListSelectPos (demo_list, 1, True); + } else { - int pos = pos_list [0]; - XmListSelectPos (demo_list, pos + 1, True); - XtFree ((char *) pos_list); - if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count)) - abort (); - if (pos_list [0] == pos) - XmListSelectPos (demo_list, 1, True); - XtFree ((char *) pos_list); + int pos = pos_list[0] + 1; + if (pos > si->prefs.screenhacks_count) + pos = 1; + XmListDeselectAllItems(demo_list); /* LessTif lossage */ + XmListSelectPos (demo_list, pos, True); } + XtFree ((char *) pos_list); ensure_selected_item_visible (demo_list); - text_cb (text_line, 0, 0); + demo_mode_hack (si, get_text_string (text_line)); + +#endif /* HAVE_MOTIF */ + } } + static void -prev_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +prev_cb (Widget button, XtPointer client_data, XtPointer call_data) { + saver_info *si = (saver_info *) client_data; + saver_preferences *p = &si->prefs; + + if (p->verbose_p) + fprintf (stderr, "%s: Run Previous\n", blurb()); + + { +#ifdef HAVE_ATHENA + XawListReturnStruct *current=XawListShowCurrent(demo_list); + if (current->list_index == XAW_LIST_NONE) + XawListHighlight(demo_list, 0); + else + { + if (current->list_index >= 1) + { + current->list_index--; + XawListHighlight(demo_list, current->list_index); + } + } + + ensure_selected_item_visible (demo_list); + current = XawListShowCurrent(demo_list); + XtVaSetValues(text_line, XtNstring, current->string, 0); + demo_mode_hack (si, current->string); + +#else /* HAVE_MOTIF */ + int *pos_list; int pos_count; if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count)) - XmListSelectPos (demo_list, 0, True); + { + XmListDeselectAllItems(demo_list); /* LessTif lossage */ + XmListSelectPos (demo_list, 0, True); + } else { + XmListDeselectAllItems(demo_list); /* LessTif lossage */ XmListSelectPos (demo_list, pos_list [0] - 1, True); XtFree ((char *) pos_list); } ensure_selected_item_visible (demo_list); - text_cb (text_line, 0, 0); + demo_mode_hack (si, get_text_string (text_line)); + +#endif /* HAVE_MOTIF */ + } } -static void pop_resources_dialog (); -static void make_resources_dialog (); +static void pop_resources_dialog (saver_info *si); +static void make_resources_dialog (saver_info *si, Widget parent); static void -edit_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +edit_cb (Widget button, XtPointer client_data, XtPointer call_data) { - Widget parent = (Widget) client_data; + saver_info *si = (saver_info *) client_data; + saver_screen_info *ssi = si->default_screen; + saver_preferences *p = &si->prefs; + Widget parent = ssi->toplevel_shell; + + if (p->verbose_p) + fprintf (stderr, "%s: Preferences\n", blurb()); + if (! resources_dialog) - make_resources_dialog (parent); - pop_resources_dialog (); + make_resources_dialog (si, parent); + pop_resources_dialog (si); } static void -done_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +done_cb (Widget button, XtPointer client_data, XtPointer call_data) { - demo_mode_done (); + saver_info *si = (saver_info *) client_data; + demo_mode_done (si); } static void -restart_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +restart_cb (Widget button, XtPointer client_data, XtPointer call_data) { - demo_mode_restart_process (); + saver_info *si = (saver_info *) client_data; + saver_preferences *p = &si->prefs; + if (p->verbose_p) + fprintf (stderr, "%s: Restart\n", blurb()); + demo_mode_restart_process (si); } + void -pop_up_dialog_box (dialog, form, where) - Widget dialog, form; - int where; +pop_up_dialog_box (Widget dialog, Widget form, int where) { /* I'm sure this is the wrong way to pop up a dialog box, but I can't figure out how else to do it. @@ -230,13 +527,28 @@ pop_up_dialog_box (dialog, form, where) Arg av [100]; int ac = 0; Dimension sw, sh, x, y, w, h; + +#ifdef HAVE_ATHENA + XtRealizeWidget (dialog); +#else /* HAVE_MOTIF */ + /* Motif likes us to realize the *child* of the shell... */ XtRealizeWidget (form); +#endif /* HAVE_MOTIF */ + sw = WidthOfScreen (XtScreen (dialog)); sh = HeightOfScreen (XtScreen (dialog)); ac = 0; - XtSetArg (av [ac], XmNwidth, &w); ac++; - XtSetArg (av [ac], XmNheight, &h); ac++; + XtSetArg (av [ac], XtNwidth, &w); ac++; + XtSetArg (av [ac], XtNheight, &h); ac++; XtGetValues (form, av, ac); + + /* for debugging -- don't ask */ + if (where >= 69) + { + where -= 69; + sw = (sw * 7) / 12; + } + switch (where) { case 0: /* center it in the top-right quadrant */ @@ -251,82 +563,185 @@ pop_up_dialog_box (dialog, form, where) x = (sw + w) / 2 - w; y = (sh + h) / 2 - h; break; + case 3: /* center it in the top 2/3rds of the screen */ + x = (sw + w) / 2 - w; + y = (sh*2/3 + h) / 2 - h; + break; default: abort (); } if (x + w > sw) x = sw - w; if (y + h > sh) y = sh - h; ac = 0; - XtSetArg (av [ac], XmNx, x); ac++; - XtSetArg (av [ac], XmNy, y); ac++; + XtSetArg (av [ac], XtNx, x); ac++; + XtSetArg (av [ac], XtNy, y); ac++; XtSetArg (av [ac], XtNoverrideRedirect, True); ac++; + +#ifdef HAVE_MOTIF XtSetArg (av [ac], XmNdefaultPosition, False); ac++; - /* I wonder whether this does anything useful? */ - /* XtSetArg (av [ac], XmNdialogStyle, XmDIALOG_SYSTEM_MODAL); ac++; */ +#endif /* HAVE_MOTIF */ + XtSetValues (dialog, av, ac); XtSetValues (form, av, ac); + +#ifdef HAVE_ATHENA + XtPopup (dialog, XtGrabNone); +#else /* HAVE_MOTIF */ XtManageChild (form); +#endif /* HAVE_MOTIF */ - focus_fuckus (dialog); + steal_focus_and_colormap (dialog); } -static void -make_screenhack_dialog (parent, hacks) - Widget parent; - char **hacks; +void +make_screenhack_dialog (saver_info *si) { - char buf [255]; - Arg av[10]; - int ac; - char *label; - XmString xm_label = 0; - XmString new_xm_label; + saver_screen_info *ssi = si->default_screen; + Widget parent = ssi->toplevel_shell; + char **hacks = si->prefs.screenhacks; - create_demo_dialog (parent); - ac = 0; - XtSetArg (av [ac], XmNlabelString, &xm_label); ac++; - XtGetValues (label1, av, ac); - XmStringGetLtoR (xm_label, XmSTRING_DEFAULT_CHARSET, &label); - if (!strcmp (label, XtName (label1))) - strcpy (buf, "ERROR: RESOURCES ARE NOT INSTALLED CORRECTLY"); - else - sprintf (buf, label, screensaver_version); - new_xm_label = XmStringCreate (buf, XmSTRING_DEFAULT_CHARSET); - ac = 0; - XtSetArg (av [ac], XmNlabelString, new_xm_label); ac++; - XtSetValues (label1, av, ac); - XmStringFree (new_xm_label); - XtFree (label); - - XtAddCallback (demo_list, XmNbrowseSelectionCallback, select_cb, - (XtPointer) hacks); - XtAddCallback (demo_list, XmNdefaultActionCallback, select_cb, - (XtPointer) hacks); - - XtAddCallback (text_line, XmNactivateCallback, text_cb, 0); - XtAddCallback (next, XmNactivateCallback, next_cb, 0); - XtAddCallback (prev, XmNactivateCallback, prev_cb, 0); - XtAddCallback (done, XmNactivateCallback, done_cb, 0); - XtAddCallback (restart, XmNactivateCallback, restart_cb, 0); - XtAddCallback (edit, XmNactivateCallback, edit_cb, (XtPointer) parent); - - for (; *hacks; hacks++) + if (ssi->demo_cmap && + ssi->demo_cmap != ssi->cmap && + ssi->demo_cmap != DefaultColormapOfScreen (ssi->screen)) { - XmString xmstr = XmStringCreate (*hacks, XmSTRING_DEFAULT_CHARSET); - XmListAddItem (demo_list, xmstr, 0); - /* XmListSelectPos (widget, i, False); */ - XmStringFree (xmstr); + XFreeColormap (si->dpy, ssi->demo_cmap); + ssi->demo_cmap = 0; } -#if 0 - /* Dialogs that have scroll-lists don't obey maxWidth! Fuck!! Hack it. */ - ac = 0; - XtSetArg (av [ac], XmNmaxWidth, &max_w); ac++; - XtGetValues (demo_dialog, av, ac); /* great, this SEGVs */ -#endif + if (ssi->default_visual == DefaultVisualOfScreen (ssi->screen)) + ssi->demo_cmap = DefaultColormapOfScreen (ssi->screen); + else + ssi->demo_cmap = XCreateColormap (si->dpy, + RootWindowOfScreen (ssi->screen), + ssi->default_visual, AllocNone); + + create_demo_dialog (parent, ssi->default_visual, ssi->demo_cmap); + format_into_label (label1, si->version); + + add_button_callback (next, next_cb, (XtPointer) si); + add_button_callback (prev, prev_cb, (XtPointer) si); + add_button_callback (done, done_cb, (XtPointer) si); + add_button_callback (restart, restart_cb, (XtPointer) si); + add_button_callback (edit, edit_cb, (XtPointer) si); + +#ifdef HAVE_MOTIF + XtAddCallback (demo_list, XmNbrowseSelectionCallback, + select_cb, (XtPointer) si); + XtAddCallback (demo_list, XmNdefaultActionCallback, + select_cb, (XtPointer) si); + XtAddCallback (text_line, XmNactivateCallback, text_cb, (XtPointer) si); + + if (hacks) + for (; *hacks; hacks++) + { + XmString xmstr = XmStringCreate (*hacks, XmSTRING_DEFAULT_CHARSET); + XmListAddItem (demo_list, xmstr, 0); + XmStringFree (xmstr); + } + + /* Cause the most-recently-run hack to be selected in the list. + Do some voodoo to make it be roughly centered in the list (really, + just make it not be within +/- 5 of the top/bottom if possible.) + */ + if (ssi->current_hack > 0) + { + int i = ssi->current_hack+1; + int top = i + 5; + int bot = i - 5; + if (bot < 1) bot = 1; + if (top > si->prefs.screenhacks_count) + top = si->prefs.screenhacks_count; + + XmListDeselectAllItems(demo_list); /* LessTif lossage */ + XmListSelectPos (demo_list, bot, False); + ensure_selected_item_visible (demo_list); + + XmListDeselectAllItems(demo_list); /* LessTif lossage */ + XmListSelectPos (demo_list, top, False); + ensure_selected_item_visible (demo_list); + + XmListDeselectAllItems(demo_list); /* LessTif lossage */ + XmListSelectPos (demo_list, i, False); + ensure_selected_item_visible (demo_list); + } - pop_up_dialog_box (demo_dialog, demo_form, 0); +#else /* HAVE_ATHENA */ + + /* Hook up the text line. */ + + XtAppAddActions(XtWidgetToApplicationContext(text_line), + actions, XtNumber(actions)); + XtOverrideTranslations(text_line, XtParseTranslationTable(translations)); + + + /* Must realize the widget before populating the list, or the dialog + will be as wide as the longest string. + */ + XtRealizeWidget (demo_dialog); + + XtVaSetValues (demo_list, + XtNlist, hacks, + XtNnumberStrings, si->prefs.screenhacks_count, + 0); + XtAddCallback (demo_list, XtNcallback, select_cb, si); + if (ssi->current_hack > 0) + XawListHighlight(demo_list, ssi->current_hack); + + /* Now that we've populated the list, make sure that the list is as + wide as the dialog itself. + */ + { + Widget viewport = XtParent(demo_list); + Widget subform = XtParent(viewport); + Widget box = XtNameToWidget(demo_dialog, "*box"); + Widget label1 = XtNameToWidget(demo_dialog, "*label1"); + Widget label2 = XtNameToWidget(demo_dialog, "*label2"); + Dimension x=0, y=0, w=0, h=0, bw=0, w2=0; + XtVaGetValues(subform, + XtNwidth, &w, XtNheight, &h, XtNborderWidth, &bw, 0); + XtVaGetValues(box, XtNwidth, &w2, 0); + if (w2 != w) + XtResizeWidget(subform, w2, h, bw); + + /* Why isn't the viewport getting centered? */ + XtVaGetValues(viewport, + XtNx, &x, XtNy, &y, XtNheight, &h, XtNborderWidth, &bw, 0); +/* printf("%d %d %d %d\n", x, y, w, h); */ + XtConfigureWidget(viewport, x, y, w2-x-x, h, bw); + + /* And the text line, too. */ + XtVaGetValues(text_line, + XtNwidth, &w, XtNheight, &h, XtNborderWidth, &bw, 0); + XtVaGetValues(viewport, XtNwidth, &w2, 0); + if (w2 != w) + XtResizeWidget(text_line, w2, h, bw); + + /* And the labels too. */ + XtVaGetValues(label1, + XtNwidth, &w, XtNheight, &h, XtNborderWidth, &bw, 0); + if (w2 != w) + XtResizeWidget(label1, w2, h, bw); + + XtVaGetValues(label2, + XtNwidth, &w, XtNheight, &h, XtNborderWidth, &bw, 0); + if (w2 != w) + XtResizeWidget(label2, w2, h, bw); + + } + +#endif /* HAVE_ATHENA */ + + monitor_power_on (si); + pop_up_dialog_box(demo_dialog, demo_form, + /* for debugging -- don't ask */ + (si->prefs.debug_p ? 69 : 0) + + 0); + +#ifdef HAVE_ATHENA + /* For Athena, have to do this after the dialog is managed. */ + ensure_selected_item_visible (demo_list); +#endif /* HAVE_ATHENA */ } @@ -338,14 +753,8 @@ static struct resources { } res; -extern int parse_time (); - static void -hack_time_cb (dpy, line, store, sec_p) - Display *dpy; - char *line; - int *store; - Bool sec_p; +hack_time_cb (Display *dpy, char *line, int *store, Bool sec_p) { if (*line) { @@ -359,29 +768,23 @@ hack_time_cb (dpy, line, store, sec_p) } static void -res_sec_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +res_sec_cb (Widget button, XtPointer client_data, XtPointer call_data) { - hack_time_cb (XtDisplay (button), XmTextGetString (button), + hack_time_cb (XtDisplay (button), get_text_string (button), (int *) client_data, True); } static void -res_min_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +res_min_cb (Widget button, XtPointer client_data, XtPointer call_data) { - hack_time_cb (XtDisplay (button), XmTextGetString (button), + hack_time_cb (XtDisplay (button), get_text_string (button), (int *) client_data, False); } static void -res_int_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +res_int_cb (Widget button, XtPointer client_data, XtPointer call_data) { - char *line = XmTextGetString (button); + char *line = get_text_string (button); int *store = (int *) client_data; unsigned int value; char c; @@ -394,104 +797,180 @@ res_int_cb (button, client_data, call_data) } static void -res_bool_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +res_bool_cb (Widget button, XtPointer client_data, XtPointer call_data) { int *store = (int *) client_data; +#ifdef HAVE_MOTIF *store = ((XmToggleButtonCallbackStruct *) call_data)->set; +#else /* HAVE_ATHENA */ + Boolean state = FALSE; + XtVaGetValues (button, XtNstate, &state, NULL); + *store = state; +#endif /* HAVE_ATHENA */ } static void -res_cancel_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +res_cancel_cb (Widget button, XtPointer client_data, XtPointer call_data) { + saver_info *si = (saver_info *) client_data; + saver_preferences *p = &si->prefs; + XtDestroyWidget (resources_dialog); resources_dialog = 0; raise_screenhack_dialog (); + + if (p->verbose_p) + fprintf (stderr, "%s: lowering preferences dialog.\n", blurb()); } static void -res_done_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +res_done_cb (Widget button, XtPointer client_data, XtPointer call_data) { + saver_info *si = (saver_info *) client_data; + saver_preferences *p = &si->prefs; + res_cancel_cb (button, client_data, call_data); - if (res.timeout < 10) res.timeout = 10; +#ifdef HAVE_ATHENA + /* Check all text widgets, since we don't have callbacks for these. */ + res_min_cb (timeout_text, (XtPointer) &res.timeout, NULL); + res_min_cb (cycle_text, (XtPointer) &res.cycle, NULL); + res_sec_cb (fade_text, (XtPointer) &res.secs, NULL); + res_int_cb (ticks_text, (XtPointer) &res.ticks, NULL); + res_min_cb (lock_time_text, (XtPointer) &res.lock_time, NULL); + res_sec_cb (passwd_time_text, (XtPointer) &res.passwd_time, NULL); +#endif /* HAVE_ATHENA */ + + /* Throttle the timeouts to minimum sane values. */ + if (res.timeout < 5) res.timeout = 5; if (res.cycle < 2) res.cycle = 2; - if (res.passwd_time < 2) res.passwd_time = 30; + if (res.passwd_time < 10) res.passwd_time = 10; - timeout = res.timeout * 1000; - cycle = res.cycle * 1000; - lock_timeout = res.lock_time * 1000; + p->timeout = res.timeout * 1000; + p->cycle = res.cycle * 1000; + p->lock_timeout = res.lock_time * 1000; #ifndef NO_LOCKING - passwd_timeout = res.passwd_time * 1000; + p->passwd_timeout = res.passwd_time * 1000; +#endif + p->fade_seconds = res.secs; + p->fade_ticks = res.ticks; + p->verbose_p = res.verb; + p->install_cmap_p = res.cmap; + p->fade_p = res.fade; + p->unfade_p = res.unfade; + p->lock_p = res.lock_p; + + if (p->debug_p && p->verbose_p) + fprintf (stderr, "%s: parameters changed:\n\ + timeout: %d\n\tcycle: %d\n\tlock: %d\n\tpasswd: %d\n\ + fade: %d\n\tfade: %d\n\tverbose: %d\n\tinstall: %d\n\ + fade: %d\n\tunfade: %d\n\tlock: %d\n", + blurb(), p->timeout, p->cycle, p->lock_timeout, +#ifdef NO_LOCKING + 0, +#else + p->passwd_timeout, #endif - fade_seconds = res.secs; - fade_ticks = res.ticks; - verbose_p = res.verb; - install_cmap_p = res.cmap; - fade_p = res.fade; - unfade_p = res.unfade; - lock_p = res.lock_p; + p->fade_seconds, p->fade_ticks, p->verbose_p, p->install_cmap_p, + p->fade_p, p->unfade_p, p->lock_p); + + +#if defined(HAVE_MIT_SAVER_EXTENSION) || defined(HAVE_SGI_SAVER_EXTENSION) + if (p->use_mit_saver_extension || p->use_sgi_saver_extension) + { + /* Need to set the server timeout to the new one the user has picked. + */ + int server_timeout, server_interval, prefer_blank, allow_exp; + XGetScreenSaver (si->dpy, &server_timeout, &server_interval, + &prefer_blank, &allow_exp); + if (server_timeout != (p->timeout / 1000)) + { + server_timeout = (p->timeout / 1000); + if (p->verbose_p) + fprintf (stderr, + "%s: configuring server for saver timeout of %d seconds.\n", + blurb(), server_timeout); + /* Leave all other parameters the same. */ + XSetScreenSaver (si->dpy, server_timeout, server_interval, + prefer_blank, allow_exp); + } + } +#endif /* HAVE_MIT_SAVER_EXTENSION || HAVE_SGI_SAVER_EXTENSION */ + + write_init_file (si); } static void -make_resources_dialog (parent) - Widget parent; +make_resources_dialog (saver_info *si, Widget parent) { - Arg av[10]; - int ac; + saver_screen_info *ssi = si->default_screen; - create_resources_dialog (parent); + if (ssi->demo_cmap && + ssi->demo_cmap != ssi->cmap && + ssi->demo_cmap != DefaultColormapOfScreen (ssi->screen)) + { + XFreeColormap (si->dpy, ssi->demo_cmap); + ssi->demo_cmap = 0; + } + + if (ssi->default_visual == DefaultVisualOfScreen (ssi->screen)) + ssi->demo_cmap = DefaultColormapOfScreen (ssi->screen); + else + ssi->demo_cmap = XCreateColormap (si->dpy, + RootWindowOfScreen (ssi->screen), + ssi->default_visual, AllocNone); - XtAddCallback (res_done, XmNactivateCallback, res_done_cb, 0); - XtAddCallback (res_cancel, XmNactivateCallback, res_cancel_cb, 0); + create_resources_dialog (parent, ssi->default_visual, ssi->demo_cmap); + + add_button_callback (res_done, res_done_cb, (XtPointer) si); + add_button_callback (res_cancel, res_cancel_cb, (XtPointer) si); #define CB(widget,type,slot) \ - XtAddCallback ((widget), XmNvalueChangedCallback, (type), \ - (XtPointer) (slot)) + add_text_callback ((widget), (type), (XtPointer) (slot)) +#define CBT(widget,type,slot) \ + add_toggle_callback ((widget), (type), (XtPointer) (slot)) + +#ifdef HAVE_MOTIF + /* When using Athena widgets, we can't set callbacks for these, + so we'll check them all if "done" gets pressed. + */ CB (timeout_text, res_min_cb, &res.timeout); CB (cycle_text, res_min_cb, &res.cycle); CB (fade_text, res_sec_cb, &res.secs); CB (ticks_text, res_int_cb, &res.ticks); CB (lock_time_text, res_min_cb, &res.lock_time); CB (passwd_time_text, res_sec_cb, &res.passwd_time); - CB (verbose_toggle, res_bool_cb, &res.verb); - CB (cmap_toggle, res_bool_cb, &res.cmap); - CB (fade_toggle, res_bool_cb, &res.fade); - CB (unfade_toggle, res_bool_cb, &res.unfade); - CB (lock_toggle, res_bool_cb, &res.lock_p); +#endif /* HAVE_MOTIF */ + + CBT (verbose_toggle, res_bool_cb, &res.verb); + CBT (cmap_toggle, res_bool_cb, &res.cmap); + CBT (fade_toggle, res_bool_cb, &res.fade); + CBT (unfade_toggle, res_bool_cb, &res.unfade); + CBT (lock_toggle, res_bool_cb, &res.lock_p); #undef CB - ac = 0; - XtSetArg (av[ac], XmNsensitive, False); ac++; +#undef CBT - if (locking_disabled_p) + if (si->locking_disabled_p) { - XtSetValues (passwd_time_text, av, ac); - XtSetValues (lock_time_text, av, ac); - XtSetValues (lock_toggle, av, ac); + disable_widget (passwd_time_text); + disable_widget (lock_time_text); + disable_widget (lock_toggle); } - if (CellsOfScreen (XtScreen (parent)) <= 2) + if (!si->fading_possible_p) { - XtSetValues (fade_text, av, ac); - XtSetValues (ticks_text, av, ac); - XtSetValues (cmap_toggle, av, ac); - XtSetValues (fade_toggle, av, ac); - XtSetValues (unfade_toggle, av, ac); + disable_widget (fade_text); + disable_widget (ticks_text); + disable_widget (cmap_toggle); + disable_widget (fade_toggle); + disable_widget (unfade_toggle); } } static void -fmt_time (buf, s, min_p) - char *buf; - unsigned int s; - int min_p; +fmt_time (char *buf, unsigned int s, int min_p) { unsigned int h = 0, m = 0; if (s >= 60) @@ -518,140 +997,159 @@ fmt_time (buf, s, min_p) } static void -pop_resources_dialog () +pop_resources_dialog (saver_info *si) { + saver_preferences *p = &si->prefs; char buf [100]; - res.timeout = timeout / 1000; - res.cycle = cycle / 1000; - res.lock_time = lock_timeout / 1000; + if (p->verbose_p) + fprintf (stderr, "%s: raising preferences dialog.\n", blurb()); + + res.timeout = p->timeout / 1000; + res.cycle = p->cycle / 1000; + res.lock_time = p->lock_timeout / 1000; #ifndef NO_LOCKING - res.passwd_time = passwd_timeout / 1000; + res.passwd_time = p->passwd_timeout / 1000; #endif - res.secs = fade_seconds; - res.ticks = fade_ticks; - res.verb = verbose_p; - res.cmap = install_cmap_p; - res.fade = fade_p; - res.unfade = unfade_p; - res.lock_p = (lock_p && !locking_disabled_p); - - fmt_time (buf, res.timeout, 1); XmTextSetString (timeout_text, buf); - fmt_time (buf, res.cycle, 1); XmTextSetString (cycle_text, buf); - fmt_time (buf, res.lock_time, 1); XmTextSetString (lock_time_text, buf); - fmt_time (buf, res.passwd_time, 0); XmTextSetString (passwd_time_text, buf); - fmt_time (buf, res.secs, 0); XmTextSetString (fade_text, buf); - sprintf (buf, "%u", res.ticks); XmTextSetString (ticks_text, buf); - - XmToggleButtonSetState (verbose_toggle, res.verb, True); - XmToggleButtonSetState (cmap_toggle, res.cmap, True); - XmToggleButtonSetState (fade_toggle, res.fade, True); - XmToggleButtonSetState (unfade_toggle, res.unfade, True); - XmToggleButtonSetState (lock_toggle, res.lock_p, True); - - pop_up_dialog_box (resources_dialog, resources_form, 1); + res.secs = p->fade_seconds; + res.ticks = p->fade_ticks; + res.verb = p->verbose_p; + res.cmap = p->install_cmap_p; + res.fade = p->fade_p; + res.unfade = p->unfade_p; + res.lock_p = (p->lock_p && !si->locking_disabled_p); + + fmt_time (buf, res.timeout, 1); set_text_string (timeout_text, buf); + fmt_time (buf, res.cycle, 1); set_text_string (cycle_text, buf); + fmt_time (buf, res.lock_time, 1); set_text_string (lock_time_text, buf); + fmt_time (buf, res.passwd_time, 0); set_text_string (passwd_time_text, buf); + fmt_time (buf, res.secs, 0); set_text_string (fade_text, buf); + sprintf (buf, "%u", res.ticks); set_text_string (ticks_text, buf); + + set_toggle_button_state (verbose_toggle, res.verb); + set_toggle_button_state (cmap_toggle, res.cmap); + set_toggle_button_state (fade_toggle, res.fade); + set_toggle_button_state (unfade_toggle, res.unfade); + set_toggle_button_state (lock_toggle, res.lock_p); + + monitor_power_on (si); + pop_up_dialog_box (resources_dialog, resources_form, + /* for debugging -- don't ask */ + (si->prefs.debug_p ? 69 : 0) + + 1); } -/* The code on this page isn't actually Motif-specific */ +/* The main demo-mode command loop. + */ -Bool dbox_up_p = False; -Bool demo_mode_p = False; +void +demo_mode (saver_info *si) +{ + saver_preferences *p = &si->prefs; + Bool prefs_p = (si->demo_mode_p == (Bool) 2); /* kludge! */ -extern XtAppContext app; -extern Widget toplevel_shell; -extern Bool use_xidle_extension; -extern Bool use_saver_extension; -extern Time notice_events_timeout; + if (p->verbose_p) + fprintf (stderr, "%s: Demo Mode.\n", blurb()); -extern char **screenhacks; -extern char *demo_hack; + si->selection_mode = 0; + si->dbox_up_p = True; + monitor_power_on (si); + raise_window (si, True, False, False); + make_screenhack_dialog (si); -extern void notice_events_timer P((XtPointer closure, XtIntervalId *timer)); -extern Bool handle_clientmessage P((/*XEvent *, Bool*/)); + if (prefs_p) + edit_cb (0, si, 0); /* pop up preferences panel */ -void -demo_mode () -{ - dbox_up_p = True; - initialize_screensaver_window (); - raise_window (True, False); - make_screenhack_dialog (toplevel_shell, screenhacks); - while (demo_mode_p) + while (si->demo_mode_p) { XEvent event; - XtAppNextEvent (app, &event); + XtAppNextEvent (si->app, &event); switch (event.xany.type) { case 0: /* synthetic "timeout" event */ break; case ClientMessage: - handle_clientmessage (&event, False); + handle_clientmessage (si, &event, False); break; case CreateNotify: - if (!use_xidle_extension && !use_saver_extension) + if (!p->use_xidle_extension && + !p->use_mit_saver_extension && + !p->use_sgi_saver_extension) { - XtAppAddTimeOut (app, notice_events_timeout, notice_events_timer, - (XtPointer) event.xcreatewindow.window); + start_notice_events_timer (si, event.xcreatewindow.window); #ifdef DEBUG_TIMERS - if (verbose_p) - printf ("%s: starting notice_events_timer for 0x%X (%lu)\n", - progname, - (unsigned int) event.xcreatewindow.window, - notice_events_timeout); + if (p->verbose_p) + fprintf (stderr, + "%s: starting notice_events_timer for 0x%X (%lu)\n", + blurb(), + (unsigned int) event.xcreatewindow.window, + p->notice_events_timeout); #endif /* DEBUG_TIMERS */ } break; case ButtonPress: case ButtonRelease: - if (!XtWindowToWidget (dpy, event.xbutton.window)) + if (!XtWindowToWidget (si->dpy, event.xbutton.window)) raise_screenhack_dialog (); /* fall through */ default: -#ifdef HAVE_SAVER_EXTENSION - if (event.type == saver_ext_event_number) +#ifdef HAVE_MIT_SAVER_EXTENSION + if (event.type == si->mit_saver_ext_event_number) { - /* Get the "real" server window out of the way as soon + /* Get the "real" server window(s) out of the way as soon as possible. */ - if (server_saver_window && - window_exists_p (dpy, server_saver_window)) - XUnmapWindow (dpy, server_saver_window); + int i = 0; + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + if (ssi->server_mit_saver_window && + window_exists_p (si->dpy, ssi->server_mit_saver_window)) + XUnmapWindow (si->dpy, ssi->server_mit_saver_window); + } } else -#endif /* HAVE_SAVER_EXTENSION */ +#endif /* HAVE_MIT_SAVER_EXTENSION */ XtDispatchEvent (&event); break; } } - destroy_screenhack_dialogs (); - initialize_screensaver_window (); - unblank_screen (); + + if (p->verbose_p) + fprintf (stderr, "%s: Demo Mode done.\n", blurb()); + + kill_screenhack (si); + + destroy_screenhack_dialogs (si); + initialize_screensaver_window (si); + + si->dbox_up_p = False; + si->demo_hack = 0; + + si->demo_mode_p = True; /* kludge to inhibit unfade... */ + unblank_screen (si); + si->demo_mode_p = False; } static void -demo_mode_hack (hack) - char *hack; +demo_mode_hack (saver_info *si, char *hack) { - if (! demo_mode_p) abort (); - kill_screenhack (); - if (! demo_hack) - blank_screen (); - demo_hack = hack; - spawn_screenhack (False); + if (! si->demo_mode_p) abort (); + kill_screenhack (si); + if (! si->demo_hack) + blank_screen (si); + si->demo_hack = hack; + spawn_screenhack (si, False); + /* raise_screenhack_dialog(); */ } static void -demo_mode_done () +demo_mode_done (saver_info *si) { - kill_screenhack (); - if (demo_hack) - unblank_screen (); - demo_mode_p = False; - dbox_up_p = False; - demo_hack = 0; + si->demo_mode_p = False; }