diff options
-rw-r--r-- | driver/XScreenSaver.ad.in | 10 | ||||
-rw-r--r-- | driver/prefs.c | 8 | ||||
-rw-r--r-- | driver/subprocs.c | 62 | ||||
-rw-r--r-- | driver/timers.c | 15 | ||||
-rw-r--r-- | driver/types.h | 6 | ||||
-rw-r--r-- | driver/windows.c | 28 | ||||
-rw-r--r-- | driver/xscreensaver.c | 12 | ||||
-rw-r--r-- | driver/xscreensaver.h | 2 |
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); |