1 /* demo.c --- implements the interactive demo-mode and options dialogs.
2 * xscreensaver, Copyright (c) 1993-1998 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 # include <X11/Xaw/Text.h>
44 #endif /* HAVE_ATHENA */
46 #include "xscreensaver.h"
47 #include "resources.h" /* for parse_time() */
52 static void demo_mode_hack (saver_info *si, char *);
53 static void demo_mode_done (saver_info *si);
55 extern Widget demo_dialog;
57 extern Widget text_line;
58 extern Widget demo_form;
59 extern Widget demo_list;
60 extern Widget next, prev, done, restart, edit;
62 extern Widget resources_dialog;
63 extern Widget resources_form;
64 extern Widget res_done, res_cancel;
65 extern Widget timeout_text, cycle_text, fade_text, ticks_text;
66 extern Widget lock_time_text, passwd_time_text;
67 extern Widget verbose_toggle, cmap_toggle, fade_toggle, unfade_toggle,
73 # define set_toggle_button_state(toggle,state) \
74 XmToggleButtonSetState ((toggle), (state), True)
75 # define set_text_string(text_widget,string) \
76 XmTextSetString ((text_widget), (string))
77 # define add_button_callback(button,cb,arg) \
78 XtAddCallback ((button), XmNactivateCallback, (cb), (arg))
79 # define add_toggle_callback(button,cb,arg) \
80 XtAddCallback ((button), XmNvalueChangedCallback, (cb), (arg))
81 # define add_text_callback add_toggle_callback
83 #else /* HAVE_ATHENA */
85 # define set_toggle_button_state(toggle,state) \
86 XtVaSetValues((toggle), XtNstate, (state), 0)
87 # define set_text_string(text_widget,string) \
88 XtVaSetValues ((text_widget), XtNvalue, (string), 0)
89 # define add_button_callback(button,cb,arg) \
90 XtAddCallback ((button), XtNcallback, (cb), (arg))
91 # define add_toggle_callback add_button_callback
92 # define add_text_callback(b,c,a) ERROR!
94 #endif /* HAVE_ATHENA */
97 #define disable_widget(widget) \
98 XtVaSetValues((widget), XtNsensitive, False, 0)
102 get_text_string (Widget text_widget)
105 return XmTextGetString (text_widget);
106 #else /* HAVE_ATHENA */
108 if (XtIsSubclass(text_widget, textWidgetClass))
109 XtVaGetValues (text_widget, XtNstring, &string, 0);
110 else if (XtIsSubclass(text_widget, dialogWidgetClass))
111 XtVaGetValues (text_widget, XtNvalue, &string, 0);
116 #endif /* HAVE_ATHENA */
120 get_label_string (Widget label_widget)
124 XmString xm_label = 0;
125 XtVaGetValues (label_widget, XmNlabelString, &xm_label, 0);
128 XmStringGetLtoR (xm_label, XmSTRING_DEFAULT_CHARSET, &label);
130 #else /* HAVE_ATHENA */
132 XtVaGetValues (label_widget, XtNlabel, &label, 0);
133 return (label ? strdup(label) : 0);
134 #endif /* HAVE_ATHENA */
139 set_label_string (Widget label_widget, char *string)
142 XmString xm_string = XmStringCreate (string, XmSTRING_DEFAULT_CHARSET);
143 XtVaSetValues (label_widget, XmNlabelString, xm_string, 0);
144 XmStringFree (xm_string);
145 #else /* HAVE_ATHENA */
146 XtVaSetValues (label_widget, XtNlabel, string, 0);
147 #endif /* HAVE_ATHENA */
152 format_into_label (Widget label, const char *arg)
154 char *text = get_label_string (label);
155 char *buf = (char *) malloc ((text ? strlen(text) : 100) + strlen(arg) + 10);
157 if (!text || !strcmp (text, XtName (label)))
158 strcpy (buf, "ERROR: RESOURCES ARE NOT INSTALLED CORRECTLY");
160 sprintf (buf, text, arg);
162 set_label_string (label, buf);
169 steal_focus_and_colormap (Widget dialog)
171 Display *dpy = XtDisplay (dialog);
172 Window window = XtWindow (dialog);
174 XSetInputFocus (dpy, window, RevertToParent, CurrentTime);
176 XtVaGetValues (dialog, XtNcolormap, &cmap, 0);
178 XInstallColormap (dpy, cmap);
182 raise_screenhack_dialog (void)
184 XMapRaised (XtDisplay (demo_dialog), XtWindow (demo_dialog));
185 if (resources_dialog)
186 XMapRaised (XtDisplay (resources_dialog), XtWindow (resources_dialog));
187 steal_focus_and_colormap (resources_dialog ? resources_dialog : demo_dialog);
191 destroy_screenhack_dialogs (saver_info *si)
193 saver_screen_info *ssi = si->default_screen;
195 if (demo_dialog) XtDestroyWidget (demo_dialog);
196 if (resources_dialog) XtDestroyWidget (resources_dialog);
197 demo_dialog = resources_dialog = 0;
199 if (ssi->demo_cmap &&
200 ssi->demo_cmap != ssi->cmap &&
201 ssi->demo_cmap != DefaultColormapOfScreen (ssi->screen))
203 XFreeColormap (si->dpy, ssi->demo_cmap);
207 /* Since we installed our colormap to display the dialogs properly, put
208 the old one back, so that the screensaver_window is now displayed
211 XInstallColormap (si->dpy, ssi->cmap);
216 text_cb (Widget text_widget, XtPointer client_data, XtPointer call_data)
218 saver_info *si = (saver_info *) client_data;
220 line = get_text_string (text_widget);
221 demo_mode_hack (si, line);
226 /* Bend over backwards to make hitting Return in the text field do the
229 extern saver_info *global_si_kludge;
230 static void text_enter (Widget w, XEvent *event, String *av, Cardinal *ac)
232 text_cb (w, global_si_kludge, 0);
235 static XtActionsRec actions[] = {{"done", text_enter}
237 static char translations[] = ("<Key>Return: done()\n"
238 "<Key>Linefeed: done()\n"
239 "Ctrl<Key>M: done()\n"
240 "Ctrl<Key>J: done()\n");
241 #endif /* HAVE_ATHENA */
245 select_cb (Widget button, XtPointer client_data, XtPointer call_data)
247 saver_info *si = (saver_info *) client_data;
250 XawListReturnStruct *item = (XawListReturnStruct*)call_data;
251 XtVaSetValues(text_line, XtNstring, item->string, 0);
253 demo_mode_hack (si, item->string);
254 if (item->list_index >= 0)
255 si->default_screen->current_hack = item->list_index;
257 #else /* HAVE_MOTIF */
258 XmListCallbackStruct *lcb = (XmListCallbackStruct *) call_data;
261 XmStringGetLtoR (lcb->item, XmSTRING_DEFAULT_CHARSET, &string);
262 set_text_string (text_line, (string ? string : ""));
263 if (lcb->reason == XmCR_DEFAULT_ACTION && string)
265 demo_mode_hack (si, string);
266 if (lcb->item_position > 0)
267 si->default_screen->current_hack = lcb->item_position - 1;
271 #endif /* HAVE_MOTIF */
272 steal_focus_and_colormap (demo_dialog);
276 #if 0 /* configure does this now */
278 # if !defined(_Viewport_h)
279 /* The R4 Athena libs don't have this function. I don't know the right
280 way to tell, but I note that the R5 version of Viewport.h defines
281 _XawViewport_h, while the R4 version defines _Viewport_h. So we'll
282 try and key off of that... */
283 # define HAVE_XawViewportSetCoordinates
285 #endif /* HAVE_ATHENA */
289 /* Why this behavior isn't automatic in *either* toolkit, I'll never know.
292 ensure_selected_item_visible (Widget list)
297 if (XmListGetSelectedPos (list, &pos_list, &pos_count) && pos_count > 0)
302 XmNtopItemPosition, &top,
303 XmNvisibleItemCount, &visible,
305 if (pos_list[0] >= top + visible)
307 int pos = pos_list[0] - visible + 1;
308 if (pos < 0) pos = 0;
309 XmListSetPos (list, pos);
311 else if (pos_list[0] < top)
313 XmListSetPos (list, pos_list[0]);
317 XtFree ((char *) pos_list);
319 #else /* HAVE_ATHENA */
320 # ifdef HAVE_XawViewportSetCoordinates
322 int margin = 16; /* should be line height or something. */
325 Dimension list_h = 0, vp_h = 0;
326 Dimension top_margin = 4; /* I don't know where this value comes from */
327 Position vp_x = 0, vp_y = 0, current_y;
329 Widget viewport = XtParent(demo_list);
330 Widget sb = (viewport ? XtNameToWidget(viewport, "*vertical") : 0);
331 float sb_top = 0, sb_size = 0;
332 XawListReturnStruct *current = XawListShowCurrent(demo_list);
333 if (!current || !sb) return;
335 XtVaGetValues(demo_list,
336 XtNnumberStrings, &count,
339 if (count < 2 || list_h < 10) return;
341 XtVaGetValues(viewport, XtNheight, &vp_h, XtNx, &vp_x, XtNy, &vp_y, 0);
342 if (vp_h < 10) return;
344 XtVaGetValues(sb, XtNtopOfThumb, &sb_top, XtNshown, &sb_size, 0);
345 if (sb_size <= 0) return;
347 pos = current->list_index;
348 cratio = ((double) pos) / ((double) count);
349 current_y = (cratio * list_h);
351 if (cratio < sb_top ||
352 cratio > sb_top + sb_size)
355 current_y -= (vp_h - margin - margin);
359 if ((long)current_y >= (long) list_h)
360 current_y = (Position) ((long)list_h - (long)vp_h);
362 if ((long)current_y < (long)top_margin)
363 current_y = (Position)top_margin;
365 XawViewportSetCoordinates (viewport, vp_x, current_y);
367 # endif /* HAVE_XawViewportSetCoordinates */
368 #endif /* HAVE_ATHENA */
373 next_cb (Widget button, XtPointer client_data, XtPointer call_data)
375 saver_info *si = (saver_info *) client_data;
379 XawListReturnStruct *current = XawListShowCurrent(demo_list);
380 if (current->list_index == XAW_LIST_NONE)
381 XawListHighlight(demo_list, 0);
384 XtVaGetValues(demo_list,
385 XtNnumberStrings, &cnt,
387 if (current->list_index + 1 < cnt)
389 current->list_index++;
390 XawListHighlight(demo_list, current->list_index);
394 ensure_selected_item_visible (demo_list);
395 current = XawListShowCurrent(demo_list);
396 XtVaSetValues(text_line, XtNstring, current->string, 0);
397 demo_mode_hack (si, current->string);
399 #else /* HAVE_MOTIF */
403 if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
405 XmListDeselectAllItems(demo_list); /* LessTif lossage */
406 XmListSelectPos (demo_list, 1, True);
410 int pos = pos_list[0] + 1;
411 if (pos > si->prefs.screenhacks_count)
413 XmListDeselectAllItems(demo_list); /* LessTif lossage */
414 XmListSelectPos (demo_list, pos, True);
416 XtFree ((char *) pos_list);
417 ensure_selected_item_visible (demo_list);
418 demo_mode_hack (si, get_text_string (text_line));
420 #endif /* HAVE_MOTIF */
425 prev_cb (Widget button, XtPointer client_data, XtPointer call_data)
427 saver_info *si = (saver_info *) client_data;
430 XawListReturnStruct *current=XawListShowCurrent(demo_list);
431 if (current->list_index == XAW_LIST_NONE)
432 XawListHighlight(demo_list, 0);
435 if (current->list_index >= 1)
437 current->list_index--;
438 XawListHighlight(demo_list, current->list_index);
442 ensure_selected_item_visible (demo_list);
443 current = XawListShowCurrent(demo_list);
444 XtVaSetValues(text_line, XtNstring, current->string, 0);
445 demo_mode_hack (si, current->string);
447 #else /* HAVE_MOTIF */
451 if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
453 XmListDeselectAllItems(demo_list); /* LessTif lossage */
454 XmListSelectPos (demo_list, 0, True);
458 XmListDeselectAllItems(demo_list); /* LessTif lossage */
459 XmListSelectPos (demo_list, pos_list [0] - 1, True);
460 XtFree ((char *) pos_list);
462 ensure_selected_item_visible (demo_list);
463 demo_mode_hack (si, get_text_string (text_line));
465 #endif /* HAVE_MOTIF */
469 static void pop_resources_dialog (saver_info *si);
470 static void make_resources_dialog (saver_info *si, Widget parent);
473 edit_cb (Widget button, XtPointer client_data, XtPointer call_data)
475 saver_info *si = (saver_info *) client_data;
476 saver_screen_info *ssi = si->default_screen;
477 Widget parent = ssi->toplevel_shell;
478 if (! resources_dialog)
479 make_resources_dialog (si, parent);
480 pop_resources_dialog (si);
484 done_cb (Widget button, XtPointer client_data, XtPointer call_data)
486 saver_info *si = (saver_info *) client_data;
492 restart_cb (Widget button, XtPointer client_data, XtPointer call_data)
494 saver_info *si = (saver_info *) client_data;
495 demo_mode_restart_process (si);
500 pop_up_dialog_box (Widget dialog, Widget form, int where)
502 /* I'm sure this is the wrong way to pop up a dialog box, but I can't
503 figure out how else to do it.
505 It's important that the screensaver dialogs not get decorated or
506 otherwise reparented by the window manager, because they need to be
507 children of the *real* root window, not the WM's virtual root, in
508 order for us to guarentee that they are visible above the screensaver
513 Dimension sw, sh, x, y, w, h;
516 XtRealizeWidget (dialog);
517 #else /* HAVE_MOTIF */
518 /* Motif likes us to realize the *child* of the shell... */
519 XtRealizeWidget (form);
520 #endif /* HAVE_MOTIF */
522 sw = WidthOfScreen (XtScreen (dialog));
523 sh = HeightOfScreen (XtScreen (dialog));
525 XtSetArg (av [ac], XtNwidth, &w); ac++;
526 XtSetArg (av [ac], XtNheight, &h); ac++;
527 XtGetValues (form, av, ac);
529 /* for debugging -- don't ask */
538 case 0: /* center it in the top-right quadrant */
539 x = (sw/2 + w) / 2 + (sw/2) - w;
540 y = (sh/2 + h) / 2 - h;
542 case 1: /* center it in the bottom-right quadrant */
543 x = (sw/2 + w) / 2 + (sw/2) - w;
544 y = (sh/2 + h) / 2 + (sh/2) - h;
546 case 2: /* center it on the screen */
547 x = (sw + w) / 2 - w;
548 y = (sh + h) / 2 - h;
553 if (x + w > sw) x = sw - w;
554 if (y + h > sh) y = sh - h;
556 XtSetArg (av [ac], XtNx, x); ac++;
557 XtSetArg (av [ac], XtNy, y); ac++;
558 XtSetArg (av [ac], XtNoverrideRedirect, True); ac++;
561 XtSetArg (av [ac], XmNdefaultPosition, False); ac++;
562 #endif /* HAVE_MOTIF */
564 XtSetValues (dialog, av, ac);
565 XtSetValues (form, av, ac);
568 XtPopup (dialog, XtGrabNone);
569 #else /* HAVE_MOTIF */
570 XtManageChild (form);
571 #endif /* HAVE_MOTIF */
573 steal_focus_and_colormap (dialog);
578 make_screenhack_dialog (saver_info *si)
580 saver_screen_info *ssi = si->default_screen;
581 Widget parent = ssi->toplevel_shell;
582 char **hacks = si->prefs.screenhacks;
584 if (ssi->demo_cmap &&
585 ssi->demo_cmap != ssi->cmap &&
586 ssi->demo_cmap != DefaultColormapOfScreen (ssi->screen))
588 XFreeColormap (si->dpy, ssi->demo_cmap);
592 if (ssi->default_visual == DefaultVisualOfScreen (ssi->screen))
593 ssi->demo_cmap = DefaultColormapOfScreen (ssi->screen);
595 ssi->demo_cmap = XCreateColormap (si->dpy,
596 RootWindowOfScreen (ssi->screen),
597 ssi->default_visual, AllocNone);
599 create_demo_dialog (parent, ssi->default_visual, ssi->demo_cmap);
600 format_into_label (label1, si->version);
602 add_button_callback (next, next_cb, (XtPointer) si);
603 add_button_callback (prev, prev_cb, (XtPointer) si);
604 add_button_callback (done, done_cb, (XtPointer) si);
605 add_button_callback (restart, restart_cb, (XtPointer) si);
606 add_button_callback (edit, edit_cb, (XtPointer) si);
609 XtAddCallback (demo_list, XmNbrowseSelectionCallback,
610 select_cb, (XtPointer) si);
611 XtAddCallback (demo_list, XmNdefaultActionCallback,
612 select_cb, (XtPointer) si);
613 XtAddCallback (text_line, XmNactivateCallback, text_cb, (XtPointer) si);
616 for (; *hacks; hacks++)
618 XmString xmstr = XmStringCreate (*hacks, XmSTRING_DEFAULT_CHARSET);
619 XmListAddItem (demo_list, xmstr, 0);
620 XmStringFree (xmstr);
623 /* Cause the most-recently-run hack to be selected in the list.
624 Do some voodoo to make it be roughly centered in the list (really,
625 just make it not be within +/- 5 of the top/bottom if possible.)
627 if (ssi->current_hack > 0)
629 int i = ssi->current_hack+1;
632 if (bot < 1) bot = 1;
633 if (top > si->prefs.screenhacks_count)
634 top = si->prefs.screenhacks_count;
636 XmListDeselectAllItems(demo_list); /* LessTif lossage */
637 XmListSelectPos (demo_list, bot, False);
638 ensure_selected_item_visible (demo_list);
640 XmListDeselectAllItems(demo_list); /* LessTif lossage */
641 XmListSelectPos (demo_list, top, False);
642 ensure_selected_item_visible (demo_list);
644 XmListDeselectAllItems(demo_list); /* LessTif lossage */
645 XmListSelectPos (demo_list, i, False);
646 ensure_selected_item_visible (demo_list);
649 #else /* HAVE_ATHENA */
651 /* Hook up the text line. */
653 XtAppAddActions(XtWidgetToApplicationContext(text_line),
654 actions, XtNumber(actions));
655 XtOverrideTranslations(text_line, XtParseTranslationTable(translations));
658 /* Must realize the widget before populating the list, or the dialog
659 will be as wide as the longest string.
661 XtRealizeWidget (demo_dialog);
663 XtVaSetValues (demo_list,
665 XtNnumberStrings, si->prefs.screenhacks_count,
667 XtAddCallback (demo_list, XtNcallback, select_cb, si);
668 if (ssi->current_hack > 0)
669 XawListHighlight(demo_list, ssi->current_hack);
671 /* Now that we've populated the list, make sure that the list is as
672 wide as the dialog itself.
675 Widget viewport = XtParent(demo_list);
676 Widget subform = XtParent(viewport);
677 Widget box = XtNameToWidget(demo_dialog, "*box");
678 Widget label1 = XtNameToWidget(demo_dialog, "*label1");
679 Widget label2 = XtNameToWidget(demo_dialog, "*label2");
680 Dimension x=0, y=0, w=0, h=0, bw=0, w2=0;
681 XtVaGetValues(subform,
682 XtNwidth, &w, XtNheight, &h, XtNborderWidth, &bw, 0);
683 XtVaGetValues(box, XtNwidth, &w2, 0);
685 XtResizeWidget(subform, w2, h, bw);
687 /* Why isn't the viewport getting centered? */
688 XtVaGetValues(viewport,
689 XtNx, &x, XtNy, &y, XtNheight, &h, XtNborderWidth, &bw, 0);
690 printf("%d %d %d %d\n", x, y, w, h);
691 XtConfigureWidget(viewport, x, y, w2-x-x, h, bw);
693 /* And the text line, too. */
694 XtVaGetValues(text_line,
695 XtNwidth, &w, XtNheight, &h, XtNborderWidth, &bw, 0);
696 XtVaGetValues(viewport, XtNwidth, &w2, 0);
698 XtResizeWidget(text_line, w2, h, bw);
700 /* And the labels too. */
701 XtVaGetValues(label1,
702 XtNwidth, &w, XtNheight, &h, XtNborderWidth, &bw, 0);
704 XtResizeWidget(label1, w2, h, bw);
706 XtVaGetValues(label2,
707 XtNwidth, &w, XtNheight, &h, XtNborderWidth, &bw, 0);
709 XtResizeWidget(label2, w2, h, bw);
713 #endif /* HAVE_ATHENA */
715 monitor_power_on (si);
716 pop_up_dialog_box(demo_dialog, demo_form,
717 /* for debugging -- don't ask */
718 (si->prefs.debug_p ? 69 : 0) +
722 /* For Athena, have to do this after the dialog is managed. */
723 ensure_selected_item_visible (demo_list);
724 #endif /* HAVE_ATHENA */
728 /* the Screensaver Parameters dialog */
730 static struct resources {
731 int timeout, cycle, secs, ticks, lock_time, passwd_time;
732 int verb, cmap, fade, unfade, lock_p;
737 hack_time_cb (Display *dpy, char *line, int *store, Bool sec_p)
742 value = parse_time (line, sec_p, True);
751 res_sec_cb (Widget button, XtPointer client_data, XtPointer call_data)
753 hack_time_cb (XtDisplay (button), get_text_string (button),
754 (int *) client_data, True);
758 res_min_cb (Widget button, XtPointer client_data, XtPointer call_data)
760 hack_time_cb (XtDisplay (button), get_text_string (button),
761 (int *) client_data, False);
765 res_int_cb (Widget button, XtPointer client_data, XtPointer call_data)
767 char *line = get_text_string (button);
768 int *store = (int *) client_data;
773 else if (sscanf (line, "%u%c", &value, &c) != 1)
774 XBell (XtDisplay (button), 0);
780 res_bool_cb (Widget button, XtPointer client_data, XtPointer call_data)
782 int *store = (int *) client_data;
784 *store = ((XmToggleButtonCallbackStruct *) call_data)->set;
785 #else /* HAVE_ATHENA */
786 Boolean state = FALSE;
787 XtVaGetValues (button, XtNstate, &state, NULL);
789 #endif /* HAVE_ATHENA */
793 res_cancel_cb (Widget button, XtPointer client_data, XtPointer call_data)
795 XtDestroyWidget (resources_dialog);
796 resources_dialog = 0;
797 raise_screenhack_dialog ();
802 res_done_cb (Widget button, XtPointer client_data, XtPointer call_data)
804 saver_info *si = (saver_info *) client_data;
805 saver_preferences *p = &si->prefs;
807 res_cancel_cb (button, client_data, call_data);
810 /* Check all text widgets, since we don't have callbacks for these. */
811 res_min_cb (timeout_text, (XtPointer) &res.timeout, NULL);
812 res_min_cb (cycle_text, (XtPointer) &res.cycle, NULL);
813 res_sec_cb (fade_text, (XtPointer) &res.secs, NULL);
814 res_int_cb (ticks_text, (XtPointer) &res.ticks, NULL);
815 res_min_cb (lock_time_text, (XtPointer) &res.lock_time, NULL);
816 res_sec_cb (passwd_time_text, (XtPointer) &res.passwd_time, NULL);
817 #endif /* HAVE_ATHENA */
819 /* Throttle the timeouts to minimum sane values. */
820 if (res.timeout < 5) res.timeout = 5;
821 if (res.cycle < 2) res.cycle = 2;
822 if (res.passwd_time < 10) res.passwd_time = 10;
824 p->timeout = res.timeout * 1000;
825 p->cycle = res.cycle * 1000;
826 p->lock_timeout = res.lock_time * 1000;
828 p->passwd_timeout = res.passwd_time * 1000;
830 p->fade_seconds = res.secs;
831 p->fade_ticks = res.ticks;
832 p->verbose_p = res.verb;
833 p->install_cmap_p = res.cmap;
834 p->fade_p = res.fade;
835 p->unfade_p = res.unfade;
836 p->lock_p = res.lock_p;
838 if (p->debug_p && p->verbose_p)
839 fprintf (stderr, "%s: parameters changed:\n\
840 timeout: %d\n\tcycle: %d\n\tlock: %d\n\tpasswd: %d\n\
841 fade: %d\n\tfade: %d\n\tverbose: %d\n\tinstall: %d\n\
842 fade: %d\n\tunfade: %d\n\tlock: %d\n",
843 blurb(), p->timeout, p->cycle, p->lock_timeout,
849 p->fade_seconds, p->fade_ticks, p->verbose_p, p->install_cmap_p,
850 p->fade_p, p->unfade_p, p->lock_p);
853 #if defined(HAVE_MIT_SAVER_EXTENSION) || defined(HAVE_SGI_SAVER_EXTENSION)
854 if (p->use_mit_saver_extension || p->use_sgi_saver_extension)
856 /* Need to set the server timeout to the new one the user has picked.
858 int server_timeout, server_interval, prefer_blank, allow_exp;
859 XGetScreenSaver (si->dpy, &server_timeout, &server_interval,
860 &prefer_blank, &allow_exp);
861 if (server_timeout != (p->timeout / 1000))
863 server_timeout = (p->timeout / 1000);
866 "%s: configuring server for saver timeout of %d seconds.\n",
867 blurb(), server_timeout);
868 /* Leave all other parameters the same. */
869 XSetScreenSaver (si->dpy, server_timeout, server_interval,
870 prefer_blank, allow_exp);
873 #endif /* HAVE_MIT_SAVER_EXTENSION || HAVE_SGI_SAVER_EXTENSION */
878 make_resources_dialog (saver_info *si, Widget parent)
880 saver_screen_info *ssi = si->default_screen;
882 if (ssi->demo_cmap &&
883 ssi->demo_cmap != ssi->cmap &&
884 ssi->demo_cmap != DefaultColormapOfScreen (ssi->screen))
886 XFreeColormap (si->dpy, ssi->demo_cmap);
890 if (ssi->default_visual == DefaultVisualOfScreen (ssi->screen))
891 ssi->demo_cmap = DefaultColormapOfScreen (ssi->screen);
893 ssi->demo_cmap = XCreateColormap (si->dpy,
894 RootWindowOfScreen (ssi->screen),
895 ssi->default_visual, AllocNone);
897 create_resources_dialog (parent, ssi->default_visual, ssi->demo_cmap);
899 add_button_callback (res_done, res_done_cb, (XtPointer) si);
900 add_button_callback (res_cancel, res_cancel_cb, (XtPointer) si);
902 #define CB(widget,type,slot) \
903 add_text_callback ((widget), (type), (XtPointer) (slot))
904 #define CBT(widget,type,slot) \
905 add_toggle_callback ((widget), (type), (XtPointer) (slot))
908 /* When using Athena widgets, we can't set callbacks for these,
909 so we'll check them all if "done" gets pressed.
911 CB (timeout_text, res_min_cb, &res.timeout);
912 CB (cycle_text, res_min_cb, &res.cycle);
913 CB (fade_text, res_sec_cb, &res.secs);
914 CB (ticks_text, res_int_cb, &res.ticks);
915 CB (lock_time_text, res_min_cb, &res.lock_time);
916 CB (passwd_time_text, res_sec_cb, &res.passwd_time);
917 #endif /* HAVE_MOTIF */
919 CBT (verbose_toggle, res_bool_cb, &res.verb);
920 CBT (cmap_toggle, res_bool_cb, &res.cmap);
921 CBT (fade_toggle, res_bool_cb, &res.fade);
922 CBT (unfade_toggle, res_bool_cb, &res.unfade);
923 CBT (lock_toggle, res_bool_cb, &res.lock_p);
927 if (si->locking_disabled_p)
929 disable_widget (passwd_time_text);
930 disable_widget (lock_time_text);
931 disable_widget (lock_toggle);
933 if (CellsOfScreen (XtScreen (parent)) <= 2)
935 disable_widget (fade_text);
936 disable_widget (ticks_text);
937 disable_widget (cmap_toggle);
938 disable_widget (fade_toggle);
939 disable_widget (unfade_toggle);
945 fmt_time (char *buf, unsigned int s, int min_p)
947 unsigned int h = 0, m = 0;
959 if (min_p && h == 0 && s == 0)
960 sprintf (buf, "%u", m);
961 else if (!min_p && h == 0 && m == 0)
962 sprintf (buf, "%u", s);
965 sprintf (buf, "%u:%02u", m, s);
968 sprintf (buf, "%u:%02u:%02u", h, m, s);
972 pop_resources_dialog (saver_info *si)
974 saver_preferences *p = &si->prefs;
977 res.timeout = p->timeout / 1000;
978 res.cycle = p->cycle / 1000;
979 res.lock_time = p->lock_timeout / 1000;
981 res.passwd_time = p->passwd_timeout / 1000;
983 res.secs = p->fade_seconds;
984 res.ticks = p->fade_ticks;
985 res.verb = p->verbose_p;
986 res.cmap = p->install_cmap_p;
987 res.fade = p->fade_p;
988 res.unfade = p->unfade_p;
989 res.lock_p = (p->lock_p && !si->locking_disabled_p);
991 fmt_time (buf, res.timeout, 1); set_text_string (timeout_text, buf);
992 fmt_time (buf, res.cycle, 1); set_text_string (cycle_text, buf);
993 fmt_time (buf, res.lock_time, 1); set_text_string (lock_time_text, buf);
994 fmt_time (buf, res.passwd_time, 0); set_text_string (passwd_time_text, buf);
995 fmt_time (buf, res.secs, 0); set_text_string (fade_text, buf);
996 sprintf (buf, "%u", res.ticks); set_text_string (ticks_text, buf);
998 set_toggle_button_state (verbose_toggle, res.verb);
999 set_toggle_button_state (cmap_toggle, res.cmap);
1000 set_toggle_button_state (fade_toggle, res.fade);
1001 set_toggle_button_state (unfade_toggle, res.unfade);
1002 set_toggle_button_state (lock_toggle, res.lock_p);
1004 monitor_power_on (si);
1005 pop_up_dialog_box (resources_dialog, resources_form,
1006 /* for debugging -- don't ask */
1007 (si->prefs.debug_p ? 69 : 0) +
1012 /* The main demo-mode command loop.
1016 demo_mode (saver_info *si)
1018 saver_preferences *p = &si->prefs;
1019 si->dbox_up_p = True;
1020 monitor_power_on (si);
1021 raise_window (si, True, False, False);
1022 make_screenhack_dialog (si);
1023 while (si->demo_mode_p)
1026 XtAppNextEvent (si->app, &event);
1027 switch (event.xany.type)
1029 case 0: /* synthetic "timeout" event */
1033 handle_clientmessage (si, &event, False);
1037 if (!p->use_xidle_extension &&
1038 !p->use_mit_saver_extension &&
1039 !p->use_sgi_saver_extension)
1041 start_notice_events_timer (si, event.xcreatewindow.window);
1044 printf ("%s: starting notice_events_timer for 0x%X (%lu)\n",
1046 (unsigned int) event.xcreatewindow.window,
1047 p->notice_events_timeout);
1048 #endif /* DEBUG_TIMERS */
1054 if (!XtWindowToWidget (si->dpy, event.xbutton.window))
1055 raise_screenhack_dialog ();
1059 #ifdef HAVE_MIT_SAVER_EXTENSION
1060 if (event.type == si->mit_saver_ext_event_number)
1062 /* Get the "real" server window(s) out of the way as soon
1065 for (i = 0; i < si->nscreens; i++)
1067 saver_screen_info *ssi = &si->screens[i];
1068 if (ssi->server_mit_saver_window &&
1069 window_exists_p (si->dpy, ssi->server_mit_saver_window))
1070 XUnmapWindow (si->dpy, ssi->server_mit_saver_window);
1074 #endif /* HAVE_MIT_SAVER_EXTENSION */
1076 XtDispatchEvent (&event);
1080 destroy_screenhack_dialogs (si);
1081 initialize_screensaver_window (si);
1083 si->demo_mode_p = True; /* kludge to inhibit unfade... */
1084 unblank_screen (si);
1085 si->demo_mode_p = False;
1089 demo_mode_hack (saver_info *si, char *hack)
1091 if (! si->demo_mode_p) abort ();
1092 kill_screenhack (si);
1093 if (! si->demo_hack)
1095 si->demo_hack = hack;
1096 spawn_screenhack (si, False);
1097 /* raise_screenhack_dialog(); */
1101 demo_mode_done (saver_info *si)
1103 kill_screenhack (si);
1105 unblank_screen (si);
1106 si->demo_mode_p = False;
1107 si->dbox_up_p = False;