1 /* demo.c --- implements the interactive demo-mode and options dialogs.
2 * xscreensaver, Copyright (c) 1993-1997 Jamie Zawinski <jwz@netscape.com>
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>
19 /* We don't actually use any widget internals, but these are included
20 so that gdb will have debug info for the widgets... */
21 #include <X11/IntrinsicP.h>
22 #include <X11/ShellP.h>
28 # include <Xm/ToggleB.h>
30 #else /* HAVE_ATHENA */
31 /* Athena demo code contributed by Jon A. Christopher <jac8782@tamu.edu> */
32 /* Copyright 1997, with the same permissions as above. */
33 # include <X11/StringDefs.h>
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 #endif /* HAVE_ATHENA */
45 #include "xscreensaver.h"
46 #include "resources.h" /* for parse_time() */
51 static void demo_mode_hack (saver_info *si, char *);
52 static void demo_mode_done (saver_info *si);
54 extern Widget demo_dialog;
56 extern Widget text_line;
57 extern Widget demo_form;
58 extern Widget demo_list;
59 extern Widget next, prev, done, restart, edit;
61 extern Widget resources_dialog;
62 extern Widget resources_form;
63 extern Widget res_done, res_cancel;
64 extern Widget timeout_text, cycle_text, fade_text, ticks_text;
65 extern Widget lock_time_text, passwd_time_text;
66 extern Widget verbose_toggle, cmap_toggle, fade_toggle, unfade_toggle,
72 # define set_toggle_button_state(toggle,state) \
73 XmToggleButtonSetState ((toggle), (state), True)
74 # define set_text_string(text_widget,string) \
75 XmTextSetString ((text_widget), (string))
76 # define add_button_callback(button,cb,arg) \
77 XtAddCallback ((button), XmNactivateCallback, (cb), (arg))
78 # define add_toggle_callback(button,cb,arg) \
79 XtAddCallback ((button), XmNvalueChangedCallback, (cb), (arg))
80 # define add_text_callback add_toggle_callback
82 #else /* HAVE_ATHENA */
84 # define set_toggle_button_state(toggle,state) \
85 XtVaSetValues((toggle), XtNstate, (state), 0)
86 # define set_text_string(text_widget,string) \
87 XtVaSetValues ((text_widget), XtNvalue, (string), 0)
88 # define add_button_callback(button,cb,arg) \
89 XtAddCallback ((button), XtNcallback, (cb), (arg))
90 # define add_toggle_callback add_button_callback
91 # define add_text_callback(b,c,a) ERROR!
93 #endif /* HAVE_ATHENA */
96 #define disable_widget(widget) \
97 XtVaSetValues((widget), XtNsensitive, False, 0)
101 get_text_string (Widget text_widget)
104 return XmTextGetString (text_widget);
105 #else /* HAVE_ATHENA */
107 XtVaGetValues (text_widget, XtNvalue, &string, 0);
109 #endif /* HAVE_ATHENA */
113 get_label_string (Widget label_widget)
117 XmString xm_label = 0;
118 XtVaGetValues (label_widget, XmNlabelString, &xm_label, 0);
121 XmStringGetLtoR (xm_label, XmSTRING_DEFAULT_CHARSET, &label);
123 #else /* HAVE_ATHENA */
125 XtVaGetValues (label_widget, XtNlabel, &label, 0);
126 return (label ? strdup(label) : 0);
127 #endif /* HAVE_ATHENA */
132 set_label_string (Widget label_widget, char *string)
135 XmString xm_string = XmStringCreate (string, XmSTRING_DEFAULT_CHARSET);
136 XtVaSetValues (label_widget, XmNlabelString, xm_string, 0);
137 XmStringFree (xm_string);
138 #else /* HAVE_ATHENA */
139 XtVaSetValues (label_widget, XtNlabel, string, 0);
140 #endif /* HAVE_ATHENA */
145 format_into_label (Widget label, const char *arg)
147 char *text = get_label_string (label);
148 char *buf = (char *) malloc ((text ? strlen(text) : 100) + strlen(arg) + 10);
150 if (!text || !strcmp (text, XtName (label)))
151 strcpy (buf, "ERROR: RESOURCES ARE NOT INSTALLED CORRECTLY");
153 sprintf (buf, text, arg);
155 set_label_string (label, buf);
162 steal_focus_and_colormap (Widget dialog)
164 Display *dpy = XtDisplay (dialog);
165 Window window = XtWindow (dialog);
167 XSetInputFocus (dpy, window, RevertToParent, CurrentTime);
169 XtVaGetValues (dialog, XtNcolormap, &cmap, 0);
171 XInstallColormap (dpy, cmap);
175 raise_screenhack_dialog (void)
177 XMapRaised (XtDisplay (demo_dialog), XtWindow (demo_dialog));
178 if (resources_dialog)
179 XMapRaised (XtDisplay (resources_dialog), XtWindow (resources_dialog));
180 steal_focus_and_colormap (resources_dialog ? resources_dialog : demo_dialog);
184 destroy_screenhack_dialogs (saver_info *si)
186 saver_screen_info *ssi = si->default_screen;
188 if (demo_dialog) XtDestroyWidget (demo_dialog);
189 if (resources_dialog) XtDestroyWidget (resources_dialog);
190 demo_dialog = resources_dialog = 0;
192 if (ssi->demo_cmap &&
193 ssi->demo_cmap != ssi->cmap &&
194 ssi->demo_cmap != DefaultColormapOfScreen (ssi->screen))
196 XFreeColormap (si->dpy, ssi->demo_cmap);
200 /* Since we installed our colormap to display the dialogs properly, put
201 the old one back, so that the screensaver_window is now displayed
204 XInstallColormap (si->dpy, ssi->cmap);
210 text_cb (Widget text_widget, XtPointer client_data, XtPointer call_data)
212 saver_info *si = (saver_info *) client_data;
214 line = get_text_string (text_widget);
215 demo_mode_hack (si, line);
218 #endif /* HAVE_MOTIF */
222 select_cb (Widget button, XtPointer client_data, XtPointer call_data)
224 saver_info *si = (saver_info *) client_data;
227 XawListReturnStruct *item = (XawListReturnStruct*)call_data;
228 demo_mode_hack (si, item->string);
229 if (item->list_index >= 0)
230 si->default_screen->current_hack = item->list_index;
232 #else /* HAVE_MOTIF */
233 XmListCallbackStruct *lcb = (XmListCallbackStruct *) call_data;
236 XmStringGetLtoR (lcb->item, XmSTRING_DEFAULT_CHARSET, &string);
237 set_text_string (text_line, (string ? string : ""));
238 if (lcb->reason == XmCR_DEFAULT_ACTION && string)
240 demo_mode_hack (si, string);
241 if (lcb->item_position > 0)
242 si->default_screen->current_hack = lcb->item_position - 1;
246 #endif /* HAVE_MOTIF */
247 steal_focus_and_colormap (demo_dialog);
251 #if 0 /* configure does this now */
253 # if !defined(_Viewport_h)
254 /* The R4 Athena libs don't have this function. I don't know the right
255 way to tell, but I note that the R5 version of Viewport.h defines
256 _XawViewport_h, while the R4 version defines _Viewport_h. So we'll
257 try and key off of that... */
258 # define HAVE_XawViewportSetCoordinates
260 #endif /* HAVE_ATHENA */
264 /* Why this behavior isn't automatic in *either* toolkit, I'll never know.
267 ensure_selected_item_visible (Widget list)
272 if (XmListGetSelectedPos (list, &pos_list, &pos_count) && pos_count > 0)
277 XmNtopItemPosition, &top,
278 XmNvisibleItemCount, &visible,
280 if (pos_list[0] >= top + visible)
282 int pos = pos_list[0] - visible + 1;
283 if (pos < 0) pos = 0;
284 XmListSetPos (list, pos);
286 else if (pos_list[0] < top)
288 XmListSetPos (list, pos_list[0]);
292 XtFree ((char *) pos_list);
294 #else /* HAVE_ATHENA */
295 # ifdef HAVE_XawViewportSetCoordinates
297 int margin = 16; /* should be line height or something. */
300 Dimension list_h = 0, vp_h = 0;
301 Dimension top_margin = 4; /* I don't know where this value comes from */
302 Position vp_x = 0, vp_y = 0, current_y;
304 Widget viewport = XtParent(demo_list);
305 Widget sb = (viewport ? XtNameToWidget(viewport, "*vertical") : 0);
306 float sb_top = 0, sb_size = 0;
307 XawListReturnStruct *current = XawListShowCurrent(demo_list);
308 if (!current || !sb) return;
310 XtVaGetValues(demo_list,
311 XtNnumberStrings, &count,
314 if (count < 2 || list_h < 10) return;
316 XtVaGetValues(viewport, XtNheight, &vp_h, XtNx, &vp_x, XtNy, &vp_y, 0);
317 if (vp_h < 10) return;
319 XtVaGetValues(sb, XtNtopOfThumb, &sb_top, XtNshown, &sb_size, 0);
320 if (sb_size <= 0) return;
322 pos = current->list_index;
323 cratio = ((double) pos) / ((double) count);
324 current_y = (cratio * list_h);
326 if (cratio < sb_top ||
327 cratio > sb_top + sb_size)
330 current_y -= (vp_h - margin - margin);
334 if ((long)current_y >= (long) list_h)
335 current_y = (Position) ((long)list_h - (long)vp_h);
337 if ((long)current_y < (long)top_margin)
338 current_y = (Position)top_margin;
340 XawViewportSetCoordinates (viewport, vp_x, current_y);
342 # endif /* HAVE_XawViewportSetCoordinates */
343 #endif /* HAVE_ATHENA */
348 next_cb (Widget button, XtPointer client_data, XtPointer call_data)
350 saver_info *si = (saver_info *) client_data;
354 XawListReturnStruct *current = XawListShowCurrent(demo_list);
355 if (current->list_index == XAW_LIST_NONE)
356 XawListHighlight(demo_list,1);
359 XtVaGetValues(demo_list,
360 XtNnumberStrings, &cnt,
362 if (current->list_index + 1 < cnt)
364 current->list_index++;
365 XawListHighlight(demo_list, current->list_index);
369 ensure_selected_item_visible (demo_list);
370 current = XawListShowCurrent(demo_list);
371 demo_mode_hack (si, current->string);
373 #else /* HAVE_MOTIF */
377 if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
379 XmListDeselectAllItems(demo_list); /* LessTif lossage */
380 XmListSelectPos (demo_list, 1, True);
384 int pos = pos_list[0] + 1;
385 if (pos > si->prefs.screenhacks_count)
387 XmListDeselectAllItems(demo_list); /* LessTif lossage */
388 XmListSelectPos (demo_list, pos, True);
390 XtFree ((char *) pos_list);
391 ensure_selected_item_visible (demo_list);
392 demo_mode_hack (si, get_text_string (text_line));
394 #endif /* HAVE_MOTIF */
399 prev_cb (Widget button, XtPointer client_data, XtPointer call_data)
401 saver_info *si = (saver_info *) client_data;
404 XawListReturnStruct *current=XawListShowCurrent(demo_list);
405 if (current->list_index == XAW_LIST_NONE)
406 XawListHighlight(demo_list,1);
409 if (current->list_index>=1)
411 current->list_index--;
412 XawListHighlight(demo_list, current->list_index);
416 ensure_selected_item_visible (demo_list);
417 current = XawListShowCurrent(demo_list);
418 demo_mode_hack (si, current->string);
420 #else /* HAVE_MOTIF */
424 if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
426 XmListDeselectAllItems(demo_list); /* LessTif lossage */
427 XmListSelectPos (demo_list, 0, True);
431 XmListDeselectAllItems(demo_list); /* LessTif lossage */
432 XmListSelectPos (demo_list, pos_list [0] - 1, True);
433 XtFree ((char *) pos_list);
435 ensure_selected_item_visible (demo_list);
436 demo_mode_hack (si, get_text_string (text_line));
438 #endif /* HAVE_MOTIF */
442 static void pop_resources_dialog (saver_info *si);
443 static void make_resources_dialog (saver_info *si, Widget parent);
446 edit_cb (Widget button, XtPointer client_data, XtPointer call_data)
448 saver_info *si = (saver_info *) client_data;
449 saver_screen_info *ssi = si->default_screen;
450 Widget parent = ssi->toplevel_shell;
451 if (! resources_dialog)
452 make_resources_dialog (si, parent);
453 pop_resources_dialog (si);
457 done_cb (Widget button, XtPointer client_data, XtPointer call_data)
459 saver_info *si = (saver_info *) client_data;
465 restart_cb (Widget button, XtPointer client_data, XtPointer call_data)
467 saver_info *si = (saver_info *) client_data;
468 demo_mode_restart_process (si);
473 pop_up_dialog_box (Widget dialog, Widget form, int where)
475 /* I'm sure this is the wrong way to pop up a dialog box, but I can't
476 figure out how else to do it.
478 It's important that the screensaver dialogs not get decorated or
479 otherwise reparented by the window manager, because they need to be
480 children of the *real* root window, not the WM's virtual root, in
481 order for us to guarentee that they are visible above the screensaver
486 Dimension sw, sh, x, y, w, h;
489 XtRealizeWidget (dialog);
490 #else /* HAVE_MOTIF */
491 /* Motif likes us to realize the *child* of the shell... */
492 XtRealizeWidget (form);
493 #endif /* HAVE_MOTIF */
495 sw = WidthOfScreen (XtScreen (dialog));
496 sh = HeightOfScreen (XtScreen (dialog));
498 XtSetArg (av [ac], XtNwidth, &w); ac++;
499 XtSetArg (av [ac], XtNheight, &h); ac++;
500 XtGetValues (form, av, ac);
502 /* for debugging -- don't ask */
511 case 0: /* center it in the top-right quadrant */
512 x = (sw/2 + w) / 2 + (sw/2) - w;
513 y = (sh/2 + h) / 2 - h;
515 case 1: /* center it in the bottom-right quadrant */
516 x = (sw/2 + w) / 2 + (sw/2) - w;
517 y = (sh/2 + h) / 2 + (sh/2) - h;
519 case 2: /* center it on the screen */
520 x = (sw + w) / 2 - w;
521 y = (sh + h) / 2 - h;
526 if (x + w > sw) x = sw - w;
527 if (y + h > sh) y = sh - h;
529 XtSetArg (av [ac], XtNx, x); ac++;
530 XtSetArg (av [ac], XtNy, y); ac++;
531 XtSetArg (av [ac], XtNoverrideRedirect, True); ac++;
534 XtSetArg (av [ac], XmNdefaultPosition, False); ac++;
535 #endif /* HAVE_MOTIF */
537 XtSetValues (dialog, av, ac);
538 XtSetValues (form, av, ac);
541 XtPopup (dialog, XtGrabNone);
542 #else /* HAVE_MOTIF */
543 XtManageChild (form);
544 #endif /* HAVE_MOTIF */
546 steal_focus_and_colormap (dialog);
551 make_screenhack_dialog (saver_info *si)
553 saver_screen_info *ssi = si->default_screen;
554 Widget parent = ssi->toplevel_shell;
555 char **hacks = si->prefs.screenhacks;
557 if (ssi->demo_cmap &&
558 ssi->demo_cmap != ssi->cmap &&
559 ssi->demo_cmap != DefaultColormapOfScreen (ssi->screen))
561 XFreeColormap (si->dpy, ssi->demo_cmap);
565 if (ssi->default_visual == DefaultVisualOfScreen (ssi->screen))
566 ssi->demo_cmap = DefaultColormapOfScreen (ssi->screen);
568 ssi->demo_cmap = XCreateColormap (si->dpy,
569 RootWindowOfScreen (ssi->screen),
570 ssi->default_visual, AllocNone);
572 create_demo_dialog (parent, ssi->default_visual, ssi->demo_cmap);
573 format_into_label (label1, si->version);
575 add_button_callback (next, next_cb, (XtPointer) si);
576 add_button_callback (prev, prev_cb, (XtPointer) si);
577 add_button_callback (done, done_cb, (XtPointer) si);
578 add_button_callback (restart, restart_cb, (XtPointer) si);
579 add_button_callback (edit, edit_cb, (XtPointer) si);
582 XtAddCallback (demo_list, XmNbrowseSelectionCallback,
583 select_cb, (XtPointer) si);
584 XtAddCallback (demo_list, XmNdefaultActionCallback,
585 select_cb, (XtPointer) si);
586 XtAddCallback (text_line, XmNactivateCallback, text_cb, (XtPointer) si);
588 for (; *hacks; hacks++)
590 XmString xmstr = XmStringCreate (*hacks, XmSTRING_DEFAULT_CHARSET);
591 XmListAddItem (demo_list, xmstr, 0);
592 XmStringFree (xmstr);
595 /* Cause the most-recently-run hack to be selected in the list.
596 Do some voodoo to make it be roughly centered in the list (really,
597 just make it not be within +/- 5 of the top/bottom if possible.)
599 if (ssi->current_hack > 0)
601 int i = ssi->current_hack+1;
604 if (bot < 1) bot = 1;
605 if (top > si->prefs.screenhacks_count)
606 top = si->prefs.screenhacks_count;
608 XmListDeselectAllItems(demo_list); /* LessTif lossage */
609 XmListSelectPos (demo_list, bot, False);
610 ensure_selected_item_visible (demo_list);
612 XmListDeselectAllItems(demo_list); /* LessTif lossage */
613 XmListSelectPos (demo_list, top, False);
614 ensure_selected_item_visible (demo_list);
616 XmListDeselectAllItems(demo_list); /* LessTif lossage */
617 XmListSelectPos (demo_list, i, False);
618 ensure_selected_item_visible (demo_list);
621 #else /* HAVE_ATHENA */
623 XtVaSetValues (demo_list,
625 XtNnumberStrings, si->prefs.screenhacks_count,
627 XtAddCallback (demo_list, XtNcallback, select_cb, si);
628 if (ssi->current_hack > 0)
629 XawListHighlight(demo_list, ssi->current_hack);
631 #endif /* HAVE_ATHENA */
633 pop_up_dialog_box(demo_dialog, demo_form,
634 /* for debugging -- don't ask */
635 (si->prefs.debug_p ? 69 : 0) +
639 /* For Athena, have to do this after the dialog is managed. */
640 ensure_selected_item_visible (demo_list);
641 #endif /* HAVE_ATHENA */
645 /* the Screensaver Parameters dialog */
647 static struct resources {
648 int timeout, cycle, secs, ticks, lock_time, passwd_time;
649 int verb, cmap, fade, unfade, lock_p;
654 hack_time_cb (Display *dpy, char *line, int *store, Bool sec_p)
659 value = parse_time (line, sec_p, True);
668 res_sec_cb (Widget button, XtPointer client_data, XtPointer call_data)
670 hack_time_cb (XtDisplay (button), get_text_string (button),
671 (int *) client_data, True);
675 res_min_cb (Widget button, XtPointer client_data, XtPointer call_data)
677 hack_time_cb (XtDisplay (button), get_text_string (button),
678 (int *) client_data, False);
682 res_int_cb (Widget button, XtPointer client_data, XtPointer call_data)
684 char *line = get_text_string (button);
685 int *store = (int *) client_data;
690 else if (sscanf (line, "%u%c", &value, &c) != 1)
691 XBell (XtDisplay (button), 0);
697 res_bool_cb (Widget button, XtPointer client_data, XtPointer call_data)
699 int *store = (int *) client_data;
701 *store = ((XmToggleButtonCallbackStruct *) call_data)->set;
702 #else /* HAVE_ATHENA */
703 Boolean state = FALSE;
704 XtVaGetValues (button, XtNstate, &state, NULL);
706 #endif /* HAVE_ATHENA */
710 res_cancel_cb (Widget button, XtPointer client_data, XtPointer call_data)
712 XtDestroyWidget (resources_dialog);
713 resources_dialog = 0;
714 raise_screenhack_dialog ();
719 res_done_cb (Widget button, XtPointer client_data, XtPointer call_data)
721 saver_info *si = (saver_info *) client_data;
722 saver_preferences *p = &si->prefs;
724 res_cancel_cb (button, client_data, call_data);
727 /* Check all text widgets, since we don't have callbacks for these. */
728 res_min_cb (timeout_text, (XtPointer) &res.timeout, NULL);
729 res_min_cb (cycle_text, (XtPointer) &res.cycle, NULL);
730 res_sec_cb (fade_text, (XtPointer) &res.secs, NULL);
731 res_int_cb (ticks_text, (XtPointer) &res.ticks, NULL);
732 res_min_cb (lock_time_text, (XtPointer) &res.lock_time, NULL);
733 res_sec_cb (passwd_time_text, (XtPointer) &res.passwd_time, NULL);
734 #endif /* HAVE_ATHENA */
736 /* Throttle the timeouts to minimum sane values. */
737 if (res.timeout < 5) res.timeout = 5;
738 if (res.cycle < 2) res.cycle = 2;
739 if (res.passwd_time < 10) res.passwd_time = 10;
741 p->timeout = res.timeout * 1000;
742 p->cycle = res.cycle * 1000;
743 p->lock_timeout = res.lock_time * 1000;
745 p->passwd_timeout = res.passwd_time * 1000;
747 p->fade_seconds = res.secs;
748 p->fade_ticks = res.ticks;
749 p->verbose_p = res.verb;
750 p->install_cmap_p = res.cmap;
751 p->fade_p = res.fade;
752 p->unfade_p = res.unfade;
753 p->lock_p = res.lock_p;
755 if (p->debug_p && p->verbose_p)
756 fprintf (stderr, "%s: parameters changed:\n\
757 timeout: %d\n\tcycle: %d\n\tlock: %d\n\tpasswd: %d\n\
758 fade: %d\n\tfade: %d\n\tverbose: %d\n\tinstall: %d\n\
759 fade: %d\n\tunfade: %d\n\tlock: %d\n",
760 progname, p->timeout, p->cycle, p->lock_timeout,
766 p->fade_seconds, p->fade_ticks, p->verbose_p, p->install_cmap_p,
767 p->fade_p, p->unfade_p, p->lock_p);
770 #if defined(HAVE_MIT_SAVER_EXTENSION) || defined(HAVE_SGI_SAVER_EXTENSION)
771 if (p->use_mit_saver_extension || p->use_sgi_saver_extension)
773 /* Need to set the server timeout to the new one the user has picked.
775 int server_timeout, server_interval, prefer_blank, allow_exp;
776 XGetScreenSaver (si->dpy, &server_timeout, &server_interval,
777 &prefer_blank, &allow_exp);
778 if (server_timeout != (p->timeout / 1000))
780 server_timeout = (p->timeout / 1000);
783 "%s: configuring server for saver timeout of %d seconds.\n",
784 progname, server_timeout);
785 /* Leave all other parameters the same. */
786 XSetScreenSaver (si->dpy, server_timeout, server_interval,
787 prefer_blank, allow_exp);
790 #endif /* HAVE_MIT_SAVER_EXTENSION || HAVE_SGI_SAVER_EXTENSION */
795 make_resources_dialog (saver_info *si, Widget parent)
797 saver_screen_info *ssi = si->default_screen;
799 if (ssi->demo_cmap &&
800 ssi->demo_cmap != ssi->cmap &&
801 ssi->demo_cmap != DefaultColormapOfScreen (ssi->screen))
803 XFreeColormap (si->dpy, ssi->demo_cmap);
807 if (ssi->default_visual == DefaultVisualOfScreen (ssi->screen))
808 ssi->demo_cmap = DefaultColormapOfScreen (ssi->screen);
810 ssi->demo_cmap = XCreateColormap (si->dpy,
811 RootWindowOfScreen (ssi->screen),
812 ssi->default_visual, AllocNone);
814 create_resources_dialog (parent, ssi->default_visual, ssi->demo_cmap);
816 add_button_callback (res_done, res_done_cb, (XtPointer) si);
817 add_button_callback (res_cancel, res_cancel_cb, (XtPointer) si);
819 #define CB(widget,type,slot) \
820 add_text_callback ((widget), (type), (XtPointer) (slot))
821 #define CBT(widget,type,slot) \
822 add_toggle_callback ((widget), (type), (XtPointer) (slot))
825 /* When using Athena widgets, we can't set callbacks for these,
826 so we'll check them all if "done" gets pressed.
828 CB (timeout_text, res_min_cb, &res.timeout);
829 CB (cycle_text, res_min_cb, &res.cycle);
830 CB (fade_text, res_sec_cb, &res.secs);
831 CB (ticks_text, res_int_cb, &res.ticks);
832 CB (lock_time_text, res_min_cb, &res.lock_time);
833 CB (passwd_time_text, res_sec_cb, &res.passwd_time);
834 #endif /* HAVE_MOTIF */
836 CBT (verbose_toggle, res_bool_cb, &res.verb);
837 CBT (cmap_toggle, res_bool_cb, &res.cmap);
838 CBT (fade_toggle, res_bool_cb, &res.fade);
839 CBT (unfade_toggle, res_bool_cb, &res.unfade);
840 CBT (lock_toggle, res_bool_cb, &res.lock_p);
844 if (si->locking_disabled_p)
846 disable_widget (passwd_time_text);
847 disable_widget (lock_time_text);
848 disable_widget (lock_toggle);
850 if (CellsOfScreen (XtScreen (parent)) <= 2)
852 disable_widget (fade_text);
853 disable_widget (ticks_text);
854 disable_widget (cmap_toggle);
855 disable_widget (fade_toggle);
856 disable_widget (unfade_toggle);
862 fmt_time (char *buf, unsigned int s, int min_p)
864 unsigned int h = 0, m = 0;
876 if (min_p && h == 0 && s == 0)
877 sprintf (buf, "%u", m);
878 else if (!min_p && h == 0 && m == 0)
879 sprintf (buf, "%u", s);
882 sprintf (buf, "%u:%02u", m, s);
885 sprintf (buf, "%u:%02u:%02u", h, m, s);
889 pop_resources_dialog (saver_info *si)
891 saver_preferences *p = &si->prefs;
894 res.timeout = p->timeout / 1000;
895 res.cycle = p->cycle / 1000;
896 res.lock_time = p->lock_timeout / 1000;
898 res.passwd_time = p->passwd_timeout / 1000;
900 res.secs = p->fade_seconds;
901 res.ticks = p->fade_ticks;
902 res.verb = p->verbose_p;
903 res.cmap = p->install_cmap_p;
904 res.fade = p->fade_p;
905 res.unfade = p->unfade_p;
906 res.lock_p = (p->lock_p && !si->locking_disabled_p);
908 fmt_time (buf, res.timeout, 1); set_text_string (timeout_text, buf);
909 fmt_time (buf, res.cycle, 1); set_text_string (cycle_text, buf);
910 fmt_time (buf, res.lock_time, 1); set_text_string (lock_time_text, buf);
911 fmt_time (buf, res.passwd_time, 0); set_text_string (passwd_time_text, buf);
912 fmt_time (buf, res.secs, 0); set_text_string (fade_text, buf);
913 sprintf (buf, "%u", res.ticks); set_text_string (ticks_text, buf);
915 set_toggle_button_state (verbose_toggle, res.verb);
916 set_toggle_button_state (cmap_toggle, res.cmap);
917 set_toggle_button_state (fade_toggle, res.fade);
918 set_toggle_button_state (unfade_toggle, res.unfade);
919 set_toggle_button_state (lock_toggle, res.lock_p);
921 pop_up_dialog_box (resources_dialog, resources_form,
922 /* for debugging -- don't ask */
923 (si->prefs.debug_p ? 69 : 0) +
928 /* The main demo-mode command loop.
932 demo_mode (saver_info *si)
934 saver_preferences *p = &si->prefs;
935 si->dbox_up_p = True;
936 raise_window (si, True, False, False);
937 make_screenhack_dialog (si);
938 while (si->demo_mode_p)
941 XtAppNextEvent (si->app, &event);
942 switch (event.xany.type)
944 case 0: /* synthetic "timeout" event */
948 handle_clientmessage (si, &event, False);
952 if (!p->use_xidle_extension &&
953 !p->use_mit_saver_extension &&
954 !p->use_sgi_saver_extension)
956 start_notice_events_timer (si, event.xcreatewindow.window);
959 printf ("%s: starting notice_events_timer for 0x%X (%lu)\n",
961 (unsigned int) event.xcreatewindow.window,
962 p->notice_events_timeout);
963 #endif /* DEBUG_TIMERS */
969 if (!XtWindowToWidget (si->dpy, event.xbutton.window))
970 raise_screenhack_dialog ();
974 #ifdef HAVE_MIT_SAVER_EXTENSION
975 if (event.type == si->mit_saver_ext_event_number)
977 /* Get the "real" server window(s) out of the way as soon
980 for (i = 0; i < si->nscreens; i++)
982 saver_screen_info *ssi = &si->screens[i];
983 if (ssi->server_mit_saver_window &&
984 window_exists_p (si->dpy, ssi->server_mit_saver_window))
985 XUnmapWindow (si->dpy, ssi->server_mit_saver_window);
989 #endif /* HAVE_MIT_SAVER_EXTENSION */
991 XtDispatchEvent (&event);
995 destroy_screenhack_dialogs (si);
996 initialize_screensaver_window (si);
998 si->demo_mode_p = True; /* kludge to inhibit unfade... */
1000 si->demo_mode_p = False;
1004 demo_mode_hack (saver_info *si, char *hack)
1006 if (! si->demo_mode_p) abort ();
1007 kill_screenhack (si);
1008 if (! si->demo_hack)
1010 si->demo_hack = hack;
1011 spawn_screenhack (si, False);
1012 /* raise_screenhack_dialog(); */
1016 demo_mode_done (saver_info *si)
1018 kill_screenhack (si);
1020 unblank_screen (si);
1021 si->demo_mode_p = False;
1022 si->dbox_up_p = False;