summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--driver/XScreenSaver.ad.in10
-rw-r--r--driver/prefs.c8
-rw-r--r--driver/subprocs.c62
-rw-r--r--driver/timers.c15
-rw-r--r--driver/types.h6
-rw-r--r--driver/windows.c28
-rw-r--r--driver/xscreensaver.c12
-rw-r--r--driver/xscreensaver.h2
8 files changed, 138 insertions, 5 deletions
diff --git a/driver/XScreenSaver.ad.in b/driver/XScreenSaver.ad.in
index 5deb334..8a4cc6c 100644
--- a/driver/XScreenSaver.ad.in
+++ b/driver/XScreenSaver.ad.in
@@ -38,6 +38,7 @@
*dpmsStandby: 2:00:00
*dpmsSuspend: 2:00:00
*dpmsOff: 4:00:00
+*dpmsFullThrottle: False
*grabDesktopImages: True
*grabVideoFrames: False
*chooseRandomImages: @DEFAULT_IMAGES_P@
@@ -142,6 +143,15 @@
@NEW_LOGIN_COMMAND_P@*newLoginCommand: @NEW_LOGIN_COMMAND@
+! External command used to help xscreensaver aquire the mouse/keyboard
+! grab. (I.e. some script that makes VMware release it).
+! This is called before xscreensaver tries to aquire the grab with
+! "pre" as parameter, and again with "post" after xscreensaver is done
+! (trying to) aquire the grab.
+!
+*externalUngrabCommand:
+
+
! Change these at your peril:
!
XScreenSaver.pointerPollTime: 0:00:05
diff --git a/driver/prefs.c b/driver/prefs.c
index 8fb029e..ec5583b 100644
--- a/driver/prefs.c
+++ b/driver/prefs.c
@@ -265,6 +265,7 @@ static const char * const prefs[] = {
"helpURL", /* not saved */
"loadURL", /* not saved */
"newLoginCommand", /* not saved */
+ "externalUngrabCommand", /* not saved */
"nice",
"memoryLimit",
"fade",
@@ -281,6 +282,7 @@ static const char * const prefs[] = {
"dpmsStandby",
"dpmsSuspend",
"dpmsOff",
+ "dpmsFullThrottle",
"grabDesktopImages",
"grabVideoFrames",
"chooseRandomImages",
@@ -805,6 +807,7 @@ write_init_file (Display *dpy,
CHECK("loadURL") continue; /* don't save */
/* CHECK("newLoginCommand") type = pref_str, s = p->new_login_command; */
CHECK("newLoginCommand") continue; /* don't save */
+ CHECK("externalUngrabCommand") continue; /* don't save */
CHECK("nice") type = pref_int, i = p->nice_inferior;
CHECK("memoryLimit") type = pref_byte, i = p->inferior_memory_limit;
CHECK("fade") type = pref_bool, b = p->fade_p;
@@ -824,6 +827,7 @@ write_init_file (Display *dpy,
CHECK("dpmsStandby") type = pref_time, t = p->dpms_standby;
CHECK("dpmsSuspend") type = pref_time, t = p->dpms_suspend;
CHECK("dpmsOff") type = pref_time, t = p->dpms_off;
+ CHECK("dpmsFullThrottle") continue; /* don't save */
CHECK("grabDesktopImages") type =pref_bool, b = p->grab_desktop_p;
CHECK("grabVideoFrames") type =pref_bool, b = p->grab_video_p;
@@ -1082,6 +1086,7 @@ load_init_file (Display *dpy, saver_preferences *p)
p->dpms_standby = 1000 * get_minutes_resource (dpy, "dpmsStandby", "Time");
p->dpms_suspend = 1000 * get_minutes_resource (dpy, "dpmsSuspend", "Time");
p->dpms_off = 1000 * get_minutes_resource (dpy, "dpmsOff", "Time");
+ p->dpms_full_throttle_p = get_boolean_resource (dpy, "dpmsFullThrottle", "Boolean");
p->grab_desktop_p = get_boolean_resource (dpy, "grabDesktopImages", "Boolean");
p->grab_video_p = get_boolean_resource (dpy, "grabVideoFrames", "Boolean");
@@ -1104,6 +1109,9 @@ load_init_file (Display *dpy, saver_preferences *p)
p->new_login_command = get_string_resource(dpy,
"newLoginCommand",
"NewLoginCommand");
+ p->external_ungrab_command = get_string_resource(dpy,
+ "externalUngrabCommand",
+ "ExternalUngrabCommand");
p->auth_warning_slack = get_integer_resource(dpy, "authWarningSlack",
"Integer");
diff --git a/driver/subprocs.c b/driver/subprocs.c
index d500f70..c46eeee 100644
--- a/driver/subprocs.c
+++ b/driver/subprocs.c
@@ -928,6 +928,66 @@ fork_and_exec_1 (saver_info *si, saver_screen_info *ssi, const char *command)
}
+/* Execute command in another process and wait for it to
+ * finish. Return exit code of process, or -1 on error
+ * with fork() or exec().
+ */
+int
+exec_and_wait (saver_info *si, const char *command)
+{
+ pid_t forked;
+ saver_preferences *p = &si->prefs;
+
+ switch ((int) (forked = fork ()))
+ {
+ case -1:
+ {
+ char buf [255];
+ sprintf (buf, "%s: couldn't fork", blurb());
+ perror (buf);
+ return -1;
+ }
+
+ case 0:
+ close (ConnectionNumber (si->dpy)); /* close display fd */
+ limit_subproc_memory (p->inferior_memory_limit, p->verbose_p);
+
+ if (p->verbose_p)
+ fprintf (stderr, "%s: spawning \"%s\" in pid %lu.\n",
+ blurb(), command,
+ (unsigned long) getpid ());
+
+ exec_command (p->shell, command, 0);
+
+ /* If that returned, we were unable to exec the subprocess.
+ Print an error message, if desired.
+ */
+ print_path_error (command);
+
+ exit (-1); /* exits child fork */
+ break;
+
+ default: /* parent */
+ {
+ pid_t retpid;
+ int wstatus;
+ while ((retpid = waitpid (forked, &wstatus, 0)) == -1) {
+ if (errno == EINTR)
+ continue;
+ perror ("Could not waitpid for child.");
+ return -1;
+ }
+ if (WIFEXITED(wstatus))
+ return WEXITSTATUS(wstatus);
+ if (WIFSIGNALED(wstatus))
+ return WTERMSIG(wstatus) + 128;
+ return -1;
+ }
+ }
+ return -1;
+}
+
+
void
spawn_screenhack (saver_screen_info *ssi)
{
@@ -935,7 +995,7 @@ spawn_screenhack (saver_screen_info *ssi)
saver_preferences *p = &si->prefs;
XFlush (si->dpy);
- if (!monitor_powered_on_p (si))
+ if (!p->dpms_full_throttle_p && !monitor_powered_on_p (si))
{
if (si->prefs.verbose_p)
fprintf (stderr,
diff --git a/driver/timers.c b/driver/timers.c
index ea97f34..591b568 100644
--- a/driver/timers.c
+++ b/driver/timers.c
@@ -689,6 +689,19 @@ swallow_unlock_typeahead_events (saver_info *si, XEvent *e)
memset (buf, 0, sizeof(buf));
}
+void
+flush_events (saver_info *si)
+{
+ int i;
+ XEvent xe;
+ for (i = 0; i < 10; ++i) {
+ while (XtAppPending (si->app) != 0) {
+ XtAppNextEvent (si->app, &xe);
+ dispatch_event (si, &xe);
+ }
+ usleep(5000);
+ }
+}
/* methods of detecting idleness:
@@ -1657,7 +1670,7 @@ watchdog_timer (XtPointer closure, XtIntervalId *id)
raise_window (si, True, True, running_p);
}
- if (screenhack_running_p (si) &&
+ if (!p->dpms_full_throttle_p && screenhack_running_p (si) &&
!monitor_powered_on_p (si))
{
int i;
diff --git a/driver/types.h b/driver/types.h
index 35992ae..98425c6 100644
--- a/driver/types.h
+++ b/driver/types.h
@@ -137,6 +137,7 @@ struct saver_preferences {
Time dpms_standby; /* how long until monitor goes black */
Time dpms_suspend; /* how long until monitor power-saves */
Time dpms_off; /* how long until monitor powers down */
+ Bool dpms_full_throttle_p; /* Never kill or suspend hack when screen is off */
Bool grab_desktop_p; /* These are not used by "xscreensaver" */
Bool grab_video_p; /* itself: they are used by the external */
@@ -164,6 +165,11 @@ struct saver_preferences {
char *help_url; /* Where the help document resides. */
char *load_url_command; /* How one loads URLs. */
char *new_login_command; /* Command for the "New Login" button. */
+ char *external_ungrab_command; /* Command that's supposed to make sure
+ nobody is holding the keyboard or
+ mouse grab. Called with params
+ "pre" and "post" before and after
+ trying to get the grab. */
int auth_warning_slack; /* Don't warn about login failures if they
all happen within this many seconds of
diff --git a/driver/windows.c b/driver/windows.c
index b7bea52..38a611b 100644
--- a/driver/windows.c
+++ b/driver/windows.c
@@ -235,7 +235,7 @@ ungrab_keyboard_and_mouse (saver_info *si)
static Bool
-grab_keyboard_and_mouse (saver_info *si, Window window, Cursor cursor,
+grab_keyboard_and_mouse_real (saver_info *si, Window window, Cursor cursor,
int screen_no)
{
Status mstatus = 0, kstatus = 0;
@@ -320,6 +320,32 @@ grab_keyboard_and_mouse (saver_info *si, Window window, Cursor cursor,
}
+static Bool
+grab_keyboard_and_mouse (saver_info *si, Window window, Cursor cursor,
+ int screen_no)
+{
+ Bool ret;
+ char *euc = si->prefs.external_ungrab_command;
+ char cmd[200];
+ if (euc && *euc)
+ {
+ snprintf (cmd, sizeof(cmd), "%s %s", euc, "pre");
+ exec_and_wait (si, cmd);
+ }
+ ret = grab_keyboard_and_mouse_real (si, window, cursor, screen_no);
+ if (euc && *euc)
+ {
+ snprintf (cmd, sizeof(cmd), "%s %s", euc, "post");
+ exec_and_wait (si, cmd);
+ if (ret) {
+ /* The external command might have generated some x/input events */
+ flush_events (si);
+ }
+ }
+ return ret;
+}
+
+
int
move_mouse_grab (saver_info *si, Window to, Cursor cursor, int to_screen_no)
{
diff --git a/driver/xscreensaver.c b/driver/xscreensaver.c
index 2add3b8..0ecb6ec 100644
--- a/driver/xscreensaver.c
+++ b/driver/xscreensaver.c
@@ -1394,8 +1394,16 @@ main_loop (saver_info *si)
was_locked = True;
si->dbox_up_p = True;
- for (i = 0; i < si->nscreens; i++)
- suspend_screenhack (&si->screens[i], True); /* suspend */
+ if (p->dpms_full_throttle_p)
+ {
+ for (i = 0; i < si->nscreens; i++)
+ if (si->screens[i].pid == 0)
+ spawn_screenhack (&si->screens[i]);
+ usleep(100000);
+ }
+ else
+ for (i = 0; i < si->nscreens; i++)
+ suspend_screenhack (&si->screens[i], True); /* suspend */
XUndefineCursor (si->dpy, ssi->screensaver_window);
ok_to_unblank = unlock_p (si);
diff --git a/driver/xscreensaver.h b/driver/xscreensaver.h
index bed6537..fe84d20 100644
--- a/driver/xscreensaver.h
+++ b/driver/xscreensaver.h
@@ -129,6 +129,7 @@ extern void activate_lock_timer (XtPointer si, XtIntervalId *id);
extern void reset_watchdog_timer (saver_info *si, Bool on_p);
extern void idle_timer (XtPointer si, XtIntervalId *id);
extern void de_race_timer (XtPointer si, XtIntervalId *id);
+void flush_events (saver_info *si);
extern void sleep_until_idle (saver_info *si, Bool until_idle_p);
extern void reset_timers (saver_info *si);
extern void schedule_wakeup_event (saver_info *si, Time when, Bool verbose_p);
@@ -159,6 +160,7 @@ extern void spawn_screenhack (saver_screen_info *ssi);
extern pid_t fork_and_exec (saver_screen_info *ssi, const char *command);
extern pid_t fork_and_exec_1 (saver_info *si, saver_screen_info *ssi,
const char *command);
+extern int exec_and_wait (saver_info *si, const char *command);
extern void kill_screenhack (saver_screen_info *ssi);
int kill_job (saver_info *si, pid_t pid, int signal);
extern void suspend_screenhack (saver_screen_info *ssi, Bool suspend_p);