1 /* xscreensaver, Copyright (c) 1991-2018 Jamie Zawinski <jwz@jwz.org>
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
16 #include <X11/Intrinsic.h>
18 #include "xscreensaver.h"
19 #include "resources.h"
20 #include "font-retry.h"
23 #define MAX(a,b) ((a)>(b)?(a):(b))
26 draw_shaded_rectangle (Display *dpy, Window window,
28 int width, int height,
30 unsigned long top_color,
31 unsigned long bottom_color)
36 if (thickness == 0) return;
38 gcv.foreground = top_color;
39 gc1 = XCreateGC (dpy, window, GCForeground, &gcv);
40 gcv.foreground = bottom_color;
41 gc2 = XCreateGC (dpy, window, GCForeground, &gcv);
45 points [1].x = x + width;
47 points [2].x = x + width - thickness;
48 points [2].y = y + thickness;
50 points [3].y = y + thickness;
51 XFillPolygon (dpy, window, gc1, points, 4, Convex, CoordModeOrigin);
54 points [0].y = y + thickness;
56 points [1].y = y + height;
57 points [2].x = x + thickness;
58 points [2].y = y + height - thickness;
59 points [3].x = x + thickness;
60 points [3].y = y + thickness;
61 XFillPolygon (dpy, window, gc1, points, 4, Convex, CoordModeOrigin);
63 points [0].x = x + width;
65 points [1].x = x + width - thickness;
66 points [1].y = y + thickness;
67 points [2].x = x + width - thickness;
68 points [2].y = y + height - thickness;
69 points [3].x = x + width;
70 points [3].y = y + height - thickness;
71 XFillPolygon (dpy, window, gc2, points, 4, Convex, CoordModeOrigin);
74 points [0].y = y + height;
75 points [1].x = x + width;
76 points [1].y = y + height;
77 points [2].x = x + width;
78 points [2].y = y + height - thickness;
79 points [3].x = x + thickness;
80 points [3].y = y + height - thickness;
81 XFillPolygon (dpy, window, gc2, points, 4, Convex, CoordModeOrigin);
89 string_width (XFontStruct *font, char *s)
91 return XTextWidth(font, s, strlen(s));
95 static void update_splash_window (saver_info *si);
96 static void draw_splash_window (saver_info *si);
97 static void destroy_splash_window (saver_info *si);
98 static void unsplash_timer (XtPointer closure, XtIntervalId *id);
100 static void do_demo (saver_screen_info *ssi);
102 static void do_prefs (saver_screen_info *ssi);
103 #endif /* PREFS_BUTTON */
104 static void do_help (saver_screen_info *ssi);
108 splash_load_font (Display *dpy, char *name, char *class)
110 char *s = get_string_resource (dpy, name, class);
113 s = "-*-helvetica-bold-r-*-*-*-140-*-*-*-*-*-*";
114 f = load_font_retry (dpy, s);
120 struct splash_dialog_data {
122 saver_screen_info *prompt_screen;
136 #endif /* PREFS_BUTTON */
139 XFontStruct *heading_font;
140 XFontStruct *body_font;
141 XFontStruct *button_font;
146 Pixel button_foreground;
147 Pixel button_background;
151 Dimension logo_width;
152 Dimension logo_height;
153 Dimension internal_border;
154 Dimension shadow_width;
156 Dimension button_width, button_height;
157 Dimension demo_button_x, demo_button_y;
159 Dimension prefs_button_x, prefs_button_y;
160 #endif /* PREFS_BUTTON */
161 Dimension help_button_x, help_button_y;
164 Pixmap logo_clipmask;
166 unsigned long *logo_pixels;
173 make_splash_dialog (saver_info *si)
175 saver_preferences *p = &si->prefs;
177 XSetWindowAttributes attrs;
178 unsigned long attrmask = 0;
179 splash_dialog_data *sp;
180 saver_screen_info *ssi;
183 Bool whyne = senesculent_p ();
187 /* If locking is not enabled, make sure they see the message. */
190 si->prefs.splash_p = True;
191 if (si->prefs.splash_duration < 5000)
192 si->prefs.splash_duration = 5000;
194 si->prefs.splash_duration += 3000;
199 if (!si->prefs.splash_p ||
200 si->prefs.splash_duration <= 0)
203 ssi = &si->screens[mouse_screen (si)];
205 if (!ssi || !ssi->screen)
206 return; /* WTF? Trying to splash while no screens connected? */
208 cmap = DefaultColormapOfScreen (ssi->screen);
210 sp = (splash_dialog_data *) calloc (1, sizeof(*sp));
211 sp->prompt_screen = ssi;
213 sp->heading_label = get_string_resource (si->dpy,
214 "splash.heading.label",
215 "Dialog.Label.Label");
216 sp->body_label = get_string_resource (si->dpy,
218 "Dialog.Label.Label");
219 sp->body2_label = get_string_resource (si->dpy,
220 "splash.body2.label",
221 "Dialog.Label.Label");
222 sp->demo_label = get_string_resource (si->dpy,
224 "Dialog.Button.Label");
226 sp->prefs_label = get_string_resource (si->dpy,
227 "splash.prefs.label",
228 "Dialog.Button.Label");
229 #endif /* PREFS_BUTTON */
230 sp->help_label = get_string_resource (si->dpy,
232 "Dialog.Button.Label");
238 sp->body3_label = strdup("WARNING: This version is very old!");
239 sp->body4_label = strdup("Please upgrade!");
242 if (!sp->heading_label)
243 sp->heading_label = strdup("ERROR: REESOURCES NOT INSTALLED CORRECTLY");
245 sp->body_label = strdup("ERROR: REESOURCES NOT INSTALLED CORRECTLY");
246 if (!sp->body2_label)
247 sp->body2_label = strdup("ERROR: REESOURCES NOT INSTALLED CORRECTLY");
248 if (!sp->demo_label) sp->demo_label = strdup("ERROR");
250 if (!sp->prefs_label) sp->prefs_label = strdup("ERROR");
251 #endif /* PREFS_BUTTON */
252 if (!sp->help_label) sp->help_label = strdup("ERROR");
254 /* Put the version number in the label. */
256 char *s = (char *) malloc (strlen(sp->heading_label) + 20);
257 sprintf(s, sp->heading_label, si->version);
258 free (sp->heading_label);
259 sp->heading_label = s;
263 splash_load_font (si->dpy, "splash.headingFont", "Dialog.Font");
265 splash_load_font (si->dpy, "splash.bodyFont", "Dialog.Font");
267 splash_load_font (si->dpy, "splash.buttonFont", "Dialog.Font");
269 sp->foreground = get_pixel_resource (si->dpy, cmap,
271 "Dialog.Foreground");
272 sp->background = get_pixel_resource (si->dpy, cmap,
274 "Dialog.Background");
275 sp->border = get_pixel_resource (si->dpy, cmap,
276 "splash.borderColor",
277 "Dialog.borderColor");
279 if (sp->foreground == sp->background)
281 /* Make sure the error messages show up. */
282 sp->foreground = BlackPixelOfScreen (ssi->screen);
283 sp->background = WhitePixelOfScreen (ssi->screen);
286 sp->button_foreground = get_pixel_resource (si->dpy, cmap,
287 "splash.Button.foreground",
288 "Dialog.Button.Foreground");
289 sp->button_background = get_pixel_resource (si->dpy, cmap,
290 "splash.Button.background",
291 "Dialog.Button.Background");
292 sp->shadow_top = get_pixel_resource (si->dpy, cmap,
293 "splash.topShadowColor",
294 "Dialog.Foreground");
295 sp->shadow_bottom = get_pixel_resource (si->dpy, cmap,
296 "splash.bottomShadowColor",
297 "Dialog.Background");
299 sp->logo_width = get_integer_resource (si->dpy,
301 "Dialog.Logo.Width");
302 sp->logo_height = get_integer_resource (si->dpy,
303 "splash.logo.height",
304 "Dialog.Logo.Height");
305 sp->internal_border = get_integer_resource (si->dpy,
306 "splash.internalBorderWidth",
307 "Dialog.InternalBorderWidth");
308 sp->shadow_width = get_integer_resource (si->dpy,
309 "splash.shadowThickness",
310 "Dialog.ShadowThickness");
312 if (sp->logo_width == 0) sp->logo_width = 150;
313 if (sp->logo_height == 0) sp->logo_height = 150;
314 if (sp->internal_border == 0) sp->internal_border = 15;
315 if (sp->shadow_width == 0) sp->shadow_width = 4;
318 int direction, ascent, descent;
324 /* Measure the heading_label. */
325 XTextExtents (sp->heading_font,
326 sp->heading_label, strlen(sp->heading_label),
327 &direction, &ascent, &descent, &overall);
328 if (overall.width > sp->width) sp->width = overall.width;
329 sp->height += ascent + descent;
331 /* Measure the body_label. */
332 XTextExtents (sp->body_font,
333 sp->body_label, strlen(sp->body_label),
334 &direction, &ascent, &descent, &overall);
335 if (overall.width > sp->width) sp->width = overall.width;
336 sp->height += ascent + descent;
338 /* Measure the body2_label. */
339 XTextExtents (sp->body_font,
340 sp->body2_label, strlen(sp->body2_label),
341 &direction, &ascent, &descent, &overall);
342 if (overall.width > sp->width) sp->width = overall.width;
343 sp->height += ascent + descent;
345 /* Measure the optional body3_label. */
348 XTextExtents (sp->heading_font,
349 sp->body3_label, strlen(sp->body3_label),
350 &direction, &ascent, &descent, &overall);
351 if (overall.width > sp->width) sp->width = overall.width;
352 XTextExtents (sp->heading_font,
353 sp->body4_label, strlen(sp->body4_label),
354 &direction, &ascent, &descent, &overall);
355 if (overall.width > sp->width) sp->width = overall.width;
356 sp->height += (ascent + descent) * 5;
360 Dimension w2 = 0, w3 = 0, w4 = 0;
361 Dimension h2 = 0, h3 = 0, h4 = 0;
363 /* Measure the Demo button. */
364 XTextExtents (sp->button_font,
365 sp->demo_label, strlen(sp->demo_label),
366 &direction, &ascent, &descent, &overall);
368 h2 = ascent + descent;
371 /* Measure the Prefs button. */
372 XTextExtents (sp->button_font,
373 sp->prefs_label, strlen(sp->prefs_label),
374 &direction, &ascent, &descent, &overall);
376 h3 = ascent + descent;
377 #else /* !PREFS_BUTTON */
380 #endif /* !PREFS_BUTTON */
382 /* Measure the Help button. */
383 XTextExtents (sp->button_font,
384 sp->help_label, strlen(sp->help_label),
385 &direction, &ascent, &descent, &overall);
387 h4 = ascent + descent;
389 w2 = MAX(w2, w3); w2 = MAX(w2, w4);
390 h2 = MAX(h2, h3); h2 = MAX(h2, h4);
392 /* Add some horizontal padding inside the buttons. */
395 w2 += ((ascent + descent) / 2) + (sp->shadow_width * 2);
396 h2 += ((ascent + descent) / 2) + (sp->shadow_width * 2);
398 sp->button_width = w2;
399 sp->button_height = h2;
403 #else /* !PREFS_BUTTON */
405 #endif /* !PREFS_BUTTON */
407 w2 += ((ascent + descent) * 2); /* for space between buttons */
409 if (w2 > sp->width) sp->width = w2;
413 sp->width += (sp->internal_border * 2);
414 sp->height += (sp->internal_border * 3);
416 if (sp->logo_height > sp->height)
417 sp->height = sp->logo_height;
418 else if (sp->height > sp->logo_height)
419 sp->logo_height = sp->height;
421 sp->logo_width = sp->logo_height;
423 sp->width += sp->logo_width;
426 attrmask |= CWOverrideRedirect; attrs.override_redirect = True;
427 attrmask |= CWEventMask;
428 attrs.event_mask = (ExposureMask | ButtonPressMask | ButtonReleaseMask);
431 int sx = 0, sy = 0, w, h;
437 if (si->prefs.debug_p) w /= 2;
438 x = sx + (((w + sp->width) / 2) - sp->width);
439 y = sy + (((h + sp->height) / 2) - sp->height);
444 bw = get_integer_resource (si->dpy,
445 "splash.borderWidth",
446 "Dialog.BorderWidth");
449 XCreateWindow (si->dpy,
450 RootWindowOfScreen(ssi->screen),
451 x, y, sp->width, sp->height, bw,
452 DefaultDepthOfScreen (ssi->screen), InputOutput,
453 DefaultVisualOfScreen(ssi->screen),
455 XSetWindowBackground (si->dpy, si->splash_dialog, sp->background);
456 XSetWindowBorder (si->dpy, si->splash_dialog, sp->border);
459 sp->logo_pixmap = xscreensaver_logo (ssi->screen,
460 /* same visual as si->splash_dialog */
461 DefaultVisualOfScreen (ssi->screen),
462 si->splash_dialog, cmap,
464 &sp->logo_pixels, &sp->logo_npixels,
465 &sp->logo_clipmask, True);
467 XMapRaised (si->dpy, si->splash_dialog);
468 XSync (si->dpy, False);
472 sp->timer = XtAppAddTimeOut (si->app, si->prefs.splash_duration,
473 unsplash_timer, (XtPointer) si);
475 draw_splash_window (si);
476 XSync (si->dpy, False);
481 draw_splash_window (saver_info *si)
483 splash_dialog_data *sp = si->sp_data;
486 int vspacing, height;
487 int x1, x2, x3, y1, y2;
493 #endif /* !PREFS_BUTTON */
495 height = (sp->heading_font->ascent + sp->heading_font->descent +
496 sp->body_font->ascent + sp->body_font->descent +
497 sp->body_font->ascent + sp->body_font->descent +
498 sp->button_font->ascent + sp->button_font->descent);
499 vspacing = ((sp->height
500 - (4 * sp->shadow_width)
501 - (2 * sp->internal_border)
503 if (vspacing < 0) vspacing = 0;
504 if (vspacing > (sp->heading_font->ascent * 2))
505 vspacing = (sp->heading_font->ascent * 2);
507 gcv.foreground = sp->foreground;
508 gc1 = XCreateGC (si->dpy, si->splash_dialog, GCForeground, &gcv);
509 gc2 = XCreateGC (si->dpy, si->splash_dialog, GCForeground, &gcv);
511 x3 = sp->width - (sp->shadow_width * 2);
512 y1 = sp->internal_border;
516 XSetFont (si->dpy, gc1, sp->heading_font->fid);
517 sw = string_width (sp->heading_font, sp->heading_label);
518 x2 = (x1 + ((x3 - x1 - sw) / 2));
519 y1 += sp->heading_font->ascent;
520 XDrawString (si->dpy, si->splash_dialog, gc1, x2, y1,
521 sp->heading_label, strlen(sp->heading_label));
522 y1 += sp->heading_font->descent;
524 /* text below top heading
526 XSetFont (si->dpy, gc1, sp->body_font->fid);
527 y1 += vspacing + sp->body_font->ascent;
528 sw = string_width (sp->body_font, sp->body_label);
529 x2 = (x1 + ((x3 - x1 - sw) / 2));
530 XDrawString (si->dpy, si->splash_dialog, gc1, x2, y1,
531 sp->body_label, strlen(sp->body_label));
532 y1 += sp->body_font->descent;
534 y1 += sp->body_font->ascent;
535 sw = string_width (sp->body_font, sp->body2_label);
536 x2 = (x1 + ((x3 - x1 - sw) / 2));
537 XDrawString (si->dpy, si->splash_dialog, gc1, x2, y1,
538 sp->body2_label, strlen(sp->body2_label));
539 y1 += sp->body_font->descent;
543 XSetFont (si->dpy, gc1, sp->heading_font->fid);
544 y1 += sp->heading_font->ascent + sp->heading_font->descent;
545 y1 += sp->heading_font->ascent;
546 sw = string_width (sp->heading_font, sp->body3_label);
547 x2 = (x1 + ((x3 - x1 - sw) / 2));
548 XDrawString (si->dpy, si->splash_dialog, gc1, x2, y1,
549 sp->body3_label, strlen(sp->body3_label));
550 y1 += sp->heading_font->descent + sp->heading_font->ascent;
551 sw = string_width (sp->heading_font, sp->body4_label);
552 x2 = (x1 + ((x3 - x1 - sw) / 2));
553 XDrawString (si->dpy, si->splash_dialog, gc1, x2, y1,
554 sp->body4_label, strlen(sp->body4_label));
555 y1 += sp->heading_font->descent;
556 XSetFont (si->dpy, gc1, sp->body_font->fid);
561 XSetForeground (si->dpy, gc1, sp->button_foreground);
562 XSetForeground (si->dpy, gc2, sp->button_background);
564 /* y1 += (vspacing * 2);*/
565 y1 = sp->height - sp->internal_border - sp->button_height;
567 x1 += sp->internal_border;
568 y2 = (y1 + ((sp->button_height -
569 (sp->button_font->ascent + sp->button_font->descent))
571 + sp->button_font->ascent);
573 hspacing = ((sp->width - x1 - (sp->shadow_width * 2) -
574 sp->internal_border - (sp->button_width * nbuttons))
578 x2 = x1 + ((sp->button_width - string_width(sp->button_font, sp->demo_label))
580 XFillRectangle (si->dpy, si->splash_dialog, gc2, x1, y1,
581 sp->button_width, sp->button_height);
582 XDrawString (si->dpy, si->splash_dialog, gc1, x2, y2,
583 sp->demo_label, strlen(sp->demo_label));
584 sp->demo_button_x = x1;
585 sp->demo_button_y = y1;
588 x1 += hspacing + sp->button_width;
589 x2 = x1 + ((sp->button_width - string_width(sp->button_font,sp->prefs_label))
591 XFillRectangle (si->dpy, si->splash_dialog, gc2, x1, y1,
592 sp->button_width, sp->button_height);
593 XDrawString (si->dpy, si->splash_dialog, gc1, x2, y2,
594 sp->prefs_label, strlen(sp->prefs_label));
595 sp->prefs_button_x = x1;
596 sp->prefs_button_y = y1;
597 #endif /* PREFS_BUTTON */
600 x1 += hspacing + sp->button_width;
601 #else /* !PREFS_BUTTON */
602 x1 = (sp->width - sp->button_width -
603 sp->internal_border - (sp->shadow_width * 2));
604 #endif /* !PREFS_BUTTON */
606 x2 = x1 + ((sp->button_width - string_width(sp->button_font,sp->help_label))
608 XFillRectangle (si->dpy, si->splash_dialog, gc2, x1, y1,
609 sp->button_width, sp->button_height);
610 XDrawString (si->dpy, si->splash_dialog, gc1, x2, y2,
611 sp->help_label, strlen(sp->help_label));
612 sp->help_button_x = x1;
613 sp->help_button_y = y1;
618 x1 = sp->shadow_width * 6;
619 y1 = sp->shadow_width * 6;
620 x2 = sp->logo_width - (sp->shadow_width * 12);
621 y2 = sp->logo_height - (sp->shadow_width * 12);
627 unsigned int w, h, bw, d;
628 XGetGeometry (si->dpy, sp->logo_pixmap, &root, &x, &y, &w, &h, &bw, &d);
629 XSetForeground (si->dpy, gc1, sp->foreground);
630 XSetBackground (si->dpy, gc1, sp->background);
631 XSetClipMask (si->dpy, gc1, sp->logo_clipmask);
632 XSetClipOrigin (si->dpy, gc1, x1 + ((x2 - (int)w) /2), y1 + ((y2 - (int)h) / 2));
634 XCopyPlane (si->dpy, sp->logo_pixmap, si->splash_dialog, gc1,
636 x1 + ((x2 - (int)w) / 2),
637 y1 + ((y2 - (int)h) / 2),
640 XCopyArea (si->dpy, sp->logo_pixmap, si->splash_dialog, gc1,
642 x1 + ((x2 - (int)w) / 2),
643 y1 + ((y2 - (int)h) / 2));
646 /* Solid border inside the logo box. */
648 XSetForeground (si->dpy, gc1, sp->foreground);
649 XDrawRectangle (si->dpy, si->splash_dialog, gc1, x1, y1, x2-1, y2-1);
652 /* The shadow around the logo
654 draw_shaded_rectangle (si->dpy, si->splash_dialog,
655 sp->shadow_width * 4,
656 sp->shadow_width * 4,
657 sp->logo_width - (sp->shadow_width * 8),
658 sp->logo_height - (sp->shadow_width * 8),
660 sp->shadow_bottom, sp->shadow_top);
662 /* The shadow around the whole window
664 draw_shaded_rectangle (si->dpy, si->splash_dialog,
665 0, 0, sp->width, sp->height, sp->shadow_width,
666 sp->shadow_top, sp->shadow_bottom);
668 XFreeGC (si->dpy, gc1);
669 XFreeGC (si->dpy, gc2);
671 update_splash_window (si);
676 update_splash_window (saver_info *si)
678 splash_dialog_data *sp = si->sp_data;
681 pressed = sp->pressed;
683 /* The shadows around the buttons
685 draw_shaded_rectangle (si->dpy, si->splash_dialog,
686 sp->demo_button_x, sp->demo_button_y,
687 sp->button_width, sp->button_height, sp->shadow_width,
688 (pressed == 1 ? sp->shadow_bottom : sp->shadow_top),
689 (pressed == 1 ? sp->shadow_top : sp->shadow_bottom));
691 draw_shaded_rectangle (si->dpy, si->splash_dialog,
692 sp->prefs_button_x, sp->prefs_button_y,
693 sp->button_width, sp->button_height, sp->shadow_width,
694 (pressed == 2 ? sp->shadow_bottom : sp->shadow_top),
695 (pressed == 2 ? sp->shadow_top : sp->shadow_bottom));
696 #endif /* PREFS_BUTTON */
697 draw_shaded_rectangle (si->dpy, si->splash_dialog,
698 sp->help_button_x, sp->help_button_y,
699 sp->button_width, sp->button_height, sp->shadow_width,
700 (pressed == 3 ? sp->shadow_bottom : sp->shadow_top),
701 (pressed == 3 ? sp->shadow_top : sp->shadow_bottom));
705 destroy_splash_window (saver_info *si)
707 splash_dialog_data *sp = si->sp_data;
708 saver_screen_info *ssi = sp->prompt_screen;
709 Colormap cmap = DefaultColormapOfScreen (ssi->screen);
710 Pixel black = BlackPixelOfScreen (ssi->screen);
711 Pixel white = WhitePixelOfScreen (ssi->screen);
714 XtRemoveTimeOut (sp->timer);
716 if (si->splash_dialog)
718 XDestroyWindow (si->dpy, si->splash_dialog);
719 si->splash_dialog = 0;
722 if (sp->heading_label) free (sp->heading_label);
723 if (sp->body_label) free (sp->body_label);
724 if (sp->body2_label) free (sp->body2_label);
725 if (sp->body3_label) free (sp->body3_label);
726 if (sp->body4_label) free (sp->body4_label);
727 if (sp->demo_label) free (sp->demo_label);
729 if (sp->prefs_label) free (sp->prefs_label);
730 #endif /* PREFS_BUTTON */
731 if (sp->help_label) free (sp->help_label);
733 if (sp->heading_font) XFreeFont (si->dpy, sp->heading_font);
734 if (sp->body_font) XFreeFont (si->dpy, sp->body_font);
735 if (sp->button_font) XFreeFont (si->dpy, sp->button_font);
737 if (sp->foreground != black && sp->foreground != white)
738 XFreeColors (si->dpy, cmap, &sp->foreground, 1, 0L);
739 if (sp->background != black && sp->background != white)
740 XFreeColors (si->dpy, cmap, &sp->background, 1, 0L);
741 if (sp->button_foreground != black && sp->button_foreground != white)
742 XFreeColors (si->dpy, cmap, &sp->button_foreground, 1, 0L);
743 if (sp->button_background != black && sp->button_background != white)
744 XFreeColors (si->dpy, cmap, &sp->button_background, 1, 0L);
745 if (sp->shadow_top != black && sp->shadow_top != white)
746 XFreeColors (si->dpy, cmap, &sp->shadow_top, 1, 0L);
747 if (sp->shadow_bottom != black && sp->shadow_bottom != white)
748 XFreeColors (si->dpy, cmap, &sp->shadow_bottom, 1, 0L);
751 XFreePixmap (si->dpy, sp->logo_pixmap);
752 if (sp->logo_clipmask)
753 XFreePixmap (si->dpy, sp->logo_clipmask);
756 if (sp->logo_npixels)
757 XFreeColors (si->dpy, cmap, sp->logo_pixels, sp->logo_npixels, 0L);
758 free (sp->logo_pixels);
760 sp->logo_npixels = 0;
763 memset (sp, 0, sizeof(*sp));
769 handle_splash_event (saver_info *si, XEvent *event)
771 splash_dialog_data *sp = si->sp_data;
772 saver_screen_info *ssi;
775 ssi = sp->prompt_screen;
777 switch (event->xany.type)
780 draw_splash_window (si);
783 case ButtonPress: case ButtonRelease:
785 if (event->xbutton.x >= sp->demo_button_x &&
786 event->xbutton.x < sp->demo_button_x + sp->button_width &&
787 event->xbutton.y >= sp->demo_button_y &&
788 event->xbutton.y < sp->demo_button_y + sp->button_height)
792 else if (event->xbutton.x >= sp->prefs_button_x &&
793 event->xbutton.x < sp->prefs_button_x + sp->button_width &&
794 event->xbutton.y >= sp->prefs_button_y &&
795 event->xbutton.y < sp->prefs_button_y + sp->button_height)
797 #endif /* PREFS_BUTTON */
799 else if (event->xbutton.x >= sp->help_button_x &&
800 event->xbutton.x < sp->help_button_x + sp->button_width &&
801 event->xbutton.y >= sp->help_button_y &&
802 event->xbutton.y < sp->help_button_y + sp->button_height)
805 if (event->xany.type == ButtonPress)
808 update_splash_window (si);
810 XBell (si->dpy, False);
812 else if (event->xany.type == ButtonRelease)
814 if (which && sp->pressed == which)
816 destroy_splash_window (si);
820 case 1: do_demo (ssi); break;
822 case 2: do_prefs (ssi); break;
823 #endif /* PREFS_BUTTON */
824 case 3: do_help (ssi); break;
828 else if (which == 0 && sp->pressed == 0)
830 /* click and release on the window but not in a button:
831 treat that as "dismiss the splash dialog." */
832 destroy_splash_window (si);
835 if (sp) sp->pressed = 0;
836 update_splash_window (si);
846 unsplash_timer (XtPointer closure, XtIntervalId *id)
848 saver_info *si = (saver_info *) closure;
849 if (si && si->sp_data)
850 destroy_splash_window (si);
854 /* Button callbacks */
863 do_demo (saver_screen_info *ssi)
865 saver_info *si = ssi->global;
866 saver_preferences *p = &si->prefs;
867 const char *cmd = p->demo_command;
870 fork_and_exec (ssi, cmd);
872 fprintf (stderr, "%s: no demo-mode command has been specified.\n",
878 do_prefs (saver_screen_info *ssi)
880 saver_info *si = ssi->global;
881 saver_preferences *p = &si->prefs;
882 const char *cmd = p->prefs_command;
884 if (command && *command)
885 fork_and_exec (ssi, cmd);
887 fprintf (stderr, "%s: no preferences command has been specified.\n",
890 #endif /* PREFS_BUTTON */
893 do_help (saver_screen_info *ssi)
895 saver_info *si = ssi->global;
896 saver_preferences *p = &si->prefs;
897 char *help_command = 0;
899 if (!p->load_url_command || !*p->load_url_command)
901 fprintf (stderr, "%s: no URL command has been specified.\n", blurb());
904 if (!p->help_url || !*p->help_url)
906 fprintf (stderr, "%s: no Help URL has been specified.\n", blurb());
910 help_command = (char *) malloc (strlen (p->load_url_command) +
911 (strlen (p->help_url) * 4) + 10);
912 sprintf (help_command, p->load_url_command,
913 p->help_url, p->help_url, p->help_url, p->help_url);
915 fork_and_exec (ssi, help_command);