summaryrefslogtreecommitdiffstats
path: root/driver/windows.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver/windows.c')
-rw-r--r--driver/windows.c77
1 files changed, 57 insertions, 20 deletions
diff --git a/driver/windows.c b/driver/windows.c
index c9cdf9d..6f67e13 100644
--- a/driver/windows.c
+++ b/driver/windows.c
@@ -1,5 +1,5 @@
/* windows.c --- turning the screen black; dealing with visuals, virtual roots.
- * xscreensaver, Copyright © 1991-2021 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright © 1991-2022 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -38,6 +38,7 @@
#include "atoms.h"
#include "visual.h"
#include "screens.h"
+#include "screenshot.h"
#include "fade.h"
#include "resources.h"
#include "xft.h"
@@ -218,7 +219,7 @@ initialize_screensaver_window_1 (saver_screen_info *ssi)
if (ssi->error_dialog)
{
- XDestroyWindow (si->dpy, ssi->error_dialog);
+ defer_XDestroyWindow (si->app, si->dpy, ssi->error_dialog);
ssi->error_dialog = 0;
}
@@ -260,7 +261,7 @@ initialize_screensaver_window_1 (saver_screen_info *ssi)
fprintf (stderr,
"%s: someone horked our saver window (0x%lx)! Recreating it...\n",
blurb(), (unsigned long) horked_window);
- XDestroyWindow (si->dpy, horked_window);
+ defer_XDestroyWindow (si->app, si->dpy, horked_window);
}
if (p->verbose_p > 1)
@@ -435,6 +436,16 @@ blank_screen (saver_info *si)
initialize_screensaver_window (si);
sync_server_dpms_settings (si->dpy, p);
+ /* Save a screenshot. Must be before fade-out. */
+ for (i = 0; i < si->nscreens; i++)
+ {
+ saver_screen_info *ssi = &si->screens[i];
+ if (ssi->screenshot)
+ XFreePixmap (si->dpy, ssi->screenshot);
+ ssi->screenshot =
+ screenshot_grab (si->dpy, ssi->screensaver_window, False, p->verbose_p);
+ }
+
if (p->fade_p &&
!si->demoing_p &&
!si->emergency_p)
@@ -687,7 +698,7 @@ select_visual (saver_screen_info *ssi, const char *visual_name)
raise_window (ssi);
/* Now we can destroy the old window without horking our grabs. */
- XDestroyWindow (si->dpy, old_w);
+ defer_XDestroyWindow (si->app, si->dpy, old_w);
if (p->verbose_p > 1)
fprintf (stderr, "%s: %d: destroyed old saver window 0x%lx\n",
@@ -724,7 +735,6 @@ update_screen_layout (saver_info *si)
free_monitors (si->monitor_layout);
si->monitor_layout = monitors;
- check_monitor_sanity (si->monitor_layout);
while (monitors[count])
{
@@ -740,13 +750,13 @@ update_screen_layout (saver_info *si)
calloc (sizeof(*si->screens), si->ssi_count);
}
- if (si->ssi_count <= good_count)
+ if (si->ssi_count < count)
{
- si->ssi_count = good_count + 10;
si->screens = (saver_screen_info *)
- realloc (si->screens, sizeof(*si->screens) * si->ssi_count);
- memset (si->screens + si->nscreens, 0,
- sizeof(*si->screens) * (si->ssi_count - si->nscreens));
+ realloc (si->screens, sizeof(*si->screens) * count);
+ memset (si->screens + si->ssi_count, 0,
+ sizeof(*si->screens) * (count - si->ssi_count));
+ si->ssi_count = count;
}
if (! si->screens) abort();
@@ -787,11 +797,7 @@ update_screen_layout (saver_info *si)
# ifndef DEBUG_MULTISCREEN
{
saver_preferences *p = &si->prefs;
- if (p->debug_p
-# ifdef QUAD_MODE
- && !p->quad_p
-# endif
- )
+ if (p->debug_p)
ssi->width /= 2;
}
# endif
@@ -814,7 +820,7 @@ cycle_timer (XtPointer closure, XtIntervalId *id)
if (ssi->error_dialog)
{
- XDestroyWindow (si->dpy, ssi->error_dialog);
+ defer_XDestroyWindow (si->app, si->dpy, ssi->error_dialog);
ssi->error_dialog = 0;
}
@@ -884,7 +890,7 @@ screenhack_obituary (saver_screen_info *ssi,
*/
cmap = ssi->cmap ? ssi->cmap : DefaultColormapOfScreen (ssi->screen);
window = ssi->error_dialog;
- if (window) XDestroyWindow (si->dpy, window);
+ if (window) defer_XDestroyWindow (si->app, si->dpy, window);
attrs.override_redirect = True;
attrs.background_pixel = ssi->black_pixel;
attrs.border_pixel = ssi->black_pixel;
@@ -912,7 +918,10 @@ screenhack_obituary (saver_screen_info *ssi,
gcv.line_width = bw;
gc = XCreateGC (si->dpy, window, GCForeground | GCLineWidth, &gcv);
- sprintf (buf, "\"%.100s\" %.100s", name, error);
+ if (name && *name)
+ sprintf (buf, "\"%.100s\" %.100s", name, error);
+ else
+ sprintf (buf, "%.100s", error);
XftTextExtentsUtf8 (si->dpy, font, (FcChar8 *) buf, strlen(buf), &overall);
x = (ssi->width - overall.width) / 2;
@@ -961,6 +970,7 @@ watchdog_timer (XtPointer closure, XtIntervalId *id)
{
saver_info *si = (saver_info *) closure;
saver_preferences *p = &si->prefs;
+ Bool running_p, on_p, terminating_p;
/* If the DPMS settings on the server have changed, change them back to
what ~/.xscreensaver says they should be. */
@@ -971,8 +981,10 @@ watchdog_timer (XtPointer closure, XtIntervalId *id)
raise_windows (si);
- if (any_screenhacks_running_p (si) &&
- !monitor_powered_on_p (si->dpy))
+ running_p = any_screenhacks_running_p (si);
+ on_p = monitor_powered_on_p (si->dpy);
+ terminating_p = si->terminating_p;
+ if (running_p && !on_p)
{
int i;
if (si->prefs.verbose_p)
@@ -981,6 +993,31 @@ watchdog_timer (XtPointer closure, XtIntervalId *id)
blurb());
for (i = 0; i < si->nscreens; i++)
kill_screenhack (&si->screens[i]);
+ /* Do not clear current_hack here. */
+ }
+ else if (terminating_p)
+ {
+ /* If we are in the process of shutting down and are about to exit,
+ don't re-launch anything just because the monitor came back on. */
+ }
+ else if (!running_p && on_p)
+ {
+ /* If the hack number is set but no hack is running, it is because the
+ hack was killed when the monitor powered off, above. This assumes
+ that kill_screenhack() clears pid but not current_hack. Start the
+ hack going again. The cycle_timer will also do this (unless "cycle"
+ is 0) but watchdog_timer runs more frequently.
+ */
+ if (si->nscreens > 0 && si->screens[0].current_hack >= 0)
+ {
+ int i;
+ if (si->prefs.verbose_p)
+ fprintf (stderr,
+ "%s: monitor has powered back on; re-launching hacks\n",
+ blurb());
+ for (i = 0; i < si->nscreens; i++)
+ spawn_screenhack (&si->screens[i]);
+ }
}
/* Re-schedule this timer. The watchdog timer defaults to a bit less