-/* xscreensaver, Copyright (c) 1991-2002 Jamie Zawinski <jwz@netscape.com>
+/* xscreensaver, Copyright (c) 1991-2017 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
int
string_width (XFontStruct *font, char *s)
{
- int direction, ascent, descent;
- XCharStruct overall;
- XTextExtents (font, s, strlen(s), &direction, &ascent, &descent, &overall);
- return overall.width;
+ return XTextWidth(font, s, strlen(s));
}
static void destroy_splash_window (saver_info *si);
static void unsplash_timer (XtPointer closure, XtIntervalId *id);
-static void do_demo (saver_info *si);
+static void do_demo (saver_screen_info *ssi);
#ifdef PREFS_BUTTON
-static void do_prefs (saver_info *si);
+static void do_prefs (saver_screen_info *ssi);
#endif /* PREFS_BUTTON */
-static void do_help (saver_info *si);
+static void do_help (saver_screen_info *ssi);
+
+
+XFontStruct *
+splash_load_font (Display *dpy, char *name, char *class)
+{
+ /* Try RES, RES2, etc. */
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ char *name2 = (char *) malloc (strlen(name) + 2);
+ char *s;
+ if (i)
+ sprintf (name2, "%s%d", name, i+1);
+ else
+ strcpy (name2, name);
+ s = get_string_resource (dpy, name2, class);
+ free (name2);
+ if (s && *s)
+ {
+ XFontStruct *f = XLoadQueryFont (dpy, s);
+ if (f) return f;
+ }
+ }
+ return XLoadQueryFont (dpy, "fixed");
+}
struct splash_dialog_data {
char *heading_label;
char *body_label;
char *body2_label;
+ char *body3_label;
+ char *body4_label;
char *demo_label;
#ifdef PREFS_BUTTON
char *prefs_label;
Pixel foreground;
Pixel background;
+ Pixel border;
Pixel button_foreground;
Pixel button_background;
Pixel shadow_top;
Dimension help_button_x, help_button_y;
Pixmap logo_pixmap;
+ Pixmap logo_clipmask;
int logo_npixels;
unsigned long *logo_pixels;
void
make_splash_dialog (saver_info *si)
{
+ saver_preferences *p = &si->prefs;
int x, y, bw;
XSetWindowAttributes attrs;
unsigned long attrmask = 0;
splash_dialog_data *sp;
saver_screen_info *ssi;
Colormap cmap;
- char *f;
+
+ Bool whine = decrepit_p ();
+
+ if (whine)
+ {
+ /* If locking is not enabled, make sure they see the message. */
+ if (!p->lock_p)
+ {
+ si->prefs.splash_p = True;
+ if (si->prefs.splash_duration < 5000)
+ si->prefs.splash_duration = 5000;
+ }
+ si->prefs.splash_duration += 3000;
+ }
if (si->sp_data)
return;
return;
ssi = &si->screens[mouse_screen (si)];
+
+ if (!ssi || !ssi->screen)
+ return; /* WTF? Trying to splash while no screens connected? */
+
cmap = DefaultColormapOfScreen (ssi->screen);
sp = (splash_dialog_data *) calloc (1, sizeof(*sp));
sp->prompt_screen = ssi;
- sp->heading_label = get_string_resource ("splash.heading.label",
+ sp->heading_label = get_string_resource (si->dpy,
+ "splash.heading.label",
"Dialog.Label.Label");
- sp->body_label = get_string_resource ("splash.body.label",
+ sp->body_label = get_string_resource (si->dpy,
+ "splash.body.label",
"Dialog.Label.Label");
- sp->body2_label = get_string_resource ("splash.body2.label",
+ sp->body2_label = get_string_resource (si->dpy,
+ "splash.body2.label",
"Dialog.Label.Label");
- sp->demo_label = get_string_resource ("splash.demo.label",
+ sp->demo_label = get_string_resource (si->dpy,
+ "splash.demo.label",
"Dialog.Button.Label");
#ifdef PREFS_BUTTON
- sp->prefs_label = get_string_resource ("splash.prefs.label",
+ sp->prefs_label = get_string_resource (si->dpy,
+ "splash.prefs.label",
"Dialog.Button.Label");
#endif /* PREFS_BUTTON */
- sp->help_label = get_string_resource ("splash.help.label",
+ sp->help_label = get_string_resource (si->dpy,
+ "splash.help.label",
"Dialog.Button.Label");
+
+
+ if (whine)
+ {
+ sp->body3_label = strdup("WARNING: This version is very old!");
+ sp->body4_label = strdup("Please upgrade!");
+ }
+
if (!sp->heading_label)
sp->heading_label = strdup("ERROR: REESOURCES NOT INSTALLED CORRECTLY");
if (!sp->body_label)
sp->heading_label = s;
}
- f = get_string_resource ("splash.headingFont", "Dialog.Font");
- sp->heading_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
- if (!sp->heading_font) sp->heading_font = XLoadQueryFont (si->dpy, "fixed");
- if (f) free (f);
-
- f = get_string_resource("splash.bodyFont", "Dialog.Font");
- sp->body_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
- if (!sp->body_font) sp->body_font = XLoadQueryFont (si->dpy, "fixed");
- if (f) free (f);
-
- f = get_string_resource("splash.buttonFont", "Dialog.Font");
- sp->button_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
- if (!sp->button_font) sp->button_font = XLoadQueryFont (si->dpy, "fixed");
- if (f) free (f);
-
- sp->foreground = get_pixel_resource ("splash.foreground",
- "Dialog.Foreground",
- si->dpy, cmap);
- sp->background = get_pixel_resource ("splash.background",
- "Dialog.Background",
- si->dpy, cmap);
+ sp->heading_font =
+ splash_load_font (si->dpy, "splash.headingFont", "Dialog.Font");
+ sp->body_font =
+ splash_load_font (si->dpy, "splash.bodyFont", "Dialog.Font");
+ sp->button_font =
+ splash_load_font (si->dpy, "splash.buttonFont", "Dialog.Font");
+
+ sp->foreground = get_pixel_resource (si->dpy, cmap,
+ "splash.foreground",
+ "Dialog.Foreground");
+ sp->background = get_pixel_resource (si->dpy, cmap,
+ "splash.background",
+ "Dialog.Background");
+ sp->border = get_pixel_resource (si->dpy, cmap,
+ "splash.borderColor",
+ "Dialog.borderColor");
if (sp->foreground == sp->background)
{
sp->background = WhitePixelOfScreen (ssi->screen);
}
- sp->button_foreground = get_pixel_resource ("splash.Button.foreground",
- "Dialog.Button.Foreground",
- si->dpy, cmap);
- sp->button_background = get_pixel_resource ("splash.Button.background",
- "Dialog.Button.Background",
- si->dpy, cmap);
- sp->shadow_top = get_pixel_resource ("splash.topShadowColor",
- "Dialog.Foreground",
- si->dpy, cmap);
- sp->shadow_bottom = get_pixel_resource ("splash.bottomShadowColor",
- "Dialog.Background",
- si->dpy, cmap);
-
- sp->logo_width = get_integer_resource ("splash.logo.width",
+ sp->button_foreground = get_pixel_resource (si->dpy, cmap,
+ "splash.Button.foreground",
+ "Dialog.Button.Foreground");
+ sp->button_background = get_pixel_resource (si->dpy, cmap,
+ "splash.Button.background",
+ "Dialog.Button.Background");
+ sp->shadow_top = get_pixel_resource (si->dpy, cmap,
+ "splash.topShadowColor",
+ "Dialog.Foreground");
+ sp->shadow_bottom = get_pixel_resource (si->dpy, cmap,
+ "splash.bottomShadowColor",
+ "Dialog.Background");
+
+ sp->logo_width = get_integer_resource (si->dpy,
+ "splash.logo.width",
"Dialog.Logo.Width");
- sp->logo_height = get_integer_resource ("splash.logo.height",
+ sp->logo_height = get_integer_resource (si->dpy,
+ "splash.logo.height",
"Dialog.Logo.Height");
- sp->internal_border = get_integer_resource ("splash.internalBorderWidth",
+ sp->internal_border = get_integer_resource (si->dpy,
+ "splash.internalBorderWidth",
"Dialog.InternalBorderWidth");
- sp->shadow_width = get_integer_resource ("splash.shadowThickness",
+ sp->shadow_width = get_integer_resource (si->dpy,
+ "splash.shadowThickness",
"Dialog.ShadowThickness");
if (sp->logo_width == 0) sp->logo_width = 150;
if (overall.width > sp->width) sp->width = overall.width;
sp->height += ascent + descent;
+ /* Measure the optional body3_label. */
+ if (sp->body3_label)
+ {
+ XTextExtents (sp->heading_font,
+ sp->body3_label, strlen(sp->body3_label),
+ &direction, &ascent, &descent, &overall);
+ if (overall.width > sp->width) sp->width = overall.width;
+ XTextExtents (sp->heading_font,
+ sp->body4_label, strlen(sp->body4_label),
+ &direction, &ascent, &descent, &overall);
+ if (overall.width > sp->width) sp->width = overall.width;
+ sp->height += (ascent + descent) * 5;
+ }
+
{
Dimension w2 = 0, w3 = 0, w4 = 0;
Dimension h2 = 0, h3 = 0, h4 = 0;
attrs.event_mask = (ExposureMask | ButtonPressMask | ButtonReleaseMask);
{
- int sx, sy, w, h;
- int mouse_x = 0, mouse_y = 0;
-
- {
- Window pointer_root, pointer_child;
- int root_x, root_y, win_x, win_y;
- unsigned int mask;
- if (XQueryPointer (si->dpy,
- RootWindowOfScreen (ssi->screen),
- &pointer_root, &pointer_child,
- &root_x, &root_y, &win_x, &win_y, &mask))
- {
- mouse_x = root_x;
- mouse_y = root_y;
- }
- }
+ int sx = 0, sy = 0, w, h;
- get_screen_viewport (ssi, &sx, &sy, &w, &h, mouse_x, mouse_y, False);
+ x = ssi->x;
+ y = ssi->y;
+ w = ssi->width;
+ h = ssi->height;
if (si->prefs.debug_p) w /= 2;
x = sx + (((w + sp->width) / 2) - sp->width);
y = sy + (((h + sp->height) / 2) - sp->height);
if (y < sy) y = sy;
}
- bw = get_integer_resource ("splash.borderWidth", "Dialog.BorderWidth");
+ bw = get_integer_resource (si->dpy,
+ "splash.borderWidth",
+ "Dialog.BorderWidth");
si->splash_dialog =
XCreateWindow (si->dpy,
DefaultVisualOfScreen(ssi->screen),
attrmask, &attrs);
XSetWindowBackground (si->dpy, si->splash_dialog, sp->background);
+ XSetWindowBorder (si->dpy, si->splash_dialog, sp->border);
- sp->logo_pixmap = xscreensaver_logo (si->dpy, si->splash_dialog, cmap,
+
+ sp->logo_pixmap = xscreensaver_logo (ssi->screen,
+ /* same visual as si->splash_dialog */
+ DefaultVisualOfScreen (ssi->screen),
+ si->splash_dialog, cmap,
sp->background,
&sp->logo_pixels, &sp->logo_npixels,
- 0, True);
+ &sp->logo_clipmask, True);
XMapRaised (si->dpy, si->splash_dialog);
XSync (si->dpy, False);
splash_dialog_data *sp = si->sp_data;
XGCValues gcv;
GC gc1, gc2;
- int hspacing, vspacing, height;
+ int vspacing, height;
int x1, x2, x3, y1, y2;
int sw;
#ifdef PREFS_BUTTON
+ int hspacing;
int nbuttons = 3;
-#else /* !PREFS_BUTTON */
- int nbuttons = 2;
#endif /* !PREFS_BUTTON */
height = (sp->heading_font->ascent + sp->heading_font->descent +
sp->body2_label, strlen(sp->body2_label));
y1 += sp->body_font->descent;
+ if (sp->body3_label)
+ {
+ XSetFont (si->dpy, gc1, sp->heading_font->fid);
+ y1 += sp->heading_font->ascent + sp->heading_font->descent;
+ y1 += sp->heading_font->ascent;
+ sw = string_width (sp->heading_font, sp->body3_label);
+ x2 = (x1 + ((x3 - x1 - sw) / 2));
+ XDrawString (si->dpy, si->splash_dialog, gc1, x2, y1,
+ sp->body3_label, strlen(sp->body3_label));
+ y1 += sp->heading_font->descent + sp->heading_font->ascent;
+ sw = string_width (sp->heading_font, sp->body4_label);
+ x2 = (x1 + ((x3 - x1 - sw) / 2));
+ XDrawString (si->dpy, si->splash_dialog, gc1, x2, y1,
+ sp->body4_label, strlen(sp->body4_label));
+ y1 += sp->heading_font->descent;
+ XSetFont (si->dpy, gc1, sp->body_font->fid);
+ }
+
/* The buttons
*/
XSetForeground (si->dpy, gc1, sp->button_foreground);
(sp->button_font->ascent + sp->button_font->descent))
/ 2)
+ sp->button_font->ascent);
+#ifdef PREFS_BUTTON
hspacing = ((sp->width - x1 - (sp->shadow_width * 2) -
sp->internal_border - (sp->button_width * nbuttons))
/ 2);
+#endif
x2 = x1 + ((sp->button_width - string_width(sp->button_font, sp->demo_label))
/ 2);
XGetGeometry (si->dpy, sp->logo_pixmap, &root, &x, &y, &w, &h, &bw, &d);
XSetForeground (si->dpy, gc1, sp->foreground);
XSetBackground (si->dpy, gc1, sp->background);
+ XSetClipMask (si->dpy, gc1, sp->logo_clipmask);
+ XSetClipOrigin (si->dpy, gc1, x1 + ((x2 - (int)w) /2), y1 + ((y2 - (int)h) / 2));
if (d == 1)
XCopyPlane (si->dpy, sp->logo_pixmap, si->splash_dialog, gc1,
0, 0, w, h,
if (sp->heading_label) free (sp->heading_label);
if (sp->body_label) free (sp->body_label);
if (sp->body2_label) free (sp->body2_label);
+ if (sp->body3_label) free (sp->body3_label);
+ if (sp->body4_label) free (sp->body4_label);
if (sp->demo_label) free (sp->demo_label);
#ifdef PREFS_BUTTON
if (sp->prefs_label) free (sp->prefs_label);
if (sp->logo_pixmap)
XFreePixmap (si->dpy, sp->logo_pixmap);
+ if (sp->logo_clipmask)
+ XFreePixmap (si->dpy, sp->logo_clipmask);
if (sp->logo_pixels)
{
if (sp->logo_npixels)
handle_splash_event (saver_info *si, XEvent *event)
{
splash_dialog_data *sp = si->sp_data;
+ saver_screen_info *ssi;
int which = 0;
if (!sp) return;
+ ssi = sp->prompt_screen;
switch (event->xany.type)
{
sp = si->sp_data;
switch (which)
{
- case 1: do_demo (si); break;
+ case 1: do_demo (ssi); break;
#ifdef PREFS_BUTTON
- case 2: do_prefs (si); break;
+ case 2: do_prefs (ssi); break;
#endif /* PREFS_BUTTON */
- case 3: do_help (si); break;
+ case 3: do_help (ssi); break;
default: abort();
}
}
# define fork vfork
#endif /* VMS */
-static void
-fork_and_exec (saver_info *si, const char *command, const char *desc)
-{
- saver_preferences *p = &si->prefs;
- pid_t forked;
- char buf [512];
- char *av[5];
- int ac;
-
- if (!command || !*command)
- {
- fprintf (stderr, "%s: no %s command has been specified.\n",
- blurb(), desc);
- return;
- }
-
- switch ((int) (forked = fork ()))
- {
- case -1:
- sprintf (buf, "%s: couldn't fork", blurb());
- perror (buf);
- break;
-
- case 0:
- close (ConnectionNumber (si->dpy)); /* close display fd */
- hack_subproc_environment (si->default_screen); /* set $DISPLAY */
- ac = 0;
- av [ac++] = (char *) p->shell;
- av [ac++] = (char *) "-c";
- av [ac++] = (char *) command;
- av [ac] = 0;
- execvp (av[0], av); /* shouldn't return. */
-
- sprintf (buf, "%s: execvp(\"%s\", \"%s\", \"%s\") failed",
- blurb(), av[0], av[1], av[2]);
- perror (buf);
- fflush (stderr);
- fflush (stdout);
- exit (1); /* Note that this only exits a child fork. */
- break;
-
- default:
- /* parent fork. */
- break;
- }
-}
-
static void
-do_demo (saver_info *si)
+do_demo (saver_screen_info *ssi)
{
+ saver_info *si = ssi->global;
saver_preferences *p = &si->prefs;
- fork_and_exec (si, p->demo_command, "demo-mode");
+ const char *cmd = p->demo_command;
+
+ if (cmd && *cmd)
+ fork_and_exec (ssi, cmd);
+ else
+ fprintf (stderr, "%s: no demo-mode command has been specified.\n",
+ blurb());
}
#ifdef PREFS_BUTTON
static void
-do_prefs (saver_info *si)
+do_prefs (saver_screen_info *ssi)
{
+ saver_info *si = ssi->global;
saver_preferences *p = &si->prefs;
- fork_and_exec (si, p->prefs_command, "preferences");
+ const char *cmd = p->prefs_command;
+
+ if (command && *command)
+ fork_and_exec (ssi, cmd);
+ else
+ fprintf (stderr, "%s: no preferences command has been specified.\n",
+ blurb());
}
#endif /* PREFS_BUTTON */
static void
-do_help (saver_info *si)
+do_help (saver_screen_info *ssi)
{
+ saver_info *si = ssi->global;
saver_preferences *p = &si->prefs;
- char *help_command;
+ char *help_command = 0;
+ if (!p->load_url_command || !*p->load_url_command)
+ {
+ fprintf (stderr, "%s: no URL command has been specified.\n", blurb());
+ return;
+ }
if (!p->help_url || !*p->help_url)
{
fprintf (stderr, "%s: no Help URL has been specified.\n", blurb());
}
help_command = (char *) malloc (strlen (p->load_url_command) +
- (strlen (p->help_url) * 2) + 10);
- sprintf (help_command, p->load_url_command, p->help_url, p->help_url);
- fork_and_exec (si, help_command, "URL-loading");
+ (strlen (p->help_url) * 4) + 10);
+ sprintf (help_command, p->load_url_command,
+ p->help_url, p->help_url, p->help_url, p->help_url);
+
+ fork_and_exec (ssi, help_command);
free (help_command);
}