1 /* xscreensaver, Copyright (c) 1993-1995 Jamie Zawinski <jwz@netscape.com>
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
12 #include <X11/Intrinsic.h>
21 #include <Xm/ToggleB.h>
23 #include "xscreensaver.h"
26 #ifdef HAVE_SAVER_EXTENSION
27 extern int saver_ext_event_number;
28 extern Window server_saver_window;
29 #endif /* HAVE_SAVER_EXTENSION */
31 extern Time timeout, cycle, lock_timeout;
33 extern Time passwd_timeout;
35 extern int fade_seconds, fade_ticks;
36 extern Bool verbose_p, install_cmap_p, fade_p, unfade_p;
37 extern Bool lock_p, locking_disabled_p;
39 static void demo_mode_hack P((char *));
40 static void demo_mode_done P((void));
42 static void focus_fuckus P((Widget dialog));
43 static void text_cb P((Widget button, XtPointer, XtPointer));
45 extern void demo_mode_restart_process ();
47 extern Widget demo_dialog;
49 extern Widget text_line;
50 extern Widget demo_form;
51 extern Widget demo_list;
52 extern Widget next, prev, done, restart, edit;
54 extern Widget resources_dialog;
55 extern Widget resources_form;
56 extern Widget res_done, res_cancel;
57 extern Widget timeout_text, cycle_text, fade_text, ticks_text;
58 extern Widget lock_time_text, passwd_time_text;
59 extern Widget verbose_toggle, cmap_toggle, fade_toggle, unfade_toggle,
62 extern create_demo_dialog ();
63 extern create_resources_dialog ();
69 XSetInputFocus (XtDisplay (dialog), XtWindow (dialog),
70 RevertToParent, CurrentTime);
74 raise_screenhack_dialog ()
76 XMapRaised (XtDisplay (demo_dialog), XtWindow (demo_dialog));
78 XMapRaised (XtDisplay (resources_dialog), XtWindow (resources_dialog));
79 focus_fuckus (resources_dialog ? resources_dialog : demo_dialog);
83 destroy_screenhack_dialogs ()
85 if (demo_dialog) XtDestroyWidget (demo_dialog);
86 if (resources_dialog) XtDestroyWidget (resources_dialog);
87 demo_dialog = resources_dialog = 0;
91 text_cb (button, client_data, call_data)
93 XtPointer client_data, call_data;
95 char *line = XmTextGetString (button);
96 demo_mode_hack (line);
101 select_cb (button, client_data, call_data)
103 XtPointer client_data, call_data;
105 char **hacks = (char **) client_data;
106 XmListCallbackStruct *lcb = (XmListCallbackStruct *) call_data;
107 XmTextSetString (text_line, hacks [lcb->item_position - 1]);
108 if (lcb->reason == XmCR_DEFAULT_ACTION)
109 text_cb (text_line, 0, 0);
110 focus_fuckus (demo_dialog);
114 ensure_selected_item_visible (list)
119 if (XmListGetSelectedPos (list, &pos_list, &pos_count) && pos_count > 0)
124 XmNtopItemPosition, &top,
125 XmNvisibleItemCount, &visible,
127 if (pos_list[0] >= top + visible)
129 int pos = pos_list[0] - visible + 1;
130 if (pos < 0) pos = 0;
131 XmListSetPos (list, pos);
133 else if (pos_list[0] < top)
135 XmListSetPos (list, pos_list[0]);
139 XtFree ((char *) pos_list);
143 next_cb (button, client_data, call_data)
145 XtPointer client_data, call_data;
149 if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
150 XmListSelectPos (demo_list, 1, True);
153 int pos = pos_list [0];
154 XmListSelectPos (demo_list, pos + 1, True);
155 XtFree ((char *) pos_list);
156 if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
158 if (pos_list [0] == pos)
159 XmListSelectPos (demo_list, 1, True);
160 XtFree ((char *) pos_list);
162 ensure_selected_item_visible (demo_list);
163 text_cb (text_line, 0, 0);
167 prev_cb (button, client_data, call_data)
169 XtPointer client_data, call_data;
173 if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
174 XmListSelectPos (demo_list, 0, True);
177 XmListSelectPos (demo_list, pos_list [0] - 1, True);
178 XtFree ((char *) pos_list);
180 ensure_selected_item_visible (demo_list);
181 text_cb (text_line, 0, 0);
185 static void pop_resources_dialog ();
186 static void make_resources_dialog ();
189 edit_cb (button, client_data, call_data)
191 XtPointer client_data, call_data;
193 Widget parent = (Widget) client_data;
194 if (! resources_dialog)
195 make_resources_dialog (parent);
196 pop_resources_dialog ();
200 done_cb (button, client_data, call_data)
202 XtPointer client_data, call_data;
209 restart_cb (button, client_data, call_data)
211 XtPointer client_data, call_data;
213 demo_mode_restart_process ();
217 pop_up_dialog_box (dialog, form, where)
221 /* I'm sure this is the wrong way to pop up a dialog box, but I can't
222 figure out how else to do it.
224 It's important that the screensaver dialogs not get decorated or
225 otherwise reparented by the window manager, because they need to be
226 children of the *real* root window, not the WM's virtual root, in
227 order for us to guarentee that they are visible above the screensaver
232 Dimension sw, sh, x, y, w, h;
233 XtRealizeWidget (form);
234 sw = WidthOfScreen (XtScreen (dialog));
235 sh = HeightOfScreen (XtScreen (dialog));
237 XtSetArg (av [ac], XmNwidth, &w); ac++;
238 XtSetArg (av [ac], XmNheight, &h); ac++;
239 XtGetValues (form, av, ac);
242 case 0: /* center it in the top-right quadrant */
243 x = (sw/2 + w) / 2 + (sw/2) - w;
244 y = (sh/2 + h) / 2 - h;
246 case 1: /* center it in the bottom-right quadrant */
247 x = (sw/2 + w) / 2 + (sw/2) - w;
248 y = (sh/2 + h) / 2 + (sh/2) - h;
250 case 2: /* center it on the screen */
251 x = (sw + w) / 2 - w;
252 y = (sh + h) / 2 - h;
257 if (x + w > sw) x = sw - w;
258 if (y + h > sh) y = sh - h;
260 XtSetArg (av [ac], XmNx, x); ac++;
261 XtSetArg (av [ac], XmNy, y); ac++;
262 XtSetArg (av [ac], XtNoverrideRedirect, True); ac++;
263 XtSetArg (av [ac], XmNdefaultPosition, False); ac++;
264 /* I wonder whether this does anything useful? */
265 /* XtSetArg (av [ac], XmNdialogStyle, XmDIALOG_SYSTEM_MODAL); ac++; */
266 XtSetValues (dialog, av, ac);
267 XtSetValues (form, av, ac);
268 XtManageChild (form);
270 focus_fuckus (dialog);
275 make_screenhack_dialog (parent, hacks)
283 XmString xm_label = 0;
284 XmString new_xm_label;
286 create_demo_dialog (parent);
288 XtSetArg (av [ac], XmNlabelString, &xm_label); ac++;
289 XtGetValues (label1, av, ac);
290 XmStringGetLtoR (xm_label, XmSTRING_DEFAULT_CHARSET, &label);
291 if (!strcmp (label, XtName (label1)))
292 strcpy (buf, "ERROR: RESOURCES ARE NOT INSTALLED CORRECTLY");
294 sprintf (buf, label, screensaver_version);
295 new_xm_label = XmStringCreate (buf, XmSTRING_DEFAULT_CHARSET);
297 XtSetArg (av [ac], XmNlabelString, new_xm_label); ac++;
298 XtSetValues (label1, av, ac);
299 XmStringFree (new_xm_label);
302 XtAddCallback (demo_list, XmNbrowseSelectionCallback, select_cb,
304 XtAddCallback (demo_list, XmNdefaultActionCallback, select_cb,
307 XtAddCallback (text_line, XmNactivateCallback, text_cb, 0);
308 XtAddCallback (next, XmNactivateCallback, next_cb, 0);
309 XtAddCallback (prev, XmNactivateCallback, prev_cb, 0);
310 XtAddCallback (done, XmNactivateCallback, done_cb, 0);
311 XtAddCallback (restart, XmNactivateCallback, restart_cb, 0);
312 XtAddCallback (edit, XmNactivateCallback, edit_cb, (XtPointer) parent);
314 for (; *hacks; hacks++)
316 XmString xmstr = XmStringCreate (*hacks, XmSTRING_DEFAULT_CHARSET);
317 XmListAddItem (demo_list, xmstr, 0);
318 /* XmListSelectPos (widget, i, False); */
319 XmStringFree (xmstr);
323 /* Dialogs that have scroll-lists don't obey maxWidth! Fuck!! Hack it. */
325 XtSetArg (av [ac], XmNmaxWidth, &max_w); ac++;
326 XtGetValues (demo_dialog, av, ac); /* great, this SEGVs */
329 pop_up_dialog_box (demo_dialog, demo_form, 0);
333 /* the Screensaver Parameters dialog */
335 static struct resources {
336 int timeout, cycle, secs, ticks, lock_time, passwd_time;
337 int verb, cmap, fade, unfade, lock_p;
341 extern int parse_time ();
344 hack_time_cb (dpy, line, store, sec_p)
353 value = parse_time (line, sec_p, True);
362 res_sec_cb (button, client_data, call_data)
364 XtPointer client_data, call_data;
366 hack_time_cb (XtDisplay (button), XmTextGetString (button),
367 (int *) client_data, True);
371 res_min_cb (button, client_data, call_data)
373 XtPointer client_data, call_data;
375 hack_time_cb (XtDisplay (button), XmTextGetString (button),
376 (int *) client_data, False);
380 res_int_cb (button, client_data, call_data)
382 XtPointer client_data, call_data;
384 char *line = XmTextGetString (button);
385 int *store = (int *) client_data;
390 else if (sscanf (line, "%u%c", &value, &c) != 1)
391 XBell (XtDisplay (button), 0);
397 res_bool_cb (button, client_data, call_data)
399 XtPointer client_data, call_data;
401 int *store = (int *) client_data;
402 *store = ((XmToggleButtonCallbackStruct *) call_data)->set;
406 res_cancel_cb (button, client_data, call_data)
408 XtPointer client_data, call_data;
410 XtDestroyWidget (resources_dialog);
411 resources_dialog = 0;
412 raise_screenhack_dialog ();
417 res_done_cb (button, client_data, call_data)
419 XtPointer client_data, call_data;
421 res_cancel_cb (button, client_data, call_data);
423 if (res.timeout < 10) res.timeout = 10;
424 if (res.cycle < 2) res.cycle = 2;
425 if (res.passwd_time < 2) res.passwd_time = 30;
427 timeout = res.timeout * 1000;
428 cycle = res.cycle * 1000;
429 lock_timeout = res.lock_time * 1000;
431 passwd_timeout = res.passwd_time * 1000;
433 fade_seconds = res.secs;
434 fade_ticks = res.ticks;
435 verbose_p = res.verb;
436 install_cmap_p = res.cmap;
438 unfade_p = res.unfade;
444 make_resources_dialog (parent)
450 create_resources_dialog (parent);
452 XtAddCallback (res_done, XmNactivateCallback, res_done_cb, 0);
453 XtAddCallback (res_cancel, XmNactivateCallback, res_cancel_cb, 0);
455 #define CB(widget,type,slot) \
456 XtAddCallback ((widget), XmNvalueChangedCallback, (type), \
458 CB (timeout_text, res_min_cb, &res.timeout);
459 CB (cycle_text, res_min_cb, &res.cycle);
460 CB (fade_text, res_sec_cb, &res.secs);
461 CB (ticks_text, res_int_cb, &res.ticks);
462 CB (lock_time_text, res_min_cb, &res.lock_time);
463 CB (passwd_time_text, res_sec_cb, &res.passwd_time);
464 CB (verbose_toggle, res_bool_cb, &res.verb);
465 CB (cmap_toggle, res_bool_cb, &res.cmap);
466 CB (fade_toggle, res_bool_cb, &res.fade);
467 CB (unfade_toggle, res_bool_cb, &res.unfade);
468 CB (lock_toggle, res_bool_cb, &res.lock_p);
471 XtSetArg (av[ac], XmNsensitive, False); ac++;
473 if (locking_disabled_p)
475 XtSetValues (passwd_time_text, av, ac);
476 XtSetValues (lock_time_text, av, ac);
477 XtSetValues (lock_toggle, av, ac);
479 if (CellsOfScreen (XtScreen (parent)) <= 2)
481 XtSetValues (fade_text, av, ac);
482 XtSetValues (ticks_text, av, ac);
483 XtSetValues (cmap_toggle, av, ac);
484 XtSetValues (fade_toggle, av, ac);
485 XtSetValues (unfade_toggle, av, ac);
491 fmt_time (buf, s, min_p)
496 unsigned int h = 0, m = 0;
508 if (min_p && h == 0 && s == 0)
509 sprintf (buf, "%u", m);
510 else if (!min_p && h == 0 && m == 0)
511 sprintf (buf, "%u", s);
514 sprintf (buf, "%u:%02u", m, s);
517 sprintf (buf, "%u:%02u:%02u", h, m, s);
521 pop_resources_dialog ()
525 res.timeout = timeout / 1000;
526 res.cycle = cycle / 1000;
527 res.lock_time = lock_timeout / 1000;
529 res.passwd_time = passwd_timeout / 1000;
531 res.secs = fade_seconds;
532 res.ticks = fade_ticks;
533 res.verb = verbose_p;
534 res.cmap = install_cmap_p;
536 res.unfade = unfade_p;
537 res.lock_p = (lock_p && !locking_disabled_p);
539 fmt_time (buf, res.timeout, 1); XmTextSetString (timeout_text, buf);
540 fmt_time (buf, res.cycle, 1); XmTextSetString (cycle_text, buf);
541 fmt_time (buf, res.lock_time, 1); XmTextSetString (lock_time_text, buf);
542 fmt_time (buf, res.passwd_time, 0); XmTextSetString (passwd_time_text, buf);
543 fmt_time (buf, res.secs, 0); XmTextSetString (fade_text, buf);
544 sprintf (buf, "%u", res.ticks); XmTextSetString (ticks_text, buf);
546 XmToggleButtonSetState (verbose_toggle, res.verb, True);
547 XmToggleButtonSetState (cmap_toggle, res.cmap, True);
548 XmToggleButtonSetState (fade_toggle, res.fade, True);
549 XmToggleButtonSetState (unfade_toggle, res.unfade, True);
550 XmToggleButtonSetState (lock_toggle, res.lock_p, True);
552 pop_up_dialog_box (resources_dialog, resources_form, 1);
556 /* The code on this page isn't actually Motif-specific */
558 Bool dbox_up_p = False;
559 Bool demo_mode_p = False;
561 extern XtAppContext app;
562 extern Widget toplevel_shell;
563 extern Bool use_xidle_extension;
564 extern Bool use_saver_extension;
565 extern Time notice_events_timeout;
567 extern char **screenhacks;
568 extern char *demo_hack;
570 extern void notice_events_timer P((XtPointer closure, XtIntervalId *timer));
571 extern Bool handle_clientmessage P((/*XEvent *, Bool*/));
577 initialize_screensaver_window ();
578 raise_window (True, False);
579 make_screenhack_dialog (toplevel_shell, screenhacks);
583 XtAppNextEvent (app, &event);
584 switch (event.xany.type)
586 case 0: /* synthetic "timeout" event */
590 handle_clientmessage (&event, False);
594 if (!use_xidle_extension && !use_saver_extension)
596 XtAppAddTimeOut (app, notice_events_timeout, notice_events_timer,
597 (XtPointer) event.xcreatewindow.window);
600 printf ("%s: starting notice_events_timer for 0x%X (%lu)\n",
602 (unsigned int) event.xcreatewindow.window,
603 notice_events_timeout);
604 #endif /* DEBUG_TIMERS */
610 if (!XtWindowToWidget (dpy, event.xbutton.window))
611 raise_screenhack_dialog ();
615 #ifdef HAVE_SAVER_EXTENSION
616 if (event.type == saver_ext_event_number)
618 /* Get the "real" server window out of the way as soon
620 if (server_saver_window &&
621 window_exists_p (dpy, server_saver_window))
622 XUnmapWindow (dpy, server_saver_window);
625 #endif /* HAVE_SAVER_EXTENSION */
627 XtDispatchEvent (&event);
631 destroy_screenhack_dialogs ();
632 initialize_screensaver_window ();
637 demo_mode_hack (hack)
640 if (! demo_mode_p) abort ();
645 spawn_screenhack (False);