]> git.hungrycats.org Git - xscreensaver/commitdiff
From https://www.jwz.org/xscreensaver/xscreensaver-6.01.tar.gz
authorZygo Blaxell <zblaxell@waya.furryterror.org>
Sat, 12 Jun 2021 04:54:48 +0000 (00:54 -0400)
committerZygo Blaxell <xss-mirror@furryterror.org>
Sat, 12 Jun 2021 04:55:32 +0000 (00:55 -0400)
-rw-rw-r-- 1 zblaxell zblaxell 27820165 Jun  9 12:00 xscreensaver-6.01.tar.gz
5e6bf477d14b8a4a07e65ac2fd32b7b7f71e422b  xscreensaver-6.01.tar.gz

37 files changed:
Makefile.in
OSX/Randomizer.plist
OSX/SaverRunner.plist
OSX/Updater.plist
OSX/XScreenSaver.plist
OSX/bindist.rtf
OSX/iSaverRunner.plist
README
config.h.in
configure
configure.ac
driver/XScreenSaver.ad.in
driver/atoms.c
driver/atoms.h
driver/atomswm.c
driver/demo-Gtk.c
driver/dialog.c
driver/dpms.c
driver/exts.c
driver/fade.c
driver/fade.h
driver/screens.c
driver/test-xinput.c
driver/windows.c
driver/xinput.c
driver/xscreensaver-settings.man
driver/xscreensaver-systemd.c
driver/xscreensaver.c
driver/xscreensaver.man
hacks/Makefile.in
hacks/analogtv-cli.c
hacks/config/README
hacks/config/covid19.xml
hacks/xscreensaver-text
po/POTFILES.in
utils/version.h
xscreensaver.spec

index 42742d3c5fe66671e4b3d81810e2e9ff5d86520e..ce469fc3640b915c40ff9f8bcdb97b370a5f325f 100644 (file)
@@ -16,7 +16,9 @@ TARFILES      = README README.hacking INSTALL \
                  intltool-merge.in intltool-extract.in intltool-update.in \
                  xscreensaver.spec
 
-TAR            = tar
+TAR            = gnutar
+TAR_ARGS       = --owner=0 --group=0 --posix --no-acls --no-xattrs --no-selinux
+
 
 # Using $(MAKE) directly means the shell executes things even with "make -n"
 MAKE2 = $(MAKE)
@@ -94,7 +96,7 @@ _tar:
   echo creating tar file $$ADIR$$NAME.tar.gz... ;                          \
   export COPYFILE_DISABLE=true ;                                           \
   export GZIP="-9v" ;                                                      \
-  $(TAR) -vczf $$ADIR$$NAME.tar.gz -T "$$LIST" ;                           \
+  $(TAR) -vczf $$ADIR$$NAME.tar.gz -T "$$LIST" $(TAR_ARGS) ;               \
   rm "$$LIST" "$$NAME"
 
 
@@ -361,7 +363,7 @@ www::
   diff -U0 download.html $$TMP ;                                           \
   echo '' ;                                                                \
                                                                            \
-  for EXT in tar.gz dmg ; do                                               \
+  for EXT in tar.gz dmg apk ; do                                           \
     OLDEST=`ls xscreensaver*.$$EXT |                                       \
       fgrep -v 5.14 |                                                      \
       fgrep -v 5.34 |                                                      \
@@ -413,7 +415,7 @@ count::
 #      rsync -vax . cerebrum:src/xscreensaver/ \
 
 cerebrum::
-       rsync -vax . pi@10.0.1.19:xscreensaver/ \
+       rsync -vax . pi@10.0.1.10:xscreensaver/ \
        --omit-dir-times \
        --delete-during \
        --exclude .git \
index e2d4c5767a60e1ac68994a92a8d12551480b354d..d2761b82d4a8f93472af008a8121744a645d7fb7 100644 (file)
@@ -17,7 +17,7 @@
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>LSMinimumSystemVersion</key>
        <string>${MACOSX_DEPLOYMENT_TARGET}</string>
        <key>NSPrincipalClass</key>
        <key>LSApplicationCategoryType</key>
        <string>public.app-category.entertainment</string>
        <key>CFBundleShortVersionString</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>CFBundleLongVersionString</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>CFBundleGetInfoString</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>NSHumanReadableCopyright</key>
-       <string>6.00</string>
+       <string>6.01</string>
 </dict>
 </plist>
index ac6292aa2ec4cba3dcf7850b6fe7a920b48c1d6b..df4d548711355ac9237a52b8276d26d5f3c5bc9c 100644 (file)
@@ -17,7 +17,7 @@
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>LSMinimumSystemVersion</key>
        <string>${MACOSX_DEPLOYMENT_TARGET}</string>
        <key>NSPrincipalClass</key>
        <key>LSApplicationCategoryType</key>
        <string>public.app-category.entertainment</string>
        <key>CFBundleShortVersionString</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>CFBundleLongVersionString</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>CFBundleGetInfoString</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>NSHumanReadableCopyright</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>NSMainNibFile</key>
        <string>SaverRunner</string>
        <key>CFBundleIconFile</key>
index e399326fcebc384973fdc6203c32f775be2676ce..9d799fa2d40eaad052deb9ad85bf236c1c5a4d13 100644 (file)
@@ -17,7 +17,7 @@
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>LSMinimumSystemVersion</key>
        <string>${MACOSX_DEPLOYMENT_TARGET}</string>
        <key>NSPrincipalClass</key>
        <key>LSApplicationCategoryType</key>
        <string>public.app-category.entertainment</string>
        <key>CFBundleShortVersionString</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>CFBundleLongVersionString</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>CFBundleGetInfoString</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>NSHumanReadableCopyright</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>NSMainNibFile</key>
        <string>Updater</string>
        <key>CFBundleIconFile</key>
index b91d3c55230ab0bc7ae1847ff7fdc639f148cc93..69c687b4c5cfa177e3693c138347fa9ca7d07d19 100644 (file)
@@ -17,7 +17,7 @@
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>LSMinimumSystemVersion</key>
        <string>${MACOSX_DEPLOYMENT_TARGET}</string>
        <key>NSPrincipalClass</key>
        <key>LSApplicationCategoryType</key>
        <string>public.app-category.entertainment</string>
        <key>CFBundleShortVersionString</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>CFBundleLongVersionString</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>CFBundleGetInfoString</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>NSHumanReadableCopyright</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>NSMainNibFile</key>
        <string>SaverRunner</string>
 </dict>
index f2909b9035a0aac4414978e0b225cf0c863d9570..469f51ff91ef59cfb610ebf107167aaaefed6403 100644 (file)
@@ -16,8 +16,8 @@
 \b0 by Jamie Zawinski\
 and many others\
 \
-version 6.00\
-01-Apr-2021\
+version 6.01\
+09-Jun-2021\
 \
 {\field{\*\fldinst{HYPERLINK "https://www.jwz.org/xscreensaver/"}}{\fldrslt \cf2 \ul \ulc2 https://www.jwz.org/xscreensaver/}}\
 \pard\pardeftab720
index a65d7be13dad1f8223dd9dc35d27787d850bcb10..835f8c43cc541933433801b6512ac3bd6b0311db 100644 (file)
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>LSApplicationCategoryType</key>
        <string>public.app-category.entertainment</string>
        <key>CFBundleShortVersionString</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>CFBundleLongVersionString</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>CFBundleGetInfoString</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>NSHumanReadableCopyright</key>
-       <string>6.00</string>
+       <string>6.01</string>
        <key>NSMainNibFile</key>
        <string>iSaverRunner</string>
        <key>CFBundleDisplayName</key>
diff --git a/README b/README
index ddb978695a199f4815d9b8be53e6b84622d18fc0..85295491ad60eb873f809d68a56d5023353c9e2d 100644 (file)
--- a/README
+++ b/README
@@ -70,6 +70,17 @@ Interested in writing a new screen saver?
 Version History
 ===============================================================================
 
+6.01   * X11: Properly disable the server's built-in screen saver.
+       * X11: The passwdTimeout option was being ignored.
+       * X11: The display of the unlock thermometer was weird.
+       * X11: Fixed password entry on old-school multi-screen setups (:0.1).
+       * X11: Worked around a KDE 5 compositor bug that caused the desktop
+          to momentarily become visible when cycling.
+       * X11: Fixed possible high CPU usage in `xscreensaver-systemd'.
+       * X11: Fixed some spurious warnings in `xscreensaver-text'.
+       * X11: Warn when Wayland is in use, since it makes both screen saving
+          and locking impossible.
+
 6.00   * X11: Major refactor of the `xscreensaver' daemon for improved
          security, dividing it into three programs: `xscreensaver',
          `xscreensaver-gfx' and `xscreensaver-auth'.
index 11a0ab9e6c95a7084f69d0eab04b62d977a31dd0..d326fb86c24a34662f09963c128cf4e24bbae104 100644 (file)
 /* Define this if your system has libcap. */
 #undef HAVE_LIBCAP
 
+/* Define this if you have libelogind. */
+#undef HAVE_LIBELOGIND
+
 /* Define this if you have the Portable Network Graphics library. */
 #undef HAVE_LIBPNG
 
index 4a03e1e85c936486c164c7bf4d526881aa49fd88..0bec009e8d5b6cbb2df572af73ecdca91a114512 100755 (executable)
--- a/configure
+++ b/configure
@@ -839,6 +839,7 @@ with_xkb_ext
 with_proc_interrupts
 with_proc_oom
 with_systemd
+with_elogind
 enable_locking
 enable_root_passwd
 with_pam
@@ -1496,6 +1497,7 @@ Server Extension Options:
   --with-proc-oom         Include support to duck the out-of-memory killer.
   --with-systemd          Support systemd requests to lock on suspend, and to
                           allow video players to inhibit the screen saver.
+  --with-elogind          Use elogind instead of systemd.
 
 Screen Locking Options:
 
@@ -10500,6 +10502,219 @@ else
   SYSTEMD_LIBS=''
 fi
 
+###############################################################################
+#
+#       Check for -lelogind, a stripped down subset of systemd.
+#
+###############################################################################
+
+have_elogind=no
+with_elogind_req=unspecified
+elogind_halfassed=no
+elogind_too_old=no
+
+# Check whether --with-elogind was given.
+if test "${with_elogind+set}" = set; then :
+  withval=$with_elogind; with_elogind="$withval"; with_elogind_req="$withval"
+else
+  with_elogind=yes
+fi
+
+   case "$with_elogind" in
+    yes) ;;
+    no)  ;;
+
+    /*)
+     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for elogind headers" >&5
+$as_echo_n "checking for elogind headers... " >&6; }
+     d=$with_elogind/include
+     if test -d $d; then
+       X_CFLAGS="-I$d $X_CFLAGS"
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $d" >&5
+$as_echo "$d" >&6; }
+     else
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found ($d: no such directory)" >&5
+$as_echo "not found ($d: no such directory)" >&6; }
+     fi
+
+     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for elogind libs" >&5
+$as_echo_n "checking for elogind libs... " >&6; }
+     d=$with_elogind/lib
+     if test -d $d; then
+       X_LIBS="-L$d $X_LIBS"
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $d" >&5
+$as_echo "$d" >&6; }
+     else
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found ($d: no such directory)" >&5
+$as_echo "not found ($d: no such directory)" >&6; }
+     fi
+
+     # replace the directory string with "yes".
+     with_elogind_req="yes"
+     with_elogind=$with_elogind_req
+     ;;
+
+    *)
+     echo ""
+     echo "error: argument to --with-elogind must be \"yes\", \"no\", or a directory."
+     echo "       If it is a directory, then \`DIR/include' will be added to"
+     echo "       the -I list, and \`DIR/lib' will be added to the -L list."
+     exit 1
+     ;;
+   esac
+
+if test "$with_elogind" != yes -a "$with_elogind" != no ; then
+  echo "error: must be yes or no: --with-elogind=$with_elogind"
+  exit 1
+fi
+
+if test "$with_elogind" = yes; then
+
+  pkgs=''
+  ok="yes"
+  pkg_check_version libelogind 221
+  have_elogind="$ok"
+
+  if test "$have_elogind" = no; then
+    if $pkg_config --exists libelogind ; then
+      elogind_too_old=yes
+    fi
+  fi
+
+  if test "$have_elogind" = yes; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libelogind includes" >&5
+$as_echo_n "checking for libelogind includes... " >&6; }
+if ${ac_cv_elogind_config_cflags+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_elogind_config_cflags=`$pkg_config --cflags $pkgs`
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_elogind_config_cflags" >&5
+$as_echo "$ac_cv_elogind_config_cflags" >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libelogind libs" >&5
+$as_echo_n "checking for libelogind libs... " >&6; }
+if ${ac_cv_elogind_config_libs+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_elogind_config_libs=`$pkg_config --libs $pkgs`
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_elogind_config_libs" >&5
+$as_echo "$ac_cv_elogind_config_libs" >&6; }
+  fi
+
+  ac_elogind_config_cflags=$ac_cv_elogind_config_cflags
+  ac_elogind_config_libs=$ac_cv_elogind_config_libs
+
+  if test "$have_elogind" = yes; then
+    #
+    # we appear to have libelogind; check for headers/libs to be sure.
+    #
+    ac_save_elogind_CPPFLAGS="$CPPFLAGS"
+    CPPFLAGS="$CPPFLAGS $ac_elogind_config_cflags"
+
+    have_elogind=no
+
+  ac_save_CPPFLAGS="$CPPFLAGS"
+  if test \! -z "$includedir" ; then
+    CPPFLAGS="$CPPFLAGS -I$includedir"
+  fi
+  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+  CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS`
+  ac_fn_c_check_header_mongrel "$LINENO" "elogind/sd-bus.h" "ac_cv_header_elogind_sd_bus_h" "$ac_includes_default"
+if test "x$ac_cv_header_elogind_sd_bus_h" = xyes; then :
+  have_elogind=yes
+fi
+
+  CPPFLAGS="$ac_save_CPPFLAGS"
+
+    CPPFLAGS="$ac_save_elogind_CPPFLAGS"
+  fi
+
+  if test "$have_elogind" = yes; then
+    # we have the headers, now check for the libraries
+    have_elogind=no
+    elogind_halfassed=yes
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: checking for libelogind usability..." >&5
+$as_echo "checking for libelogind usability..." >&6; }
+
+  ac_save_CPPFLAGS="$CPPFLAGS"
+  ac_save_LDFLAGS="$LDFLAGS"
+#  ac_save_LIBS="$LIBS"
+
+  if test \! -z "$includedir" ; then
+    CPPFLAGS="$CPPFLAGS -I$includedir"
+  fi
+  # note: $X_CFLAGS includes $x_includes
+  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+
+  if test \! -z "$libdir" ; then
+    LDFLAGS="$LDFLAGS -L$libdir"
+  fi
+  # note: $X_LIBS includes $x_libraries
+  LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS"
+
+  CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS`
+  LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS`
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sd_bus_open_system in -lc" >&5
+$as_echo_n "checking for sd_bus_open_system in -lc... " >&6; }
+if ${ac_cv_lib_c_sd_bus_open_system+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc $ac_elogind_config_libs -lX11 -lXext -lm $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char sd_bus_open_system ();
+int
+main ()
+{
+return sd_bus_open_system ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_c_sd_bus_open_system=yes
+else
+  ac_cv_lib_c_sd_bus_open_system=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_sd_bus_open_system" >&5
+$as_echo "$ac_cv_lib_c_sd_bus_open_system" >&6; }
+if test "x$ac_cv_lib_c_sd_bus_open_system" = xyes; then :
+  have_elogind=yes; elogind_halfassed=no
+fi
+
+  CPPFLAGS="$ac_save_CPPFLAGS"
+  LDFLAGS="$ac_save_LDFLAGS"
+#  LIBS="$ac_save_LIBS"
+
+  fi
+
+  if test "$have_elogind" = no; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: checking for libelogind usability... no" >&5
+$as_echo "checking for libelogind usability... no" >&6; }
+  fi
+fi
+
+if test "$have_elogind" = yes; then
+  INCLUDES="$INCLUDES $ac_elogind_config_cflags"
+  EXES_SYSTEMD='$(EXES_SYSTEMD)'
+  SYSTEMD_LIBS="$ac_elogind_config_libs"
+  $as_echo "#define HAVE_LIBELOGIND 1" >>confdefs.h
+
+fi
+
 ###############################################################################
 #
 #       The --enable-locking option
@@ -19080,7 +19295,7 @@ if test \! -z "$rpm_vers" ; then
   pkg_bindir2=`rpm -ql $rpmnames | sed -n 's@^\(.*/\)xscreensaver-demo$@\1@p'`
   pkg_hackdir=`rpm -ql $rpmnames | sed -n 's@^\(.*/\)popsquares$@\1@p'`
   pkg_confdir=`rpm -ql $rpmnames | sed -n 's@^\(.*/\)popsquares\.xml$@\1@p'`
-  pkg_fontdir=`rpm -ql $rpmnames | sed -n 's@^\(.*/\)\.ttf$@\1@p'`
+  pkg_fontdir=`rpm -ql $rpmnames | sed -n 's@^\(.*/\).*\.ttf$@\1@p' | head -1`
   pkg_addir=`rpm   -ql $rpmnames | sed -n 's@^\(.*/\)XScreenSaver$@\1@p'`
 
   if test -z "$pkg_bindir" ; then pkg_bindir="$pkg_bindir2" ; fi
@@ -19109,7 +19324,7 @@ if test \! -z "$deb_vers" ; then
   pkg_bindir2=`dpkg -L $debnames 2>&- | sed -n 's@^\(.*/\)xscreensaver-demo$@\1@p'`
   pkg_hackdir=`dpkg -L $debnames 2>&- | sed -n 's@^\(.*/\)popsquares$@\1@p'`
   pkg_confdir=`dpkg -L $debnames 2>&- | sed -n 's@^\(.*/\)popsquares\.xml$@\1@p'`
-  pkg_fontdir=`dpkg -L $debnames 2>&- | sed -n 's@^\(.*/\)\.ttf$@\1@p'`
+  pkg_fontdir=`dpkg -L $debnames 2>&- | sed -n 's@^\(.*/\).*\.ttf$@\1@p' | head -1`
   pkg_addir=`dpkg   -L $debnames 2>&- | sed -n 's@^\(.*/\)XScreenSaver[^/]*$@\1@p'`
 
   if test -z "$pkg_bindir" ; then pkg_bindir="$pkg_bindir2" ; fi
index c3f0b5b56990fd1d1443eab1b36f179c01c8009b..0b92abcfc368a8215264c7470b8c408b3f4dad53 100644 (file)
@@ -126,6 +126,9 @@ AH_TEMPLATE([HAVE_XKB],
 AH_TEMPLATE([HAVE_LIBSYSTEMD],
            [Define this if you have libsystemd.])
 
+AH_TEMPLATE([HAVE_LIBELOGIND],
+           [Define this if you have libelogind.])
+
 AH_TEMPLATE([HAVE_PROC_INTERRUPTS],
            [Define this if you have a Linux-like /proc/interrupts file which
            can be examined to determine when keyboard activity has
@@ -2138,6 +2141,87 @@ else
 fi
 
 
+###############################################################################
+#
+#       Check for -lelogind, a stripped down subset of systemd.
+#
+###############################################################################
+
+have_elogind=no
+with_elogind_req=unspecified
+elogind_halfassed=no
+elogind_too_old=no
+AC_ARG_WITH(elogind,
+[  --with-elogind          Use elogind instead of systemd.],
+  [with_elogind="$withval"; with_elogind_req="$withval"],
+  [with_elogind=yes])
+
+HANDLE_X_PATH_ARG(with_elogind, --with-elogind, elogind)
+
+if test "$with_elogind" != yes -a "$with_elogind" != no ; then
+  echo "error: must be yes or no: --with-elogind=$with_elogind"
+  exit 1
+fi
+
+if test "$with_elogind" = yes; then
+
+  pkgs=''
+  ok="yes"
+  pkg_check_version libelogind 221
+  have_elogind="$ok"
+
+  if test "$have_elogind" = no; then
+    if $pkg_config --exists libelogind ; then
+      elogind_too_old=yes
+    fi
+  fi
+
+  if test "$have_elogind" = yes; then
+    AC_CACHE_CHECK([for libelogind includes], ac_cv_elogind_config_cflags,
+               [ac_cv_elogind_config_cflags=`$pkg_config --cflags $pkgs`])
+    AC_CACHE_CHECK([for libelogind libs], ac_cv_elogind_config_libs,
+               [ac_cv_elogind_config_libs=`$pkg_config --libs $pkgs`])
+  fi
+
+  ac_elogind_config_cflags=$ac_cv_elogind_config_cflags
+  ac_elogind_config_libs=$ac_cv_elogind_config_libs
+
+  if test "$have_elogind" = yes; then
+    #
+    # we appear to have libelogind; check for headers/libs to be sure.
+    #
+    ac_save_elogind_CPPFLAGS="$CPPFLAGS"
+    CPPFLAGS="$CPPFLAGS $ac_elogind_config_cflags"
+
+    have_elogind=no
+    AC_CHECK_X_HEADER(elogind/sd-bus.h, [have_elogind=yes])
+
+    CPPFLAGS="$ac_save_elogind_CPPFLAGS"
+  fi
+
+  if test "$have_elogind" = yes; then
+    # we have the headers, now check for the libraries
+    have_elogind=no
+    elogind_halfassed=yes
+    AC_MSG_RESULT(checking for libelogind usability...)
+    AC_CHECK_X_LIB(c, sd_bus_open_system,
+                   [have_elogind=yes; elogind_halfassed=no],,
+                   $ac_elogind_config_libs -lX11 -lXext -lm)
+  fi
+
+  if test "$have_elogind" = no; then
+    AC_MSG_RESULT(checking for libelogind usability... no)
+  fi
+fi
+
+if test "$have_elogind" = yes; then
+  INCLUDES="$INCLUDES $ac_elogind_config_cflags"
+  EXES_SYSTEMD='$(EXES_SYSTEMD)'
+  SYSTEMD_LIBS="$ac_elogind_config_libs"
+  AC_DEFINE(HAVE_LIBELOGIND)
+fi
+
+
 ###############################################################################
 #
 #       The --enable-locking option
@@ -4774,7 +4858,7 @@ if test \! -z "$rpm_vers" ; then
   pkg_bindir2=`rpm -ql $rpmnames | sed -n 's@^\(.*/\)xscreensaver-demo$@\1@p'`
   pkg_hackdir=`rpm -ql $rpmnames | sed -n 's@^\(.*/\)popsquares$@\1@p'`
   pkg_confdir=`rpm -ql $rpmnames | sed -n 's@^\(.*/\)popsquares\.xml$@\1@p'`
-  pkg_fontdir=`rpm -ql $rpmnames | sed -n 's@^\(.*/\)\.ttf$@\1@p'`
+  pkg_fontdir=`rpm -ql $rpmnames | sed -n 's@^\(.*/\).*\.ttf$@\1@p' | head -1`
   pkg_addir=`rpm   -ql $rpmnames | sed -n 's@^\(.*/\)XScreenSaver$@\1@p'`
 
   if test -z "$pkg_bindir" ; then pkg_bindir="$pkg_bindir2" ; fi
@@ -4804,7 +4888,7 @@ if test \! -z "$deb_vers" ; then
   pkg_bindir2=`dpkg -L $debnames 2>&- | sed -n 's@^\(.*/\)xscreensaver-demo$@\1@p'`
   pkg_hackdir=`dpkg -L $debnames 2>&- | sed -n 's@^\(.*/\)popsquares$@\1@p'`
   pkg_confdir=`dpkg -L $debnames 2>&- | sed -n 's@^\(.*/\)popsquares\.xml$@\1@p'`
-  pkg_fontdir=`dpkg -L $debnames 2>&- | sed -n 's@^\(.*/\)\.ttf$@\1@p'`
+  pkg_fontdir=`dpkg -L $debnames 2>&- | sed -n 's@^\(.*/\).*\.ttf$@\1@p' | head -1`
   pkg_addir=`dpkg   -L $debnames 2>&- | sed -n 's@^\(.*/\)XScreenSaver[^/]*$@\1@p'`
   changequote([,])
 
index bfc6414223dbafd47cbe8b9ecc2b4e04c6899ba0..764ae34f92dcee8d4d128a07b014fb87fec57b61 100644 (file)
@@ -4,8 +4,8 @@
 !            a screen saver and locker for the X window system
 !                            by Jamie Zawinski
 !
-!                              version 6.00
-!                              01-Apr-2021
+!                              version 6.01
+!                              09-Jun-2021
 !
 ! See "man xscreensaver" for more info.  The latest version is always
 ! available at https://www.jwz.org/xscreensaver/
index e8b6addc031b220491f8e7a25e7664e4e683f8b1..d8847e9095448237655e65e91f65f4299dcb587b 100644 (file)
@@ -28,6 +28,7 @@ Atom XA_SCREENSAVER, XA_SCREENSAVER_VERSION, XA_SCREENSAVER_RESPONSE,
      XA_DEACTIVATE, XA_CYCLE, XA_RESTART, XA_PREFS,
      XA_NET_WM_PID, XA_NET_WM_STATE, XA_NET_WM_STATE_ABOVE,
      XA_NET_WM_STATE_FULLSCREEN, XA_NET_WM_BYPASS_COMPOSITOR,
+     XA_NET_WM_STATE_STAYS_ON_TOP, XA_KDE_NET_WM_WINDOW_TYPE_OVERRIDE,
      XA_NET_WM_WINDOW_TYPE, XA_NET_WM_WINDOW_TYPE_SPLASH,
      XA_NET_WM_WINDOW_TYPE_DIALOG, XA_NET_WM_WINDOW_TYPE_NOTIFICATION,
      XA_NET_WM_WINDOW_TYPE_NORMAL;
@@ -66,5 +67,8 @@ init_xscreensaver_atoms (Display *dpy)
   XA_NET_WM_WINDOW_TYPE_DIALOG       = A("_NET_WM_WINDOW_TYPE_DIALOG");
   XA_NET_WM_WINDOW_TYPE_NOTIFICATION = A("_NET_WM_WINDOW_TYPE_NOTIFICATION");
   XA_NET_WM_WINDOW_TYPE_NORMAL       = A("_NET_WM_WINDOW_TYPE_NORMAL");
+  XA_NET_WM_STATE_STAYS_ON_TOP       = A("_NET_WM_STATE_STAYS_ON_TOP");
+  XA_KDE_NET_WM_WINDOW_TYPE_OVERRIDE = A("_KDE_NET_WM_WINDOW_TYPE_OVERRIDE");
+
 # undef A
 }
index b5a7b7c38b547f8a48af9d2a1d38d4c49950bfcd..9dcacce981a263ba9ecd829cc835813fa3b589e8 100644 (file)
@@ -18,6 +18,7 @@ extern Atom XA_SCREENSAVER, XA_SCREENSAVER_VERSION, XA_SCREENSAVER_RESPONSE,
      XA_DEACTIVATE, XA_CYCLE, XA_RESTART, XA_PREFS,
      XA_NET_WM_PID, XA_NET_WM_STATE, XA_NET_WM_STATE_ABOVE,
      XA_NET_WM_STATE_FULLSCREEN, XA_NET_WM_BYPASS_COMPOSITOR,
+     XA_NET_WM_STATE_STAYS_ON_TOP, XA_KDE_NET_WM_WINDOW_TYPE_OVERRIDE,
      XA_NET_WM_WINDOW_TYPE, XA_NET_WM_WINDOW_TYPE_SPLASH,
      XA_NET_WM_WINDOW_TYPE_DIALOG, XA_NET_WM_WINDOW_TYPE_NOTIFICATION,
      XA_NET_WM_WINDOW_TYPE_NORMAL;
index 887dc2c387c99baae1fbf579fad420d75a5906e3..1ddf47adf9afaafe758b6a7fd690496f833c61db 100644 (file)
@@ -43,6 +43,7 @@ xscreensaver_set_wm_atoms (Display *dpy, Window window, int width, int height,
 # endif
   Atom va[10];
   long vl[10];
+  int i;
   class_hints.res_name  = "xscreensaver";  /* not progname */
   class_hints.res_class = "XScreenSaver";
   size_hints.flags      = PMinSize | PMaxSize;
@@ -73,22 +74,27 @@ xscreensaver_set_wm_atoms (Display *dpy, Window window, int width, int height,
      grubby paws off of our windows.
    */
 
-  vl[0] = 1;  /* _NET_WM_BYPASS_COMPOSITOR = 1 */
+  i = 0;
+  vl[i++] = 1;  /* _NET_WM_BYPASS_COMPOSITOR = 1 */
   XChangeProperty (dpy, window, XA_NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,
-                   PropModeReplace, (unsigned char *) vl, 1);
+                   PropModeReplace, (unsigned char *) vl, i);
 
   /* _NET_WM_STATE = [ _NET_WM_STATE_ABOVE, _NET_WM_STATE_FULLSCREEN ] */
-  va[0] = XA_NET_WM_STATE_ABOVE;
-  va[1] = XA_NET_WM_STATE_FULLSCREEN;
+  i = 0;
+  va[i++] = XA_NET_WM_STATE_ABOVE;
+  va[i++] = XA_NET_WM_STATE_FULLSCREEN;
+  va[i++] = XA_NET_WM_STATE_STAYS_ON_TOP;  /* Does this do anything? */
   XChangeProperty (dpy, window, XA_NET_WM_STATE, XA_ATOM, 32,
-                   PropModeReplace, (unsigned char *) va, 2);
+                   PropModeReplace, (unsigned char *) va, i);
 
   /* As there is no _NET_WM_WINDOW_TYPE_SCREENSAVER, which property is
      most likely to effectively communicate "on top always" to the WM?
      _NET_WM_WINDOW_TYPE = NORMAL, SPLASH, DIALOG or NOTIFICATION? */
-  va[0] = XA_NET_WM_WINDOW_TYPE_NOTIFICATION;
+  i = 0;
+  va[i++] = XA_NET_WM_WINDOW_TYPE_NOTIFICATION;
+  va[i++] = XA_KDE_NET_WM_WINDOW_TYPE_OVERRIDE;  /* Does this do anything? */
   XChangeProperty (dpy, window, XA_NET_WM_WINDOW_TYPE, XA_ATOM, 32,
-                   PropModeReplace, (unsigned char *) va, 1);
+                   PropModeReplace, (unsigned char *) va, i);
 
   if (for_window)  /* This is the error dialog for a saver window */
     {
index b5e82e26af7a55766a8cd3d488e5a9cc38de1146..b94a8ce7b0c48567e49fc6e803ac3643ea570dfe 100644 (file)
@@ -4407,7 +4407,7 @@ mapper (XrmDatabase *db, XrmBindingList bindings, XrmQuarkList quarks,
 
 
 static Window
-gnome_screensaver_window (Screen *screen)
+gnome_screensaver_window (Screen *screen, char **name_ret)
 {
   Display *dpy = DisplayOfScreen (screen);
   Window root = RootWindowOfScreen (screen);
@@ -4418,6 +4418,8 @@ gnome_screensaver_window (Screen *screen)
 
   if (! XQueryTree (dpy, root, &root, &parent, &kids, &nkids))
     abort ();
+  if (name_ret)
+    *name_ret = 0;
   for (i = 0; i < nkids; i++)
     {
       Atom type;
@@ -4434,6 +4436,8 @@ gnome_screensaver_window (Screen *screen)
               !strcmp ((char *) name, "cinnamon-screensaver")))
        {
          gnome_window = kids[i];
+          if (name_ret)
+            *name_ret = strdup ((char *) name);
           break;
        }
     }
@@ -4443,10 +4447,10 @@ gnome_screensaver_window (Screen *screen)
 }
 
 static Bool
-gnome_screensaver_active_p (void)
+gnome_screensaver_active_p (char **name_ret)
 {
   Display *dpy = GDK_DISPLAY();
-  Window w = gnome_screensaver_window (DefaultScreenOfDisplay (dpy));
+  Window w = gnome_screensaver_window (DefaultScreenOfDisplay (dpy), name_ret);
   return (w ? True : False);
 }
 
@@ -4454,13 +4458,18 @@ static void
 kill_gnome_screensaver (void)
 {
   Display *dpy = GDK_DISPLAY();
-  Window w = gnome_screensaver_window (DefaultScreenOfDisplay (dpy));
+  Window w = gnome_screensaver_window (DefaultScreenOfDisplay (dpy), NULL);
   if (w) XKillClient (dpy, (XID) w);
 }
 
 static Bool
 kde_screensaver_active_p (void)
 {
+  /* Apparently this worked in KDE 3, but not 4 or 5.
+     Maybe parsing the output of this would work in KDE 5:
+     kreadconfig5 --file kscreenlockerrc --group Daemon --key Autolock
+     but there's probably no way to kill the KDE saver.
+     Fuck it. */
   FILE *p = popen ("dcop kdesktop KScreensaverIface isEnabled 2>/dev/null",
                    "r");
   char buf[255];
@@ -4491,6 +4500,7 @@ the_network_is_not_the_computer (state *s)
   char *rversion = 0, *ruser = 0, *rhost = 0;
   char *luser, *lhost;
   char *msg = 0;
+  char *oname = 0;
   struct passwd *p = getpwuid (getuid ());
   const char *d = DisplayString (dpy);
 
@@ -4608,14 +4618,18 @@ the_network_is_not_the_computer (state *s)
      running" dialog so that these are on top.  Good enough.
    */
 
-  if (gnome_screensaver_active_p ())
-    warning_dialog (s->toplevel_widget,
-                    _("Warning:\n\n"
-                      "The GNOME screensaver daemon appears to be running.\n"
-                      "It must be stopped for XScreenSaver to work properly.\n"
-                      "\n"
-                      "Stop the GNOME screen saver daemon now?\n"),
-                    D_GNOME, 1);
+  if (gnome_screensaver_active_p (&oname))
+    {
+      char msg [1024];
+      sprintf (msg,
+               _("Warning:\n\n"
+                 "The GNOME screen saver daemon (%s) appears to be running.\n"
+                 "It must be stopped for XScreenSaver to work properly.\n"
+                 "\n"
+                 "Stop the \"%s\" daemon now?\n"),
+               oname, oname);
+      warning_dialog (s->toplevel_widget, msg, D_GNOME, 1);
+    }
 
   if (kde_screensaver_active_p ())
     warning_dialog (s->toplevel_widget,
@@ -4625,6 +4639,19 @@ the_network_is_not_the_computer (state *s)
                       "\n"
                       "Stop the KDE screen saver daemon now?\n"),
                     D_KDE, 1);
+
+  if (getenv ("WAYLAND_DISPLAY") || getenv ("WAYLAND_SOCKET"))
+    warning_dialog (s->toplevel_widget,
+                    _("Warning:\n\n"
+                   "You are running Wayland rather than the X Window System.\n"
+                   "\n"
+                   "Under Wayland, idle-detection fails when non-X11 programs\n"
+                   "are selected, meaning the screen may blank prematurely.\n"
+                   "Also, locking is impossible.\n"
+                   "\n"
+                   "See the XScreenSaver manual for instructions on\n"
+                   "configuring your system to use X11 instead of Wayland.\n"),
+                    D_NONE, 1);
 }
 
 
index fce74c4d3d78e33bdf00265bd4c8af1018b449a6..e115cee087abe1a26645c39dc798102c090480fa 100644 (file)
@@ -180,6 +180,7 @@ struct window_state {
   int i_beam;
 
   double start_time, end_time;
+  int passwd_timeout;
 
   Bool show_stars_p; /* "I regret that I have but one asterisk for my country."
                         -- Nathan Hale, 1776. */
@@ -733,43 +734,44 @@ splash_pick_window_position (Display *dpy, Position *xP, Position *yP)
 static void unlock_cb (window_state *ws);
 
 
-/* This program only needs one option from the init file, so it
-   just reads the .ad file and the .xscreensaver file directly rather
-   than going through Xt and Xrm.
+/* This program only needs a few options from .xscreensaver.
+   Read that file directly and store those into the Xrm database.
  */
-static void init_line_handler (int lineno, 
+static void init_line_handler (int lineno,
                                const char *key, const char *val,
                                void *closure)
 {
   window_state *ws = (window_state *) closure;
-  if (val && *val && !strcmp (key, "dialogTheme"))
+  if (!val || !*val)
+    ;
+  else if (!strcmp (key, "dialogTheme") ||
+           !strcmp (key, "passwdTimeout"))
     {
-      if (ws->dialog_theme) free (ws->dialog_theme);
-      ws->dialog_theme = strdup (val);
+      XrmDatabase db = XtDatabase (ws->dpy);
+      char *key2 = (char *) malloc (strlen (progname) + strlen (val) + 10);
+      sprintf (key2, "%s.%s", progname, key);
+      XrmPutStringResource (&db, key2, val);
+      free (key2);
     }
+  /* We read additional resources, such as "PROGCLASS.THEME.Dialog.foreground",
+     but those are from the .ad file only, not from .xscreensaver, so they
+     don't need a clause here in the file parser.  They have already been
+     read into the DB by Xt's Xrm initialization. */
 }
 
+
 static void
 read_init_file_simple (window_state *ws)
 {
   const char *home = getenv("HOME");
-  const char *fn1 = AD_DIR "/XScreenSaver";
-  char *fn2;
+  char *fn;
   if (!home || !*home) return;
-  fn2 = (char *) malloc (strlen(home) + 40);
-  sprintf (fn2, "%s/.xscreensaver", home);
-
-  if (debug_p)
-    fprintf (stderr, "%s: reading %s\n", blurb(), fn1);
-  parse_init_file (fn1, init_line_handler, ws);
-
+  fn = (char *) malloc (strlen(home) + 40);
+  sprintf (fn, "%s/.xscreensaver", home);
   if (debug_p)
-    fprintf (stderr, "%s: reading %s\n", blurb(), fn2);
-  parse_init_file (fn2, init_line_handler, ws);
-
-  if (verbose_p)
-    fprintf (stderr, "%s: theme: %s\n", blurb(),
-             (ws->dialog_theme ? ws->dialog_theme : "none"));
+    fprintf (stderr, "%s: reading %s\n", blurb(), fn);
+  parse_init_file (fn, init_line_handler, ws);
+  free (fn);
 }
 
 
@@ -921,15 +923,9 @@ window_init (Widget root_widget, Bool splash_p)
   ws->dpy = dpy;
   ws->screen = screen;
   ws->app = XtWidgetToApplicationContext (root_widget);
-
-  /* Read default theme from resources before the init file. */
-  ws->dialog_theme =
-    get_string_resource (ws->dpy, "dialogTheme", "DialogTheme");
-  if (!ws->dialog_theme || !*ws->dialog_theme)
-    ws->dialog_theme = strdup ("default");
-
-  /* Read theme from init file before any other resources. */
-  read_init_file_simple (ws);
+  ws->cmap = XCreateColormap (dpy, RootWindowOfScreen (screen), /* Old skool */
+                              DefaultVisualOfScreen (screen),
+                              AllocNone);
 
   {
     struct passwd *p = getpwuid (getuid());
@@ -937,15 +933,25 @@ window_init (Widget root_widget, Bool splash_p)
     ws->user = p->pw_name;
   }
 
-  ws->cmap = XCreateColormap (dpy, RootWindowOfScreen (screen), /* Old skool */
-                              DefaultVisualOfScreen (screen),
-                              AllocNone);
+  /* Read resources and .xscreensaver file settings.
+   */
+  read_init_file_simple (ws);
+
+  ws->dialog_theme =  /* must be first */
+    get_string_resource (ws->dpy, "dialogTheme", "DialogTheme");
+  if (!ws->dialog_theme || !*ws->dialog_theme)
+    ws->dialog_theme = strdup ("default");
+  if (verbose_p)
+    fprintf (stderr, "%s: theme: %s\n", blurb(), ws->dialog_theme);
 
   ws->newlogin_cmd = get_str (ws, "newLoginCommand", "NewLoginCommand");
   ws->date_format = get_str (ws, "dateFormat", "DateFormat"); 
   ws->show_stars_p =
     get_boolean_resource (ws->dpy, "passwd.asterisks", "Passwd.Boolean");
 
+  ws->passwd_timeout = get_seconds_resource (ws->dpy, "passwdTimeout", "Time");
+  if (ws->passwd_timeout <= 5) ws->passwd_timeout = 5;
+
   /* Put the version number in the label. */
   {
     char *version = strdup (screensaver_id + 17);
@@ -1234,8 +1240,6 @@ window_draw (window_state *ws)
   char date_text[100];
   time_t now = time ((time_t *) 0);
   struct tm *tm = localtime (&now);
-  double ratio = 1 - ((double_time() - ws->start_time) /
-                      (ws->end_time - ws->start_time));
   dialog_line *lines =
     (dialog_line *) calloc (ws->nmsgs + 40, sizeof(*lines));
   Bool emitted_user_p = False;
@@ -1536,10 +1540,12 @@ window_draw (window_state *ws)
     {
       if (ws->auth_state != AUTH_NOTIFY)
         {
+          double remain = ws->end_time - double_time();
+          double ratio = remain / ws->passwd_timeout;
           int thermo_w = ws->thermo_width;
           int thermo_h = window_height - ext_border * 2;
           int thermo_h2 = thermo_h - ws->shadow_width * 2;
-          int thermo_h3 = thermo_h2 * (1.0 - ratio);
+          int thermo_h3 = thermo_h2 * (1.0 - (ratio > 1 ? 1 : ratio));
 
           XSetForeground (dpy, gc, ws->thermo_foreground);
           XFillRectangle (dpy, dbuf, gc,
@@ -1914,15 +1920,13 @@ handle_keypress (window_state *ws, XKeyEvent *event)
   /* Add 10% to the time remaining every time a key is pressed, but don't
      go past the max duration. */
   {
-    time_t now = time ((time_t *) 0);
-    int max = get_seconds_resource (ws->dpy, "passwdTimeout", "Time");
-    int remain = ws->end_time - now;
+    double now = double_time();
+    double remain = ws->end_time - now;
     remain *= 1.1;
-    if (remain > max) remain = max;
+    if (remain > ws->passwd_timeout) remain = ws->passwd_timeout;
     if (remain < 3) remain = 3;
     ws->end_time = now + remain;
   }
-    
 
   if (decoded_size == 1)               /* Handle single-char commands */
     {
@@ -2121,8 +2125,7 @@ gui_main_loop (window_state *ws, Bool splash_p, Bool notification_p)
     timeout = 5;
   else
     {
-      timeout = get_seconds_resource (ws->dpy, "passwdTimeout", "Time");
-      if (timeout <= 5) timeout = 5;
+      timeout = ws->passwd_timeout;
       cursor_timer (ws, 0);
     }
 
index 15721eae31e0ee5fc2b99bbefe0afddedb4868b3..18a59b626a2e984f84b22458cad8dcf41da94d3d 100644 (file)
 
 #include "xscreensaver.h"
 
+/* Disable the X11 built-in screen saver. This is not directly related
+   to DPMS, but it does need to be prevented from fighting with us.
+  */
+static void
+disable_builtin_saver (Display *dpy)
+{
+  int otimeout   = -1;
+  int ointerval  = -1;
+  int oblanking  = -1;
+  int oexposures = -1;
+  XGetScreenSaver (dpy, &otimeout, &ointerval, &oblanking, &oexposures);
+  if (otimeout == 0 && ointerval == 0 && oblanking == 0 && oexposures == 0)
+    {
+      if (verbose_p > 1)
+        fprintf (stderr, "%s: builtin saver already disabled\n", blurb());
+    }
+  else
+    {
+      if (verbose_p)
+        fprintf (stderr, "%s: disabling server's builtin saver\n", blurb());
+      XSetScreenSaver (dpy, 0, 0, 0, 0);
+      XForceScreenSaver (dpy, ScreenSaverReset);
+    }
+}
+
+
 #ifndef HAVE_DPMS_EXTENSION   /* almost the whole file */
 
 void
 sync_server_dpms_settings (Display *dpy, struct saver_preferences *p)
 {
+  disable_builtin_saver (dpy);
   if (p->verbose_p)
     fprintf (stderr, "%s: DPMS not supported at compile time\n", blurb());
 }
 
-Bool monitor_powered_on_p (Display *dpy) { return True; }
-void monitor_power_on (saver_info *si, Bool on_p) { return; }
+Bool monitor_powered_on_p (Display *dpy)
+{
+  if (verbose_p > 1)
+    fprintf (stderr,
+             "%s: DPMS disabled at compile time, assuming monitor on\n",
+             blurb());
+  return True;
+}
+
+void monitor_power_on (saver_info *si, Bool on_p)
+{
+  if (verbose_p > 1)
+    fprintf (stderr,
+             "%s: DPMS disabled at compile time, not turning monitor %s\n",
+             blurb(), (on ? "on" : "off"));
+  return;
+}
 
 #else /* HAVE_DPMS_EXTENSION -- whole file */
 
@@ -68,12 +110,13 @@ sync_server_dpms_settings (Display *dpy, struct saver_preferences *p)
   /* If the monitor is currently powered off, defer any changes until
      we are next called while it is powered on. */
   if (! monitor_powered_on_p (dpy))
-    return;
+    {
+      if (verbose_p > 1)
+        fprintf (stderr, "%s: DPMS: monitor off, skipping sync\n", blurb());
+      return;
+    }
 
-  /* Why did I do this?  It makes DPMS never happen.
-     XSetScreenSaver (dpy, 0, 0, 0, 0);
-     XForceScreenSaver (dpy, ScreenSaverReset);
-   */
+  disable_builtin_saver (dpy);
 
   if (dpms_quickoff_p && !off_secs)
     {
@@ -102,7 +145,7 @@ sync_server_dpms_settings (Display *dpy, struct saver_preferences *p)
 
   if (! DPMSQueryExtension (dpy, &event, &error))
     {
-      if (verbose_p && !warned_p)
+      if (verbose_p > 1 || (verbose_p && !warned_p))
         fprintf (stderr, "%s: XDPMS extension not supported\n", blurb());
       warned_p = True;
       return;
@@ -110,7 +153,7 @@ sync_server_dpms_settings (Display *dpy, struct saver_preferences *p)
 
   if (! DPMSCapable (dpy))
     {
-      if (verbose_p && !warned_p)
+      if (verbose_p > 1 || (verbose_p && !warned_p))
         fprintf (stderr, "%s: DPMS not supported\n", blurb());
       warned_p = True;
       return;
@@ -118,7 +161,7 @@ sync_server_dpms_settings (Display *dpy, struct saver_preferences *p)
 
   if (! DPMSInfo (dpy, &o_power, &o_enabled))
     {
-      if (verbose_p && !warned_p)
+      if (verbose_p > 1 || (verbose_p && !warned_p))
         fprintf (stderr, "%s: unable to get DPMS state\n", blurb());
       warned_p = True;
       return;
@@ -167,6 +210,9 @@ sync_server_dpms_settings (Display *dpy, struct saver_preferences *p)
         fprintf (stderr, "%s: set DPMS timeouts: %d %d %d\n", blurb(),
                  standby_secs, suspend_secs, off_secs);
     }
+  else if (verbose_p > 1)
+    fprintf (stderr, "%s: DPMS timeouts already %d %d %d\n", blurb(),
+             o_standby, o_suspend, o_off);
 }
 
 Bool
@@ -178,19 +224,34 @@ monitor_powered_on_p (Display *dpy)
   CARD16 state;
 
   if (!DPMSQueryExtension(dpy, &event_number, &error_number))
-    /* Server doesn't know -- assume the monitor is on. */
-    result = True;
+    {
+      /* Server doesn't know -- assume the monitor is on. */
+      if (verbose_p > 1)
+        fprintf (stderr, "%s: DPMSQueryExtension failed, assuming monitor on\n",
+                 blurb());
+      result = True;
+    }
 
   else if (!DPMSCapable(dpy))
-    /* Server says the monitor doesn't do power management -- so it's on. */
-    result = True;
+    {
+      /* Server says the monitor doesn't do power management -- so it's on. */
+      if (verbose_p > 1)
+        fprintf (stderr, "%s: DPMSCapable false; assuming monitor on\n",
+                 blurb());
+      result = True;
+    }
 
   else
     {
       DPMSInfo(dpy, &state, &onoff);
       if (!onoff)
-       /* Server says DPMS is disabled -- so the monitor is on. */
-       result = True;
+        {
+          /* Server says DPMS is disabled -- so the monitor is on. */
+          if (verbose_p > 1)
+            fprintf (stderr, "%s: DPMSInfo disabled; assuming monitor on\n",
+                     blurb());
+          result = True;
+        }
       else
        switch (state) {
        case DPMSModeOn:      result = True;  break;  /* really on */
@@ -199,6 +260,13 @@ monitor_powered_on_p (Display *dpy)
        case DPMSModeOff:     result = False; break;  /* really off */
        default:              result = True;  break;  /* protocol error? */
        }
+      if (verbose_p > 1)
+        fprintf (stderr, "%s: DPMSInfo = %s %s\n", blurb(),
+                 (state == DPMSModeOn      ? "DPMSModeOn" :
+                  state == DPMSModeStandby ? "DPMSModeStandby" :
+                  state == DPMSModeSuspend ? "DPMSModeSuspend" :
+                  state == DPMSModeOff     ? "DPMSModeOff" : "???"),
+                 (result ? "True" : "False"));
     }
 
   return result;
@@ -207,6 +275,7 @@ monitor_powered_on_p (Display *dpy)
 void
 monitor_power_on (saver_info *si, Bool on_p)
 {
+  Bool verbose_p = si->prefs.verbose_p;
   if ((!!on_p) != monitor_powered_on_p (si->dpy))
     {
       XErrorHandler old_handler;
@@ -215,7 +284,7 @@ monitor_power_on (saver_info *si, Bool on_p)
       if (!DPMSQueryExtension(si->dpy, &event_number, &error_number) ||
           !DPMSCapable(si->dpy))
         {
-          if (si->prefs.verbose_p && !warned_p)
+          if (verbose_p > 1 || (verbose_p && !warned_p))
             fprintf (stderr,
                      "%s: unable to power %s monitor: no DPMS extension\n",
                      blurb(), (on_p ? "on" : "off"));
@@ -243,12 +312,18 @@ monitor_power_on (saver_info *si, Bool on_p)
       XSetErrorHandler (old_handler);
       /* Ignore error_handler_hit_p, just probe monitor instead */
 
+      if (verbose_p > 1 && error_handler_hit_p)
+        fprintf (stderr, "%s: DPMSForceLevel got an X11 error\n", blurb());
+
       if ((!!on_p) != monitor_powered_on_p (si->dpy))  /* double-check */
        fprintf (stderr,
        "%s: DPMSForceLevel(dpy, %s) did not change monitor power state\n",
                 blurb(),
                  (on_p ? "DPMSModeOn" : "DPMSModeOff"));
     }
+  else if (verbose_p > 1)
+    fprintf (stderr, "%s: monitor is already %s\n", blurb(),
+             on_p ? "on" : "off");
 }
 
 #endif /* HAVE_DPMS_EXTENSION -- whole file */
index 641325d3011b5fa43b746e1019af2a0c08b95abe..ffc2d1a119498f7bb812a776f17950070a756894 100644 (file)
@@ -190,8 +190,13 @@ print_available_extensions (saver_info *si)
 
 # ifdef HAVE_LIBSYSTEMD
   fprintf (stderr, "%s:   libsystemd\n", blurb());
-# else
-  fprintf (stderr, "%s:   libsystemd (disabled at compile time)\n", blurb());
+# endif
+# ifdef HAVE_LIBELOGIND
+  fprintf (stderr, "%s:   libelogind\n", blurb());
+# endif
+# if !defined(HAVE_LIBSYSTEMD) && !defined(HAVE_LIBELOGIND)
+  fprintf (stderr, "%s:   libsystemd/libelogind (disabled at compile time)\n",
+           blurb());
 # endif
 
   for (i = 0; i < si->nscreens; i++)
index 94515827ab789cbbb27633cb36de89bd29fe549d..4a2d3bc66d09a9a05edf800f736ab75c41500ac0 100644 (file)
@@ -294,6 +294,46 @@ ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error)
 }
 
 
+/* Like XDestroyWindow, but destroys the window later, on a timer.  This is
+   necessary to work around a KDE 5 compositor bug.  Without this, destroying
+   an old window causes the desktop to briefly become visible, even though a
+   new window has already been mapped that is obscuring both of them!
+ */
+typedef struct {
+  XtAppContext app;
+  Display *dpy;
+  Window window;
+} defer_destroy_closure;
+
+static void
+defer_destroy_handler (XtPointer closure, XtIntervalId *id)
+{
+  defer_destroy_closure *c = (defer_destroy_closure *) closure;
+  XErrorHandler old_handler;
+  XSync (c->dpy, False);
+  error_handler_hit_p = False;
+  old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
+  XDestroyWindow (c->dpy, c->window);
+  XSync (c->dpy, False);
+  XSetErrorHandler (old_handler);
+  if (verbose_p > 1 && !error_handler_hit_p)
+    fprintf (stderr, "%s: destroyed old window 0x%lx\n",
+             blurb(), (unsigned long) c->window);
+  free (c);
+}
+
+/* Used here and in windows.c */
+void
+defer_XDestroyWindow (XtAppContext app, Display *dpy, Window w)
+{
+  defer_destroy_closure *c = (defer_destroy_closure *) malloc (sizeof (*c));
+  c->app = app;
+  c->dpy = dpy;
+  c->window = w;
+  XtAppAddTimeOut (app, 5 * 1000, defer_destroy_handler, (XtPointer) c);
+}
+
+
 /* Returns true if canceled by user activity. */
 Bool
 fade_screens (XtAppContext app, Display *dpy,
@@ -1659,8 +1699,10 @@ xshm_fade (XtAppContext app, Display *dpy,
        {
           XClearWindow (dpy, saver_windows[screen]);
          XMapRaised (dpy, saver_windows[screen]);
-          if (info[screen].window)
-            XUnmapWindow (dpy, info[screen].window);
+          /* Doing this here triggers the same KDE 5 compositor bug that
+             defer_XDestroyWindow is to work around. */
+          /* if (info[screen].window)
+            XUnmapWindow (dpy, info[screen].window); */
        }
     }
 
@@ -1688,7 +1730,7 @@ xshm_fade (XtAppContext app, Display *dpy,
           if (info[screen].intermediate)
             destroy_xshm_image (dpy, info[screen].intermediate, &shm_info);
           if (info[screen].window)
-            XDestroyWindow (dpy, info[screen].window);
+            defer_XDestroyWindow (app, dpy, info[screen].window);
           if (info[screen].gc)
             XFreeGC (dpy, info[screen].gc);
         }
index 56725b59a7ac72fe287322d9059d349570309a3c..6c62d33e6892f7a959717667f0f66d62c6b4f819 100644 (file)
@@ -17,4 +17,12 @@ extern Bool fade_screens (XtAppContext app, Display *dpy,
                           Window *black_windows, int nwindows,
                          double seconds, Bool out_p, Bool from_desktop_p,
                           void **closureP);
+
+/* Like XDestroyWindow, but destroys the window later, on a timer.  This is
+   necessary to work around a KDE 5 compositor bug.  Without this, destroying
+   an old window causes the desktop to briefly become visible, even though a
+   new window has already been mapped that is obscuring both of them!
+ */
+extern void defer_XDestroyWindow (XtAppContext, Display *, Window);
+
 #endif /* __FADE_H__ */
index dc87e51ce658a65be40230fd8680cbe7cae454bb..1e90b97e4ed524c31e82d73a47f696a25e912c4a 100644 (file)
@@ -27,7 +27,7 @@
  *      another.  The mouse can be moved from one screen to another, though.
  *      Screens may be different depths (e.g., one can be TrueColor and one
  *      can be PseudoColor.)  Screens cannot be resized or moved without
- *      restarting X.
+ *      restarting X.  Sometimes this mode is referred to as "ZaphodHeads".
  *
  *      Everyone hates this way of doing things because of the inability to
  *      move a window from one screen to another without restarting the
@@ -43,7 +43,7 @@
  *      middle of the screen actually spanning the gap between two
  *      monitors.)
  *
- *      Xinerama didn't? work with DRI, which means that Xinerama precluded
+ *      Xinerama didn't work with DRI, which means that Xinerama precluded
  *      hardware acceleration in OpenGL programs.  Also, screens couldn't
  *      be resized or moved without restarting X.
  *
  *
  *      No longer supported as of XScreenSaver 6.
  *
- *      With this extension, the root window can be bigger than the
- *      monitor.  Moving the mouse near the edges of the screen scrolls
- *      around, like a pan-and-scan movie.  There was also a hot-key for
- *      changing the monitor's resolution (zooming in/out).
+ *      With this extension, the root window could be bigger than the
+ *      monitor.  Moving the mouse near the edges of the screen would
+ *      scroll around, like a pan-and-scan movie.  There was also a
+ *      hot-key for changing the monitor's resolution (zooming in/out).
  *
- *      Trying to combine this with Xinerama crashes the server, so you
- *      could only use this if you had only a single screen, or were in old
- *      multi-screen mode.
+ *      Trying to combine this with Xinerama crashed the server, so you
+ *      could ONLY use this if you had only a single screen, or were in
+ *      old multi-screen mode.
  *
  *      Also, half the time it didn't work at all: it tended to lie about
  *      the size of the rectangle in use.
index e3a64874ffa5beeda12955205f7cdc4180449106..eea707cf519f46acec65621d6fa9ee4a86e7a492 100644 (file)
@@ -73,8 +73,8 @@ main (int argc, char **argv)
   int xi_opcode;
   Bool grab_kbd_p   = False;
   Bool grab_mouse_p = False;
-  Bool mouse_sync_p = True;
-  Bool kbd_sync_p   = True;
+  Bool mouse_sync_p = False;
+  Bool kbd_sync_p   = False;
   int i;
 
   progname = argv[0];
index c9cdf9d2bfda4954195ba14bb3367e0e57cc77e1..0152c96d577cc54bbe8d8590af27c01810852d91 100644 (file)
@@ -218,7 +218,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 +260,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)
@@ -687,7 +687,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",
@@ -814,7 +814,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 +884,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;
index 3b21db02134f930593d1fd01af2f97bd64e2beef..c9e8b91e9d8936ec4a2dfb346c11336955127b07 100644 (file)
@@ -117,11 +117,62 @@ init_xinput (Display *dpy, int *opcode_ret)
 }
 
 
+/* If there is more than one Screen on the Display, XInput2 sends a duplicate
+   event for each Screen.  You'd think that they would have the 'root' member
+   set to the root window of that screen, so that we could ignore events not
+   destined for our screen, but no, they all have the same root window.  But
+   they also have the same 'serial' and 'time', so (in theory) we can ignore
+   the duplicates by noticing recently-duplicated event serial numbers, which
+   ought never happen.  BUT...!
+ */
+static Bool
+duplicate_xinput_event_p (int evtype, XIDeviceEvent *in)
+{
+  static unsigned long dups[50] = { 0, };
+  int i;
+
+  /* Great news, everybody: XEvent.xany.serial is apparently not unique.  Wny?
+     Because fuck you that's why.  XtAppNextEvent is returning a RawKeyRelease
+     followed by a RawKeyPress with the same serial.  It doesn't happen every
+     time, but seems to happen most often if a second key goes down before the
+     first key is released, e.g., which often happens when typing fast.
+
+     I have not seen it duplicating serials between two different KeyPress
+     events, but I have seen it being duplicated between a KeyPress and a
+     non-corresponding KeyRelease event; and between two different KeyRelease
+     events.  It does this even when there is only one Screen.
+
+     So we must compare both 'serial' and 'type' when looking for duplicates.
+     This should be ok if it really does not duplicate serials between
+     unrelated KeyPress events.  And we ignore KeyRelease events, so what
+     happens with those doesn't matter.
+
+     Between this shit and the random noise that shows up in XIDeviceEvent,
+     I'm starting to suspect that maybe, just maybe, the XInput2 library is
+     extremely careless about memory management!
+   */
+  unsigned long key = (in->serial & 0xFFFF) | (evtype << 16);
+
+  for (i = 0; i < countof(dups); i++)
+    if (dups[i] == key)
+      {
+        if (debug_p)
+          fprintf (stderr, "%s: discard duplicate XInput event %08lx\n",
+                   blurb(), key);
+        return True;
+      }
+  for (i = 0; i < countof(dups)-1; i++)
+    dups[i] = dups[i+1];
+  dups[i] = key;
+  return False;
+}
+
+
 /* Convert an XInput2 event to corresponding old-school Xlib event.
    Returns true on success.
  */
-Bool
-xinput_event_to_xlib (int evtype, XIDeviceEvent *in, XEvent *out)
+static Bool
+xinput_event_to_xlib_1 (int evtype, XIDeviceEvent *in, XEvent *out)
 {
   Display *dpy = in->display;
   Bool ok = False;
@@ -228,6 +279,16 @@ xinput_event_to_xlib (int evtype, XIDeviceEvent *in, XEvent *out)
   return ok;
 }
 
+Bool
+xinput_event_to_xlib (int evtype, XIDeviceEvent *in, XEvent *out)
+{
+  Bool ok = xinput_event_to_xlib_1 (evtype, in, out);
+  if (ok && duplicate_xinput_event_p (evtype, in))
+    ok = False;
+  return ok;
+}
+
+
 
 static void
 print_kbd_event (XEvent *xev, XComposeStatus *compose, Bool x11_p)
@@ -321,9 +382,9 @@ print_xinput_event (Display *dpy, XEvent *xev, const char *desc)
       {
         /* Fake up an XKeyEvent in order to call XKeysymToString(). */
         XEvent ev2;
-        Bool ok = xinput_event_to_xlib (xev->xcookie.evtype,
-                                        (XIDeviceEvent *) re,
-                                        &ev2);
+        Bool ok = xinput_event_to_xlib_1 (re->evtype,
+                                          (XIDeviceEvent *) re,
+                                          &ev2);
         if (!ok)
           fprintf (stderr, "%s: unable to translate XInput2 event\n", blurb());
         else
index 6b9657d6dbfbd71afafc2dd8058f590bd5f18dc1..df2798d803bb5950435e76ff4ea101e967ea7659 100644 (file)
@@ -315,16 +315,13 @@ the screen will be powered off when black.
 .B Blanking
 
 These options control how the screen fades to or from black when
-a screen saver begins or ends.  Note: fading doesn't work with all
-video drivers.
-In particular, it does not work on the 2020-vintage Raspberry Pi.
+a screen saver begins or ends.
 .RS 4
 
 .TP 4
 .B Fade To Black When Blanking
 If selected, then when the screensaver activates, the current contents
-of the screen will fade to black instead of simply winking out.  A fade
-will also be done when switching from one display mode to another.
+of the screen will fade to black instead of simply winking out.
 
 .TP 4
 .B Unfade From Black When Unblanking
index d06174a1e48c02c33ad69dc4bac86c0eefd5e4b6..2a5a11ffad2963a05ad89ab821ad513b7da0c98f 100644 (file)
  *    I'm told that the proprietary Zoom executable for Linux sends "inhibit"
  *    to "org.freedesktop.ScreenSaver", but I don't have any further details.
  *
+ *
+ *****************************************************************************
+ *
+ * Steam:
+ *
+ *     Inhibits as "My SDL application" (ooh, "Baby's First Hello World",
+ *     nice!  You get a gold star sticker) and then 30 seconds later,
+ *     uninhibits and immediately re-inhibits, forever.  This works, but
+ *     is dumb.
+ *
  *****************************************************************************
  *
+ *
  * TO DO:
  *
  *   - What precisely does the standalone Zoom executable do on Linux?
 #include <signal.h>
 #include <X11/Xlib.h>
 
-#include <systemd/sd-bus.h>
+#if defined (HAVE_LIBSYSTEMD)
+# include <systemd/sd-bus.h>
+#elif defined (HAVE_LIBELOGIND)
+# include <elogind/sd-bus.h>
+#else
+# error Neither HAVE_LIBSYSTEMD nor HAVE_LIBELOGIND is defined.
+#endif
 
 #include "version.h"
 #include "blurb.h"
@@ -797,7 +814,7 @@ xscreensaver_systemd_loop (void)
    */
   while (1) {
     struct pollfd fds[3];
-    uint64_t poll_timeout, system_timeout, user_timeout;
+    uint64_t poll_timeout_msec, system_timeout_usec, user_timeout_usec;
     struct inhibit_entry *entry;
 
     /* We MUST call sd_bus_process() on each bus at least once before calling
@@ -821,32 +838,6 @@ xscreensaver_systemd_loop (void)
       }
     } while (rc > 0);
 
-    fds[0].fd = sd_bus_get_fd (system_bus);
-    fds[0].events = sd_bus_get_events (system_bus);
-    fds[0].revents = 0;
-
-    fds[1].fd = sd_bus_get_fd (user_bus);
-    fds[1].events = sd_bus_get_events (user_bus);
-    fds[1].revents = 0;
-
-    fds[2].fd = XConnectionNumber (dpy);
-    fds[2].events = POLLIN;
-    fds[2].revents = 0;
-
-
-    sd_bus_get_timeout (system_bus, &system_timeout);
-    sd_bus_get_timeout (user_bus, &user_timeout);
-
-    if (system_timeout == 0 && user_timeout == 0)
-      poll_timeout = 0;
-    else if (system_timeout == UINT64_MAX && user_timeout == UINT64_MAX)
-      poll_timeout = -1;
-    else {
-      poll_timeout = (system_timeout < user_timeout
-                      ? system_timeout : user_timeout);
-      poll_timeout /= 1000000;
-    }
-
     /* Prune any entries whose original sender has gone away: this happens
        if a program inhibits, then exits without having called uninhibit.
        That would have left us inhibited forever, even if the inhibiting
@@ -873,24 +864,8 @@ xscreensaver_systemd_loop (void)
       }
     }
 
-
-    /* We want to wake up at least once every N seconds to de-activate
-       the screensaver if we have been inhibited.
-     */
-    if (poll_timeout > HEARTBEAT_INTERVAL * 1000)
-      poll_timeout = HEARTBEAT_INTERVAL * 1000;
-
-    rc = poll (fds, 3, poll_timeout);
-    if (rc < 0) {
-      fprintf (stderr, "%s: poll failed: %s\n", blurb(), strerror(-rc));
-      exit (EXIT_FAILURE);
-    }
-
-    if (fds[2].revents & (POLLERR | POLLHUP | POLLNVAL)) {
-      fprintf (stderr, "%s: X connection closed\n", blurb());
-      goto FAIL;
-    }
-
+    /* If we are inhibited and HEARTBEAT_INTERVAL has passed, de-activate the
+       screensaver. */
     if (ctx->is_inhibited) {
       time_t now = time ((time_t *) 0);
       if (now - last_deactivate_time >= HEARTBEAT_INTERVAL) {
@@ -906,11 +881,99 @@ xscreensaver_systemd_loop (void)
         last_deactivate_time = now;
       }
     }
-  }
 
- FAIL:
+    /* The remainder of the code that follows is concerned solely with
+       determining how long we should wait until the next iteration of the
+       event loop.
+    */
+    rc = sd_bus_get_fd (system_bus);
+    if (rc < 0) {
+      fprintf (stderr, "%s: sd_bus_get_fd failed for system bus: %s\n",
+               blurb(), strerror(-rc));
+      goto FAIL;
+    }
+    fds[0].fd = rc;
+    rc = sd_bus_get_events (system_bus);
+    if (rc < 0) {
+      fprintf (stderr, "%s: sd_bus_get_events failed for system bus: %s\n",
+               blurb(), strerror(-rc));
+      goto FAIL;
+    }
+    fds[0].events = rc;
+    fds[0].revents = 0;
 
-  XCloseDisplay(dpy);
+    rc = sd_bus_get_fd (user_bus);
+    if (rc < 0) {
+      fprintf (stderr, "%s: sd_bus_get_fd failed for user bus: %s\n",
+               blurb(), strerror(-rc));
+      goto FAIL;
+    }
+    fds[1].fd = rc;
+    rc = sd_bus_get_events (user_bus);
+    if (rc < 0) {
+      fprintf (stderr, "%s: sd_bus_get_events failed for user bus: %s\n",
+               blurb(), strerror(-rc));
+      goto FAIL;
+    }
+    fds[1].events = rc;
+    fds[1].revents = 0;
+
+    /* Activity on the X server connection will wake us from the poll(). */
+    fds[2].fd = XConnectionNumber (dpy);
+    fds[2].events = POLLIN;
+    fds[2].revents = 0;
+
+    rc = sd_bus_get_timeout (system_bus, &system_timeout_usec);
+    if (rc < 0) {
+      fprintf (stderr, "%s: sd_bus_get_timeout failed for system bus: %s\n",
+               blurb(), strerror(-rc));
+      goto FAIL;
+    }
+    sd_bus_get_timeout (user_bus, &user_timeout_usec);
+    if (rc < 0) {
+      fprintf (stderr, "%s: sd_bus_get_timeout failed for user bus: %s\n",
+               blurb(), strerror(-rc));
+      goto FAIL;
+    }
+
+    /* Pick the smaller of the two bus timeouts and convert from microseconds
+       to milliseconds expected by poll(). */
+    poll_timeout_msec = ((system_timeout_usec < user_timeout_usec
+                          ? system_timeout_usec : user_timeout_usec)
+                         / 1000);
+
+    /* If we have been inhibited, we want to wake up at least once every N
+       seconds to de-activate the screensaver.
+     */
+    if (ctx->is_inhibited &&
+        poll_timeout_msec > HEARTBEAT_INTERVAL * 1000)
+      poll_timeout_msec = HEARTBEAT_INTERVAL * 1000;
+
+    if (poll_timeout_msec < 1000)
+      poll_timeout_msec = 1000;
+
+    rc = poll (fds, 3, poll_timeout_msec);
+    if (rc < 0) {
+      fprintf (stderr, "%s: poll failed: %s\n", blurb(), strerror(errno));
+      goto FAIL;
+    }
+
+    if (fds[2].revents & (POLLERR | POLLHUP | POLLNVAL)) {
+      fprintf (stderr, "%s: X connection closed\n", blurb());
+      dpy = 0;
+      goto FAIL;
+    } else if (fds[2].revents & POLLIN) {
+      /* Even though we have requested no events, there are some events that
+         the X server sends anyway, e.g. MappingNotify, and if we don't flush
+         the fd, it will constantly be ready for reading, and we busy-loop. */
+      char buf[1024];
+      while (read (fds[2].fd, buf, sizeof(buf)) > 0)
+        ;
+    }
+
+  } /* Event loop end */
+
+ FAIL:
 
   if (system_bus)
     sd_bus_flush_close_unref (system_bus);
@@ -923,6 +986,9 @@ xscreensaver_systemd_loop (void)
 
   sd_bus_error_free (&error);
 
+  if (dpy)
+    XCloseDisplay (dpy);
+
   return EXIT_FAILURE;
 }
 
index 5eb71674ce5d1f9963cf551238474b6c1851aee9..bfce5f731bcedfa180349b0cc70f5b2debed017d 100644 (file)
@@ -456,8 +456,10 @@ handle_sigchld (Display *dpy, Bool blanked_p)
                   int ac = 0;
                   av[ac++] = SAVER_GFX_PROGRAM;
                   av[ac++] = "--emergency";
-                  if (verbose_p) av[ac++] = "--verbose";
-                  if (debug_p)   av[ac++] = "--debug";
+                  if (verbose_p)     av[ac++] = "--verbose";
+                  if (verbose_p > 1) av[ac++] = "--verbose";
+                  if (verbose_p > 2) av[ac++] = "--verbose";
+                  if (debug_p)       av[ac++] = "--debug";
                   av[ac] = 0;
                   fprintf (stderr, "%s: pid %lu: " SAVER_GFX_PROGRAM
                            " exited unexpectedly %s: re-launching\n",
@@ -1304,6 +1306,8 @@ static void
 maybe_disable_locking (Display *dpy)
 {
   const char *why = 0;
+  Bool wayland_p = (getenv ("WAYLAND_DISPLAY") ||
+                    getenv ("WAYLAND_SOCKET"));
 
 # ifdef NO_LOCKING
   why = "locking disabled at compile time";
@@ -1322,7 +1326,7 @@ maybe_disable_locking (Display *dpy)
 
   /* X11 grabs don't work under Wayland's embedded X11 server.  The Wayland
      window manager lives at a higher level than the X11 emulation layer. */
-  if (!why && getenv ("WAYLAND_DISPLAY"))
+  if (!why && wayland_p)
     why = "cannot lock securely under Wayland";
 
   if (!why)
@@ -1344,6 +1348,25 @@ maybe_disable_locking (Display *dpy)
           fprintf (stderr, "%s: DEBUG MODE: allowing locking anyway!\n",
                    blurb());
         }
+      else if (wayland_p)
+        {
+          const char *s = blurb();
+          locking_disabled_p = True;
+
+          /* Maybe we should just refuse to launch instead?  We can operate
+             properly only if the user uses only X11 programs, and doesn't
+             want to lock the screen.
+           */
+          fprintf (stderr, "\n"
+              "%s: WARNING: Wayland is not supported.\n"
+              "\n"
+              "%s:     Under Wayland, idle-detection fails when non-X11\n"
+              "%s:     programs are selected, meaning the screen may\n"
+              "%s:     blank prematurely.  Also, locking is impossible.\n"
+              "%s:     See the manual for instructions on configuring\n"
+              "%s:     your system to use X11 instead of Wayland.\n\n",
+                   s, s, s, s, s, s);
+        }
       else
         {
           locking_disabled_p = True;
@@ -1377,6 +1400,14 @@ main_loop (Display *dpy)
   if (! init_xinput (dpy, &xi_opcode))
     saver_exit (1);
 
+  /* Disable server built-in screen saver. */
+  XSetScreenSaver (dpy, 0, 0, 0, 0);
+  XForceScreenSaver (dpy, ScreenSaverReset);
+
+  /* It would be nice to sync the server's DPMS settings here to what is
+     specified in the .xscreensaver file, but xscreensaver-gfx handles that,
+     so that won't happen until the first time the screen blanks. */
+
   create_daemon_window (dpy);
 
   handle_signals();
@@ -1402,7 +1433,7 @@ main_loop (Display *dpy)
     saver_auth_pid = fork_and_exec (dpy, ac, av);
   }
 
-# ifdef HAVE_LIBSYSTEMD
+# if defined(HAVE_LIBSYSTEMD) || defined(HAVE_LIBELOGIND) 
   /* Launch xscreensaver-systemd at startup. */
   {
     char *av[10];
@@ -1413,7 +1444,7 @@ main_loop (Display *dpy)
     av[ac] = 0;
     saver_systemd_pid = fork_and_exec (dpy, ac, av);
   }
-# endif /* HAVE_LIBSYSTEMD */
+# endif /* HAVE_LIBSYSTEMD || HAVE_LIBELOGIND */
 
 
   /* X11 errors during startup initialization were fatal.
@@ -1930,9 +1961,11 @@ main_loop (Display *dpy)
                 char *av[20];
                 int ac = 0;
                 av[ac++] = SAVER_GFX_PROGRAM;
-                if (first_time_p) av[ac++] = "--init";
-                if (verbose_p) av[ac++] = "--verbose";
-                if (debug_p)   av[ac++] = "--debug";
+                if (first_time_p)  av[ac++] = "--init";
+                if (verbose_p)     av[ac++] = "--verbose";
+                if (verbose_p > 1) av[ac++] = "--verbose";
+                if (verbose_p > 2) av[ac++] = "--verbose";
+                if (debug_p)       av[ac++] = "--debug";
 
                 if (blank_mode == XA_NEXT)
                   av[ac++] = "--next";
index 9c3bdd0d69bcf4649c9c20aa878b9d81c42c75e2..ff4a67b718b5ac2d9d7e0e9f0b7d254043b83880 100644 (file)
@@ -86,7 +86,7 @@ then closing the lid of your laptop will cause the screen to lock immediately.
 If not, then the screen might not lock until a few seconds \fIafter\fP you
 re-open the lid.  Which is less than ideal.  So if you don't 
 use \fIsystemd\fP, you might want to get in the habit of
-doing \fIxscreensaver-command --lock\fP before closing the lid.
+doing \fIxscreensaver-command \-\-lock\fP before closing the lid.
 
 .SH PLAYING VIDEOS
 Likewise, if you have
@@ -146,10 +146,7 @@ Be careful that it doesn't try to uninstall all of GNOME.
 
 Select "\fIStartup Applications\fP" from the menu (or manually
 launch "\fIgnome-session-properties\fP") and add "\fIxscreensaver\fP".
-
 Do this as your normal user account, not as root.
-(This should go without saying, because you should never, ever, ever
-be logged in to the graphical desktop as user "root".)
 .TP 3
 \fB3: Make GNOME's "Lock Screen" use XScreenSaver.\fP
 .nf
@@ -158,12 +155,6 @@ be logged in to the graphical desktop as user "root".)
             /usr/bin/gnome-screensaver-command
 .sp
 .fi
-That doesn't work under Unity, though.  Apparently it has its own
-built-in screen locker which is not gnome-screensaver, and cannot be
-removed, and yet still manages to be bug-addled and insecure. 
-Keep reinventing that wheel, guys!  (If you have figured out how to
-replace Unity's locking "feature" with XScreenSaver, let me know.)
-
 .TP 3
 \fB4: Turn off Unity's built-in blanking.\fP
 
@@ -173,6 +164,7 @@ Un-check "\fIStart Automatically\fP";
 .br
 Set \fI"Turn screen off when inactive for"\fP to \fI"Never".\fP
 .br
+
 Or possibly that has been randomly renamed again:
 .br
 Set "\fISettings / Power / Power Settings\fP" to \fI"Never".\fP
@@ -181,13 +173,15 @@ Set "\fISettings / Power / Power Settings\fP" to \fI"Never".\fP
 .nf
 .sp
        sudo systemctl \-\-user mask gsd\-screensaver\-proxy.service
+       sudo systemctl \-\-user mask \\
+         org.gnome.SettingsDaemon.ScreensaverProxy.service
 .sp
 .fi
 Without the above, video players will not be able to tell XScreenSaver
 not to blank the screen while videos are playing, and the screen will not
 auto-lock when you close your laptop's lid.
 
-After running that command, reboot.  Yes, you have to reboot; it won't let
+After running those commands, reboot.  Yes, you have to reboot; it won't let
 you simply stop the service.  Logging out won't do it either.
 
 .SS INSTALLING XSCREENSAVER ON KDE
@@ -217,7 +211,7 @@ If that doesn't work, then try this:
 Open "\fISystem Settings / Startup/Shutdown / Autostart\fP", and then
 add "\fI/usr/bin/xscreensaver\fP".
 
-If you are lucky, that will create a \fI"xscreensaver.desktop"\fP file 
+If you are lucky, that will create an \fI"xscreensaver.desktop"\fP file 
 for you in \fI~/.config/autostart/\fP or \fI~/.kde/Autostart/\fP.
 .TP 3
 \fB3: Make XScreenSaver be an Autostart program.\fP
@@ -250,16 +244,22 @@ of that file with these two lines:
 .sp
 .fi
 Make sure the file is executable (chmod a+x).
+
+This change will probably get blown away the next time your system
+upgrades KDE.
 .TP 3
 \fB5: Stop KDE from blocking XScreenSaver's "systemd" integration:\fP
 You must arrange for KDE's
 .BR ksmserver (1)
-daemon to be launched with the command line switch \fI\-\-no\-lockscreen\fP.
+daemon to be launched with the command line option \fI\-\-no\-lockscreen\fP.
 
-One way to accomplish that is to edit the
+Under KDE 5.00 through 5.16, you can accomplish that by editing the
 .BR startkde (1)
-script in \fI/usr/bin/\fP by hand, then log out and log back in.  Another
-way would be to wrap the \fIksmserver\fP program:
+script in \fI/usr/bin/\fP by hand, then logging out and back in again.
+
+Under KDE 5.17 through 5.20, you must wrap
+.BR ksmserver (1)
+instead:
 .nf
 .sp
        mv /usr/bin/ksmserver /usr/bin/ksmserver-orig
@@ -276,17 +276,27 @@ Either change will, of course, get blown away the next time your system
 upgrades KDE.
 
 Instead of being in \fI/usr/bin/\fP, the \fIksmserver\fP program might be
-in \fI/usr/lib/\fP or \fIusr/lib*/libexec/\fP or \fIusr/lib/*/libexec/\fP
+in \fI/usr/lib/\fP or \fI/usr/lib*/libexec/\fP or \fIusr/lib/*/libexec/\fP
 or somewhere else, depending on your distro.
 
-But without this, video players will not be able to tell XScreenSaver not to
-blank the screen while videos are playing, and the screen will not auto-lock
-when you close your laptop's lid.
-
-It seems that KDE 5.17 replaced \fIstartkde\fP with \fIstartplasma-x11\fP,
-and I don't know how to change how \fIthat\fP launches \fIksmserver\fP.
-Let me know if you figure it out.
-
+Under KDE 5.21+ this might work instead, and might persist through upgrades:
+.nf
+.sp
+       systemctl edit plasma-ksmserver.service
+.sp
+.fi
+and then put this in the file you get to edit:
+.nf
+.sp
+       [Service]
+       ExecStart=/usr/bin/ksmserver \-\-no\-lockscreen
+.sp
+.fi
+Regardless of which approach you need to use, if you do not force
+.BR ksmserver (1)
+to stop squatting on the DBus endpoint, video players will not be able to tell
+XScreenSaver not to blank the screen while videos are playing, and the screen
+will not auto-lock when you close your laptop's lid.
 .SS LAUNCHING XSCREENSAVER FROM SYSTEMD
 If the above didn't do it, and your system has
 .BR systemd (1),
@@ -343,7 +353,7 @@ On the \fIGeneral\fP page set the \fILocal Greeter\fP to
 \fIStandard Greeter\fP.
 
 On the \fIBackground\fP page, type the
-command \fB"xscreensaver \-\-nosplash"\fP into the \fIBackground Program\fP
+command \fI"xscreensaver \-\-nosplash"\fP into the \fIBackground Program\fP
 field.  That will cause gdm to run XScreenSaver while nobody is logged
 in, and kill it as soon as someone does log in.  (The user will then
 be responsible for starting XScreenSaver on their own, if they want.)
@@ -390,11 +400,58 @@ might have luck by adding \fIxscreensaver\-command \-\-suspend\fP to
 some appropriate spot in \fI/etc/acpi/events/anything\fP or in
 \fI/etc/acpi/handler.sh\fP, if those files exist.
 
+.SH THE WAYLAND PROBLEM
+Wayland is a completely different window system that is intended to replace
+X11.  After 13+ years of trying, some Linux distros have finally begun
+enabling it by default.  Most deployments of it also include XWayland, which
+is a compatibility layer that allows \fIsome\fP X11 programs to continue to
+work within a Wayland environment.
+
+Unfortunately, XScreenSaver is not one of those programs.
+
+If your system is running XWayland, XScreenSaver will malfunction in two
+ways:
+.RS 0
+.TP 3
+\fB1:\fP It will be unable to detect user activity in non-X11 programs.
+
+This means that while a native Wayland program is selected, XScreenSaver will
+think that you are idle, and may blank the screen prematurely.
+.TP 3
+\fB2:\fP It will be unable to lock the screen.
+
+This is because X11 grabs don't work properly under XWayland, so there is no
+way for XScreenSaver to prevent the user from switching away from the screen
+locker to another application.
+.RE
+
+In short, for XScreenSaver to work properly, you will need to switch off
+Wayland and use the X Window System like in the "good old days".
+.SS TO DISABLE WAYLAND UNDER GNOME
+The login screen should have a gear-icon menu that lets you change the session
+type from "GNOME" (the Wayland session) to "GNOME on Xorg" (the X11 session).
+
+Alternately, edit \fI/etc/gdm/custom.conf\fP and make sure it includes this
+line:
+.nf
+.sp
+       WaylandEnable=false
+.fi
+.SS TO DISABLE WAYLAND UNDER KDE
+The login screen should have a menu that lets you change the session type to
+"Plasma (X11)".
+
+Alternately, edit \fI/etc/sddm.conf\fP and change the \fISessionDir\fP line
+under the \fI[Wayland]\fP section to say:
+.nf
+.sp
+        SessionDir=/dev/null
+.fi
+
 .SH SECURITY CONCERNS
 XScreenSaver has a decades-long track record of securely locking your screen.
 However, there are many things that can go wrong.  X11 is a very old system,
 and has a number of design flaws that make it susceptible to foot-shooting.
-
 .SS MAGIC BACKDOOR KEYSTROKES
 The XFree86 and Xorg X servers, as well as the Linux kernel, both trap
 certain magic keystrokes before X11 client programs ever see them.
@@ -791,9 +848,9 @@ might set this in your \fI~/.xscreensaver\fP file:
 .sp
 .fi
 .RS 8
-Make sure your \fB$PATH\fP environment variable is set up correctly
-\fIbefore\fP XScreenSaver is launched, or it won't be able to find the
-programs listed in the \fIprograms\fP resource.
+The default XScreenSaver hacks directory (typically
+\fI/usr/libexec/xscreensaver/\fP) is prepended to \fB$PATH\fP
+before searching for these programs.
 
 To use a program as a screensaver, it must be able to render onto
 the window provided to it in the \fB$XSCREENSAVER_WINDOW\fP environment
@@ -921,6 +978,9 @@ If the mouse moves less than this-many pixels in a second, ignore it
 doesn't un-blank (or fail to blank) just because you bumped the desk.
 Default: 10 pixels.
 
+A single pixel of motion will still cause the monitor to power back on,
+but not un-blank. This is because the X11 server itself unfortunately handles
+power-management-related activity detection rather than XScreenSaver.
 .SH BUGS
 https://www.jwz.org/xscreensaver/bugs.html explains how to write the most
 useful bug reports.  If you find a bug, please let me know!
index ef6ee5cdbe17ea6f3fc1ee3254518cfebc276ada..d7cb4dd0f11d294c032165375b5760df90a4719b 100644 (file)
@@ -680,7 +680,8 @@ analogtv-cli.o: $(srcdir)/analogtv-cli.c
        $(CC) -o $@ -c $(ATVCLI_CFLAGS) $<
 
 ATVCLI = analogtv2.o $(UTILS_BIN)/yarandom.o \
-        $(UTILS_BIN)/aligned_malloc.o $(THRO) $(PNG) @ANIM_OBJS@
+        $(UTILS_BIN)/aligned_malloc.o $(THRO) $(PNG) \
+        $(UTILS_BIN)/font-retry.o @ANIM_OBJS@
 analogtv-cli:  analogtv-cli.o  $(ATVCLI)
        $(CC_HACK) -o $@ $@.o   $(ATVCLI) $(THRL) $(PNG_LIBS) -lpng
 clean::
index 2c4a880b35bf0b159dbdb7f9d7a1c3c3ecad86c6..975c79ad44cfeeac13ff4e7c87ad4bd9bce535f2 100644 (file)
@@ -1,4 +1,4 @@
-/* xanalogtv-cli, Copyright (c) 2018-2020 Jamie Zawinski <jwz@jwz.org>
+/* xanalogtv-cli, Copyright © 2018-2021 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
@@ -345,12 +345,6 @@ get_pixel_resource (Display *dpy, Colormap cmap, char *name, char *class)
   abort();
 }
 
-XFontStruct *
-load_font_retry (Display *dpy, const char *xlfd)
-{
-  abort();
-}
-
 Bool
 put_xshm_image (Display *dpy, Drawable d, GC gc, XImage *image,
                 int src_x, int src_y, int dest_x, int dest_y,
index b031323146fef4739f451ed52208d1802e10247d..43a64908437bfa42ebe85136cbb6ae4a6c77cbd8 100644 (file)
@@ -4,8 +4,8 @@
             a screen saver and locker for the X window system
                             by Jamie Zawinski
 
-                              version 6.00
-                               01-Apr-2021
+                              version 6.01
+                               09-Jun-2021
 
                      https://www.jwz.org/xscreensaver/
 
index 96f395b1b2bd16b00cd863f39538e9a7aef80f90..f5943f449f27bedfef45dc50d38788a5c4b761ee 100644 (file)
@@ -31,7 +31,7 @@
   <xscreensaver-updater />
 
   <_description>
-SARS-CoV-2. Stay the fuck home. Wear a fucking mask.
+SARS-CoV-2. Get vaccinated. Wear a mask.
 
 Written by Jamie Zawinski; 2020.
   </_description>
index 421fae7d89cb17d4870310dd7a3c35b8a96ef939..641f9653067a6ce0f91679e2a68e33536cd077d0 100755 (executable)
@@ -39,7 +39,7 @@ BEGIN { eval 'use Text::Wrap qw(wrap);' }
 
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.60 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.62 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 0;
 my $http_proxy = undef;
@@ -380,6 +380,8 @@ sub output() {
     # In a truly shocking turn of events, nearly every distro uses a different
     # file to identify itself.  Are you shocked?  I for one am shocked.
 
+    $ENV{LC_NUMERIC} = 'C';   # Decimals with periods, not commas, plz.
+
     if (open (my $in, "<:utf8", "/etc/os-release")) {
       while (<$in>) {                    # PRETTY_NAME="CentOS Linux 7 (Core)"
         if (m/^PRETTY_NAME="(.*)"/si) {   # PRETTY_NAME="Raspbian 10 (buster)"
@@ -991,7 +993,7 @@ sub main() {
     # amount of time (e.g., url-mode.)
     #
     my $secs = 10;
-    $secs = 1 if ($truncate_lines < 10);  # for 'gltext'
+    $secs = 1 if (($truncate_lines || 0) < 10);  # for 'gltext'
     sleep ($secs);
   }
 }
index c288450a02b01809714a8e42f962d42d107273ba..60aa6d28198cc4733123e764225f0aa0d2b05d6d 100644 (file)
@@ -1,4 +1,4 @@
-# Auto-generated: Thu Apr  1 03:16:58 PDT 2021
+# Auto-generated: Wed Jun  9 08:47:14 PDT 2021
 driver/demo-Gtk-conf.c
 driver/demo-Gtk.c
 driver/dialog.c
index 8e38585151479fa8847ccac0cbbe711dae3019df..579bcc6b15713436feabb8e505a8f30ee9094093 100644 (file)
@@ -1,4 +1,4 @@
 static const char screensaver_id[] =
-       "@(#)xscreensaver 6.00 (01-Apr-2021), by Jamie Zawinski (jwz@jwz.org)";
-#define XSCREENSAVER_VERSION "6.00"
-#define XSCREENSAVER_RELEASED 1617303600
+       "@(#)xscreensaver 6.01 (09-Jun-2021), by Jamie Zawinski (jwz@jwz.org)";
+#define XSCREENSAVER_VERSION "6.01"
+#define XSCREENSAVER_RELEASED 1623265200
index d9d239b048450daf0da830cfbf7d474d6f58dbb2..ac012f54785f0b67d75498197bfb99da5e05551e 100644 (file)
@@ -1,5 +1,5 @@
 %define        name xscreensaver
-%define        version 6.00
+%define        version 6.01
 
 Summary:       X screen saver and locker
 Name:          %{name}