1 /* xscreensaver, Copyright (c) 1993 Jamie Zawinski <jwz@mcom.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 extern Time timeout, cycle, lock_timeout;
28 extern Time passwd_timeout;
30 extern int fade_seconds, fade_ticks;
31 extern Bool verbose_p, install_cmap_p, fade_p, unfade_p;
32 extern Bool lock_p, locking_disabled_p;
34 static void demo_mode_hack P((char *));
35 static void demo_mode_done P((void));
37 static void focus_fuckus P((Widget dialog));
38 static void text_cb P((Widget button, XtPointer, XtPointer));
40 extern void demo_mode_restart_process ();
42 extern Widget demo_dialog;
44 extern Widget text_line;
45 extern Widget demo_form;
46 extern Widget demo_list;
47 extern Widget next, prev, done, restart, edit;
49 extern Widget resources_dialog;
50 extern Widget resources_form;
51 extern Widget res_done, res_cancel;
52 extern Widget timeout_text, cycle_text, fade_text, ticks_text;
53 extern Widget lock_time_text, passwd_time_text;
54 extern Widget verbose_toggle, cmap_toggle, fade_toggle, unfade_toggle,
57 extern create_demo_dialog ();
58 extern create_resources_dialog ();
64 XSetInputFocus (XtDisplay (dialog), XtWindow (dialog),
65 RevertToParent, CurrentTime);
69 raise_screenhack_dialog ()
71 XMapRaised (XtDisplay (demo_dialog), XtWindow (demo_dialog));
73 XMapRaised (XtDisplay (resources_dialog), XtWindow (resources_dialog));
74 focus_fuckus (resources_dialog ? resources_dialog : demo_dialog);
78 destroy_screenhack_dialogs ()
80 if (demo_dialog) XtDestroyWidget (demo_dialog);
81 if (resources_dialog) XtDestroyWidget (resources_dialog);
82 demo_dialog = resources_dialog = 0;
86 text_cb (button, client_data, call_data)
88 XtPointer client_data, call_data;
90 char *line = XmTextGetString (button);
91 demo_mode_hack (line);
96 select_cb (button, client_data, call_data)
98 XtPointer client_data, call_data;
100 char **hacks = (char **) client_data;
101 XmListCallbackStruct *lcb = (XmListCallbackStruct *) call_data;
102 XmTextSetString (text_line, hacks [lcb->item_position - 1]);
103 if (lcb->reason == XmCR_DEFAULT_ACTION)
104 text_cb (text_line, 0, 0);
105 focus_fuckus (demo_dialog);
109 next_cb (button, client_data, call_data)
111 XtPointer client_data, call_data;
115 if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
116 XmListSelectPos (demo_list, 1, True);
119 int pos = pos_list [0];
120 XmListSelectPos (demo_list, pos + 1, True);
121 XtFree ((char *) pos_list);
122 if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
124 if (pos_list [0] == pos)
125 XmListSelectPos (demo_list, 1, True);
126 XtFree ((char *) pos_list);
128 text_cb (text_line, 0, 0);
132 prev_cb (button, client_data, call_data)
134 XtPointer client_data, call_data;
138 if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
139 XmListSelectPos (demo_list, 0, True);
142 XmListSelectPos (demo_list, pos_list [0] - 1, True);
143 XtFree ((char *) pos_list);
145 text_cb (text_line, 0, 0);
149 static void pop_resources_dialog ();
150 static void make_resources_dialog ();
153 edit_cb (button, client_data, call_data)
155 XtPointer client_data, call_data;
157 Widget parent = (Widget) client_data;
158 if (! resources_dialog)
159 make_resources_dialog (parent);
160 pop_resources_dialog ();
164 done_cb (button, client_data, call_data)
166 XtPointer client_data, call_data;
173 restart_cb (button, client_data, call_data)
175 XtPointer client_data, call_data;
177 demo_mode_restart_process ();
181 pop_up_dialog_box (dialog, form, where)
185 /* I'm sure this is the wrong way to pop up a dialog box, but I can't
186 figure out how else to do it.
188 It's important that the screensaver dialogs not get decorated or
189 otherwise reparented by the window manager, because they need to be
190 children of the *real* root window, not the WM's virtual root, in
191 order for us to guarentee that they are visible above the screensaver
196 Dimension sw, sh, x, y, w, h;
197 XtRealizeWidget (form);
198 sw = WidthOfScreen (XtScreen (dialog));
199 sh = HeightOfScreen (XtScreen (dialog));
201 XtSetArg (av [ac], XmNwidth, &w); ac++;
202 XtSetArg (av [ac], XmNheight, &h); ac++;
203 XtGetValues (form, av, ac);
206 case 0: /* center it in the top-right quadrant */
207 x = (sw/2 + w) / 2 + (sw/2) - w;
208 y = (sh/2 + h) / 2 - h;
210 case 1: /* center it in the bottom-right quadrant */
211 x = (sw/2 + w) / 2 + (sw/2) - w;
212 y = (sh/2 + h) / 2 + (sh/2) - h;
214 case 2: /* center it on the screen */
215 x = (sw + w) / 2 - w;
216 y = (sh + h) / 2 - h;
221 if (x + w > sw) x = sw - w;
222 if (y + h > sh) y = sh - h;
224 XtSetArg (av [ac], XmNx, x); ac++;
225 XtSetArg (av [ac], XmNy, y); ac++;
226 XtSetArg (av [ac], XtNoverrideRedirect, True); ac++;
227 XtSetArg (av [ac], XmNdefaultPosition, False); ac++;
228 /* I wonder whether this does anything useful? */
229 /* XtSetArg (av [ac], XmNdialogStyle, XmDIALOG_SYSTEM_MODAL); ac++; */
230 XtSetValues (dialog, av, ac);
231 XtSetValues (form, av, ac);
232 XtManageChild (form);
234 focus_fuckus (dialog);
239 make_screenhack_dialog (parent, hacks)
247 XmString xm_label = 0;
248 XmString new_xm_label;
250 create_demo_dialog (parent);
252 XtSetArg (av [ac], XmNlabelString, &xm_label); ac++;
253 XtGetValues (label1, av, ac);
254 XmStringGetLtoR (xm_label, XmSTRING_DEFAULT_CHARSET, &label);
255 if (!strcmp (label, XtName (label1)))
256 strcpy (buf, "ERROR: RESOURCES ARE NOT INSTALLED CORRECTLY");
258 sprintf (buf, label, screensaver_version);
259 new_xm_label = XmStringCreate (buf, XmSTRING_DEFAULT_CHARSET);
261 XtSetArg (av [ac], XmNlabelString, new_xm_label); ac++;
262 XtSetValues (label1, av, ac);
263 XmStringFree (new_xm_label);
266 XtAddCallback (demo_list, XmNbrowseSelectionCallback, select_cb,
268 XtAddCallback (demo_list, XmNdefaultActionCallback, select_cb,
271 XtAddCallback (text_line, XmNactivateCallback, text_cb, 0);
272 XtAddCallback (next, XmNactivateCallback, next_cb, 0);
273 XtAddCallback (prev, XmNactivateCallback, prev_cb, 0);
274 XtAddCallback (done, XmNactivateCallback, done_cb, 0);
275 XtAddCallback (restart, XmNactivateCallback, restart_cb, 0);
276 XtAddCallback (edit, XmNactivateCallback, edit_cb, (XtPointer) parent);
278 for (; *hacks; hacks++)
280 XmString xmstr = XmStringCreate (*hacks, XmSTRING_DEFAULT_CHARSET);
281 XmListAddItem (demo_list, xmstr, 0);
282 /* XmListSelectPos (widget, i, False); */
283 XmStringFree (xmstr);
287 /* Dialogs that have scroll-lists don't obey maxWidth! Fuck!! Hack it. */
289 XtSetArg (av [ac], XmNmaxWidth, &max_w); ac++;
290 XtGetValues (demo_dialog, av, ac); /* great, this SEGVs */
293 pop_up_dialog_box (demo_dialog, demo_form, 0);
297 /* the Screensaver Parameters dialog */
299 static struct resources {
300 int timeout, cycle, secs, ticks, lock_time, passwd_time;
301 int verb, cmap, fade, unfade, lock_p;
305 extern int parse_time ();
308 hack_time_cb (dpy, line, store, sec_p)
317 value = parse_time (line, sec_p, True);
326 res_sec_cb (button, client_data, call_data)
328 XtPointer client_data, call_data;
330 hack_time_cb (XtDisplay (button), XmTextGetString (button),
331 (int *) client_data, True);
335 res_min_cb (button, client_data, call_data)
337 XtPointer client_data, call_data;
339 hack_time_cb (XtDisplay (button), XmTextGetString (button),
340 (int *) client_data, False);
344 res_int_cb (button, client_data, call_data)
346 XtPointer client_data, call_data;
348 char *line = XmTextGetString (button);
349 int *store = (int *) client_data;
354 else if (sscanf (line, "%u%c", &value, &c) != 1)
355 XBell (XtDisplay (button), 0);
361 res_bool_cb (button, client_data, call_data)
363 XtPointer client_data, call_data;
365 int *store = (int *) client_data;
366 *store = ((XmToggleButtonCallbackStruct *) call_data)->set;
370 res_cancel_cb (button, client_data, call_data)
372 XtPointer client_data, call_data;
374 XtDestroyWidget (resources_dialog);
375 resources_dialog = 0;
376 raise_screenhack_dialog ();
381 res_done_cb (button, client_data, call_data)
383 XtPointer client_data, call_data;
385 res_cancel_cb (button, client_data, call_data);
387 if (res.timeout < 10) res.timeout = 10;
388 if (res.cycle < 2) res.cycle = 2;
389 if (res.passwd_time < 2) res.passwd_time = 30;
391 timeout = res.timeout * 1000;
392 cycle = res.cycle * 1000;
393 lock_timeout = res.lock_time * 1000;
395 passwd_timeout = res.passwd_time * 1000;
397 fade_seconds = res.secs;
398 fade_ticks = res.ticks;
399 verbose_p = res.verb;
400 install_cmap_p = res.cmap;
402 unfade_p = res.unfade;
408 make_resources_dialog (parent)
414 create_resources_dialog (parent);
416 XtAddCallback (res_done, XmNactivateCallback, res_done_cb, 0);
417 XtAddCallback (res_cancel, XmNactivateCallback, res_cancel_cb, 0);
419 #define CB(widget,type,slot) \
420 XtAddCallback ((widget), XmNvalueChangedCallback, (type), \
422 CB (timeout_text, res_min_cb, &res.timeout);
423 CB (cycle_text, res_min_cb, &res.cycle);
424 CB (fade_text, res_sec_cb, &res.secs);
425 CB (ticks_text, res_int_cb, &res.ticks);
426 CB (lock_time_text, res_min_cb, &res.lock_time);
427 CB (passwd_time_text, res_sec_cb, &res.passwd_time);
428 CB (verbose_toggle, res_bool_cb, &res.verb);
429 CB (cmap_toggle, res_bool_cb, &res.cmap);
430 CB (fade_toggle, res_bool_cb, &res.fade);
431 CB (unfade_toggle, res_bool_cb, &res.unfade);
432 CB (lock_toggle, res_bool_cb, &res.lock_p);
435 XtSetArg (av[ac], XmNsensitive, False); ac++;
437 if (locking_disabled_p)
439 XtSetValues (passwd_time_text, av, ac);
440 XtSetValues (lock_time_text, av, ac);
441 XtSetValues (lock_toggle, av, ac);
443 if (CellsOfScreen (XtScreen (parent)) <= 2)
445 XtSetValues (fade_text, av, ac);
446 XtSetValues (ticks_text, av, ac);
447 XtSetValues (cmap_toggle, av, ac);
448 XtSetValues (fade_toggle, av, ac);
449 XtSetValues (unfade_toggle, av, ac);
455 fmt_time (buf, s, min_p)
460 unsigned int h = 0, m = 0;
472 if (min_p && h == 0 && s == 0)
473 sprintf (buf, "%u", m);
474 else if (!min_p && h == 0 && m == 0)
475 sprintf (buf, "%u", s);
478 sprintf (buf, "%u:%02u", m, s);
481 sprintf (buf, "%u:%02u:%02u", h, m, s);
485 pop_resources_dialog ()
489 res.timeout = timeout / 1000;
490 res.cycle = cycle / 1000;
491 res.lock_time = lock_timeout / 1000;
493 res.passwd_time = passwd_timeout / 1000;
495 res.secs = fade_seconds;
496 res.ticks = fade_ticks;
497 res.verb = verbose_p;
498 res.cmap = install_cmap_p;
500 res.unfade = unfade_p;
501 res.lock_p = (lock_p && !locking_disabled_p);
503 fmt_time (buf, res.timeout, 1); XmTextSetString (timeout_text, buf);
504 fmt_time (buf, res.cycle, 1); XmTextSetString (cycle_text, buf);
505 fmt_time (buf, res.lock_time, 1); XmTextSetString (lock_time_text, buf);
506 fmt_time (buf, res.passwd_time, 0); XmTextSetString (passwd_time_text, buf);
507 fmt_time (buf, res.secs, 0); XmTextSetString (fade_text, buf);
508 sprintf (buf, "%u", res.ticks); XmTextSetString (ticks_text, buf);
510 XmToggleButtonSetState (verbose_toggle, res.verb, True);
511 XmToggleButtonSetState (cmap_toggle, res.cmap, True);
512 XmToggleButtonSetState (fade_toggle, res.fade, True);
513 XmToggleButtonSetState (unfade_toggle, res.unfade, True);
514 XmToggleButtonSetState (lock_toggle, res.lock_p, True);
516 pop_up_dialog_box (resources_dialog, resources_form, 1);
520 /* The code on this page isn't actually Motif-specific */
522 Bool dbox_up_p = False;
523 Bool demo_mode_p = False;
525 extern XtAppContext app;
526 extern Widget toplevel_shell;
527 extern Bool use_xidle;
528 extern Time notice_events_timeout;
530 extern char **screenhacks;
531 extern char *demo_hack;
533 extern void notice_events_timer P((XtPointer closure, void *timer));
534 extern Bool handle_clientmessage P((/*XEvent *, Bool*/));
540 initialize_screensaver_window ();
541 raise_window (True, False);
542 make_screenhack_dialog (toplevel_shell, screenhacks);
546 XtAppNextEvent (app, &event);
547 switch (event.xany.type)
549 case 0: /* synthetic "timeout" event */
553 handle_clientmessage (&event, False);
560 XtAppAddTimeOut (app, notice_events_timeout, notice_events_timer,
561 (XtPointer) event.xcreatewindow.window);
566 if (!XtWindowToWidget (dpy, event.xbutton.window))
567 raise_screenhack_dialog ();
571 XtDispatchEvent (&event);
575 destroy_screenhack_dialogs ();
576 initialize_screensaver_window ();
581 demo_mode_hack (hack)
584 if (! demo_mode_p) abort ();
589 spawn_screenhack (False);