The screensaver_freedesktop Inhibit call only prevents the screensaver from activating during the lifetime of the calling process. Unfortunately, since xdg-screensaver uses dbus-send to send the request, it expires as soon as the dbus-send process terminates. Therefore, this patch changes the screensaver_freedesktop to use SimulateUserActivity in a screensaver_suspend_loop. The ideal solution would be to change the specification for the D-Bus interface to either allow an option "OnBehalfOf" argument for the Inhibit method call or to add a new method allowing an application to send a request for another application. The D-Bus interface for the screensavers seems to have been created by freedesktop.org, so perhaps the Portland group can apply some pressure to the D-Bus interface designers so that we can finally have one application that allows interfacing with all screensavers--even those that don't, and won't ever, support D-Bus (like xscreensaver). --- xdg-screensaver | 98 42 + 56 - 0 ! 1 file changed, 42 insertions(+), 56 deletions(-) --- xdg-screensaver-cvs-1.48 2010-08-28 21:34:19.000000000 -0400 +++ xdg-screensaver 2010-08-28 21:33:52.000000000 -0400 @@ -540,37 +540,50 @@ cleanup_suspend } +screensaver_suspend_loop() +{ + lockfile + test "${TMPDIR+set}" = set || TMPDIR=/tmp + tmpfile=`mktemp $TMPDIR/tmp.XXXXXXXXXX` + # Filter stale entries from the xdg-screensaver status file + cat "$screensaver_file" 2> /dev/null | ( + IFS_save="$IFS" + IFS=":" + while read wid pid; do + if ps -p "$pid" 2> /dev/null | grep xprop > /dev/null; then + echo "$wid:$pid" + fi + done + IFS="$IFS_save" + ) > $tmpfile + if [ -s "$tmpfile" ] ; then + # Suspend pending, don't do a thing + $MV "$tmpfile" "$screensaver_file" + unlockfile + return + fi + $MV "$tmpfile" "$screensaver_file" + unlockfile + (while [ -f "$screensaver_file" ]; do $*; sleep 50; done) > /dev/null 2> /dev/null & +} + screensaver_freedesktop() { case "$1" in suspend) + screensaver_suspend_loop \ dbus-send --session \ --dest=org.freedesktop.ScreenSaver \ --type=method_call \ - --print-reply \ - --reply-timeout=2000 \ /ScreenSaver \ - org.freedesktop.ScreenSaver.Inhibit \ - string:$window_id \ - string:xdg-screensaver \ - | grep uint32 | cut -d ' ' -f 5 >| "$screensaver_file.cookie" \ + org.freedesktop.ScreenSaver.SimulateUserActivity \ 2> /dev/null result=$? ;; resume) - if [ -f "$screensaver_file.cookie" ] ; then - value=`cat "$screensaver_file.cookie"` - dbus-send --session \ - --dest=org.freedesktop.ScreenSaver \ - --type=method_call \ - /ScreenSaver \ - org.freedesktop.ScreenSaver.UnInhibit \ - uint32:$value \ - 2> /dev/null - rm -f "$screensaver_file.cookie" - fi - result=$? + # Automatic resume when $screensaver_file disappears + result=0 ;; activate) @@ -594,17 +607,12 @@ ;; reset) - if [ -f "$screensaver_file.cookie" ] ; then - value=`cat "$screensaver_file.cookie"` - dbus-send --session \ - --dest=org.freedesktop.ScreenSaver \ - --type=method_call \ - /ScreenSaver \ - org.freedesktop.ScreenSaver.UnInhibit \ - uint32:$value \ - 2> /dev/null - rm -f "$screensaver_file.cookie" - fi + dbus-send --session \ + --dest=org.freedesktop.ScreenSaver \ + --type=method_call \ + /ScreenSaver \ + org.freedesktop.ScreenSaver.SimulateUserActivity \ + 2> /dev/null result=$? ;; @@ -684,33 +692,6 @@ esac } -screensaver_suspend_loop() -{ - lockfile - test "${TMPDIR+set}" = set || TMPDIR=/tmp - tmpfile=`mktemp $TMPDIR/tmp.XXXXXXXXXX` - # Filter stale entries from the xdg-screensaver status file - cat "$screensaver_file" 2> /dev/null | ( - IFS_save="$IFS" - IFS=":" - while read wid pid; do - if ps -p "$pid" 2> /dev/null | grep xprop > /dev/null; then - echo "$wid:$pid" - fi - done - IFS="$IFS_save" - ) > $tmpfile - if [ -s "$tmpfile" ] ; then - # Suspend pending, don't do a thing - $MV "$tmpfile" "$screensaver_file" - unlockfile - return - fi - $MV "$tmpfile" "$screensaver_file" - unlockfile - (while [ -f "$screensaver_file" ]; do $*; sleep 50; done) > /dev/null 2> /dev/null & -} - screensaver_gnome_screensaver() { # TODO @@ -719,6 +700,11 @@ # http://cvs.gnome.org/viewcvs/gnome-screensaver/src/gs-listener-dbus.c?rev=1.36&view=log # A problem seems to be that Inhibit is tied to the lifetime of the DBUS appname and # this can not be used from a script +# +# SimulateUserActivity can be used in a screensaver_suspend_loop, as with the +# screensaver_freedesktop, above, so enabling the dbus interface in GNOME +# probably just requires determining when to use dbus and when to use +# gnome-screensaver-command case "$1" in suspend) screensaver_suspend_loop gnome-screensaver-command --poke