diff options
Diffstat (limited to 'driver')
-rw-r--r-- | driver/XScreenSaver.ad.in | 10 | ||||
-rw-r--r-- | driver/dpms.c | 23 | ||||
-rw-r--r-- | driver/prefs.c | 8 | ||||
-rw-r--r-- | driver/prefs.h | 2 | ||||
-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 | 75 | ||||
-rw-r--r-- | driver/xscreensaver.c | 12 | ||||
-rw-r--r-- | driver/xscreensaver.h | 2 |
10 files changed, 210 insertions, 5 deletions
diff --git a/driver/XScreenSaver.ad.in b/driver/XScreenSaver.ad.in index cfdd1a2..0b51f0c 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/dpms.c b/driver/dpms.c index a0dd7b8..3a8803c 100644 --- a/driver/dpms.c +++ b/driver/dpms.c @@ -86,8 +86,12 @@ #ifdef HAVE_DPMS_EXTENSION +#define CLAMP_DOWN(var,val,mi) do { int old = (var); (var) -= (val); if ((var) < (mi) || (var) > old) (var) = (mi); } while (0) + static Bool error_handler_hit_p = False; +static int idle_offset = 0; + static int ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error) { @@ -95,6 +99,12 @@ ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error) return 0; } +void +store_dpms_offset(int offset) +{ + idle_offset = offset < 15 ? 0 : offset; +} + void sync_server_dpms_settings (Display *dpy, Bool enabled_p, Bool dpms_quickoff_p, @@ -125,6 +135,13 @@ sync_server_dpms_settings (Display *dpy, Bool enabled_p, Bool dpms_quickoff_p, if (bogus_p) enabled_p = False; + if (idle_offset != 0) + { + CLAMP_DOWN (standby_secs, idle_offset, 10); + CLAMP_DOWN (suspend_secs, idle_offset, 10); + CLAMP_DOWN (off_secs, idle_offset, 10); + } + /* X protocol sends these values in a CARD16, so truncate them to 16 bits. This means that the maximum timeout is 18:12:15. */ @@ -280,6 +297,12 @@ monitor_power_on (saver_info *si, Bool on_p) #else /* !HAVE_DPMS_EXTENSION */ void +store_dpms_offset(Display *dpy, Bool reset_p) +{ +} + + +void sync_server_dpms_settings (Display *dpy, Bool enabled_p, Bool dpms_quickoff_p, int standby_secs, int suspend_secs, int off_secs, diff --git a/driver/prefs.c b/driver/prefs.c index 94e7a0c..e5762ff 100644 --- a/driver/prefs.c +++ b/driver/prefs.c @@ -270,6 +270,7 @@ static const char * const prefs[] = { "helpURL", /* not saved */ "loadURL", /* not saved */ "newLoginCommand", /* not saved */ + "externalUngrabCommand", /* not saved */ "nice", "memoryLimit", "fade", @@ -286,6 +287,7 @@ static const char * const prefs[] = { "dpmsStandby", "dpmsSuspend", "dpmsOff", + "dpmsFullThrottle", "grabDesktopImages", "grabVideoFrames", "chooseRandomImages", @@ -810,6 +812,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; @@ -829,6 +832,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; @@ -1087,6 +1091,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"); @@ -1109,6 +1114,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/prefs.h b/driver/prefs.h index cd1016d..c494eaf 100644 --- a/driver/prefs.h +++ b/driver/prefs.h @@ -34,4 +34,6 @@ extern void sync_server_dpms_settings (Display *, Bool enabled_p, int off_secs, Bool verbose_p); +extern void store_dpms_offset(int offset); + #endif /* __XSCREENSAVER_PREFS_H__ */ diff --git a/driver/subprocs.c b/driver/subprocs.c index e251842..6cb96d3 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 5aa568c..b096000 100644 --- a/driver/timers.c +++ b/driver/timers.c @@ -695,6 +695,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) & XtIMXEvent) { + XtAppNextEvent (si->app, &xe); + dispatch_event (si, &xe); + } + usleep(5000); + } +} /* methods of detecting idleness: @@ -1663,7 +1676,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 ebea9e0..705750b 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 9e47c45..5854c49 100644 --- a/driver/windows.c +++ b/driver/windows.c @@ -35,6 +35,7 @@ #include <X11/Xutil.h> /* for XSetClassHint() */ #include <X11/Xatom.h> #include <X11/Xos.h> /* for time() */ +#include <X11/extensions/scrnsaver.h> #include <signal.h> /* for the signal names */ #include <time.h> #include <sys/time.h> @@ -235,7 +236,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 +321,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) { @@ -1639,6 +1666,17 @@ mouse_screen (saver_info *si) return 0; } +static int +get_idle_time (saver_info *si) +{ + int ret = 0; + XScreenSaverInfo *info; + info = XScreenSaverAllocInfo (); + if (info != NULL && XScreenSaverQueryInfo (si->dpy, DefaultRootWindow (si->dpy), info)) + ret = info->idle / 1000; + XFree (info); + return ret; +} Bool blank_screen (saver_info *si) @@ -1647,7 +1685,16 @@ blank_screen (saver_info *si) Bool ok; Window w; int mscreen; + int idle_s = 0; + Bool screen_on = True; + const char *euc = si->prefs.external_ungrab_command; + if (euc && *euc) + { + screen_on = monitor_powered_on_p (si); + if (screen_on) + idle_s = get_idle_time(si); + } /* Note: we do our grabs on the root window, not on the screensaver window. If we grabbed on the saver window, then the demo mode and lock dialog boxes wouldn't get any events. @@ -1679,6 +1726,31 @@ blank_screen (saver_info *si) if (!ok) return False; + if (euc && *euc) + { + /* ungrab hooks might have messed up idle time -- account for that. + this might look like the math is backwards, but this handles both + cases -- ungrab hook did mess up idle time, and ungrab hook + did *not* mess up idle time. In the latter case the value will be + zero or negative, so it gets clamped to zero. + */ + if (screen_on) + { + saver_preferences *p = &si->prefs; + store_dpms_offset (idle_s - get_idle_time(si)); + sync_server_dpms_settings (si->dpy, + (p->dpms_enabled_p && + p->mode != DONT_BLANK), + p->dpms_quickoff_p, + p->dpms_standby / 1000, + p->dpms_suspend / 1000, + p->dpms_off / 1000, + False); + } + else /* screen was off before, might have been turned on by fake events */ + monitor_power_on (si, False); + } + for (i = 0; i < si->nscreens; i++) { saver_screen_info *ssi = &si->screens[i]; @@ -1719,6 +1791,7 @@ unblank_screen (saver_info *si) Bool unfade_p = (si->fading_possible_p && p->unfade_p); int i; + store_dpms_offset (0); monitor_power_on (si, True); reset_watchdog_timer (si, False); diff --git a/driver/xscreensaver.c b/driver/xscreensaver.c index 40f8207..b9c54f1 100644 --- a/driver/xscreensaver.c +++ b/driver/xscreensaver.c @@ -1399,8 +1399,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); |