1 /* demo.c --- implements the interactive demo-mode and options dialogs.
2 * xscreensaver, Copyright (c) 1993-1998 Jamie Zawinski <jwz@jwz.org>
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
17 #include <X11/Intrinsic.h>
18 #include <X11/StringDefs.h>
20 /* We don't actually use any widget internals, but these are included
21 so that gdb will have debug info for the widgets... */
22 #include <X11/IntrinsicP.h>
23 #include <X11/ShellP.h>
29 # include <Xm/ToggleB.h>
31 #else /* HAVE_ATHENA */
32 /* Athena demo code contributed by Jon A. Christopher <jac8782@tamu.edu> */
33 /* Copyright 1997, with the same permissions as above. */
34 # include <X11/Shell.h>
35 # include <X11/Xaw/Form.h>
36 # include <X11/Xaw/Box.h>
37 # include <X11/Xaw/List.h>
38 # include <X11/Xaw/Command.h>
39 # include <X11/Xaw/Toggle.h>
40 # include <X11/Xaw/Viewport.h>
41 # include <X11/Xaw/Dialog.h>
42 # include <X11/Xaw/Scrollbar.h>
43 # include <X11/Xaw/Text.h>
44 #endif /* HAVE_ATHENA */
46 #include "xscreensaver.h"
47 #include "resources.h" /* for parse_time() */
53 ERROR! You must not include vroot.h in this file.
56 static void demo_mode_hack (saver_info *si, char *);
57 static void demo_mode_done (saver_info *si);
59 extern Widget demo_dialog;
61 extern Widget text_line;
62 extern Widget demo_form;
63 extern Widget demo_list;
64 extern Widget next, prev, done, restart, edit;
66 extern Widget resources_dialog;
67 extern Widget resources_form;
68 extern Widget res_done, res_cancel;
69 extern Widget timeout_text, cycle_text, fade_text, ticks_text;
70 extern Widget lock_time_text, passwd_time_text;
71 extern Widget verbose_toggle, cmap_toggle, fade_toggle, unfade_toggle,
74 extern Widget splash_dialog;
79 # define set_toggle_button_state(toggle,state) \
80 XmToggleButtonSetState ((toggle), (state), True)
81 # define set_text_string(text_widget,string) \
82 XmTextSetString ((text_widget), (string))
83 # define add_button_callback(button,cb,arg) \
84 XtAddCallback ((button), XmNactivateCallback, (cb), (arg))
85 # define add_toggle_callback(button,cb,arg) \
86 XtAddCallback ((button), XmNvalueChangedCallback, (cb), (arg))
87 # define add_text_callback add_toggle_callback
89 #else /* HAVE_ATHENA */
91 # define set_toggle_button_state(toggle,state) \
92 XtVaSetValues((toggle), XtNstate, (state), 0)
93 # define set_text_string(text_widget,string) \
94 XtVaSetValues ((text_widget), XtNvalue, (string), 0)
95 # define add_button_callback(button,cb,arg) \
96 XtAddCallback ((button), XtNcallback, (cb), (arg))
97 # define add_toggle_callback add_button_callback
98 # define add_text_callback(b,c,a) ERROR!
100 #endif /* HAVE_ATHENA */
103 #define disable_widget(widget) \
104 XtVaSetValues((widget), XtNsensitive, False, 0)
108 get_text_string (Widget text_widget)
111 return XmTextGetString (text_widget);
112 #else /* HAVE_ATHENA */
114 if (XtIsSubclass(text_widget, textWidgetClass))
115 XtVaGetValues (text_widget, XtNstring, &string, 0);
116 else if (XtIsSubclass(text_widget, dialogWidgetClass))
117 XtVaGetValues (text_widget, XtNvalue, &string, 0);
122 #endif /* HAVE_ATHENA */
126 get_label_string (Widget label_widget)
130 XmString xm_label = 0;
131 XtVaGetValues (label_widget, XmNlabelString, &xm_label, 0);
134 XmStringGetLtoR (xm_label, XmSTRING_DEFAULT_CHARSET, &label);
136 #else /* HAVE_ATHENA */
138 XtVaGetValues (label_widget, XtNlabel, &label, 0);
139 return (label ? strdup(label) : 0);
140 #endif /* HAVE_ATHENA */
145 set_label_string (Widget label_widget, char *string)
148 XmString xm_string = XmStringCreate (string, XmSTRING_DEFAULT_CHARSET);
149 XtVaSetValues (label_widget, XmNlabelString, xm_string, 0);
150 XmStringFree (xm_string);
151 #else /* HAVE_ATHENA */
152 XtVaSetValues (label_widget, XtNlabel, string, 0);
153 #endif /* HAVE_ATHENA */
158 format_into_label (Widget label, const char *arg)
160 char *text = get_label_string (label);
161 char *buf = (char *) malloc ((text ? strlen(text) : 100) + strlen(arg) + 10);
163 if (!text || !strcmp (text, XtName (label)))
164 strcpy (buf, "ERROR: RESOURCES ARE NOT INSTALLED CORRECTLY");
166 sprintf (buf, text, arg);
168 set_label_string (label, buf);
175 steal_focus_and_colormap (Widget dialog)
177 Display *dpy = XtDisplay (dialog);
178 Window window = XtWindow (dialog);
180 XSetInputFocus (dpy, window, RevertToParent, CurrentTime);
182 XtVaGetValues (dialog, XtNcolormap, &cmap, 0);
184 XInstallColormap (dpy, cmap);
188 raise_screenhack_dialog (void)
190 XMapRaised (XtDisplay (demo_dialog), XtWindow (demo_dialog));
191 if (resources_dialog)
192 XMapRaised (XtDisplay (resources_dialog), XtWindow (resources_dialog));
193 steal_focus_and_colormap (resources_dialog ? resources_dialog : demo_dialog);
197 destroy_screenhack_dialogs (saver_info *si)
199 saver_screen_info *ssi = si->default_screen;
201 if (demo_dialog) XtDestroyWidget (demo_dialog);
202 if (resources_dialog) XtDestroyWidget (resources_dialog);
203 demo_dialog = resources_dialog = 0;
205 if (ssi->demo_cmap &&
206 ssi->demo_cmap != ssi->cmap &&
207 ssi->demo_cmap != DefaultColormapOfScreen (ssi->screen))
209 XFreeColormap (si->dpy, ssi->demo_cmap);
213 /* Since we installed our colormap to display the dialogs properly, put
214 the old one back, so that the screensaver_window is now displayed
217 XInstallColormap (si->dpy, ssi->cmap);
222 text_cb (Widget text_widget, XtPointer client_data, XtPointer call_data)
224 saver_info *si = (saver_info *) client_data;
225 saver_preferences *p = &si->prefs;
227 line = get_text_string (text_widget);
230 fprintf (stderr, "%s: processing text \"%s\".\n", blurb(), line);
232 demo_mode_hack (si, line);
237 /* Bend over backwards to make hitting Return in the text field do the
240 extern saver_info *global_si_kludge;
241 static void text_enter (Widget w, XEvent *event, String *av, Cardinal *ac)
243 text_cb (w, global_si_kludge, 0);
246 static XtActionsRec actions[] = {{"done", text_enter}
248 static char translations[] = ("<Key>Return: done()\n"
249 "<Key>Linefeed: done()\n"
250 "Ctrl<Key>M: done()\n"
251 "Ctrl<Key>J: done()\n");
252 #endif /* HAVE_ATHENA */
256 select_cb (Widget button, XtPointer client_data, XtPointer call_data)
258 saver_info *si = (saver_info *) client_data;
261 XawListReturnStruct *item = (XawListReturnStruct*)call_data;
262 XtVaSetValues(text_line, XtNstring, item->string, 0);
264 demo_mode_hack (si, item->string);
265 if (item->list_index >= 0)
266 si->default_screen->current_hack = item->list_index;
268 #else /* HAVE_MOTIF */
269 XmListCallbackStruct *lcb = (XmListCallbackStruct *) call_data;
272 XmStringGetLtoR (lcb->item, XmSTRING_DEFAULT_CHARSET, &string);
273 set_text_string (text_line, (string ? string : ""));
274 if (lcb->reason == XmCR_DEFAULT_ACTION && string)
276 demo_mode_hack (si, string);
277 if (lcb->item_position > 0)
278 si->default_screen->current_hack = lcb->item_position - 1;
282 #endif /* HAVE_MOTIF */
283 steal_focus_and_colormap (demo_dialog);
287 /* Why this behavior isn't automatic in *either* toolkit, I'll never know.
290 ensure_selected_item_visible (Widget list)
295 if (XmListGetSelectedPos (list, &pos_list, &pos_count) && pos_count > 0)
300 XmNtopItemPosition, &top,
301 XmNvisibleItemCount, &visible,
303 if (pos_list[0] >= top + visible)
305 int pos = pos_list[0] - visible + 1;
306 if (pos < 0) pos = 0;
307 XmListSetPos (list, pos);
309 else if (pos_list[0] < top)
311 XmListSetPos (list, pos_list[0]);
315 XtFree ((char *) pos_list);
317 #else /* HAVE_ATHENA */
318 # ifdef HAVE_XawViewportSetCoordinates
320 int margin = 16; /* should be line height or something. */
323 Dimension list_h = 0, vp_h = 0;
324 Dimension top_margin = 4; /* I don't know where this value comes from */
325 Position vp_x = 0, vp_y = 0, current_y;
327 Widget viewport = XtParent(demo_list);
328 Widget sb = (viewport ? XtNameToWidget(viewport, "*vertical") : 0);
329 float sb_top = 0, sb_size = 0;
330 XawListReturnStruct *current = XawListShowCurrent(demo_list);
331 if (!current || !sb) return;
333 XtVaGetValues(demo_list,
334 XtNnumberStrings, &count,
337 if (count < 2 || list_h < 10) return;
339 XtVaGetValues(viewport, XtNheight, &vp_h, XtNx, &vp_x, XtNy, &vp_y, 0);
340 if (vp_h < 10) return;
342 XtVaGetValues(sb, XtNtopOfThumb, &sb_top, XtNshown, &sb_size, 0);
343 if (sb_size <= 0) return;
345 pos = current->list_index;
346 cratio = ((double) pos) / ((double) count);
347 current_y = (cratio * list_h);
349 if (cratio < sb_top ||
350 cratio > sb_top + sb_size)
353 current_y -= (vp_h - margin - margin);
357 if ((long)current_y >= (long) list_h)
358 current_y = (Position) ((long)list_h - (long)vp_h);
360 if ((long)current_y < (long)top_margin)
361 current_y = (Position)top_margin;
363 XawViewportSetCoordinates (viewport, vp_x, current_y);
365 # endif /* HAVE_XawViewportSetCoordinates */
366 #endif /* HAVE_ATHENA */
371 next_cb (Widget button, XtPointer client_data, XtPointer call_data)
373 saver_info *si = (saver_info *) client_data;
374 saver_preferences *p = &si->prefs;
377 fprintf (stderr, "%s: Run Next\n", blurb());
382 XawListReturnStruct *current = XawListShowCurrent(demo_list);
383 if (current->list_index == XAW_LIST_NONE)
384 XawListHighlight(demo_list, 0);
387 XtVaGetValues(demo_list,
388 XtNnumberStrings, &cnt,
390 if (current->list_index + 1 < cnt)
392 current->list_index++;
393 XawListHighlight(demo_list, current->list_index);
397 ensure_selected_item_visible (demo_list);
398 current = XawListShowCurrent(demo_list);
399 XtVaSetValues(text_line, XtNstring, current->string, 0);
400 demo_mode_hack (si, current->string);
402 #else /* HAVE_MOTIF */
406 if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
408 XmListDeselectAllItems(demo_list); /* LessTif lossage */
409 XmListSelectPos (demo_list, 1, True);
413 int pos = pos_list[0] + 1;
414 if (pos > si->prefs.screenhacks_count)
416 XmListDeselectAllItems(demo_list); /* LessTif lossage */
417 XmListSelectPos (demo_list, pos, True);
419 XtFree ((char *) pos_list);
420 ensure_selected_item_visible (demo_list);
421 demo_mode_hack (si, get_text_string (text_line));
423 #endif /* HAVE_MOTIF */
429 prev_cb (Widget button, XtPointer client_data, XtPointer call_data)
431 saver_info *si = (saver_info *) client_data;
432 saver_preferences *p = &si->prefs;
435 fprintf (stderr, "%s: Run Previous\n", blurb());
439 XawListReturnStruct *current=XawListShowCurrent(demo_list);
440 if (current->list_index == XAW_LIST_NONE)
441 XawListHighlight(demo_list, 0);
444 if (current->list_index >= 1)
446 current->list_index--;
447 XawListHighlight(demo_list, current->list_index);
451 ensure_selected_item_visible (demo_list);
452 current = XawListShowCurrent(demo_list);
453 XtVaSetValues(text_line, XtNstring, current->string, 0);
454 demo_mode_hack (si, current->string);
456 #else /* HAVE_MOTIF */
460 if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
462 XmListDeselectAllItems(demo_list); /* LessTif lossage */
463 XmListSelectPos (demo_list, 0, True);
467 XmListDeselectAllItems(demo_list); /* LessTif lossage */
468 XmListSelectPos (demo_list, pos_list [0] - 1, True);
469 XtFree ((char *) pos_list);
471 ensure_selected_item_visible (demo_list);
472 demo_mode_hack (si, get_text_string (text_line));
474 #endif /* HAVE_MOTIF */
479 static void pop_resources_dialog (saver_info *si);
480 static void make_resources_dialog (saver_info *si, Widget parent);
483 edit_cb (Widget button, XtPointer client_data, XtPointer call_data)
485 saver_info *si = (saver_info *) client_data;
486 saver_screen_info *ssi = si->default_screen;
487 saver_preferences *p = &si->prefs;
488 Widget parent = ssi->toplevel_shell;
491 fprintf (stderr, "%s: Preferences\n", blurb());
493 if (! resources_dialog)
494 make_resources_dialog (si, parent);
495 pop_resources_dialog (si);
499 done_cb (Widget button, XtPointer client_data, XtPointer call_data)
501 saver_info *si = (saver_info *) client_data;
507 restart_cb (Widget button, XtPointer client_data, XtPointer call_data)
509 saver_info *si = (saver_info *) client_data;
510 saver_preferences *p = &si->prefs;
512 fprintf (stderr, "%s: Restart\n", blurb());
513 demo_mode_restart_process (si);
518 pop_up_dialog_box (Widget dialog, Widget form, int where)
520 /* I'm sure this is the wrong way to pop up a dialog box, but I can't
521 figure out how else to do it.
523 It's important that the screensaver dialogs not get decorated or
524 otherwise reparented by the window manager, because they need to be
525 children of the *real* root window, not the WM's virtual root, in
526 order for us to guarentee that they are visible above the screensaver
531 Dimension sw, sh, x, y, w, h;
534 XtRealizeWidget (dialog);
535 #else /* HAVE_MOTIF */
536 /* Motif likes us to realize the *child* of the shell... */
537 XtRealizeWidget (form);
538 #endif /* HAVE_MOTIF */
540 sw = WidthOfScreen (XtScreen (dialog));
541 sh = HeightOfScreen (XtScreen (dialog));
543 XtSetArg (av [ac], XtNwidth, &w); ac++;
544 XtSetArg (av [ac], XtNheight, &h); ac++;
545 XtGetValues (form, av, ac);
547 /* for debugging -- don't ask */
556 case 0: /* center it in the top-right quadrant */
557 x = (sw/2 + w) / 2 + (sw/2) - w;
558 y = (sh/2 + h) / 2 - h;
560 case 1: /* center it in the bottom-right quadrant */
561 x = (sw/2 + w) / 2 + (sw/2) - w;
562 y = (sh/2 + h) / 2 + (sh/2) - h;
564 case 2: /* center it on the screen */
565 x = (sw + w) / 2 - w;
566 y = (sh + h) / 2 - h;
568 case 3: /* center it in the top 2/3rds of the screen */
569 x = (sw + w) / 2 - w;
570 y = (sh*2/3 + h) / 2 - h;
575 if (x + w > sw) x = sw - w;
576 if (y + h > sh) y = sh - h;
578 XtSetArg (av [ac], XtNx, x); ac++;
579 XtSetArg (av [ac], XtNy, y); ac++;
580 XtSetArg (av [ac], XtNoverrideRedirect, True); ac++;
583 XtSetArg (av [ac], XmNdefaultPosition, False); ac++;
584 #endif /* HAVE_MOTIF */
586 XtSetValues (dialog, av, ac);
587 XtSetValues (form, av, ac);
590 XtPopup (dialog, XtGrabNone);
591 #else /* HAVE_MOTIF */
592 XtManageChild (form);
593 #endif /* HAVE_MOTIF */
595 if (dialog != splash_dialog)
596 steal_focus_and_colormap (dialog);
601 make_screenhack_dialog (saver_info *si)
603 saver_screen_info *ssi = si->default_screen;
604 Widget parent = ssi->toplevel_shell;
605 char **hacks = si->prefs.screenhacks;
607 if (ssi->demo_cmap &&
608 ssi->demo_cmap != ssi->cmap &&
609 ssi->demo_cmap != DefaultColormapOfScreen (ssi->screen))
611 XFreeColormap (si->dpy, ssi->demo_cmap);
615 if (ssi->default_visual == DefaultVisualOfScreen (ssi->screen))
616 ssi->demo_cmap = DefaultColormapOfScreen (ssi->screen);
618 ssi->demo_cmap = XCreateColormap (si->dpy,
619 RootWindowOfScreen (ssi->screen),
620 ssi->default_visual, AllocNone);
622 create_demo_dialog (parent, ssi->default_visual, ssi->demo_cmap);
623 format_into_label (label1, si->version);
625 add_button_callback (next, next_cb, (XtPointer) si);
626 add_button_callback (prev, prev_cb, (XtPointer) si);
627 add_button_callback (done, done_cb, (XtPointer) si);
628 add_button_callback (restart, restart_cb, (XtPointer) si);
629 add_button_callback (edit, edit_cb, (XtPointer) si);
632 XtAddCallback (demo_list, XmNbrowseSelectionCallback,
633 select_cb, (XtPointer) si);
634 XtAddCallback (demo_list, XmNdefaultActionCallback,
635 select_cb, (XtPointer) si);
636 XtAddCallback (text_line, XmNactivateCallback, text_cb, (XtPointer) si);
639 for (; *hacks; hacks++)
641 XmString xmstr = XmStringCreate (*hacks, XmSTRING_DEFAULT_CHARSET);
642 XmListAddItem (demo_list, xmstr, 0);
643 XmStringFree (xmstr);
646 /* Cause the most-recently-run hack to be selected in the list.
647 Do some voodoo to make it be roughly centered in the list (really,
648 just make it not be within +/- 5 of the top/bottom if possible.)
650 if (ssi->current_hack > 0)
652 int i = ssi->current_hack+1;
655 if (bot < 1) bot = 1;
656 if (top > si->prefs.screenhacks_count)
657 top = si->prefs.screenhacks_count;
659 XmListDeselectAllItems(demo_list); /* LessTif lossage */
660 XmListSelectPos (demo_list, bot, False);
661 ensure_selected_item_visible (demo_list);
663 XmListDeselectAllItems(demo_list); /* LessTif lossage */
664 XmListSelectPos (demo_list, top, False);
665 ensure_selected_item_visible (demo_list);
667 XmListDeselectAllItems(demo_list); /* LessTif lossage */
668 XmListSelectPos (demo_list, i, False);
669 ensure_selected_item_visible (demo_list);
672 #else /* HAVE_ATHENA */
674 /* Hook up the text line. */
676 XtAppAddActions(XtWidgetToApplicationContext(text_line),
677 actions, XtNumber(actions));
678 XtOverrideTranslations(text_line, XtParseTranslationTable(translations));
681 /* Must realize the widget before populating the list, or the dialog
682 will be as wide as the longest string.
684 XtRealizeWidget (demo_dialog);
686 XtVaSetValues (demo_list,
688 XtNnumberStrings, si->prefs.screenhacks_count,
690 XtAddCallback (demo_list, XtNcallback, select_cb, si);
691 if (ssi->current_hack > 0)
692 XawListHighlight(demo_list, ssi->current_hack);
694 /* Now that we've populated the list, make sure that the list is as
695 wide as the dialog itself.
698 Widget viewport = XtParent(demo_list);
699 Widget subform = XtParent(viewport);
700 Widget box = XtNameToWidget(demo_dialog, "*box");
701 Widget label1 = XtNameToWidget(demo_dialog, "*label1");
702 Widget label2 = XtNameToWidget(demo_dialog, "*label2");
703 Dimension x=0, y=0, w=0, h=0, bw=0, w2=0;
704 XtVaGetValues(subform,
705 XtNwidth, &w, XtNheight, &h, XtNborderWidth, &bw, 0);
706 XtVaGetValues(box, XtNwidth, &w2, 0);
708 XtResizeWidget(subform, w2, h, bw);
710 /* Why isn't the viewport getting centered? */
711 XtVaGetValues(viewport,
712 XtNx, &x, XtNy, &y, XtNheight, &h, XtNborderWidth, &bw, 0);
713 /* printf("%d %d %d %d\n", x, y, w, h); */
714 XtConfigureWidget(viewport, x, y, w2-x-x, h, bw);
716 /* And the text line, too. */
717 XtVaGetValues(text_line,
718 XtNwidth, &w, XtNheight, &h, XtNborderWidth, &bw, 0);
719 XtVaGetValues(viewport, XtNwidth, &w2, 0);
721 XtResizeWidget(text_line, w2, h, bw);
723 /* And the labels too. */
724 XtVaGetValues(label1,
725 XtNwidth, &w, XtNheight, &h, XtNborderWidth, &bw, 0);
727 XtResizeWidget(label1, w2, h, bw);
729 XtVaGetValues(label2,
730 XtNwidth, &w, XtNheight, &h, XtNborderWidth, &bw, 0);
732 XtResizeWidget(label2, w2, h, bw);
736 #endif /* HAVE_ATHENA */
738 monitor_power_on (si);
739 pop_up_dialog_box(demo_dialog, demo_form,
740 /* for debugging -- don't ask */
741 (si->prefs.debug_p ? 69 : 0) +
745 /* For Athena, have to do this after the dialog is managed. */
746 ensure_selected_item_visible (demo_list);
747 #endif /* HAVE_ATHENA */
751 /* the Screensaver Parameters dialog */
753 static struct resources {
754 int timeout, cycle, secs, ticks, lock_time, passwd_time;
755 int verb, cmap, fade, unfade, lock_p;
760 hack_time_cb (Display *dpy, char *line, int *store, Bool sec_p)
765 value = parse_time (line, sec_p, True);
774 res_sec_cb (Widget button, XtPointer client_data, XtPointer call_data)
776 hack_time_cb (XtDisplay (button), get_text_string (button),
777 (int *) client_data, True);
781 res_min_cb (Widget button, XtPointer client_data, XtPointer call_data)
783 hack_time_cb (XtDisplay (button), get_text_string (button),
784 (int *) client_data, False);
788 res_int_cb (Widget button, XtPointer client_data, XtPointer call_data)
790 char *line = get_text_string (button);
791 int *store = (int *) client_data;
796 else if (sscanf (line, "%u%c", &value, &c) != 1)
797 XBell (XtDisplay (button), 0);
803 res_bool_cb (Widget button, XtPointer client_data, XtPointer call_data)
805 int *store = (int *) client_data;
807 *store = ((XmToggleButtonCallbackStruct *) call_data)->set;
808 #else /* HAVE_ATHENA */
809 Boolean state = FALSE;
810 XtVaGetValues (button, XtNstate, &state, NULL);
812 #endif /* HAVE_ATHENA */
816 res_cancel_cb (Widget button, XtPointer client_data, XtPointer call_data)
818 saver_info *si = (saver_info *) client_data;
819 saver_preferences *p = &si->prefs;
821 XtDestroyWidget (resources_dialog);
822 resources_dialog = 0;
823 raise_screenhack_dialog ();
826 fprintf (stderr, "%s: lowering preferences dialog.\n", blurb());
831 res_done_cb (Widget button, XtPointer client_data, XtPointer call_data)
833 saver_info *si = (saver_info *) client_data;
834 saver_preferences *p = &si->prefs;
836 res_cancel_cb (button, client_data, call_data);
839 /* Check all text widgets, since we don't have callbacks for these. */
840 res_min_cb (timeout_text, (XtPointer) &res.timeout, NULL);
841 res_min_cb (cycle_text, (XtPointer) &res.cycle, NULL);
842 res_sec_cb (fade_text, (XtPointer) &res.secs, NULL);
843 res_int_cb (ticks_text, (XtPointer) &res.ticks, NULL);
844 res_min_cb (lock_time_text, (XtPointer) &res.lock_time, NULL);
845 res_sec_cb (passwd_time_text, (XtPointer) &res.passwd_time, NULL);
846 #endif /* HAVE_ATHENA */
848 /* Throttle the timeouts to minimum sane values. */
849 if (res.timeout < 5) res.timeout = 5;
850 if (res.cycle < 2) res.cycle = 2;
851 if (res.passwd_time < 10) res.passwd_time = 10;
853 p->timeout = res.timeout * 1000;
854 p->cycle = res.cycle * 1000;
855 p->lock_timeout = res.lock_time * 1000;
857 p->passwd_timeout = res.passwd_time * 1000;
859 p->fade_seconds = res.secs;
860 p->fade_ticks = res.ticks;
861 p->verbose_p = res.verb;
862 p->install_cmap_p = res.cmap;
863 p->fade_p = res.fade;
864 p->unfade_p = res.unfade;
865 p->lock_p = res.lock_p;
867 if (p->debug_p && p->verbose_p)
868 fprintf (stderr, "%s: parameters changed:\n\
869 timeout: %d\n\tcycle: %d\n\tlock: %d\n\tpasswd: %d\n\
870 fade: %d\n\tfade: %d\n\tverbose: %d\n\tinstall: %d\n\
871 fade: %d\n\tunfade: %d\n\tlock: %d\n",
872 blurb(), p->timeout, p->cycle, p->lock_timeout,
878 p->fade_seconds, p->fade_ticks, p->verbose_p, p->install_cmap_p,
879 p->fade_p, p->unfade_p, p->lock_p);
882 #if defined(HAVE_MIT_SAVER_EXTENSION) || defined(HAVE_SGI_SAVER_EXTENSION)
883 if (p->use_mit_saver_extension || p->use_sgi_saver_extension)
885 /* Need to set the server timeout to the new one the user has picked.
887 int server_timeout, server_interval, prefer_blank, allow_exp;
888 XGetScreenSaver (si->dpy, &server_timeout, &server_interval,
889 &prefer_blank, &allow_exp);
890 if (server_timeout != (p->timeout / 1000))
892 server_timeout = (p->timeout / 1000);
895 "%s: configuring server for saver timeout of %d seconds.\n",
896 blurb(), server_timeout);
897 /* Leave all other parameters the same. */
898 XSetScreenSaver (si->dpy, server_timeout, server_interval,
899 prefer_blank, allow_exp);
902 #endif /* HAVE_MIT_SAVER_EXTENSION || HAVE_SGI_SAVER_EXTENSION */
907 make_resources_dialog (saver_info *si, Widget parent)
909 saver_screen_info *ssi = si->default_screen;
911 if (ssi->demo_cmap &&
912 ssi->demo_cmap != ssi->cmap &&
913 ssi->demo_cmap != DefaultColormapOfScreen (ssi->screen))
915 XFreeColormap (si->dpy, ssi->demo_cmap);
919 if (ssi->default_visual == DefaultVisualOfScreen (ssi->screen))
920 ssi->demo_cmap = DefaultColormapOfScreen (ssi->screen);
922 ssi->demo_cmap = XCreateColormap (si->dpy,
923 RootWindowOfScreen (ssi->screen),
924 ssi->default_visual, AllocNone);
926 create_resources_dialog (parent, ssi->default_visual, ssi->demo_cmap);
928 add_button_callback (res_done, res_done_cb, (XtPointer) si);
929 add_button_callback (res_cancel, res_cancel_cb, (XtPointer) si);
931 #define CB(widget,type,slot) \
932 add_text_callback ((widget), (type), (XtPointer) (slot))
933 #define CBT(widget,type,slot) \
934 add_toggle_callback ((widget), (type), (XtPointer) (slot))
937 /* When using Athena widgets, we can't set callbacks for these,
938 so we'll check them all if "done" gets pressed.
940 CB (timeout_text, res_min_cb, &res.timeout);
941 CB (cycle_text, res_min_cb, &res.cycle);
942 CB (fade_text, res_sec_cb, &res.secs);
943 CB (ticks_text, res_int_cb, &res.ticks);
944 CB (lock_time_text, res_min_cb, &res.lock_time);
945 CB (passwd_time_text, res_sec_cb, &res.passwd_time);
946 #endif /* HAVE_MOTIF */
948 CBT (verbose_toggle, res_bool_cb, &res.verb);
949 CBT (cmap_toggle, res_bool_cb, &res.cmap);
950 CBT (fade_toggle, res_bool_cb, &res.fade);
951 CBT (unfade_toggle, res_bool_cb, &res.unfade);
952 CBT (lock_toggle, res_bool_cb, &res.lock_p);
956 if (si->locking_disabled_p)
958 disable_widget (passwd_time_text);
959 disable_widget (lock_time_text);
960 disable_widget (lock_toggle);
962 if (CellsOfScreen (XtScreen (parent)) <= 2)
964 disable_widget (fade_text);
965 disable_widget (ticks_text);
966 disable_widget (cmap_toggle);
967 disable_widget (fade_toggle);
968 disable_widget (unfade_toggle);
974 fmt_time (char *buf, unsigned int s, int min_p)
976 unsigned int h = 0, m = 0;
988 if (min_p && h == 0 && s == 0)
989 sprintf (buf, "%u", m);
990 else if (!min_p && h == 0 && m == 0)
991 sprintf (buf, "%u", s);
994 sprintf (buf, "%u:%02u", m, s);
997 sprintf (buf, "%u:%02u:%02u", h, m, s);
1001 pop_resources_dialog (saver_info *si)
1003 saver_preferences *p = &si->prefs;
1007 fprintf (stderr, "%s: raising preferences dialog.\n", blurb());
1009 res.timeout = p->timeout / 1000;
1010 res.cycle = p->cycle / 1000;
1011 res.lock_time = p->lock_timeout / 1000;
1013 res.passwd_time = p->passwd_timeout / 1000;
1015 res.secs = p->fade_seconds;
1016 res.ticks = p->fade_ticks;
1017 res.verb = p->verbose_p;
1018 res.cmap = p->install_cmap_p;
1019 res.fade = p->fade_p;
1020 res.unfade = p->unfade_p;
1021 res.lock_p = (p->lock_p && !si->locking_disabled_p);
1023 fmt_time (buf, res.timeout, 1); set_text_string (timeout_text, buf);
1024 fmt_time (buf, res.cycle, 1); set_text_string (cycle_text, buf);
1025 fmt_time (buf, res.lock_time, 1); set_text_string (lock_time_text, buf);
1026 fmt_time (buf, res.passwd_time, 0); set_text_string (passwd_time_text, buf);
1027 fmt_time (buf, res.secs, 0); set_text_string (fade_text, buf);
1028 sprintf (buf, "%u", res.ticks); set_text_string (ticks_text, buf);
1030 set_toggle_button_state (verbose_toggle, res.verb);
1031 set_toggle_button_state (cmap_toggle, res.cmap);
1032 set_toggle_button_state (fade_toggle, res.fade);
1033 set_toggle_button_state (unfade_toggle, res.unfade);
1034 set_toggle_button_state (lock_toggle, res.lock_p);
1036 monitor_power_on (si);
1037 pop_up_dialog_box (resources_dialog, resources_form,
1038 /* for debugging -- don't ask */
1039 (si->prefs.debug_p ? 69 : 0) +
1044 /* The main demo-mode command loop.
1048 demo_mode (saver_info *si)
1050 saver_preferences *p = &si->prefs;
1051 Bool prefs_p = (si->demo_mode_p == (Bool) 2); /* kludge! */
1054 fprintf (stderr, "%s: Demo Mode.\n", blurb());
1056 si->dbox_up_p = True;
1057 monitor_power_on (si);
1058 raise_window (si, True, False, False);
1059 make_screenhack_dialog (si);
1062 edit_cb (0, si, 0); /* pop up preferences panel */
1064 while (si->demo_mode_p)
1067 XtAppNextEvent (si->app, &event);
1068 switch (event.xany.type)
1070 case 0: /* synthetic "timeout" event */
1074 handle_clientmessage (si, &event, False);
1078 if (!p->use_xidle_extension &&
1079 !p->use_mit_saver_extension &&
1080 !p->use_sgi_saver_extension)
1082 start_notice_events_timer (si, event.xcreatewindow.window);
1086 "%s: starting notice_events_timer for 0x%X (%lu)\n",
1088 (unsigned int) event.xcreatewindow.window,
1089 p->notice_events_timeout);
1090 #endif /* DEBUG_TIMERS */
1096 if (!XtWindowToWidget (si->dpy, event.xbutton.window))
1097 raise_screenhack_dialog ();
1101 #ifdef HAVE_MIT_SAVER_EXTENSION
1102 if (event.type == si->mit_saver_ext_event_number)
1104 /* Get the "real" server window(s) out of the way as soon
1107 for (i = 0; i < si->nscreens; i++)
1109 saver_screen_info *ssi = &si->screens[i];
1110 if (ssi->server_mit_saver_window &&
1111 window_exists_p (si->dpy, ssi->server_mit_saver_window))
1112 XUnmapWindow (si->dpy, ssi->server_mit_saver_window);
1116 #endif /* HAVE_MIT_SAVER_EXTENSION */
1118 XtDispatchEvent (&event);
1124 fprintf (stderr, "%s: Demo Mode done.\n", blurb());
1126 kill_screenhack (si);
1128 destroy_screenhack_dialogs (si);
1129 initialize_screensaver_window (si);
1131 si->dbox_up_p = False;
1134 si->demo_mode_p = True; /* kludge to inhibit unfade... */
1135 unblank_screen (si);
1136 si->demo_mode_p = False;
1140 demo_mode_hack (saver_info *si, char *hack)
1142 if (! si->demo_mode_p) abort ();
1143 kill_screenhack (si);
1144 if (! si->demo_hack)
1146 si->demo_hack = hack;
1147 spawn_screenhack (si, False);
1148 /* raise_screenhack_dialog(); */
1152 demo_mode_done (saver_info *si)
1154 si->demo_mode_p = False;