-/* xscreensaver, Copyright (c) 1993-1996 Jamie Zawinski <jwz@netscape.com>
+/* demo.c --- implements the interactive demo-mode and options dialogs.
+ * xscreensaver, Copyright (c) 1993-1998 Jamie Zawinski <jwz@netscape.com>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* implied warranty.
*/
-#include <X11/Intrinsic.h>
-
-#if !__STDC__
-# define _NO_PROTO
+#ifdef HAVE_CONFIG_H
+# include "config.h"
#endif
-#include <Xm/Xm.h>
-#include <Xm/Text.h>
-#include <Xm/List.h>
-#include <Xm/ToggleB.h>
+#include <X11/Intrinsic.h>
+
+/* We don't actually use any widget internals, but these are included
+ so that gdb will have debug info for the widgets... */
+#include <X11/IntrinsicP.h>
+#include <X11/ShellP.h>
+
+#ifdef HAVE_MOTIF
+# include <Xm/Xm.h>
+# include <Xm/Text.h>
+# include <Xm/List.h>
+# include <Xm/ToggleB.h>
+
+#else /* HAVE_ATHENA */
+ /* Athena demo code contributed by Jon A. Christopher <jac8782@tamu.edu> */
+ /* Copyright 1997, with the same permissions as above. */
+# include <X11/StringDefs.h>
+# include <X11/Shell.h>
+# include <X11/Xaw/Form.h>
+# include <X11/Xaw/Box.h>
+# include <X11/Xaw/List.h>
+# include <X11/Xaw/Command.h>
+# include <X11/Xaw/Toggle.h>
+# include <X11/Xaw/Viewport.h>
+# include <X11/Xaw/Dialog.h>
+# include <X11/Xaw/Scrollbar.h>
+# include <X11/Xaw/Text.h>
+#endif /* HAVE_ATHENA */
#include "xscreensaver.h"
+#include "resources.h" /* for parse_time() */
#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
-#ifdef HAVE_MIT_SAVER_EXTENSION
-extern int mit_saver_ext_event_number;
-extern Window server_mit_saver_window;
-#endif /* HAVE_MIT_SAVER_EXTENSION */
-
-#ifdef HAVE_SGI_SAVER_EXTENSION
-/* extern int sgi_saver_ext_event_number; */
-#endif /* HAVE_SGI_SAVER_EXTENSION */
-
-extern Bool use_mit_saver_extension;
-extern Bool use_sgi_saver_extension;
-
-extern Time timeout, cycle, lock_timeout;
-#ifndef NO_LOCKING
-extern Time passwd_timeout;
-#endif
-extern int fade_seconds, fade_ticks;
-extern Bool verbose_p, install_cmap_p, fade_p, unfade_p;
-extern Bool lock_p, locking_disabled_p;
-
-static void demo_mode_hack P((char *));
-static void demo_mode_done P((void));
-
-static void focus_fuckus P((Widget dialog));
-static void text_cb P((Widget button, XtPointer, XtPointer));
-
-extern void demo_mode_restart_process ();
+static void demo_mode_hack (saver_info *si, char *);
+static void demo_mode_done (saver_info *si);
extern Widget demo_dialog;
extern Widget label1;
extern Widget verbose_toggle, cmap_toggle, fade_toggle, unfade_toggle,
lock_toggle;
-extern create_demo_dialog ();
-extern create_resources_dialog ();
+
+#ifdef HAVE_MOTIF
+
+# define set_toggle_button_state(toggle,state) \
+ XmToggleButtonSetState ((toggle), (state), True)
+# define set_text_string(text_widget,string) \
+ XmTextSetString ((text_widget), (string))
+# define add_button_callback(button,cb,arg) \
+ XtAddCallback ((button), XmNactivateCallback, (cb), (arg))
+# define add_toggle_callback(button,cb,arg) \
+ XtAddCallback ((button), XmNvalueChangedCallback, (cb), (arg))
+# define add_text_callback add_toggle_callback
+
+#else /* HAVE_ATHENA */
+
+# define set_toggle_button_state(toggle,state) \
+ XtVaSetValues((toggle), XtNstate, (state), 0)
+# define set_text_string(text_widget,string) \
+ XtVaSetValues ((text_widget), XtNvalue, (string), 0)
+# define add_button_callback(button,cb,arg) \
+ XtAddCallback ((button), XtNcallback, (cb), (arg))
+# define add_toggle_callback add_button_callback
+# define add_text_callback(b,c,a) ERROR!
+
+#endif /* HAVE_ATHENA */
+
+
+#define disable_widget(widget) \
+ XtVaSetValues((widget), XtNsensitive, False, 0)
+
+
+static char *
+get_text_string (Widget text_widget)
+{
+#ifdef HAVE_MOTIF
+ return XmTextGetString (text_widget);
+#else /* HAVE_ATHENA */
+ char *string = 0;
+ if (XtIsSubclass(text_widget, textWidgetClass))
+ XtVaGetValues (text_widget, XtNstring, &string, 0);
+ else if (XtIsSubclass(text_widget, dialogWidgetClass))
+ XtVaGetValues (text_widget, XtNvalue, &string, 0);
+ else
+ string = 0;
+
+ return string;
+#endif /* HAVE_ATHENA */
+}
+
+static char *
+get_label_string (Widget label_widget)
+{
+#ifdef HAVE_MOTIF
+ char *label = 0;
+ XmString xm_label = 0;
+ XtVaGetValues (label_widget, XmNlabelString, &xm_label, 0);
+ if (!xm_label)
+ return 0;
+ XmStringGetLtoR (xm_label, XmSTRING_DEFAULT_CHARSET, &label);
+ return label;
+#else /* HAVE_ATHENA */
+ char *label = 0;
+ XtVaGetValues (label_widget, XtNlabel, &label, 0);
+ return (label ? strdup(label) : 0);
+#endif /* HAVE_ATHENA */
+}
+
static void
-focus_fuckus (dialog)
- Widget dialog;
+set_label_string (Widget label_widget, char *string)
+{
+#ifdef HAVE_MOTIF
+ XmString xm_string = XmStringCreate (string, XmSTRING_DEFAULT_CHARSET);
+ XtVaSetValues (label_widget, XmNlabelString, xm_string, 0);
+ XmStringFree (xm_string);
+#else /* HAVE_ATHENA */
+ XtVaSetValues (label_widget, XtNlabel, string, 0);
+#endif /* HAVE_ATHENA */
+}
+
+
+void
+format_into_label (Widget label, const char *arg)
+{
+ char *text = get_label_string (label);
+ char *buf = (char *) malloc ((text ? strlen(text) : 100) + strlen(arg) + 10);
+
+ if (!text || !strcmp (text, XtName (label)))
+ strcpy (buf, "ERROR: RESOURCES ARE NOT INSTALLED CORRECTLY");
+ else
+ sprintf (buf, text, arg);
+
+ set_label_string (label, buf);
+ free (buf);
+ XtFree (text);
+}
+
+
+void
+steal_focus_and_colormap (Widget dialog)
{
- XSetInputFocus (XtDisplay (dialog), XtWindow (dialog),
- RevertToParent, CurrentTime);
+ Display *dpy = XtDisplay (dialog);
+ Window window = XtWindow (dialog);
+ Colormap cmap = 0;
+ XSetInputFocus (dpy, window, RevertToParent, CurrentTime);
+
+ XtVaGetValues (dialog, XtNcolormap, &cmap, 0);
+ if (cmap)
+ XInstallColormap (dpy, cmap);
}
static void
-raise_screenhack_dialog ()
+raise_screenhack_dialog (void)
{
XMapRaised (XtDisplay (demo_dialog), XtWindow (demo_dialog));
if (resources_dialog)
XMapRaised (XtDisplay (resources_dialog), XtWindow (resources_dialog));
- focus_fuckus (resources_dialog ? resources_dialog : demo_dialog);
+ steal_focus_and_colormap (resources_dialog ? resources_dialog : demo_dialog);
}
static void
-destroy_screenhack_dialogs ()
+destroy_screenhack_dialogs (saver_info *si)
{
+ saver_screen_info *ssi = si->default_screen;
+
if (demo_dialog) XtDestroyWidget (demo_dialog);
if (resources_dialog) XtDestroyWidget (resources_dialog);
demo_dialog = resources_dialog = 0;
+
+ if (ssi->demo_cmap &&
+ ssi->demo_cmap != ssi->cmap &&
+ ssi->demo_cmap != DefaultColormapOfScreen (ssi->screen))
+ {
+ XFreeColormap (si->dpy, ssi->demo_cmap);
+ ssi->demo_cmap = 0;
+ }
+
+ /* Since we installed our colormap to display the dialogs properly, put
+ the old one back, so that the screensaver_window is now displayed
+ properly. */
+ if (ssi->cmap)
+ XInstallColormap (si->dpy, ssi->cmap);
}
+
static void
-text_cb (button, client_data, call_data)
- Widget button;
- XtPointer client_data, call_data;
+text_cb (Widget text_widget, XtPointer client_data, XtPointer call_data)
+{
+ saver_info *si = (saver_info *) client_data;
+ char *line;
+ line = get_text_string (text_widget);
+ demo_mode_hack (si, line);
+}
+
+
+#ifdef HAVE_ATHENA
+/* Bend over backwards to make hitting Return in the text field do the
+ right thing.
+ */
+extern saver_info *global_si_kludge;
+static void text_enter (Widget w, XEvent *event, String *av, Cardinal *ac)
{
- char *line = XmTextGetString (button);
- demo_mode_hack (line);
+ text_cb (w, global_si_kludge, 0);
}
+static XtActionsRec actions[] = {{"done", text_enter}
+ };
+static char translations[] = ("<Key>Return: done()\n"
+ "<Key>Linefeed: done()\n"
+ "Ctrl<Key>M: done()\n"
+ "Ctrl<Key>J: done()\n");
+#endif /* HAVE_ATHENA */
+
static void
-select_cb (button, client_data, call_data)
- Widget button;
- XtPointer client_data, call_data;
+select_cb (Widget button, XtPointer client_data, XtPointer call_data)
{
- char **hacks = (char **) client_data;
+ saver_info *si = (saver_info *) client_data;
+
+#ifdef HAVE_ATHENA
+ XawListReturnStruct *item = (XawListReturnStruct*)call_data;
+ XtVaSetValues(text_line, XtNstring, item->string, 0);
+
+ demo_mode_hack (si, item->string);
+ if (item->list_index >= 0)
+ si->default_screen->current_hack = item->list_index;
+
+#else /* HAVE_MOTIF */
XmListCallbackStruct *lcb = (XmListCallbackStruct *) call_data;
- XmTextSetString (text_line, hacks [lcb->item_position - 1]);
- if (lcb->reason == XmCR_DEFAULT_ACTION)
- text_cb (text_line, 0, 0);
- focus_fuckus (demo_dialog);
+ char *string = 0;
+ if (lcb->item)
+ XmStringGetLtoR (lcb->item, XmSTRING_DEFAULT_CHARSET, &string);
+ set_text_string (text_line, (string ? string : ""));
+ if (lcb->reason == XmCR_DEFAULT_ACTION && string)
+ {
+ demo_mode_hack (si, string);
+ if (lcb->item_position > 0)
+ si->default_screen->current_hack = lcb->item_position - 1;
+ }
+ if (string)
+ XtFree (string);
+#endif /* HAVE_MOTIF */
+ steal_focus_and_colormap (demo_dialog);
}
+
+#if 0 /* configure does this now */
+#ifdef HAVE_ATHENA
+# if !defined(_Viewport_h)
+ /* The R4 Athena libs don't have this function. I don't know the right
+ way to tell, but I note that the R5 version of Viewport.h defines
+ _XawViewport_h, while the R4 version defines _Viewport_h. So we'll
+ try and key off of that... */
+# define HAVE_XawViewportSetCoordinates
+# endif
+#endif /* HAVE_ATHENA */
+#endif /* 0 */
+
+
+/* Why this behavior isn't automatic in *either* toolkit, I'll never know.
+ */
static void
-ensure_selected_item_visible (list)
- Widget list;
+ensure_selected_item_visible (Widget list)
{
+#ifdef HAVE_MOTIF
int *pos_list = 0;
int pos_count = 0;
if (XmListGetSelectedPos (list, &pos_list, &pos_count) && pos_count > 0)
}
if (pos_list)
XtFree ((char *) pos_list);
+
+#else /* HAVE_ATHENA */
+# ifdef HAVE_XawViewportSetCoordinates
+
+ int margin = 16; /* should be line height or something. */
+ int count = 0;
+ int pos;
+ Dimension list_h = 0, vp_h = 0;
+ Dimension top_margin = 4; /* I don't know where this value comes from */
+ Position vp_x = 0, vp_y = 0, current_y;
+ double cratio;
+ Widget viewport = XtParent(demo_list);
+ Widget sb = (viewport ? XtNameToWidget(viewport, "*vertical") : 0);
+ float sb_top = 0, sb_size = 0;
+ XawListReturnStruct *current = XawListShowCurrent(demo_list);
+ if (!current || !sb) return;
+
+ XtVaGetValues(demo_list,
+ XtNnumberStrings, &count,
+ XtNheight, &list_h,
+ 0);
+ if (count < 2 || list_h < 10) return;
+
+ XtVaGetValues(viewport, XtNheight, &vp_h, XtNx, &vp_x, XtNy, &vp_y, 0);
+ if (vp_h < 10) return;
+
+ XtVaGetValues(sb, XtNtopOfThumb, &sb_top, XtNshown, &sb_size, 0);
+ if (sb_size <= 0) return;
+
+ pos = current->list_index;
+ cratio = ((double) pos) / ((double) count);
+ current_y = (cratio * list_h);
+
+ if (cratio < sb_top ||
+ cratio > sb_top + sb_size)
+ {
+ if (cratio < sb_top)
+ current_y -= (vp_h - margin - margin);
+ else
+ current_y -= margin;
+
+ if ((long)current_y >= (long) list_h)
+ current_y = (Position) ((long)list_h - (long)vp_h);
+
+ if ((long)current_y < (long)top_margin)
+ current_y = (Position)top_margin;
+
+ XawViewportSetCoordinates (viewport, vp_x, current_y);
+ }
+# endif /* HAVE_XawViewportSetCoordinates */
+#endif /* HAVE_ATHENA */
}
+
static void
-next_cb (button, client_data, call_data)
- Widget button;
- XtPointer client_data, call_data;
+next_cb (Widget button, XtPointer client_data, XtPointer call_data)
{
+ saver_info *si = (saver_info *) client_data;
+
+#ifdef HAVE_ATHENA
+ int cnt;
+ XawListReturnStruct *current = XawListShowCurrent(demo_list);
+ if (current->list_index == XAW_LIST_NONE)
+ XawListHighlight(demo_list, 0);
+ else
+ {
+ XtVaGetValues(demo_list,
+ XtNnumberStrings, &cnt,
+ NULL);
+ if (current->list_index + 1 < cnt)
+ {
+ current->list_index++;
+ XawListHighlight(demo_list, current->list_index);
+ }
+ }
+
+ ensure_selected_item_visible (demo_list);
+ current = XawListShowCurrent(demo_list);
+ XtVaSetValues(text_line, XtNstring, current->string, 0);
+ demo_mode_hack (si, current->string);
+
+#else /* HAVE_MOTIF */
+
int *pos_list;
int pos_count;
if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
- XmListSelectPos (demo_list, 1, True);
+ {
+ XmListDeselectAllItems(demo_list); /* LessTif lossage */
+ XmListSelectPos (demo_list, 1, True);
+ }
else
{
- int pos = pos_list [0];
- XmListSelectPos (demo_list, pos + 1, True);
- XtFree ((char *) pos_list);
- if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
- abort ();
- if (pos_list [0] == pos)
- XmListSelectPos (demo_list, 1, True);
- XtFree ((char *) pos_list);
+ int pos = pos_list[0] + 1;
+ if (pos > si->prefs.screenhacks_count)
+ pos = 1;
+ XmListDeselectAllItems(demo_list); /* LessTif lossage */
+ XmListSelectPos (demo_list, pos, True);
}
+ XtFree ((char *) pos_list);
ensure_selected_item_visible (demo_list);
- text_cb (text_line, 0, 0);
+ demo_mode_hack (si, get_text_string (text_line));
+
+#endif /* HAVE_MOTIF */
}
+
static void
-prev_cb (button, client_data, call_data)
- Widget button;
- XtPointer client_data, call_data;
+prev_cb (Widget button, XtPointer client_data, XtPointer call_data)
{
+ saver_info *si = (saver_info *) client_data;
+
+#ifdef HAVE_ATHENA
+ XawListReturnStruct *current=XawListShowCurrent(demo_list);
+ if (current->list_index == XAW_LIST_NONE)
+ XawListHighlight(demo_list, 0);
+ else
+ {
+ if (current->list_index >= 1)
+ {
+ current->list_index--;
+ XawListHighlight(demo_list, current->list_index);
+ }
+ }
+
+ ensure_selected_item_visible (demo_list);
+ current = XawListShowCurrent(demo_list);
+ XtVaSetValues(text_line, XtNstring, current->string, 0);
+ demo_mode_hack (si, current->string);
+
+#else /* HAVE_MOTIF */
+
int *pos_list;
int pos_count;
if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
- XmListSelectPos (demo_list, 0, True);
+ {
+ XmListDeselectAllItems(demo_list); /* LessTif lossage */
+ XmListSelectPos (demo_list, 0, True);
+ }
else
{
+ XmListDeselectAllItems(demo_list); /* LessTif lossage */
XmListSelectPos (demo_list, pos_list [0] - 1, True);
XtFree ((char *) pos_list);
}
ensure_selected_item_visible (demo_list);
- text_cb (text_line, 0, 0);
+ demo_mode_hack (si, get_text_string (text_line));
+
+#endif /* HAVE_MOTIF */
}
-static void pop_resources_dialog ();
-static void make_resources_dialog ();
+static void pop_resources_dialog (saver_info *si);
+static void make_resources_dialog (saver_info *si, Widget parent);
static void
-edit_cb (button, client_data, call_data)
- Widget button;
- XtPointer client_data, call_data;
+edit_cb (Widget button, XtPointer client_data, XtPointer call_data)
{
- Widget parent = (Widget) client_data;
+ saver_info *si = (saver_info *) client_data;
+ saver_screen_info *ssi = si->default_screen;
+ Widget parent = ssi->toplevel_shell;
if (! resources_dialog)
- make_resources_dialog (parent);
- pop_resources_dialog ();
+ make_resources_dialog (si, parent);
+ pop_resources_dialog (si);
}
static void
-done_cb (button, client_data, call_data)
- Widget button;
- XtPointer client_data, call_data;
+done_cb (Widget button, XtPointer client_data, XtPointer call_data)
{
- demo_mode_done ();
+ saver_info *si = (saver_info *) client_data;
+ demo_mode_done (si);
}
static void
-restart_cb (button, client_data, call_data)
- Widget button;
- XtPointer client_data, call_data;
+restart_cb (Widget button, XtPointer client_data, XtPointer call_data)
{
- demo_mode_restart_process ();
+ saver_info *si = (saver_info *) client_data;
+ demo_mode_restart_process (si);
}
+
void
-pop_up_dialog_box (dialog, form, where)
- Widget dialog, form;
- int where;
+pop_up_dialog_box (Widget dialog, Widget form, int where)
{
/* I'm sure this is the wrong way to pop up a dialog box, but I can't
figure out how else to do it.
Arg av [100];
int ac = 0;
Dimension sw, sh, x, y, w, h;
+
+#ifdef HAVE_ATHENA
+ XtRealizeWidget (dialog);
+#else /* HAVE_MOTIF */
+ /* Motif likes us to realize the *child* of the shell... */
XtRealizeWidget (form);
+#endif /* HAVE_MOTIF */
+
sw = WidthOfScreen (XtScreen (dialog));
sh = HeightOfScreen (XtScreen (dialog));
ac = 0;
- XtSetArg (av [ac], XmNwidth, &w); ac++;
- XtSetArg (av [ac], XmNheight, &h); ac++;
+ XtSetArg (av [ac], XtNwidth, &w); ac++;
+ XtSetArg (av [ac], XtNheight, &h); ac++;
XtGetValues (form, av, ac);
+
+ /* for debugging -- don't ask */
+ if (where >= 69)
+ {
+ where -= 69;
+ sw = (sw * 7) / 12;
+ }
+
switch (where)
{
case 0: /* center it in the top-right quadrant */
if (x + w > sw) x = sw - w;
if (y + h > sh) y = sh - h;
ac = 0;
- XtSetArg (av [ac], XmNx, x); ac++;
- XtSetArg (av [ac], XmNy, y); ac++;
+ XtSetArg (av [ac], XtNx, x); ac++;
+ XtSetArg (av [ac], XtNy, y); ac++;
XtSetArg (av [ac], XtNoverrideRedirect, True); ac++;
+
+#ifdef HAVE_MOTIF
XtSetArg (av [ac], XmNdefaultPosition, False); ac++;
- /* I wonder whether this does anything useful? */
- /* XtSetArg (av [ac], XmNdialogStyle, XmDIALOG_SYSTEM_MODAL); ac++; */
+#endif /* HAVE_MOTIF */
+
XtSetValues (dialog, av, ac);
XtSetValues (form, av, ac);
+
+#ifdef HAVE_ATHENA
+ XtPopup (dialog, XtGrabNone);
+#else /* HAVE_MOTIF */
XtManageChild (form);
+#endif /* HAVE_MOTIF */
- focus_fuckus (dialog);
+ steal_focus_and_colormap (dialog);
}
-static void
-make_screenhack_dialog (parent, hacks)
- Widget parent;
- char **hacks;
+void
+make_screenhack_dialog (saver_info *si)
{
- char buf [255];
- Arg av[10];
- int ac;
- char *label;
- XmString xm_label = 0;
- XmString new_xm_label;
+ saver_screen_info *ssi = si->default_screen;
+ Widget parent = ssi->toplevel_shell;
+ char **hacks = si->prefs.screenhacks;
- create_demo_dialog (parent);
- ac = 0;
- XtSetArg (av [ac], XmNlabelString, &xm_label); ac++;
- XtGetValues (label1, av, ac);
- XmStringGetLtoR (xm_label, XmSTRING_DEFAULT_CHARSET, &label);
- if (!strcmp (label, XtName (label1)))
- strcpy (buf, "ERROR: RESOURCES ARE NOT INSTALLED CORRECTLY");
- else
- sprintf (buf, label, screensaver_version);
- new_xm_label = XmStringCreate (buf, XmSTRING_DEFAULT_CHARSET);
- ac = 0;
- XtSetArg (av [ac], XmNlabelString, new_xm_label); ac++;
- XtSetValues (label1, av, ac);
- XmStringFree (new_xm_label);
- XtFree (label);
-
- XtAddCallback (demo_list, XmNbrowseSelectionCallback, select_cb,
- (XtPointer) hacks);
- XtAddCallback (demo_list, XmNdefaultActionCallback, select_cb,
- (XtPointer) hacks);
-
- XtAddCallback (text_line, XmNactivateCallback, text_cb, 0);
- XtAddCallback (next, XmNactivateCallback, next_cb, 0);
- XtAddCallback (prev, XmNactivateCallback, prev_cb, 0);
- XtAddCallback (done, XmNactivateCallback, done_cb, 0);
- XtAddCallback (restart, XmNactivateCallback, restart_cb, 0);
- XtAddCallback (edit, XmNactivateCallback, edit_cb, (XtPointer) parent);
-
- for (; *hacks; hacks++)
+ if (ssi->demo_cmap &&
+ ssi->demo_cmap != ssi->cmap &&
+ ssi->demo_cmap != DefaultColormapOfScreen (ssi->screen))
{
- XmString xmstr = XmStringCreate (*hacks, XmSTRING_DEFAULT_CHARSET);
- XmListAddItem (demo_list, xmstr, 0);
- /* XmListSelectPos (widget, i, False); */
- XmStringFree (xmstr);
+ XFreeColormap (si->dpy, ssi->demo_cmap);
+ ssi->demo_cmap = 0;
}
-#if 0
- /* Dialogs that have scroll-lists don't obey maxWidth! Fuck!! Hack it. */
- ac = 0;
- XtSetArg (av [ac], XmNmaxWidth, &max_w); ac++;
- XtGetValues (demo_dialog, av, ac); /* great, this SEGVs */
-#endif
+ if (ssi->default_visual == DefaultVisualOfScreen (ssi->screen))
+ ssi->demo_cmap = DefaultColormapOfScreen (ssi->screen);
+ else
+ ssi->demo_cmap = XCreateColormap (si->dpy,
+ RootWindowOfScreen (ssi->screen),
+ ssi->default_visual, AllocNone);
+
+ create_demo_dialog (parent, ssi->default_visual, ssi->demo_cmap);
+ format_into_label (label1, si->version);
+
+ add_button_callback (next, next_cb, (XtPointer) si);
+ add_button_callback (prev, prev_cb, (XtPointer) si);
+ add_button_callback (done, done_cb, (XtPointer) si);
+ add_button_callback (restart, restart_cb, (XtPointer) si);
+ add_button_callback (edit, edit_cb, (XtPointer) si);
+
+#ifdef HAVE_MOTIF
+ XtAddCallback (demo_list, XmNbrowseSelectionCallback,
+ select_cb, (XtPointer) si);
+ XtAddCallback (demo_list, XmNdefaultActionCallback,
+ select_cb, (XtPointer) si);
+ XtAddCallback (text_line, XmNactivateCallback, text_cb, (XtPointer) si);
+
+ if (hacks)
+ for (; *hacks; hacks++)
+ {
+ XmString xmstr = XmStringCreate (*hacks, XmSTRING_DEFAULT_CHARSET);
+ XmListAddItem (demo_list, xmstr, 0);
+ XmStringFree (xmstr);
+ }
+
+ /* Cause the most-recently-run hack to be selected in the list.
+ Do some voodoo to make it be roughly centered in the list (really,
+ just make it not be within +/- 5 of the top/bottom if possible.)
+ */
+ if (ssi->current_hack > 0)
+ {
+ int i = ssi->current_hack+1;
+ int top = i + 5;
+ int bot = i - 5;
+ if (bot < 1) bot = 1;
+ if (top > si->prefs.screenhacks_count)
+ top = si->prefs.screenhacks_count;
+
+ XmListDeselectAllItems(demo_list); /* LessTif lossage */
+ XmListSelectPos (demo_list, bot, False);
+ ensure_selected_item_visible (demo_list);
+
+ XmListDeselectAllItems(demo_list); /* LessTif lossage */
+ XmListSelectPos (demo_list, top, False);
+ ensure_selected_item_visible (demo_list);
+
+ XmListDeselectAllItems(demo_list); /* LessTif lossage */
+ XmListSelectPos (demo_list, i, False);
+ ensure_selected_item_visible (demo_list);
+ }
- pop_up_dialog_box (demo_dialog, demo_form, 0);
+#else /* HAVE_ATHENA */
+
+ /* Hook up the text line. */
+
+ XtAppAddActions(XtWidgetToApplicationContext(text_line),
+ actions, XtNumber(actions));
+ XtOverrideTranslations(text_line, XtParseTranslationTable(translations));
+
+
+ /* Must realize the widget before populating the list, or the dialog
+ will be as wide as the longest string.
+ */
+ XtRealizeWidget (demo_dialog);
+
+ XtVaSetValues (demo_list,
+ XtNlist, hacks,
+ XtNnumberStrings, si->prefs.screenhacks_count,
+ 0);
+ XtAddCallback (demo_list, XtNcallback, select_cb, si);
+ if (ssi->current_hack > 0)
+ XawListHighlight(demo_list, ssi->current_hack);
+
+ /* Now that we've populated the list, make sure that the list is as
+ wide as the dialog itself.
+ */
+ {
+ Widget viewport = XtParent(demo_list);
+ Widget subform = XtParent(viewport);
+ Widget box = XtNameToWidget(demo_dialog, "*box");
+ Widget label1 = XtNameToWidget(demo_dialog, "*label1");
+ Widget label2 = XtNameToWidget(demo_dialog, "*label2");
+ Dimension x=0, y=0, w=0, h=0, bw=0, w2=0;
+ XtVaGetValues(subform,
+ XtNwidth, &w, XtNheight, &h, XtNborderWidth, &bw, 0);
+ XtVaGetValues(box, XtNwidth, &w2, 0);
+ if (w2 != w)
+ XtResizeWidget(subform, w2, h, bw);
+
+ /* Why isn't the viewport getting centered? */
+ XtVaGetValues(viewport,
+ XtNx, &x, XtNy, &y, XtNheight, &h, XtNborderWidth, &bw, 0);
+ printf("%d %d %d %d\n", x, y, w, h);
+ XtConfigureWidget(viewport, x, y, w2-x-x, h, bw);
+
+ /* And the text line, too. */
+ XtVaGetValues(text_line,
+ XtNwidth, &w, XtNheight, &h, XtNborderWidth, &bw, 0);
+ XtVaGetValues(viewport, XtNwidth, &w2, 0);
+ if (w2 != w)
+ XtResizeWidget(text_line, w2, h, bw);
+
+ /* And the labels too. */
+ XtVaGetValues(label1,
+ XtNwidth, &w, XtNheight, &h, XtNborderWidth, &bw, 0);
+ if (w2 != w)
+ XtResizeWidget(label1, w2, h, bw);
+
+ XtVaGetValues(label2,
+ XtNwidth, &w, XtNheight, &h, XtNborderWidth, &bw, 0);
+ if (w2 != w)
+ XtResizeWidget(label2, w2, h, bw);
+
+ }
+
+#endif /* HAVE_ATHENA */
+
+ monitor_power_on (si);
+ pop_up_dialog_box(demo_dialog, demo_form,
+ /* for debugging -- don't ask */
+ (si->prefs.debug_p ? 69 : 0) +
+ 0);
+
+#ifdef HAVE_ATHENA
+ /* For Athena, have to do this after the dialog is managed. */
+ ensure_selected_item_visible (demo_list);
+#endif /* HAVE_ATHENA */
}
\f
} res;
-extern int parse_time ();
-
static void
-hack_time_cb (dpy, line, store, sec_p)
- Display *dpy;
- char *line;
- int *store;
- Bool sec_p;
+hack_time_cb (Display *dpy, char *line, int *store, Bool sec_p)
{
if (*line)
{
}
static void
-res_sec_cb (button, client_data, call_data)
- Widget button;
- XtPointer client_data, call_data;
+res_sec_cb (Widget button, XtPointer client_data, XtPointer call_data)
{
- hack_time_cb (XtDisplay (button), XmTextGetString (button),
+ hack_time_cb (XtDisplay (button), get_text_string (button),
(int *) client_data, True);
}
static void
-res_min_cb (button, client_data, call_data)
- Widget button;
- XtPointer client_data, call_data;
+res_min_cb (Widget button, XtPointer client_data, XtPointer call_data)
{
- hack_time_cb (XtDisplay (button), XmTextGetString (button),
+ hack_time_cb (XtDisplay (button), get_text_string (button),
(int *) client_data, False);
}
static void
-res_int_cb (button, client_data, call_data)
- Widget button;
- XtPointer client_data, call_data;
+res_int_cb (Widget button, XtPointer client_data, XtPointer call_data)
{
- char *line = XmTextGetString (button);
+ char *line = get_text_string (button);
int *store = (int *) client_data;
unsigned int value;
char c;
}
static void
-res_bool_cb (button, client_data, call_data)
- Widget button;
- XtPointer client_data, call_data;
+res_bool_cb (Widget button, XtPointer client_data, XtPointer call_data)
{
int *store = (int *) client_data;
+#ifdef HAVE_MOTIF
*store = ((XmToggleButtonCallbackStruct *) call_data)->set;
+#else /* HAVE_ATHENA */
+ Boolean state = FALSE;
+ XtVaGetValues (button, XtNstate, &state, NULL);
+ *store = state;
+#endif /* HAVE_ATHENA */
}
static void
-res_cancel_cb (button, client_data, call_data)
- Widget button;
- XtPointer client_data, call_data;
+res_cancel_cb (Widget button, XtPointer client_data, XtPointer call_data)
{
XtDestroyWidget (resources_dialog);
resources_dialog = 0;
static void
-res_done_cb (button, client_data, call_data)
- Widget button;
- XtPointer client_data, call_data;
+res_done_cb (Widget button, XtPointer client_data, XtPointer call_data)
{
+ saver_info *si = (saver_info *) client_data;
+ saver_preferences *p = &si->prefs;
+
res_cancel_cb (button, client_data, call_data);
+#ifdef HAVE_ATHENA
+ /* Check all text widgets, since we don't have callbacks for these. */
+ res_min_cb (timeout_text, (XtPointer) &res.timeout, NULL);
+ res_min_cb (cycle_text, (XtPointer) &res.cycle, NULL);
+ res_sec_cb (fade_text, (XtPointer) &res.secs, NULL);
+ res_int_cb (ticks_text, (XtPointer) &res.ticks, NULL);
+ res_min_cb (lock_time_text, (XtPointer) &res.lock_time, NULL);
+ res_sec_cb (passwd_time_text, (XtPointer) &res.passwd_time, NULL);
+#endif /* HAVE_ATHENA */
+
/* Throttle the timeouts to minimum sane values. */
if (res.timeout < 5) res.timeout = 5;
if (res.cycle < 2) res.cycle = 2;
if (res.passwd_time < 10) res.passwd_time = 10;
- timeout = res.timeout * 1000;
- cycle = res.cycle * 1000;
- lock_timeout = res.lock_time * 1000;
+ p->timeout = res.timeout * 1000;
+ p->cycle = res.cycle * 1000;
+ p->lock_timeout = res.lock_time * 1000;
#ifndef NO_LOCKING
- passwd_timeout = res.passwd_time * 1000;
+ p->passwd_timeout = res.passwd_time * 1000;
+#endif
+ p->fade_seconds = res.secs;
+ p->fade_ticks = res.ticks;
+ p->verbose_p = res.verb;
+ p->install_cmap_p = res.cmap;
+ p->fade_p = res.fade;
+ p->unfade_p = res.unfade;
+ p->lock_p = res.lock_p;
+
+ if (p->debug_p && p->verbose_p)
+ fprintf (stderr, "%s: parameters changed:\n\
+ timeout: %d\n\tcycle: %d\n\tlock: %d\n\tpasswd: %d\n\
+ fade: %d\n\tfade: %d\n\tverbose: %d\n\tinstall: %d\n\
+ fade: %d\n\tunfade: %d\n\tlock: %d\n",
+ blurb(), p->timeout, p->cycle, p->lock_timeout,
+#ifdef NO_LOCKING
+ 0,
+#else
+ p->passwd_timeout,
#endif
- fade_seconds = res.secs;
- fade_ticks = res.ticks;
- verbose_p = res.verb;
- install_cmap_p = res.cmap;
- fade_p = res.fade;
- unfade_p = res.unfade;
- lock_p = res.lock_p;
+ p->fade_seconds, p->fade_ticks, p->verbose_p, p->install_cmap_p,
+ p->fade_p, p->unfade_p, p->lock_p);
+
#if defined(HAVE_MIT_SAVER_EXTENSION) || defined(HAVE_SGI_SAVER_EXTENSION)
- if (use_mit_saver_extension || use_sgi_saver_extension)
+ if (p->use_mit_saver_extension || p->use_sgi_saver_extension)
{
/* Need to set the server timeout to the new one the user has picked.
*/
int server_timeout, server_interval, prefer_blank, allow_exp;
- XGetScreenSaver (dpy, &server_timeout, &server_interval,
+ XGetScreenSaver (si->dpy, &server_timeout, &server_interval,
&prefer_blank, &allow_exp);
- if (server_timeout != (timeout / 1000))
+ if (server_timeout != (p->timeout / 1000))
{
- server_timeout = (timeout / 1000);
- if (verbose_p)
+ server_timeout = (p->timeout / 1000);
+ if (p->verbose_p)
fprintf (stderr,
"%s: configuring server for saver timeout of %d seconds.\n",
- progname, server_timeout);
+ blurb(), server_timeout);
/* Leave all other parameters the same. */
- XSetScreenSaver (dpy, server_timeout, server_interval,
+ XSetScreenSaver (si->dpy, server_timeout, server_interval,
prefer_blank, allow_exp);
}
}
static void
-make_resources_dialog (parent)
- Widget parent;
+make_resources_dialog (saver_info *si, Widget parent)
{
- Arg av[10];
- int ac;
+ saver_screen_info *ssi = si->default_screen;
- create_resources_dialog (parent);
+ if (ssi->demo_cmap &&
+ ssi->demo_cmap != ssi->cmap &&
+ ssi->demo_cmap != DefaultColormapOfScreen (ssi->screen))
+ {
+ XFreeColormap (si->dpy, ssi->demo_cmap);
+ ssi->demo_cmap = 0;
+ }
- XtAddCallback (res_done, XmNactivateCallback, res_done_cb, 0);
- XtAddCallback (res_cancel, XmNactivateCallback, res_cancel_cb, 0);
+ if (ssi->default_visual == DefaultVisualOfScreen (ssi->screen))
+ ssi->demo_cmap = DefaultColormapOfScreen (ssi->screen);
+ else
+ ssi->demo_cmap = XCreateColormap (si->dpy,
+ RootWindowOfScreen (ssi->screen),
+ ssi->default_visual, AllocNone);
+
+ create_resources_dialog (parent, ssi->default_visual, ssi->demo_cmap);
+
+ add_button_callback (res_done, res_done_cb, (XtPointer) si);
+ add_button_callback (res_cancel, res_cancel_cb, (XtPointer) si);
#define CB(widget,type,slot) \
- XtAddCallback ((widget), XmNvalueChangedCallback, (type), \
- (XtPointer) (slot))
+ add_text_callback ((widget), (type), (XtPointer) (slot))
+#define CBT(widget,type,slot) \
+ add_toggle_callback ((widget), (type), (XtPointer) (slot))
+
+#ifdef HAVE_MOTIF
+ /* When using Athena widgets, we can't set callbacks for these,
+ so we'll check them all if "done" gets pressed.
+ */
CB (timeout_text, res_min_cb, &res.timeout);
CB (cycle_text, res_min_cb, &res.cycle);
CB (fade_text, res_sec_cb, &res.secs);
CB (ticks_text, res_int_cb, &res.ticks);
CB (lock_time_text, res_min_cb, &res.lock_time);
CB (passwd_time_text, res_sec_cb, &res.passwd_time);
- CB (verbose_toggle, res_bool_cb, &res.verb);
- CB (cmap_toggle, res_bool_cb, &res.cmap);
- CB (fade_toggle, res_bool_cb, &res.fade);
- CB (unfade_toggle, res_bool_cb, &res.unfade);
- CB (lock_toggle, res_bool_cb, &res.lock_p);
+#endif /* HAVE_MOTIF */
+
+ CBT (verbose_toggle, res_bool_cb, &res.verb);
+ CBT (cmap_toggle, res_bool_cb, &res.cmap);
+ CBT (fade_toggle, res_bool_cb, &res.fade);
+ CBT (unfade_toggle, res_bool_cb, &res.unfade);
+ CBT (lock_toggle, res_bool_cb, &res.lock_p);
#undef CB
- ac = 0;
- XtSetArg (av[ac], XmNsensitive, False); ac++;
+#undef CBT
- if (locking_disabled_p)
+ if (si->locking_disabled_p)
{
- XtSetValues (passwd_time_text, av, ac);
- XtSetValues (lock_time_text, av, ac);
- XtSetValues (lock_toggle, av, ac);
+ disable_widget (passwd_time_text);
+ disable_widget (lock_time_text);
+ disable_widget (lock_toggle);
}
if (CellsOfScreen (XtScreen (parent)) <= 2)
{
- XtSetValues (fade_text, av, ac);
- XtSetValues (ticks_text, av, ac);
- XtSetValues (cmap_toggle, av, ac);
- XtSetValues (fade_toggle, av, ac);
- XtSetValues (unfade_toggle, av, ac);
+ disable_widget (fade_text);
+ disable_widget (ticks_text);
+ disable_widget (cmap_toggle);
+ disable_widget (fade_toggle);
+ disable_widget (unfade_toggle);
}
}
static void
-fmt_time (buf, s, min_p)
- char *buf;
- unsigned int s;
- int min_p;
+fmt_time (char *buf, unsigned int s, int min_p)
{
unsigned int h = 0, m = 0;
if (s >= 60)
}
static void
-pop_resources_dialog ()
+pop_resources_dialog (saver_info *si)
{
+ saver_preferences *p = &si->prefs;
char buf [100];
- res.timeout = timeout / 1000;
- res.cycle = cycle / 1000;
- res.lock_time = lock_timeout / 1000;
+ res.timeout = p->timeout / 1000;
+ res.cycle = p->cycle / 1000;
+ res.lock_time = p->lock_timeout / 1000;
#ifndef NO_LOCKING
- res.passwd_time = passwd_timeout / 1000;
+ res.passwd_time = p->passwd_timeout / 1000;
#endif
- res.secs = fade_seconds;
- res.ticks = fade_ticks;
- res.verb = verbose_p;
- res.cmap = install_cmap_p;
- res.fade = fade_p;
- res.unfade = unfade_p;
- res.lock_p = (lock_p && !locking_disabled_p);
-
- fmt_time (buf, res.timeout, 1); XmTextSetString (timeout_text, buf);
- fmt_time (buf, res.cycle, 1); XmTextSetString (cycle_text, buf);
- fmt_time (buf, res.lock_time, 1); XmTextSetString (lock_time_text, buf);
- fmt_time (buf, res.passwd_time, 0); XmTextSetString (passwd_time_text, buf);
- fmt_time (buf, res.secs, 0); XmTextSetString (fade_text, buf);
- sprintf (buf, "%u", res.ticks); XmTextSetString (ticks_text, buf);
-
- XmToggleButtonSetState (verbose_toggle, res.verb, True);
- XmToggleButtonSetState (cmap_toggle, res.cmap, True);
- XmToggleButtonSetState (fade_toggle, res.fade, True);
- XmToggleButtonSetState (unfade_toggle, res.unfade, True);
- XmToggleButtonSetState (lock_toggle, res.lock_p, True);
-
- pop_up_dialog_box (resources_dialog, resources_form, 1);
+ res.secs = p->fade_seconds;
+ res.ticks = p->fade_ticks;
+ res.verb = p->verbose_p;
+ res.cmap = p->install_cmap_p;
+ res.fade = p->fade_p;
+ res.unfade = p->unfade_p;
+ res.lock_p = (p->lock_p && !si->locking_disabled_p);
+
+ fmt_time (buf, res.timeout, 1); set_text_string (timeout_text, buf);
+ fmt_time (buf, res.cycle, 1); set_text_string (cycle_text, buf);
+ fmt_time (buf, res.lock_time, 1); set_text_string (lock_time_text, buf);
+ fmt_time (buf, res.passwd_time, 0); set_text_string (passwd_time_text, buf);
+ fmt_time (buf, res.secs, 0); set_text_string (fade_text, buf);
+ sprintf (buf, "%u", res.ticks); set_text_string (ticks_text, buf);
+
+ set_toggle_button_state (verbose_toggle, res.verb);
+ set_toggle_button_state (cmap_toggle, res.cmap);
+ set_toggle_button_state (fade_toggle, res.fade);
+ set_toggle_button_state (unfade_toggle, res.unfade);
+ set_toggle_button_state (lock_toggle, res.lock_p);
+
+ monitor_power_on (si);
+ pop_up_dialog_box (resources_dialog, resources_form,
+ /* for debugging -- don't ask */
+ (si->prefs.debug_p ? 69 : 0) +
+ 1);
}
\f
-/* The code on this page isn't actually Motif-specific */
-
-Bool dbox_up_p = False;
-Bool demo_mode_p = False;
-
-extern XtAppContext app;
-extern Widget toplevel_shell;
-extern Bool use_xidle_extension;
-extern Bool use_mit_saver_extension;
-extern Bool use_sgi_saver_extension;
-extern Time notice_events_timeout;
-
-extern char **screenhacks;
-extern char *demo_hack;
-
-extern void notice_events_timer P((XtPointer closure, XtIntervalId *timer));
-extern Bool handle_clientmessage P((/*XEvent *, Bool*/));
+/* The main demo-mode command loop.
+ */
void
-demo_mode ()
+demo_mode (saver_info *si)
{
- dbox_up_p = True;
- initialize_screensaver_window ();
- raise_window (True, False);
- make_screenhack_dialog (toplevel_shell, screenhacks);
- while (demo_mode_p)
+ saver_preferences *p = &si->prefs;
+ si->dbox_up_p = True;
+ monitor_power_on (si);
+ raise_window (si, True, False, False);
+ make_screenhack_dialog (si);
+ while (si->demo_mode_p)
{
XEvent event;
- XtAppNextEvent (app, &event);
+ XtAppNextEvent (si->app, &event);
switch (event.xany.type)
{
case 0: /* synthetic "timeout" event */
break;
case ClientMessage:
- handle_clientmessage (&event, False);
+ handle_clientmessage (si, &event, False);
break;
case CreateNotify:
- if (!use_xidle_extension &&
- !use_mit_saver_extension &&
- !use_sgi_saver_extension)
+ if (!p->use_xidle_extension &&
+ !p->use_mit_saver_extension &&
+ !p->use_sgi_saver_extension)
{
- XtAppAddTimeOut (app, notice_events_timeout, notice_events_timer,
- (XtPointer) event.xcreatewindow.window);
+ start_notice_events_timer (si, event.xcreatewindow.window);
#ifdef DEBUG_TIMERS
- if (verbose_p)
+ if (p->verbose_p)
printf ("%s: starting notice_events_timer for 0x%X (%lu)\n",
- progname,
+ blurb(),
(unsigned int) event.xcreatewindow.window,
- notice_events_timeout);
+ p->notice_events_timeout);
#endif /* DEBUG_TIMERS */
}
break;
case ButtonPress:
case ButtonRelease:
- if (!XtWindowToWidget (dpy, event.xbutton.window))
+ if (!XtWindowToWidget (si->dpy, event.xbutton.window))
raise_screenhack_dialog ();
/* fall through */
default:
#ifdef HAVE_MIT_SAVER_EXTENSION
- if (event.type == mit_saver_ext_event_number)
+ if (event.type == si->mit_saver_ext_event_number)
{
- /* Get the "real" server window out of the way as soon
+ /* Get the "real" server window(s) out of the way as soon
as possible. */
- if (server_mit_saver_window &&
- window_exists_p (dpy, server_mit_saver_window))
- XUnmapWindow (dpy, server_mit_saver_window);
+ int i = 0;
+ for (i = 0; i < si->nscreens; i++)
+ {
+ saver_screen_info *ssi = &si->screens[i];
+ if (ssi->server_mit_saver_window &&
+ window_exists_p (si->dpy, ssi->server_mit_saver_window))
+ XUnmapWindow (si->dpy, ssi->server_mit_saver_window);
+ }
}
else
#endif /* HAVE_MIT_SAVER_EXTENSION */
break;
}
}
- destroy_screenhack_dialogs ();
- initialize_screensaver_window ();
- unblank_screen ();
+ destroy_screenhack_dialogs (si);
+ initialize_screensaver_window (si);
+
+ si->demo_mode_p = True; /* kludge to inhibit unfade... */
+ unblank_screen (si);
+ si->demo_mode_p = False;
}
static void
-demo_mode_hack (hack)
- char *hack;
+demo_mode_hack (saver_info *si, char *hack)
{
- if (! demo_mode_p) abort ();
- kill_screenhack ();
- if (! demo_hack)
- blank_screen ();
- demo_hack = hack;
- spawn_screenhack (False);
+ if (! si->demo_mode_p) abort ();
+ kill_screenhack (si);
+ if (! si->demo_hack)
+ blank_screen (si);
+ si->demo_hack = hack;
+ spawn_screenhack (si, False);
/* raise_screenhack_dialog(); */
}
static void
-demo_mode_done ()
+demo_mode_done (saver_info *si)
{
- kill_screenhack ();
- if (demo_hack)
- unblank_screen ();
- demo_mode_p = False;
- dbox_up_p = False;
- demo_hack = 0;
+ kill_screenhack (si);
+ if (si->demo_hack)
+ unblank_screen (si);
+ si->demo_mode_p = False;
+ si->dbox_up_p = False;
+ si->demo_hack = 0;
}