-# Makefile.in --- xscreensaver, Copyright (c) 1999-2005 Jamie Zawinski.
+# Makefile.in --- xscreensaver, Copyright (c) 1999-2008 Jamie Zawinski.
# the `../configure' script generates `Makefile' from this file.
@SET_MAKE@
distdepend::
@$(MAKE) update_spec_version
@$(MAKE_SUBDIR2)
- @cd po ; $(MAKE) generate_potfiles_in
+ @cd po ; $(MAKE) update-po
TAGS:: tags
tags::
diff -U0 download.html $$TMP ; \
echo '' ; \
\
- OLDEST=`ls xscreensaver*.tar.gz | head -1` ; \
- /bin/echo -n "Delete $$DEST/$$OLDEST? "; \
- read line; \
- if [ "x$$line" = "xyes" -o "x$$line" = "xy" ]; then \
- set -x ; \
- rm $$OLDEST ; \
- cvs remove $$OLDEST ; \
- else \
- set -x ; \
- fi ; \
+ for EXT in tar.gz dmg ; do \
+ OLDEST=`ls xscreensaver*.$$EXT | head -n 1` ; \
+ /bin/echo -n "Delete $$DEST/$$OLDEST? "; \
+ read line; \
+ if [ "x$$line" = "xyes" -o "x$$line" = "xy" ]; then \
+ set -x ; \
+ rm $$OLDEST ; \
+ cvs remove $$OLDEST ; \
+ else \
+ set -x ; \
+ fi ; \
+ done ; \
cvs add -kb $$BNAME $$BNAME2 ; \
cat $$TMP > download.html ; \
rm -f $$TMP ; \
\
cvs commit -m "$$VERS"
-check_years::
- @for file in `find . -name '*.*' \
- \! -name '*~' \! -name '*.o' \! -name '*.gz' \! -name '*.Z' \
- \! -name '*.po' \! -name 'config.*' \! -name '*.glade*' \
- \! -name '*.m4' \! -name '*.pdb' \! -name '*.xpm' \
- \! -name '*.jpg' \! -name '*.gif' \! -name '*.eps' \
- \! -name '*.png' \! -name '*.tif' \! -name '*.bak' \
- | sort` \
- ; do \
- y=`date -r "$$file" '+%Y'` ; \
- if ! ( grep "\b$$y\b" $$file >/dev/null ); then \
- if ( grep "opyright\|(c)\|\.BR" $$file >/dev/null ); then \
- echo "$$file does not mention $$y" ; \
- fi ; \
- fi ; \
- done
count::
@ \
release:: sign
sign:
- codesign -vfs 'Jamie Zawinski' build/Release/*.saver
+ @for f in build/Release/*.saver ; do \
+ codesign -vfs 'Jamie Zawinski' $$f ; \
+ done
check_versions:
@\
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
- <string>5.05</string>
+ <string>5.06</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>5.05</string>
+ <string>5.06</string>
<key>LSMinimumSystemVersion</key>
<string>10.4.0</string>
<key>NSMainNibFile</key>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
- <string>5.05</string>
+ <string>5.06</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>5.05</string>
+ <string>5.06</string>
<key>LSMinimumSystemVersion</key>
<string>10.4.0</string>
<key>NSMainNibFile</key>
// And finally:
//
+ NSDisableScreenUpdates();
unsigned long delay = xsft->draw_cb (xdpy, xwindow, xdata);
-
XSync (xdpy, 0);
-
+ NSEnableScreenUpdates();
+
gettimeofday (&tv, 0);
now = tv.tv_sec + (tv.tv_usec / 1000000.0);
next_frame_time = now + (delay / 1000000.0);
\f1\b0 \
by Jamie Zawinski \uc0\u8232 and many others\
\
-version 5.05 \uc0\u8232 01-Mar-2008\
+version 5.06 \uc0\u8232 16-Jul-2008\
\
{\field{\*\fldinst{HYPERLINK "http://www.jwz.org/xscreensaver/"}}{\fldrslt \cf2 \ul \ulc2 http://www.jwz.org/xscreensaver/}}\
\pard\pardeftab720\li720
===============================================================================
+Changes since 5.05: * Xinerama/RANDR fixes: this time for sure. It should
+ now work to add/remove monitors or resize screens at
+ any time.
+ * New hack, `skytentacles'.
+ * New version of `gleidescope'.
+ * Added the `-log' option to the xscreensaver daemon,
+ since a truly shocking number of Linux users seem to
+ have no idea how to redirect output to a file.
+ * Added `-duration' arg to most image-loading hacks,
+ so that they pick a new image every few minutes.
+ * Added an ATM crash to BSOD.
Changes since 5.04: * New hacks, `cubicgrid', `hypnowheel', and
`lcdscrub' (which isn't really a screen saver).
* Updates to `m6502' and `gears'.
yoursavername_free -- Free everything you've allocated.
yoursavername_reshape -- Called when the window is resized.
yoursavername_event -- Called when a keyboard or mouse event happens.
- The "reshape" and "event" functions are only
- called when running in a window (not as a
- screen saver). It's ok for them to do nothing.
+
+ The "event" function will only be called when running in a window
+ (not as a screen saver). The "reshape" event will be called when the
+ window size changes, or (as a screen saver) when the display size
+ changes as a result of a RANDR event (e.g., plugging in a new monitor).
+
+ It's ok for both the "event" and "resize" functions to do nothing.
- All other functions should be static.
available if the file /usr/include/X11/extensions/Xrandr.h exists.) */
#undef HAVE_RANDR
+/* Define this if the RANDR library is version 1.2 or newer. */
+#undef HAVE_RANDR_12
+
/* Define this if you have the XReadDisplay extension (I think this is an
SGI-only thing; it's in <X11/extensions/readdisplay.h>.) A few of the
screenhacks will take advantage of this if it's available. */
+
+
+
+# Need to disable Objective C extensions in ANSI C on MacOS X to work
+# around an Apple-specific gcc bug.
+#
+
###############################################################################
#
-###############################################################################
-#
-# Function to figure out how to turn off Objective C on MacOS X.
-# (We have to do this to work around an Apple-specific gcc bug.)
-#
-###############################################################################
-
-
-
-
-
-
###############################################################################
#
# Function to figure out how to create directory trees.
ac_cv_gcc_accepts_no_overlength=no
else
ac_cv_gcc_accepts_no_overlength=yes
+ CC="$CC -Wno-overlength-strings"
fi
fi
{ echo "$as_me:$LINENO: result: $ac_cv_gcc_accepts_no_overlength" >&5
ac_cv_gcc_accepts_no_decl_after=no
else
ac_cv_gcc_accepts_no_decl_after=yes
+ CC="$CC -Wdeclaration-after-statement"
fi
fi
{ echo "$as_me:$LINENO: result: $ac_cv_gcc_accepts_no_decl_after" >&5
fi
if test -n "$GCC"; then
- if test -n "$GCC"; then
{ echo "$as_me:$LINENO: checking whether gcc accepts -no-cpp-precomp" >&5
echo $ECHO_N "checking whether gcc accepts -no-cpp-precomp... $ECHO_C" >&6; }
if test "${ac_cv_gcc_accepts_no_cpp_precomp+set}" = set; then
ac_cv_gcc_accepts_no_cpp_precomp=no
else
ac_cv_gcc_accepts_no_cpp_precomp=yes
+ CC="$CC -no-cpp-precomp"
fi
fi
{ echo "$as_me:$LINENO: result: $ac_cv_gcc_accepts_no_cpp_precomp" >&5
ac_gcc_accepts_no_cpp_precomp="$ac_cv_gcc_accepts_no_cpp_precomp"
fi
- if test "$ac_gcc_accepts_no_cpp_precomp" = yes ; then
- { echo "$as_me:$LINENO: result: Disabling Objective C extensions in ANSI C code." >&5
-echo "${ECHO_T}Disabling Objective C extensions in ANSI C code." >&6; }
- CC="$CC -no-cpp-precomp"
- fi
- fi
-
if test -n "$GCC"; then
if test -n "$GCC"; then
{ echo "$as_me:$LINENO: checking whether gcc accepts -std=c89" >&5
ac_cv_gcc_accepts_std=no
else
ac_cv_gcc_accepts_std=yes
+ CC="$CC -std=c89"
fi
fi
{ echo "$as_me:$LINENO: result: $ac_cv_gcc_accepts_std" >&5
# before they were in the ANSI C 99 spec... (gcc 2.96 permits //
# with -std=gnu89 but not with -std=c89.)
#
- CC="$CC -std=c89 -U__STRICT_ANSI__"
+ # $CC already contains "-std=c89" via AC_GCC_ACCEPTS_STD
+ CC="$CC -U__STRICT_ANSI__"
else
# The old way:
CC="$CC -Wp,-lang-c89"
if test "$with_randr" = yes; then
- # first check for Randr.h
+ # first check for Xrandr.h
ac_save_CPPFLAGS="$CPPFLAGS"
if test \! -z "$includedir" ; then
#define HAVE_RANDR 1
_ACEOF
+
+ # Now check for version 1.2 in the same libs.
+
+ 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`
+ { echo "$as_me:$LINENO: checking for XRRGetOutputInfo in -lc" >&5
+echo $ECHO_N "checking for XRRGetOutputInfo in -lc... $ECHO_C" >&6; }
+if test "${ac_cv_lib_c_XRRGetOutputInfo+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc $SAVER_LIBS $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* 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 XRRGetOutputInfo ();
+int
+main ()
+{
+return XRRGetOutputInfo ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -rf conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -rf conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_c_XRRGetOutputInfo=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_c_XRRGetOutputInfo=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_c_XRRGetOutputInfo" >&5
+echo "${ECHO_T}$ac_cv_lib_c_XRRGetOutputInfo" >&6; }
+if test $ac_cv_lib_c_XRRGetOutputInfo = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_RANDR_12 1
+_ACEOF
+
+else
+ true
+fi
+
+ CPPFLAGS="$ac_save_CPPFLAGS"
+ LDFLAGS="$ac_save_LDFLAGS"
+# LIBS="$ac_save_LIBS"
+
+ fi
+
elif test "$with_randr" != no; then
echo "error: must be yes or no: --with-randr-ext=$with_randr"
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat > conftest.$ac_ext <<EOF
-#line 16680 "configure"
+#line 16768 "configure"
#include "confdefs.h"
#include <GL/gl.h>
#ifndef MESA_MAJOR_VERSION
#### Could use some more defaults here...
for f in \
- "/usr/X11R6/lib/X11/doc/README" \
- "/usr/share/doc/xserver-common/copyright" \
- "/usr/X11R6/README" \
+ "/usr/X11R6/lib/X11/doc/README" \
+ "/usr/share/doc/xserver-common/copyright" \
+ "/usr/share/doc/xserver-xorg-core/copyright" \
+ "/usr/X11R6/README" \
+ "/usr/share/doc/debian/debian-manifesto" \
; do
if test -z "$with_textfile"; then
{ echo "$as_me:$LINENO: checking for text file $f" >&5
pgl="$preferred_mesagl"
if test "$ac_mesagl_version" = unknown; then
- warnL "Unable to determine the MesaGL version number!"
- warn2 "Make sure you are using version $preferred_mesagl or newer."
+ true
+ # warnL "Unable to determine the MesaGL version number!"
+ # warn2 "Make sure you are using version $preferred_mesagl or newer."
elif test \! "$ac_mesagl_version" -gt 2006; then
warnL "MesaGL version number is $mgv --"
if test \! -z "$rpmv" ; then
rpmbdir=`rpm -ql $rpmnames | sed -n 's@^\(.*\)/xscreensaver-demo$@\1@p'`
- rpmhdir=`rpm -ql $rpmnames | sed -n 's@^\(.*\)/attraction$@\1@p'`
+ rpmhdir=`rpm -ql $rpmnames | sed -n 's@^\(.*\)/popsquares$@\1@p'`
warning=no
warnL "There is already an installed RPM of xscreensaver $rpmv"
fi
fi
+# Also warn if there's a Debian package installed.
+#
+debnames="xscreensaver xscreensaver-data xscreensaver-data-extra"
+debv=''
+for dpkg in $debnames ; do
+ if test -z "$debv"; then
+ debv=`dpkg -s $dpkg 2>/dev/null | sed -n 's/^Version: \(.*\)$/\1/p'`
+ fi
+done
+
+if test \! -z "$debv" ; then
+ debbdir=`dpkg -L $debnames 2>/dev/null | \
+ sed -n 's@^\(.*/bin/\)xscreensaver$@\1@p'`
+ debhdir=`dpkg -L $debnames 2>/dev/null | \
+ sed -n 's@^\(.*/\)popsquares$@\1@p'`
+ if test -z "$debbdir" ; then debbdir='???'; fi
+ if test -z "$debhdir" ; then debhdir='???'; fi
+
+ warning=no
+ warnL "There is already an installed dpkg of xscreensaver"
+ warn2 "version \"$debv\" on this system."
+ echo ""
+ warn2 "The dpkg was installed in $debbdir,"
+ warn2 "with demos in $debhdir."
+fi
+
+
if test "${bindir}" = "${HACKDIR}" ; then
do_dir_warning=yes
fi
possibly elsewhere. (It's available if the file
/usr/include/X11/extensions/Xrandr.h exists.)])
+AH_TEMPLATE([HAVE_RANDR_12],
+ [Define this if the RANDR library is version 1.2 or newer.])
+
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
ac_cv_gcc_accepts_[$1]=no
else
ac_cv_gcc_accepts_[$1]=yes
+ CC="$CC [$2]"
fi])
ac_gcc_accepts_[$1]="$ac_cv_gcc_accepts_[$1]"
fi
AC_DEFUN(AC_NO_MISPLACED_DECLARATIONS,
[AC_CHECK_GCC_ARG(no_decl_after, -Wdeclaration-after-statement)])
+# Need to disable Objective C extensions in ANSI C on MacOS X to work
+# around an Apple-specific gcc bug.
+#
+AC_DEFUN(AC_NO_OBJECTIVE_C,
+ [AC_CHECK_GCC_ARG(no_cpp_precomp, -no-cpp-precomp)])
###############################################################################
#
# before they were in the ANSI C 99 spec... (gcc 2.96 permits //
# with -std=gnu89 but not with -std=c89.)
#
- CC="$CC -std=c89 -U__STRICT_ANSI__"
+ # $CC already contains "-std=c89" via AC_GCC_ACCEPTS_STD
+ CC="$CC -U__STRICT_ANSI__"
else
# The old way:
CC="$CC -Wp,-lang-c89"
])
-###############################################################################
-#
-# Function to figure out how to turn off Objective C on MacOS X.
-# (We have to do this to work around an Apple-specific gcc bug.)
-#
-###############################################################################
-
-AC_DEFUN(AC_GCC_ACCEPTS_NO_CPP_PRECOMP,
- [AC_CHECK_GCC_ARG(no_cpp_precomp, -no-cpp-precomp)])
-
-AC_DEFUN(AC_NO_OBJECTIVE_C,
- [if test -n "$GCC"; then
- AC_GCC_ACCEPTS_NO_CPP_PRECOMP
- if test "$ac_gcc_accepts_no_cpp_precomp" = yes ; then
- AC_MSG_RESULT(Disabling Objective C extensions in ANSI C code.)
- CC="$CC -no-cpp-precomp"
- fi
- fi
-])
-
-
###############################################################################
#
# Function to figure out how to create directory trees.
if test "$with_randr" = yes; then
- # first check for Randr.h
+ # first check for Xrandr.h
AC_CHECK_X_HEADER(X11/extensions/Xrandr.h, [have_randr=yes],,
[#include <X11/Xlib.h>])
# if that succeeded, then we've really got it.
if test "$have_randr" = yes; then
AC_DEFINE(HAVE_RANDR)
+
+ # Now check for version 1.2 in the same libs.
+ AC_CHECK_X_LIB(c, XRRGetOutputInfo, [AC_DEFINE(HAVE_RANDR_12)],
+ [true], $SAVER_LIBS)
fi
+
elif test "$with_randr" != no; then
echo "error: must be yes or no: --with-randr-ext=$with_randr"
exit 1
#### Could use some more defaults here...
for f in \
- "/usr/X11R6/lib/X11/doc/README" \
- "/usr/share/doc/xserver-common/copyright" \
- "/usr/X11R6/README" \
+ "/usr/X11R6/lib/X11/doc/README" \
+ "/usr/share/doc/xserver-common/copyright" \
+ "/usr/share/doc/xserver-xorg-core/copyright" \
+ "/usr/X11R6/README" \
+ "/usr/share/doc/debian/debian-manifesto" \
; do
if test -z "$with_textfile"; then
AC_MSG_CHECKING([for text file $f])
pgl="$preferred_mesagl"
if test "$ac_mesagl_version" = unknown; then
- warnL "Unable to determine the MesaGL version number!"
- warn2 "Make sure you are using version $preferred_mesagl or newer."
+ true
+ # warnL "Unable to determine the MesaGL version number!"
+ # warn2 "Make sure you are using version $preferred_mesagl or newer."
elif test \! "$ac_mesagl_version" -gt 2006; then
warnL "MesaGL version number is $mgv --"
if test \! -z "$rpmv" ; then
rpmbdir=`rpm -ql $rpmnames | sed -n 's@^\(.*\)/xscreensaver-demo$@\1@p'`
- rpmhdir=`rpm -ql $rpmnames | sed -n 's@^\(.*\)/attraction$@\1@p'`
+ rpmhdir=`rpm -ql $rpmnames | sed -n 's@^\(.*\)/popsquares$@\1@p'`
warning=no
warnL "There is already an installed RPM of xscreensaver $rpmv"
fi
fi
+# Also warn if there's a Debian package installed.
+#
+debnames="xscreensaver xscreensaver-data xscreensaver-data-extra"
+debv=''
+for dpkg in $debnames ; do
+ if test -z "$debv"; then
+ debv=`dpkg -s $dpkg 2>/dev/null | sed -n 's/^Version: \(.*\)$/\1/p'`
+ fi
+done
+
+if test \! -z "$debv" ; then
+ debbdir=`dpkg -L $debnames 2>/dev/null | \
+ sed -n 's@^\(.*/bin/\)xscreensaver$@\1@p'`
+ debhdir=`dpkg -L $debnames 2>/dev/null | \
+ sed -n 's@^\(.*/\)popsquares$@\1@p'`
+ if test -z "$debbdir" ; then debbdir='???'; fi
+ if test -z "$debhdir" ; then debhdir='???'; fi
+
+ warning=no
+ warnL "There is already an installed dpkg of xscreensaver"
+ warn2 "version \"$debv\" on this system."
+ echo ""
+ warn2 "The dpkg was installed in $debbdir,"
+ warn2 "with demos in $debhdir."
+fi
+
+
if test "${bindir}" = "${HACKDIR}" ; then
do_dir_warning=yes
fi
#handle 13 pass nostop
#handle 15 pass nostop
#handle 19 pass nostop
+set env MallocGuardEdges 1
+set env MallocPreScribble 1
+set env MallocScribble 1
b exit
set args -debug
-#b purify_stop_here
TEST_SRCS = test-passwd.c test-uid.c test-xdpms.c test-grab.c \
test-apm.c test-fade.c test-xinerama.c test-vp.c \
- test-randr.c xdpyinfo.c test-mlstring.c
+ test-randr.c xdpyinfo.c test-mlstring.c test-screens.c
TEST_EXES = test-passwd test-uid test-xdpms test-grab \
test-apm test-fade test-xinerama test-vp \
- test-randr xdpyinfo test-mlstring
+ test-randr xdpyinfo test-mlstring test-screens
MOTIF_LIBS = @MOTIF_LIBS@ @XPM_LIBS@ $(XMU_LIBS)
GTK_LIBS = @GTK_LIBS@ $(XMU_LIBS)
GTK_ICONS = $(ICON_SRC)/screensaver-*.png
DEMO_UTIL_SRCS = $(UTILS_SRC)/resources.c $(UTILS_SRC)/usleep.c \
- $(UTILS_SRC)/visual.c
+ $(UTILS_SRC)/visual.c $(XMU_SRCS)
DEMO_UTIL_OBJS = $(UTILS_BIN)/resources.o $(UTILS_BIN)/usleep.o \
- $(UTILS_BIN)/visual.o
+ $(UTILS_BIN)/visual.o $(XMU_OBJS)
SAVER_UTIL_SRCS = $(UTILS_SRC)/fade.c $(UTILS_SRC)/overlay.c \
$(UTILS_SRC)/logo.c $(UTILS_SRC)/yarandom.c \
$(UTILS_BIN)/logo.o $(UTILS_BIN)/minixpm.o prefs.o \
$(XMU_OBJS)
-SAVER_SRCS_1 = xscreensaver.c windows.c timers.c subprocs.c exec.c \
- xset.c splash.c setuid.c stderr.c mlstring.c
-SAVER_OBJS_1 = xscreensaver.o windows.o timers.o subprocs.o exec.o \
- xset.o splash.o setuid.o stderr.o mlstring.o
+SAVER_SRCS_1 = xscreensaver.c windows.c screens.c timers.c subprocs.c \
+ exec.c xset.c splash.c setuid.c stderr.c mlstring.c
+SAVER_OBJS_1 = xscreensaver.o windows.o screens.o timers.o subprocs.o \
+ exec.o xset.o splash.o setuid.o stderr.o mlstring.o
SAVER_SRCS = $(SAVER_SRCS_1) prefs.c dpms.c $(LOCK_SRCS) \
- $(SAVER_UTIL_SRCS) $(GL_SRCS) $(XMU_SRCS)
+ $(SAVER_UTIL_SRCS) $(GL_SRCS)
SAVER_OBJS = $(SAVER_OBJS_1) prefs.o dpms.o $(LOCK_OBJS) \
- $(SAVER_UTIL_OBJS) $(GL_OBJS) $(XMU_OBJS)
+ $(SAVER_UTIL_OBJS) $(GL_OBJS)
CMD_SRCS = remote.c xscreensaver-command.c
CMD_OBJS = remote.o xscreensaver-command.o
-DEMO_SRCS_1 = prefs.c dpms.c $(XMU_SRCS)
-DEMO_OBJS_1 = prefs.o dpms.o $(XMU_OBJS)
+DEMO_SRCS_1 = prefs.c dpms.c
+DEMO_OBJS_1 = prefs.o dpms.o
-DEMO_SRCS = prefs.c dpms.c remote.c exec.c $(DEMO_UTIL_SRCS)
-DEMO_OBJS = prefs.o dpms.o remote.o exec.o $(DEMO_UTIL_OBJS)
+DEMO_SRCS = $(DEMO_SRCS_1) remote.c exec.c $(DEMO_UTIL_SRCS)
+DEMO_OBJS = $(DEMO_OBJS_1) remote.o exec.o $(DEMO_UTIL_OBJS)
PDF2JPEG_SRCS = pdf2jpeg.m
PDF2JPEG_OBJS = pdf2jpeg.o
$$e " ####################################################################";\
$$e "" ;\
fi ; \
- elif [ -f $$conf ]; then \
+ elif [ -f $$conf -a "x$$dest" != "x" ]; then \
if ( grep $$dest $$conf >/dev/null ); then \
echo "$$conf unchanged: already has an entry for $$dest" ; \
else \
echo $(INSTALL_DIRS) "$(install_prefix)$(GTK_APPDIR)" ;\
$(INSTALL_DIRS) "$(install_prefix)$(GTK_APPDIR)" ;\
fi ;\
- name2=gnome-screensaver-properties.desktop ;\
+ name2=xscreensaver-properties.desktop ;\
echo $(INSTALL_DATA) screensaver-properties.desktop \
$(install_prefix)$(GTK_APPDIR)/$$name2 ;\
$(INSTALL_DATA) screensaver-properties.desktop \
# into /usr/share/applications/
uninstall-gnome::
@if [ "$(GTK_DATADIR)" != "" ]; then \
- f=gnome-screensaver-properties.desktop ;\
+ f=xscreensaver-properties.desktop ;\
echo rm -f $(install_prefix)$(GTK_APPDIR)/$$f ;\
rm -f $(install_prefix)$(GTK_APPDIR)/$$f ;\
fi
test-fade: test-fade.o $(UTILS_BIN)/fade.o
$(CC) $(LDFLAGS) -o $@ $(TEST_FADE_OBJS) $(SAVER_LIBS)
+TEST_SCREENS_OBJS = test-screens.o $(DEMO_UTIL_OBJS)
+test-screens.o: screens.c
+test-screens: test-screens.o
+ $(CC) $(LDFLAGS) -o $@ $(TEST_SCREENS_OBJS) $(SAVER_LIBS)
+
xdpyinfo.o: xdpyinfo.c
$(CC) -c $(INCLUDES) -DHAVE_GLX $(CFLAGS) $(X_CFLAGS) \
prefs.o: $(UTILS_SRC)/resources.h
remote.o: ../config.h
remote.o: $(srcdir)/remote.h
+screens.o: ../config.h
+screens.o: $(srcdir)/prefs.h
+screens.o: $(srcdir)/types.h
+screens.o: $(UTILS_SRC)/visual.h
+screens.o: $(srcdir)/xscreensaver.h
setuid.o: ../config.h
setuid.o: $(srcdir)/prefs.h
setuid.o: $(srcdir)/types.h
test-passwd.o: $(UTILS_SRC)/visual.h
test-passwd.o: $(srcdir)/xscreensaver.h
test-randr.o: ../config.h
+test-screens.o: ../config.h
+test-screens.o: $(srcdir)/prefs.h
+test-screens.o: $(srcdir)/screens.c
+test-screens.o: $(srcdir)/types.h
+test-screens.o: $(UTILS_SRC)/visual.h
+test-screens.o: $(srcdir)/xscreensaver.h
test-uid.o: ../config.h
test-vp.o: ../config.h
test-xdpms.o: ../config.h
! a screen saver and locker for the X window system
! by Jamie Zawinski
!
-! version 5.05
-! 01-Mar-2008
+! version 5.06
+! 16-Jul-2008
!
! See "man xscreensaver" for more info. The latest version is always
! available at http://www.jwz.org/xscreensaver/
! This command is executed by the "New Login" button on the lock dialog.
-! (That button does not appear if this program does not exist.)
+! (That button does not appear on the dialog if this program does not exist.)
+! For Gnome: probably "gdmflexiserver -ls". KDE, probably "kdmctl reserve".
!
@NEW_LOGIN_COMMAND_P@*newLoginCommand: @NEW_LOGIN_COMMAND@
@GL_KLUDGE@ GL: hypnowheel -root \n\
@GL_KLUDGE@ GL: "Hypnowheel (dense)" hypnowheel -root -count 3 -layers 50 \n\
@GL_KLUDGE@ GL: "Hypnowheel (trifoil)" hypnowheel -root -count 3 -layers 2 -speed 9 -twist 9 -wander \n\
+@GL_KLUDGE@ GL: skytentacles -root \n\
\
- xdaliclock -root -font BUILTIN3 \n\
- xplanet -vroot -wait 1 -timewarp 90000 \
*hacks.moebiusgears.name: MoebiusGears
*hacks.cubicgrid.name: CubicGrid
*hacks.lcdscrub.name: LCDscrub
+*hacks.hypnowheel.name: HypnoWheel
+*hacks.skytentacles.name: SkyTentacles
! obsolete, but still used by xscreensaver-demo-Xm.
*hacks.documentation.isInstalled: True
GL: hypnowheel -root \\n\
GL: \"Hypnowheel (dense)\" hypnowheel -root -count 3 -layers 50 \\n\
GL: \"Hypnowheel (trifoil)\" hypnowheel -root -count 3 -layers 2 -speed 9 -twist 9 -wander \\n\
+ GL: skytentacles -root \\n\
\
- xdaliclock -root -font BUILTIN3 \\n\
- xplanet -vroot -wait 1 -timewarp 90000 \
"*hacks.moebiusgears.name: MoebiusGears",
"*hacks.cubicgrid.name: CubicGrid",
"*hacks.lcdscrub.name: LCDscrub",
+"*hacks.hypnowheel.name: HypnoWheel",
+"*hacks.skytentacles.name: SkyTentacles",
"*hacks.documentation.isInstalled: True",
void settings_cancel_cb (GtkButton *, gpointer user_data);
void settings_ok_cb (GtkButton *, gpointer user_data);
+static void kill_gnome_screensaver (void);
+static void kill_kde_screensaver (void);
+
\f
/* Some random utility functions
*/
warning_dialog_dismiss_cb (widget, user_data);
}
+static void warning_dialog_killg_cb (GtkWidget *widget, gpointer user_data)
+{
+ kill_gnome_screensaver ();
+ warning_dialog_dismiss_cb (widget, user_data);
+}
+
+static void warning_dialog_killk_cb (GtkWidget *widget, gpointer user_data)
+{
+ kill_kde_screensaver ();
+ warning_dialog_dismiss_cb (widget, user_data);
+}
+
+typedef enum { D_NONE, D_LAUNCH, D_GNOME, D_KDE } dialog_button;
+
static void
warning_dialog (GtkWidget *parent, const char *message,
- Boolean restart_button_p, int center)
+ dialog_button button_type, int center)
{
char *msg = strdup (message);
char *head;
label, TRUE, TRUE, 0);
#ifdef HAVE_GTK2
- if (restart_button_p)
+ if (button_type != D_NONE)
{
cancel = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
gtk_container_add (GTK_CONTAINER (label), cancel);
ok = gtk_button_new_with_label ("OK");
gtk_container_add (GTK_CONTAINER (label), ok);
- if (restart_button_p)
+ if (button_type != D_NONE)
{
cancel = gtk_button_new_with_label ("Cancel");
gtk_container_add (GTK_CONTAINER (label), cancel);
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
gtk_container_set_border_width (GTK_CONTAINER (dialog), 10);
gtk_window_set_title (GTK_WINDOW (dialog), progclass);
- STFU GTK_WIDGET_SET_FLAGS (ok, GTK_CAN_DEFAULT);
+ GTK_WIDGET_SET_FLAGS (ok, GTK_CAN_DEFAULT);
gtk_widget_show (ok);
gtk_widget_grab_focus (ok);
if (cancel)
{
- STFU GTK_WIDGET_SET_FLAGS (cancel, GTK_CAN_DEFAULT);
+ GTK_WIDGET_SET_FLAGS (cancel, GTK_CAN_DEFAULT);
gtk_widget_show (cancel);
}
gtk_widget_show (label);
gtk_widget_show (dialog);
- if (restart_button_p)
+ if (button_type != D_NONE)
{
- gtk_signal_connect_object (GTK_OBJECT (ok), "clicked",
- GTK_SIGNAL_FUNC (warning_dialog_restart_cb),
+ GtkSignalFunc fn;
+ switch (button_type) {
+ case D_LAUNCH: fn = GTK_SIGNAL_FUNC (warning_dialog_restart_cb); break;
+ case D_GNOME: fn = GTK_SIGNAL_FUNC (warning_dialog_killg_cb); break;
+ case D_KDE: fn = GTK_SIGNAL_FUNC (warning_dialog_killk_cb); break;
+ default: abort(); break;
+ }
+ gtk_signal_connect_object (GTK_OBJECT (ok), "clicked", fn,
(gpointer) dialog);
gtk_signal_connect_object (GTK_OBJECT (cancel), "clicked",
GTK_SIGNAL_FUNC (warning_dialog_dismiss_cb),
sprintf (buf, "Error:\n\n%s", err);
else
strcpy (buf, "Unknown error!");
- warning_dialog (s->toplevel_widget, buf, False, 100);
+ warning_dialog (s->toplevel_widget, buf, D_NONE, 100);
}
if (err) free (err);
sprintf (buf, "Error:\n\n%s", err);
else
strcpy (buf, "Unknown error!");
- warning_dialog (s->toplevel_widget, buf, False, 100);
+ warning_dialog (s->toplevel_widget, buf, D_NONE, 100);
}
}
else
"The XScreenSaver daemon doesn't seem to be running\n"
"on display \"%s\". Launch it now?"),
d);
- warning_dialog (s->toplevel_widget, msg, True, 1);
+ warning_dialog (s->toplevel_widget, msg, D_LAUNCH, 1);
}
}
{
warning_dialog (s->toplevel_widget,
_("Error:\n\n"
- "No Help URL has been specified.\n"), False, 100);
+ "No Help URL has been specified.\n"), D_NONE, 100);
return;
}
else
strcat (buf, _("Please check your $PATH and permissions."));
- warning_dialog (s->toplevel_widget, buf, False, 1);
+ warning_dialog (s->toplevel_widget, buf, D_NONE, 1);
}
force_dialog_repaint (s);
if (!f || !*f)
warning_dialog (s->toplevel_widget,
_("Error:\n\nCouldn't determine init file name!\n"),
- False, 100);
+ D_NONE, 100);
else
{
char *b = (char *) malloc (strlen(f) + 1024);
sprintf (b, _("Error:\n\nCouldn't write %s\n"), f);
- warning_dialog (s->toplevel_widget, b, False, 100);
+ warning_dialog (s->toplevel_widget, b, D_NONE, 100);
free (b);
}
return -1;
{
warning_dialog (GTK_WIDGET (button),
_("Error:\n\nno `manualCommand' resource set."),
- False, 100);
+ D_NONE, 100);
}
free (oname);
_("Error:\n\n"
"Unparsable time format: \"%s\"\n"),
line);
- warning_dialog (s->toplevel_widget, b, False, 100);
+ warning_dialog (s->toplevel_widget, b, D_NONE, 100);
}
else
*store = value;
char b[255];
sprintf (b, "Error:\n\n" "Directory does not exist: \"%s\"\n",
p2->image_directory);
- warning_dialog (s->toplevel_widget, b, False, 100);
+ warning_dialog (s->toplevel_widget, b, D_NONE, 100);
}
char *str;
int list_elt;
- STFU g_return_if_fail (!gdk_pointer_is_grabbed ());
+ g_return_if_fail (!gdk_pointer_is_grabbed ());
str = gtk_tree_path_to_string (path);
list_elt = strtol (str, NULL, 10);
{
char b[255];
sprintf (b, _("Error:\n\n" "Directory does not exist: \"%s\"\n"), path);
- warning_dialog (GTK_WIDGET (top), b, False, 100);
+ warning_dialog (GTK_WIDGET (top), b, D_NONE, 100);
return;
}
{
char b[255];
sprintf (b, _("Error:\n\n" "File does not exist: \"%s\"\n"), path);
- warning_dialog (GTK_WIDGET (top), b, False, 100);
+ warning_dialog (GTK_WIDGET (top), b, D_NONE, 100);
return;
}
{
char b[255];
sprintf (b, _("Error:\n\n" "File does not exist: \"%s\"\n"), path);
- warning_dialog (GTK_WIDGET (top), b, False, 100);
+ warning_dialog (GTK_WIDGET (top), b, D_NONE, 100);
return;
}
# endif
_("Warning:\n\n"
"file \"%s\" has changed, reloading.\n"),
f);
- warning_dialog (s->toplevel_widget, b, False, 100);
+ warning_dialog (s->toplevel_widget, b, D_NONE, 100);
free (b);
load_init_file (dpy, p);
#endif
+static Window
+gnome_screensaver_window (Screen *screen)
+{
+ Display *dpy = DisplayOfScreen (screen);
+ Window root = RootWindowOfScreen (screen);
+ Window parent, *kids;
+ unsigned int nkids;
+ Window gnome_window = 0;
+ int i;
+
+ if (! XQueryTree (dpy, root, &root, &parent, &kids, &nkids))
+ abort ();
+ for (i = 0; i < nkids; i++)
+ {
+ Atom type;
+ int format;
+ unsigned long nitems, bytesafter;
+ unsigned char *name;
+ if (XGetWindowProperty (dpy, kids[i], XA_WM_COMMAND, 0, 128,
+ False, XA_STRING, &type, &format, &nitems,
+ &bytesafter, &name)
+ == Success
+ && type != None
+ && !strcmp ((char *) name, "gnome-screensaver"))
+ {
+ gnome_window = kids[i];
+ break;
+ }
+ }
+
+ if (kids) XFree ((char *) kids);
+ return gnome_window;
+}
+
+static Bool
+gnome_screensaver_active_p (void)
+{
+ Display *dpy = GDK_DISPLAY();
+ Window w = gnome_screensaver_window (DefaultScreenOfDisplay (dpy));
+ return (w ? True : False);
+}
+
+static void
+kill_gnome_screensaver (void)
+{
+ Display *dpy = GDK_DISPLAY();
+ Window w = gnome_screensaver_window (DefaultScreenOfDisplay (dpy));
+ if (w) XKillClient (dpy, (XID) w);
+}
+
+static Bool
+kde_screensaver_active_p (void)
+{
+ FILE *p = popen ("dcop kdesktop KScreensaverIface isEnabled 2>/dev/null",
+ "r");
+ char buf[255];
+ fgets (buf, sizeof(buf)-1, p);
+ pclose (p);
+ if (!strcmp (buf, "true\n"))
+ return True;
+ else
+ return False;
+}
+
+static void
+kill_kde_screensaver (void)
+{
+ system ("dcop kdesktop KScreensaverIface enable false");
+}
+
+
static void
the_network_is_not_the_computer (state *s)
{
if (*msg)
- warning_dialog (s->toplevel_widget, msg, True, 1);
+ warning_dialog (s->toplevel_widget, msg, D_LAUNCH, 1);
if (rversion) free (rversion);
if (ruser) free (ruser);
if (rhost) free (rhost);
free (msg);
+ msg = 0;
+
+ /* Note: since these dialogs are not modal, they will stack up.
+ So we do this check *after* popping up the "xscreensaver is not
+ 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 (kde_screensaver_active_p ())
+ warning_dialog (s->toplevel_widget,
+ _("Warning:\n\n"
+ "The KDE screen saver daemon appears to be running.\n"
+ "It must be stopped for XScreenSaver to work properly.\n"
+ "\n"
+ "Stop the KDE screen saver daemon now?\n"),
+ D_KDE, 1);
}
/* exec.c --- executes a program in *this* pid, without an intervening process.
- * xscreensaver, Copyright (c) 1991-2006 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1991-2008 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
int hairy_p;
#ifndef VMS
- if (nice != 0)
- nice_process (nice_level);
+ nice_process (nice_level);
hairy_p = !!strpbrk (command, "*?$&!<>[];`'\\\"=");
/* note: = is in the above because of the sh syntax "FOO=bar cmd". */
/* lock.c --- handling the password dialog for locking-mode.
- * xscreensaver, Copyright (c) 1993-2007 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1993-2008 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
extern void xss_authenticate(saver_info *si, Bool verbose_p);
-static void
+static int
new_passwd_window (saver_info *si)
{
passwd_dialog_data *pw;
pw = (passwd_dialog_data *) calloc (1, sizeof(*pw));
if (!pw)
- return;
+ return -1;
/* Display the button only if the "newLoginCommand" pref is non-null.
*/
}
si->pw_data = pw;
+ return 0;
}
/**
* info_msg and prompt may be NULL.
*/
-static void
+static int
make_passwd_window (saver_info *si,
const char *info_msg,
const char *prompt,
cleanup_passwd_window (si);
+ if (! ssi) /* WTF? Trying to prompt while no screens connected? */
+ return -1;
+
if (!si->pw_data)
- new_passwd_window (si);
+ if (new_passwd_window (si) < 0)
+ return -1;
if (!(pw = si->pw_data))
- return;
+ return -1;
pw->ratio = 1.0;
actually be visible; this takes into account virtual viewports as
well as Xinerama. */
{
- int x, y, w, h;
- get_screen_viewport (pw->prompt_screen, &x, &y, &w, &h,
- pw->previous_mouse_x, pw->previous_mouse_y,
- si->prefs.verbose_p);
+ saver_screen_info *ssi = &si->screens [mouse_screen (si)];
+ int x = ssi->x;
+ int y = ssi->y;
+ int w = ssi->width;
+ int h = ssi->height;
if (si->prefs.debug_p) w /= 2;
pw->x = x + ((w + pw->width) / 2) - pw->width;
pw->y = y + ((h + pw->height) / 2) - pw->height;
if (cmap)
XInstallColormap (si->dpy, cmap);
draw_passwd_window (si);
+
+ return 0;
}
{
saver_preferences *p = &si->prefs;
int status;
-
+ int event, error;
XErrorHandler old_handler;
+
+ if (!XF86MiscQueryExtension(si->dpy, &event, &error))
+ return;
+
XSync (si->dpy, False);
error_handler_hit_p = False;
old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
static Bool any_mode_locked_p = False;
saver_preferences *p = &si->prefs;
int screen;
+ int real_nscreens = ScreenCount (si->dpy);
int event, error;
Bool status;
XErrorHandler old_handler;
if (!XF86VidModeQueryExtension (si->dpy, &event, &error))
return;
- for (screen = 0; screen < (si->xinerama_p ? 1 : si->nscreens); screen++)
+ for (screen = 0; screen < real_nscreens; screen++)
{
XSync (si->dpy, False);
old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
#ifdef HAVE_XF86VMODE
saver_preferences *p = &si->prefs;
int screen;
+ int real_nscreens = ScreenCount (si->dpy);
int event, error;
if (!XF86VidModeQueryExtension (si->dpy, &event, &error))
return;
- for (screen = 0; screen < si->nscreens; screen++)
+ for (screen = 0; screen < real_nscreens; screen++)
{
saver_screen_info *ssi = &si->screens[screen];
int x, y;
info_msg_trimmed = remove_trailing_whitespace(info_msg);
prompt_trimmed = remove_trailing_whitespace(prompt);
- make_passwd_window(si, info_msg_trimmed, prompt_trimmed,
- auth_msgs[i].type == AUTH_MSGTYPE_PROMPT_ECHO
- ? True : False);
+ if (make_passwd_window(si, info_msg_trimmed, prompt_trimmed,
+ auth_msgs[i].type == AUTH_MSGTYPE_PROMPT_ECHO
+ ? True : False)
+ < 0)
+ goto fail;
if (info_msg_trimmed)
free(info_msg_trimmed);
static const char *tk_file;
#endif /* !HAVE_DARWIN */
+/* warning suppression: duplicated in passwd.c */
+extern Bool kerberos_lock_init (int argc, char **argv, Bool verbose_p);
+extern Bool kerberos_passwd_valid_p (const char *typed_passwd, Bool verbose_p);
+
/* Called at startup to grab user, instance, and realm information
from the user's ticketfile (remember, name.inst@realm). Since we're
ret = si->unlock_cb(nmsgs, messages, &authresp, si);
+ /* #### If the user times out, or hits ESC or Cancel, we return PAM_CONV_ERR,
+ and PAM logs this as an authentication failure. It would be nice if
+ there was some way to indicate that this was a "cancel" rather than
+ a "fail", so that it wouldn't show up in syslog, but I think the
+ only options are PAM_SUCCESS and PAM_CONV_ERR. (I think that
+ PAM_ABORT means "internal error", not "cancel".) Bleh.
+ */
+
if (ret == 0)
{
for (i = 0; i < nmsgs; ++i)
/* pdf2jpeg -- converts a PDF file to a JPEG file, using Cocoa
*
- * Copyright (c) 2003 by Jamie Zawinski <jwz@jwz.org>
+ * Copyright (c) 2003, 2008 by 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
const char *progname = argv[0];
const char *infile = 0, *outfile = 0;
double compression = 0.85;
+ double scale = 1.0;
int verbose = 0;
int i;
}
compression = q / 100.0;
}
+ else if (!strcmp (argv[i], "-scale"))
+ {
+ float s;
+ if (1 != sscanf (argv[++i], " %f %c", &s, &c) ||
+ s <= 0 || s > 50)
+ {
+ fprintf (stderr, "%s: scale must be 0.0 - 50.0 (%f)\n",
+ progname, s);
+ goto USAGE;
+ }
+ scale = s;
+ }
else if (!strcmp (argv[i], "-verbose"))
verbose++;
else if (!strcmp (argv[i], "-v") ||
{
USAGE:
fprintf (stderr,
- "usage: %s [-verbose] [-quality NN] "
+ "usage: %s [-verbose] [-scale N] [-quality NN] "
"infile.pdf outfile.jpg\n",
progname);
exit (1);
NSPDFImageRep *pdf_rep = [NSPDFImageRep imageRepWithData:pdf_data];
// Create an NSImage instance
- NSImage *image = [[NSImage alloc] initWithSize:[pdf_rep size]];
+ NSRect rect;
+ rect.size = [pdf_rep size];
+ rect.size.width *= scale;
+ rect.size.height *= scale;
+ rect.origin.x = rect.origin.y = 0;
+ NSImage *image = [[NSImage alloc] initWithSize:rect.size];
// Draw the PDFImageRep in the NSImage
[image lockFocus];
- [pdf_rep drawAtPoint:NSMakePoint(0.0,0.0)];
+ [pdf_rep drawInRect:rect];
[image unlockFocus];
// Load the NSImage's contents into an NSBitmapImageRep:
/* dotfile.c --- management of the ~/.xscreensaver file.
- * xscreensaver, Copyright (c) 1998-2006 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1998-2008 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
"fadeTicks",
"captureStderr",
"captureStdout", /* not saved -- obsolete */
+ "logFile", /* not saved */
"ignoreUninstalledPrograms",
"font",
"dpmsEnabled",
CHECK("fadeTicks") type = pref_int, i = p->fade_ticks;
CHECK("captureStderr") type = pref_bool, b = p->capture_stderr_p;
CHECK("captureStdout") continue; /* don't save */
+ CHECK("logFile") continue; /* don't save */
CHECK("ignoreUninstalledPrograms")
type = pref_bool, b = p->ignore_uninstalled_p;
--- /dev/null
+/* screens.c --- dealing with RANDR, Xinerama, and VidMode Viewports.
+ * xscreensaver, Copyright (c) 1991-2008 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
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+/* There are a bunch of different mechanisms for multiple monitors
+ * available in X. XScreenSaver needs to care about this for two
+ * reasons: first, to ensure that all visible areas go black; and
+ * second, so that the windows of screen savers exactly fill the
+ * glass of each monitor (instead of one saver spanning multiple
+ * monitors, or a monitor displaying only a sub-rectangle of the
+ * screen saver.)
+ *
+ * 1) Multi-screen:
+ *
+ * This is the original way. Each monitor gets its own display
+ * number. :0.0 is the first one, :0.1 is the next, etc. The
+ * value of $DISPLAY determines which screen windows open on by
+ * default. A single app can open windows on multiple screens
+ * with the same display connection, but windows cannot be moved
+ * from one screen to 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.
+ *
+ * Everyone hates this way of doing things because of the
+ * inability to move a window from one screen to another without
+ * restarting the application.
+ *
+ * 2) Xinerama:
+ *
+ * There is a single giant root window that spans all the
+ * monitors. All monitors are the same depth, and windows can be
+ * moved around. Applications can learn which rectangles are
+ * actually visible on monitors by querying the Xinerama server
+ * extension. (If you don't do that, you end up with dialog
+ * boxes that try to appear in the middle of the screen actually
+ * spanning the gap between two monitors.)
+ *
+ * Xinerama doesn't work with DRI, which means that if you use
+ * it, you lose hardware acceleration on OpenGL programs. Also,
+ * screens can't be resized or moved without restarting X.
+ *
+ * 3) Vidmode Viewports:
+ *
+ * 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 can also be
+ * a hot key for changing the monitor's resolution (zooming
+ * in/out).
+ *
+ * Trying to combine this with Xinerama crashes the server, so
+ * you can only use this if you have only a single screen, or are
+ * in old-multi-screen mode.
+ *
+ * Also, half the time it doesn't work at all: it tends to lie
+ * about the size of the rectangle in use.
+ *
+ * 4) RANDR 1.0:
+ *
+ * The first version of the "Resize and Rotate" extension let you
+ * change the resolution of a screen on the fly. The root window
+ * would actually resize. However, it was also incompatible with
+ * Xinerama (did it crash, or just do nothing? I can't remember)
+ * so you needed to be in single-screen or old multi-screen mode.
+ * I believe RANDR could co-exist with Vidmode Viewports, but I'm
+ * not sure.
+ *
+ * 5) RANDR 1.2:
+ *
+ * Finally, RANDR added the functionality of Xinerama, plus some.
+ * Each X screen (in the sense of #1, "multi-screen") can have a
+ * number of sub-rectangles that are displayed on monitors, and
+ * each of those sub-rectangles can be displayed on more than one
+ * monitor. So it's possible (I think) to have a hybrid of
+ * multi-screen and Xinerama (e.g., to have two monitors running
+ * in one depth, and three monitors running in another?)
+ * Typically though, there will be a single X screen, with
+ * Xinerama-like division of that large root window onto multiple
+ * monitors. Also everything's dynamic: monitors can be added,
+ * removed, and resized at runtime.
+ *
+ * I believe that as of RANDR 1.2, the Xinerama extension still
+ * exists but only as a compatiblity layer: it's actually
+ * returning data from the RANDR extension.
+ *
+ * Though RANDR 1.2 allows the same image to be cloned onto more
+ * than one monitor, and also allows one monitor to show a
+ * subsection of something on another monitor (e.g., the
+ * rectangles can be enclosed or overlap). Since there's no way
+ * to put seperate savers on those duplicated-or-overlapping
+ * monitors, xscreensaver just ignores them (which allows them to
+ * display duplicates or overlaps).
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <X11/Xlib.h>
+
+#ifdef HAVE_RANDR
+# include <X11/extensions/Xrandr.h>
+#endif /* HAVE_RANDR */
+
+#ifdef HAVE_XINERAMA
+# include <X11/extensions/Xinerama.h>
+#endif /* HAVE_XINERAMA */
+
+#ifdef HAVE_XF86VMODE
+# include <X11/extensions/xf86vmode.h>
+#endif /* HAVE_XF86VMODE */
+
+/* This file doesn't need the Xt headers, so stub these types out... */
+#undef XtPointer
+#define XtAppContext void*
+#define XrmDatabase void*
+#define XtIntervalId void*
+#define XtPointer void*
+#define Widget void*
+
+#include "xscreensaver.h"
+#include "visual.h"
+
+
+typedef enum { S_SANE, S_ENCLOSED, S_DUPLICATE, S_OVERLAP,
+ S_OFFSCREEN, S_DISABLED } monitor_sanity;
+
+/* 'typedef monitor' is in types.h */
+struct _monitor {
+ int id;
+ char *desc;
+ Screen *screen;
+ int x, y, width, height;
+ monitor_sanity sanity; /* I'm not crazy you're the one who's crazy */
+ int enemy; /* which monitor it overlaps or duplicates */
+};
+
+static void
+free_monitors (monitor **monitors)
+{
+ monitor **m2 = monitors;
+ if (! monitors) return;
+ while (*m2)
+ {
+ if ((*m2)->desc) free ((*m2)->desc);
+ free (*m2);
+ m2++;
+ }
+ free (monitors);
+}
+
+
+#ifdef HAVE_XINERAMA
+
+static monitor **
+xinerama_scan_monitors (Display *dpy)
+{
+ Screen *screen = DefaultScreenOfDisplay (dpy);
+ int event, error, nscreens, i;
+ XineramaScreenInfo *xsi;
+ monitor **monitors;
+
+ if (! XineramaQueryExtension (dpy, &event, &error))
+ return 0;
+
+ if (! XineramaIsActive (dpy))
+ return 0;
+
+ xsi = XineramaQueryScreens (dpy, &nscreens);
+ if (!xsi) return 0;
+
+ monitors = (monitor **) calloc (nscreens + 1, sizeof(*monitors));
+ if (!monitors) return 0;
+
+ for (i = 0; i < nscreens; i++)
+ {
+ monitor *m = (monitor *) calloc (1, sizeof (monitor));
+ monitors[i] = m;
+ m->id = i;
+ m->screen = screen;
+ m->x = xsi[i].x_org;
+ m->y = xsi[i].y_org;
+ m->width = xsi[i].width;
+ m->height = xsi[i].height;
+ }
+ return monitors;
+}
+
+#endif /* HAVE_XINERAMA */
+
+
+#ifdef HAVE_XF86VMODE
+
+static monitor **
+vidmode_scan_monitors (Display *dpy)
+{
+ int event, error, nscreens, i;
+ monitor **monitors;
+
+ /* Note that XF86VidModeGetViewPort() tends to be full of lies on laptops
+ that have a docking station or external monitor that runs in a different
+ resolution than the laptop's screen:
+
+ http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=81593
+ http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=208417
+ http://bugs.xfree86.org/show_bug.cgi?id=421
+
+ Presumably this is fixed by using RANDR instead of VidMode.
+ */
+
+# ifdef HAVE_XINERAMA
+ /* Attempts to use the VidMode extension when the Xinerama extension is
+ active can result in a server crash! Yay! */
+ if (XQueryExtension (dpy, "XINERAMA", &error, &event, &error))
+ return 0;
+# endif /* !HAVE_XINERAMA */
+
+ if (! XF86VidModeQueryExtension (dpy, &event, &error))
+ return 0;
+
+ nscreens = ScreenCount (dpy);
+ monitors = (monitor **) calloc (nscreens + 1, sizeof(*monitors));
+ if (!monitors) return 0;
+
+ for (i = 0; i < nscreens; i++)
+ {
+ monitor *m = (monitor *) calloc (1, sizeof (monitor));
+ XF86VidModeModeLine ml;
+ int dot;
+ Screen *screen = ScreenOfDisplay (dpy, i);
+
+ monitors[i] = m;
+ m->id = i;
+ m->screen = screen;
+
+ if (! safe_XF86VidModeGetViewPort (dpy, i, &m->x, &m->y))
+ m->x = m->y = -1;
+
+ if (XF86VidModeGetModeLine (dpy, i, &dot, &ml))
+ {
+ m->width = ml.hdisplay;
+ m->height = ml.vdisplay;
+ }
+
+ /* Apparently, though the server stores the X position in increments of
+ 1 pixel, it will only make changes to the *display* in some other
+ increment. With XF86_SVGA on a Thinkpad, the display only updates
+ in multiples of 8 pixels when in 8-bit mode, and in multiples of 4
+ pixels in 16-bit mode. I don't know what it does in 24- and 32-bit
+ mode, because I don't have enough video memory to find out.
+
+ I consider it a bug that XF86VidModeGetViewPort() is telling me the
+ server's *target* scroll position rather than the server's *actual*
+ scroll position. David Dawes agrees, and says they may fix this in
+ XFree86 4.0, but it's notrivial.
+
+ He also confirms that this behavior is server-dependent, so the
+ actual scroll position cannot be reliably determined by the client.
+ So... that means the only solution is to provide a ``sandbox''
+ around the blackout window -- we make the window be up to N pixels
+ larger than the viewport on both the left and right sides. That
+ means some part of the outer edges of each hack might not be
+ visible, but screw it.
+
+ I'm going to guess that 16 pixels is enough, and that the Y dimension
+ doesn't have this problem.
+
+ The drawback of doing this, of course, is that some of the screenhacks
+ will still look pretty stupid -- for example, "slidescreen" will cut
+ off the left and right edges of the grid, etc.
+ */
+# define FUDGE 16
+ if (m->x > 0 && m->x < m->width - ml.hdisplay)
+ {
+ /* Not at left edge or right edge:
+ Round X position down to next lower multiple of FUDGE.
+ Increase width by 2*FUDGE in case some server rounds up.
+ */
+ m->x = ((m->x - 1) / FUDGE) * FUDGE;
+ m->width += (FUDGE * 2);
+ }
+# undef FUDGE
+ }
+
+ return monitors;
+}
+
+#endif /* HAVE_XF86VMODE */
+
+
+#ifdef HAVE_RANDR
+
+static monitor **
+randr_scan_monitors (Display *dpy)
+{
+ int event, error, major, minor, nscreens, i, j;
+ monitor **monitors;
+ Bool new_randr_p = False;
+
+ if (! XRRQueryExtension (dpy, &event, &error))
+ return 0;
+
+ if (! XRRQueryVersion (dpy, &major, &minor))
+ return 0;
+
+ if (major <= 0) /* Protocol was still in flux back then -- fuck it. */
+ return 0;
+
+# ifdef HAVE_RANDR_12
+ new_randr_p = (major > 1 || (major == 1 && minor >= 2));
+# endif
+
+ if (! new_randr_p)
+ /* RANDR 1.0 -- no Xinerama-like virtual screens. */
+ nscreens = ScreenCount (dpy);
+ else /* RANDR 1.2 or newer -- built-in Xinerama */
+ {
+# ifdef HAVE_RANDR_12
+ int xsc = ScreenCount (dpy);
+ nscreens = 0;
+ /* Add up the virtual screens on each X screen. */
+ for (i = 0; i < xsc; i++)
+ {
+ XRRScreenResources *res =
+ XRRGetScreenResources (dpy, RootWindow (dpy, i));
+ nscreens += res->noutput;
+ XRRFreeScreenResources (res);
+ }
+# endif /* HAVE_RANDR_12 */
+ }
+
+ monitors = (monitor **) calloc (nscreens + 1, sizeof(*monitors));
+ if (!monitors) return 0;
+
+ for (i = 0, j = 0; i < ScreenCount (dpy); i++)
+ {
+ Screen *screen = ScreenOfDisplay (dpy, j);
+
+ if (! new_randr_p) /* RANDR 1.0 */
+ {
+ XRRScreenConfiguration *rrc;
+ monitor *m = (monitor *) calloc (1, sizeof (monitor));
+ monitors[i] = m;
+ m->screen = screen;
+ m->id = i;
+
+ rrc = XRRGetScreenInfo (dpy, RootWindowOfScreen (screen));
+ if (rrc)
+ {
+ SizeID size = -1;
+ Rotation rot = ~0;
+ XRRScreenSize *rrsizes;
+ int nsizes;
+
+ size = XRRConfigCurrentConfiguration (rrc, &rot);
+ rrsizes = XRRConfigSizes (rrc, &nsizes);
+
+ if (rot & (RR_Rotate_90|RR_Rotate_270))
+ {
+ m->width = rrsizes[size].height;
+ m->height = rrsizes[size].width;
+ }
+ else
+ {
+ m->width = rrsizes[size].width;
+ m->height = rrsizes[size].height;
+ }
+
+ /* don't free 'rrsizes' */
+ XRRFreeScreenConfigInfo (rrc);
+ }
+ }
+ else /* RANDR 1.2 or newer */
+ {
+# ifdef HAVE_RANDR_12
+ int k;
+ XRRScreenResources *res =
+ XRRGetScreenResources (dpy, RootWindowOfScreen (screen));
+ for (k = 0; k < res->noutput; k++)
+ {
+ monitor *m = (monitor *) calloc (1, sizeof (monitor));
+ XRROutputInfo *rroi = XRRGetOutputInfo (dpy, res,
+ res->outputs[k]);
+ RRCrtc crtc = (rroi->crtc ? rroi->crtc : rroi->crtcs[0]);
+ XRRCrtcInfo *crtci = XRRGetCrtcInfo (dpy, res, crtc);
+
+ monitors[j] = m;
+ m->screen = screen;
+ m->id = (i * 1000) + j;
+ m->desc = (rroi->name ? strdup (rroi->name) : 0);
+ m->x = crtci->x;
+ m->y = crtci->y;
+
+ if (crtci->rotation & (RR_Rotate_90|RR_Rotate_270))
+ {
+ m->width = crtci->height;
+ m->height = crtci->width;
+ }
+ else
+ {
+ m->width = crtci->width;
+ m->height = crtci->height;
+ }
+
+ j++;
+
+ if (rroi->connection == RR_Disconnected)
+ m->sanity = S_DISABLED;
+ /* #### do the same for RR_UnknownConnection? */
+
+ XRRFreeCrtcInfo (crtci);
+ XRRFreeOutputInfo (rroi);
+ }
+ XRRFreeScreenResources (res);
+# endif /* HAVE_RANDR_12 */
+ }
+ }
+
+ return monitors;
+}
+
+#endif /* HAVE_RANDR */
+
+
+static monitor **
+basic_scan_monitors (Display *dpy)
+{
+ int nscreens = ScreenCount (dpy);
+ int i;
+ monitor **monitors = (monitor **) calloc (nscreens + 1, sizeof(*monitors));
+ if (!monitors) return 0;
+
+ for (i = 0; i < nscreens; i++)
+ {
+ Screen *screen = ScreenOfDisplay (dpy, i);
+ monitor *m = (monitor *) calloc (1, sizeof (monitor));
+ monitors[i] = m;
+ m->id = i;
+ m->screen = screen;
+ m->x = 0;
+ m->y = 0;
+ m->width = WidthOfScreen (screen);
+ m->height = HeightOfScreen (screen);
+ }
+ return monitors;
+}
+
+
+#ifdef DEBUG_MULTISCREEN
+
+/* If DEBUG_MULTISCREEN is defined, then in "-debug" mode, xscreensaver
+ will pretend that it is changing the number of connected monitors
+ every few seconds, using the geometries in the following list,
+ for stress-testing purposes.
+ */
+static monitor **
+debug_scan_monitors (Display *dpy)
+{
+ static const char * const geoms[] = {
+ "1600x1028+0+22",
+ "1024x768+0+22",
+ "800x600+0+22",
+ "800x600+0+22,800x600+800+22",
+ "800x600+0+22,800x600+800+22,800x600+300+622",
+ "800x600+0+22,800x600+800+22,800x600+0+622,800x600+800+622",
+ "640x480+0+22,640x480+640+22,640x480+0+502,640x480+640+502",
+ "640x480+240+22,640x480+0+502,640x480+640+502",
+ "640x480+0+200,640x480+640+200",
+ "800x600+400+22",
+ "320x200+0+22,320x200+320+22,320x200+640+22,320x200+960+22,320x200+0+222,320x200+320+222,320x200+640+222,320x200+960+222,320x200+0+422,320x200+320+422,320x200+640+422,320x200+960+422,320x200+0+622,320x200+320+622,320x200+640+622,320x200+960+622,320x200+0+822,320x200+320+822,320x200+640+822,320x200+960+822"
+ };
+ static int index = 0;
+ monitor **monitors = (monitor **) calloc (100, sizeof(*monitors));
+ int nscreens = 0;
+ Screen *screen = DefaultScreenOfDisplay (dpy);
+
+ char *s = strdup (geoms[index]);
+ char *token = strtok (s, ",");
+ while (token)
+ {
+ monitor *m = calloc (1, sizeof (monitor));
+ char c;
+ m->id = nscreens;
+ m->screen = screen;
+ if (4 != sscanf (token, "%dx%d+%d+%d%c",
+ &m->width, &m->height, &m->x, &m->y, &c))
+ abort();
+ m->width -= 2;
+ m->height -= 2;
+ monitors[nscreens++] = m;
+ token = strtok (0, ",");
+ }
+ free (s);
+
+ index = (index+1) % countof(geoms);
+ return monitors;
+}
+
+#endif /* DEBUG_MULTISCREEN */
+
+
+#ifdef QUAD_MODE
+static monitor **
+quadruple (monitor **monitors, Bool debug_p)
+{
+ int i, j, count = 0;
+ monitor **monitors2;
+ while (monitors[count])
+ count++;
+ monitors2 = (monitor **) calloc (count * 4 + 1, sizeof(*monitors));
+ if (!monitors2) abort();
+
+ for (i = 0, j = 0; i < count; i++)
+ {
+ int k;
+ for (k = 0; k < 4; k++)
+ {
+ monitors2[j+k] = (monitor *) calloc (1, sizeof (monitor));
+ *monitors2[j+k] = *monitors[i];
+ monitors2[j+k]->width /= (debug_p ? 4 : 2);
+ monitors2[j+k]->height /= 2;
+ monitors2[j+k]->id = (monitors[i]->id * 4) + k;
+ monitors2[j+k]->name = (monitors[i]->name
+ ? strdup (monitors[i]->name) : 0);
+ }
+ monitors2[j+1]->x += monitors2[j]->width;
+ monitors2[j+2]->y += monitors2[j]->height;
+ monitors2[j+3]->x += monitors2[j]->width;
+ monitors2[j+3]->y += monitors2[j]->height;
+ j += 4;
+ }
+
+ free_monitors (monitors);
+ return monitors2;
+}
+#endif /* QUAD_MODE */
+
+
+static monitor **
+scan_monitors (saver_info *si)
+{
+ saver_preferences *p = &si->prefs;
+ monitor **monitors = 0;
+
+# ifdef DEBUG_MULTISCREEN
+ if (! monitors) monitors = debug_scan_monitors (si->dpy);
+# endif
+
+# ifdef HAVE_RANDR
+ if (! p->getviewport_full_of_lies_p)
+ if (! monitors) monitors = randr_scan_monitors (si->dpy);
+# endif
+
+# ifdef HAVE_XF86VMODE
+ if (! monitors) monitors = vidmode_scan_monitors (si->dpy);
+# endif
+
+# ifdef HAVE_XF86VMODE
+ if (! monitors) monitors = xinerama_scan_monitors (si->dpy);
+# endif
+
+ if (! monitors) monitors = basic_scan_monitors (si->dpy);
+
+# ifdef QUAD_MODE
+ if (p->quad_p)
+ monitors = quadruple (monitors, p->debug_p);
+# endif
+
+ return monitors;
+}
+
+
+static Bool
+monitors_overlap_p (monitor *a, monitor *b)
+{
+ /* Two rectangles overlap if the max of the tops is less than the
+ min of the bottoms and the max of the lefts is less than the min
+ of the rights.
+ */
+# undef MAX
+# undef MIN
+# define MAX(A,B) ((A)>(B)?(A):(B))
+# define MIN(A,B) ((A)<(B)?(A):(B))
+
+ int maxleft = MAX(a->x, b->x);
+ int maxtop = MAX(a->y, b->y);
+ int minright = MIN(a->x + a->width - 1, b->x + b->width);
+ int minbot = MIN(a->y + a->height - 1, b->y + b->height);
+ return (maxtop < minbot && maxleft < minright);
+}
+
+
+/* Mark the ones that overlap, etc.
+ */
+static void
+check_monitor_sanity (monitor **monitors)
+{
+ int i, j, count = 0;
+
+ while (monitors[count])
+ count++;
+
+# define X1 monitors[i]->x
+# define X2 monitors[j]->x
+# define Y1 monitors[i]->y
+# define Y2 monitors[j]->y
+# define W1 monitors[i]->width
+# define W2 monitors[j]->width
+# define H1 monitors[i]->height
+# define H2 monitors[j]->height
+
+ /* If a monitor is enclosed by any other monitor, that's insane.
+ */
+ for (i = 0; i < count; i++)
+ for (j = 0; j < count; j++)
+ if (i != j &&
+ monitors[i]->sanity == S_SANE &&
+ monitors[j]->sanity == S_SANE &&
+ X2 >= X1 &&
+ Y2 >= Y1 &&
+ (X2+W2) <= (X1+W1) &&
+ (Y2+H2) <= (Y1+H1))
+ {
+ if (X1 == X2 &&
+ Y1 == Y2 &&
+ W1 == W2 &&
+ H1 == H2)
+ monitors[j]->sanity = S_DUPLICATE;
+ else
+ monitors[j]->sanity = S_ENCLOSED;
+ monitors[j]->enemy = i;
+ }
+
+ /* After checking for enclosure, check for other lossage against earlier
+ monitors. We do enclosure first so that we make sure to pick the
+ larger one.
+ */
+ for (i = 0; i < count; i++)
+ for (j = 0; j < i; j++)
+ {
+ if (monitors[i]->sanity != S_SANE) continue; /* already marked */
+ if (monitors[j]->sanity != S_SANE) continue;
+
+ if (monitors_overlap_p (monitors[i], monitors[j]))
+ {
+ monitors[i]->sanity = S_OVERLAP;
+ monitors[i]->enemy = j;
+ }
+ }
+
+ /* Finally, make sure all monitors are enclosed by their X screen.
+ Xinerama sometimes reports 1024x768 VPs at -1936862040, -1953705044.
+ */
+ for (i = 0; i < count; i++)
+ {
+ int sw = WidthOfScreen (monitors[i]->screen) * 2;
+ int sh = HeightOfScreen (monitors[i]->screen) * 2;
+ if (monitors[i]->sanity != S_SANE) continue; /* already marked */
+ if (X1 < 0 || Y1 < 0 ||
+ W1 <= 0 || H1 <= 0 ||
+ X1+W1 > sw || Y1+H1 > sh)
+ {
+ monitors[i]->sanity = S_OFFSCREEN;
+ monitors[i]->enemy = 0;
+ }
+ }
+
+# undef X1
+# undef X2
+# undef Y1
+# undef Y2
+# undef W1
+# undef W2
+# undef H1
+# undef H2
+}
+
+
+static Bool
+layouts_differ_p (monitor **a, monitor **b)
+{
+ if (!a || !b) return True;
+ while (1)
+ {
+ if (!*a) break;
+ if (!*b) break;
+ if ((*a)->screen != (*b)->screen ||
+ (*a)->x != (*b)->x ||
+ (*a)->y != (*b)->y ||
+ (*a)->width != (*b)->width ||
+ (*a)->height != (*b)->height)
+ return True;
+ a++;
+ b++;
+ }
+ if (*a) return True;
+ if (*b) return True;
+
+ return False;
+}
+
+
+void
+describe_monitor_layout (saver_info *si)
+{
+ monitor **monitors = si->monitor_layout;
+ int count = 0;
+ int good_count = 0;
+ int bad_count = 0;
+ while (monitors[count])
+ {
+ if (monitors[count]->sanity == S_SANE)
+ good_count++;
+ else
+ bad_count++;
+ count++;
+ }
+
+ if (count == 0)
+ fprintf (stderr, "%s: no screens!\n", blurb());
+ else
+ {
+ int i;
+ fprintf (stderr, "%s: screens in use: %d\n", blurb(), good_count);
+ for (i = 0; i < count; i++)
+ {
+ monitor *m = monitors[i];
+ if (m->sanity != S_SANE) continue;
+ fprintf (stderr, "%s: %3d/%d: %dx%d+%d+%d",
+ blurb(), m->id, screen_number (m->screen),
+ m->width, m->height, m->x, m->y);
+ if (m->desc && *m->desc) fprintf (stderr, " (%s)", m->desc);
+ fprintf (stderr, "\n");
+ }
+ if (bad_count > 0)
+ {
+ fprintf (stderr, "%s: rejected screens: %d\n", blurb(), bad_count);
+ for (i = 0; i < count; i++)
+ {
+ monitor *m = monitors[i];
+ monitor *e = monitors[m->enemy];
+ if (m->sanity == S_SANE) continue;
+ fprintf (stderr, "%s: %3d/%d: %dx%d+%d+%d",
+ blurb(), m->id, screen_number (m->screen),
+ m->width, m->height, m->x, m->y);
+ if (m->desc && *m->desc) fprintf (stderr, " (%s)", m->desc);
+ fprintf (stderr, " -- ");
+ switch (m->sanity)
+ {
+ case S_SANE: abort(); break;
+ case S_ENCLOSED:
+ fprintf (stderr, "enclosed by %d (%dx%d+%d+%d)\n",
+ e->id, e->width, e->height, e->x, e->y);
+ break;
+ case S_DUPLICATE:
+ fprintf (stderr, "duplicate of %d\n", e->id);
+ break;
+ case S_OVERLAP:
+ fprintf (stderr, "overlaps %d (%dx%d+%d+%d)\n",
+ e->id, e->width, e->height, e->x, e->y);
+ break;
+ case S_OFFSCREEN:
+ fprintf (stderr, "off screen (%dx%d)\n",
+ WidthOfScreen (e->screen),
+ HeightOfScreen (e->screen));
+ break;
+ case S_DISABLED:
+ fprintf (stderr, "output disabled\n");
+ break;
+ }
+ }
+ }
+ }
+}
+
+
+/* Synchronize the contents of si->ssi to the current state of the monitors.
+ Doesn't change anything if nothing has changed; otherwise, alters and
+ reuses existing saver_screen_info structs as much as possible.
+ Returns True if anything changed.
+ */
+Bool
+update_screen_layout (saver_info *si)
+{
+ monitor **monitors = scan_monitors (si);
+ int count = 0;
+ int good_count = 0;
+ int i, j;
+ int seen_screens[100] = { 0, };
+
+ if (! layouts_differ_p (monitors, si->monitor_layout))
+ {
+ free_monitors (monitors);
+ return False;
+ }
+
+ free_monitors (si->monitor_layout);
+ si->monitor_layout = monitors;
+ check_monitor_sanity (si->monitor_layout);
+
+ while (monitors[count])
+ {
+ if (monitors[count]->sanity == S_SANE)
+ good_count++;
+ count++;
+ }
+
+ if (si->ssi_count == 0)
+ {
+ si->ssi_count = 10;
+ si->screens = (saver_screen_info *)
+ calloc (sizeof(*si->screens), si->ssi_count);
+ }
+
+ if (si->ssi_count <= good_count)
+ {
+ si->ssi_count = good_count + 10;
+ si->screens = (saver_screen_info *)
+ realloc (si->screens, sizeof(*si->screens) * si->ssi_count);
+ memset (si->screens + si->nscreens, 0,
+ sizeof(*si->screens) * (si->ssi_count - si->nscreens));
+ }
+
+ if (! si->screens) abort();
+
+ si->nscreens = good_count;
+
+ /* Regenerate the list of GL visuals as needed. */
+ if (si->best_gl_visuals)
+ free (si->best_gl_visuals);
+ si->best_gl_visuals = 0;
+
+ for (i = 0, j = 0; i < count; i++)
+ {
+ monitor *m = monitors[i];
+ saver_screen_info *ssi = &si->screens[j];
+ Screen *old_screen = ssi->screen;
+ int sn;
+ if (monitors[i]->sanity != S_SANE) continue;
+
+ ssi->global = si;
+ ssi->number = j;
+
+ sn = screen_number (m->screen);
+ ssi->screen = m->screen;
+ ssi->real_screen_number = sn;
+ ssi->real_screen_p = (seen_screens[sn] == 0);
+ seen_screens[sn]++;
+
+ ssi->default_visual =
+ get_visual_resource (ssi->screen, "visualID", "VisualID", False);
+ ssi->current_visual = ssi->default_visual;
+ ssi->current_depth = visual_depth (ssi->screen, ssi->current_visual);
+
+ /* If the screen changed (or if this is the first time) we need
+ a new toplevel shell for this screen's depth.
+ */
+ if (ssi->screen != old_screen)
+ initialize_screen_root_widget (ssi);
+
+ ssi->poll_mouse_last_root_x = -1;
+ ssi->poll_mouse_last_root_y = -1;
+
+ ssi->x = m->x;
+ ssi->y = m->y;
+ ssi->width = m->width;
+ ssi->height = m->height;
+
+# ifndef DEBUG_MULTISCREEN
+ {
+ saver_preferences *p = &si->prefs;
+ if (p->debug_p
+# ifdef QUAD_MODE
+ && !p->quad_p
+# endif
+ )
+ ssi->width /= 2;
+ }
+# endif
+
+ j++;
+ }
+
+ si->default_screen = &si->screens[0];
+ return True;
+}
-/* xscreensaver, Copyright (c) 1991-2006 Jamie Zawinski <jwz@netscape.com>
+/* xscreensaver, Copyright (c) 1991-2008 Jamie Zawinski <jwz@netscape.com>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
return;
ssi = &si->screens[mouse_screen (si)];
+
+ if (!ssi || !ssi->screen)
+ return; /* WTF? Trying to splash while no screens connected? */
+
cmap = DefaultColormapOfScreen (ssi->screen);
sp = (splash_dialog_data *) calloc (1, sizeof(*sp));
attrs.event_mask = (ExposureMask | ButtonPressMask | ButtonReleaseMask);
{
- int sx, sy, w, h;
+ int sx = 0, sy = 0, w, h;
int mouse_x = 0, mouse_y = 0;
{
}
}
- get_screen_viewport (ssi, &sx, &sy, &w, &h, mouse_x, mouse_y, False);
+ x = ssi->x;
+ y = ssi->y;
+ w = ssi->width;
+ h = ssi->height;
if (si->prefs.debug_p) w /= 2;
x = sx + (((w + sp->width) / 2) - sp->width);
y = sy + (((h + sp->height) / 2) - sp->height);
/* stderr.c --- capturing stdout/stderr output onto the screensaver window.
- * xscreensaver, Copyright (c) 1991-2006 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1991-2008 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
}
+/* If the "-log file" command-line option has been specified,
+ open the file for append, and redirect stdout/stderr there.
+ This is called very early, before initialize_stderr().
+ */
+void
+stderr_log_file (saver_info *si)
+{
+ int stdout_fd = 1;
+ int stderr_fd = 2;
+ const char *filename = get_string_resource (si->dpy, "logFile", "LogFile");
+ int fd;
+
+ if (!filename || !*filename) return;
+
+ fd = open (filename, O_WRONLY | O_APPEND | O_CREAT, 0666);
+
+ if (fd < 0)
+ {
+ char buf[255];
+ FAIL:
+ sprintf (buf, "%.100s: %.100s", blurb(), filename);
+ perror (buf);
+ fflush (stderr);
+ fflush (stdout);
+ exit (1);
+ }
+
+ fprintf (stderr, "%s: logging to file %s\n", blurb(), filename);
+
+ if (dup2 (fd, stdout_fd) < 0) goto FAIL;
+ if (dup2 (fd, stderr_fd) < 0) goto FAIL;
+
+ fprintf (stderr, "\n\n"
+ "##########################################################################\n"
+ "%s: logging to \"%s\" at %s\n"
+ "##########################################################################\n"
+ "\n",
+ blurb(), filename, timestring());
+}
+
+
/* If there is anything in the stderr buffer, flush it to the real stderr.
This does no X operations. Call this when exiting to make sure any
last words actually show up.
stderr_callback ((XtPointer) si, &stderr_stdout_read_fd, 0);
- if (stderr_buffer &&
- stderr_tail &&
+ if (stderr_tail &&
stderr_buffer < stderr_tail)
{
*stderr_tail = 0;
case 0:
close (ConnectionNumber (si->dpy)); /* close display fd */
limit_subproc_memory (p->inferior_memory_limit, p->verbose_p);
- hack_subproc_environment (ssi); /* set $DISPLAY */
+ hack_subproc_environment (ssi->screen, ssi->screensaver_window);
if (p->verbose_p)
fprintf (stderr, "%s: %d: spawning \"%s\" in pid %lu.\n",
}
-static void
-spawn_screenhack_1 (saver_screen_info *ssi, Bool first_time_p)
+void
+spawn_screenhack (saver_screen_info *ssi)
{
saver_info *si = ssi->global;
saver_preferences *p = &si->prefs;
- raise_window (si, first_time_p, True, False);
XFlush (si->dpy);
+ if (!monitor_powered_on_p (si))
+ {
+ if (si->prefs.verbose_p)
+ fprintf (stderr,
+ "%s: %d: X says monitor has powered down; "
+ "not launching a hack.\n", blurb(), ssi->number);
+ return;
+ }
+
if (p->screenhacks_count)
{
screenhack *hack;
break;
}
}
-}
-
-
-void
-spawn_screenhack (saver_info *si, Bool first_time_p)
-{
- if (monitor_powered_on_p (si))
- {
- int i;
- for (i = 0; i < si->nscreens; i++)
- {
- saver_screen_info *ssi = &si->screens[i];
- spawn_screenhack_1 (ssi, first_time_p);
- }
- }
- else if (si->prefs.verbose_p)
- fprintf (stderr,
- "%s: X says monitor has powered down; "
- "not launching a hack.\n", blurb());
- store_saver_status (si); /* store current hack numbers */
+ store_saver_status (si); /* store current hack number */
}
void
-kill_screenhack (saver_info *si)
+kill_screenhack (saver_screen_info *ssi)
{
- int i;
- for (i = 0; i < si->nscreens; i++)
- {
- saver_screen_info *ssi = &si->screens[i];
- if (ssi->pid)
- kill_job (si, ssi->pid, SIGTERM);
- ssi->pid = 0;
- }
+ saver_info *si = ssi->global;
+ if (ssi->pid)
+ kill_job (si, ssi->pid, SIGTERM);
+ ssi->pid = 0;
}
void
-suspend_screenhack (saver_info *si, Bool suspend_p)
+suspend_screenhack (saver_screen_info *ssi, Bool suspend_p)
{
#ifdef SIGSTOP /* older VMS doesn't have it... */
- int i;
- for (i = 0; i < si->nscreens; i++)
- {
- saver_screen_info *ssi = &si->screens[i];
- if (ssi->pid)
- kill_job (si, ssi->pid, (suspend_p ? SIGSTOP : SIGCONT));
- }
+ saver_info *si = ssi->global;
+ if (ssi->pid)
+ kill_job (si, ssi->pid, (suspend_p ? SIGSTOP : SIGCONT));
#endif /* SIGSTOP */
}
void
-hack_subproc_environment (saver_screen_info *ssi)
+hack_subproc_environment (Screen *screen, Window saver_window)
{
/* Store $DISPLAY into the environment, so that the $DISPLAY variable that
the spawned processes inherit is correct. First, it must be on the same
us to (eventually) run multiple hacks in Xinerama mode, where each hack
has the same $DISPLAY but a different piece of glass.
*/
- saver_info *si = ssi->global;
- const char *odpy = DisplayString (si->dpy);
+ Display *dpy = DisplayOfScreen (screen);
+ const char *odpy = DisplayString (dpy);
char *ndpy = (char *) malloc (strlen(odpy) + 20);
char *nssw = (char *) malloc (40);
char *s, *c;
while (isdigit(*s)) s++; /* skip over dpy number */
while (*s == '.') s++; /* skip over dot */
if (s[-1] != '.') *s++ = '.'; /* put on a dot */
- sprintf(s, "%d", ssi->real_screen_number); /* put on screen number */
+ sprintf(s, "%d", screen_number (screen)); /* put on screen number */
- sprintf (nssw, "XSCREENSAVER_WINDOW=0x%lX",
- (unsigned long) ssi->screensaver_window);
+ sprintf (nssw, "XSCREENSAVER_WINDOW=0x%lX", (unsigned long) saver_window);
/* Allegedly, BSD 4.3 didn't have putenv(), but nobody runs such systems
any more, right? It's not Posix, but everyone seems to have it. */
/* GL crap */
Visual *
-get_best_gl_visual (saver_screen_info *ssi)
+get_best_gl_visual (saver_info *si, Screen *screen)
{
- saver_info *si = ssi->global;
pid_t forked;
int fds [2];
int in, out;
in = fds [0];
out = fds [1];
+ block_sigchld(); /* This blocks it in the parent and child, to avoid
+ racing. It is never unblocked in the child before
+ the child exits, but that doesn't matter.
+ */
+
switch ((int) (forked = fork ()))
{
case -1:
perror ("could not dup() a new stdout:");
return 0;
}
- hack_subproc_environment (ssi); /* set $DISPLAY */
+ hack_subproc_environment (screen, 0); /* set $DISPLAY */
execvp (av[0], av); /* shouldn't return. */
/* Wait for the child to die. */
waitpid (-1, &wait_status, 0);
+ unblock_sigchld(); /* child is dead and waited, unblock now. */
+
if (1 == sscanf (buf, "0x%lx %c", &v, &c))
result = (int) v;
}
else
{
- Visual *v = id_to_visual (ssi->screen, result);
+ Visual *v = id_to_visual (screen, result);
if (si->prefs.verbose_p)
fprintf (stderr, "%s: %d: %s: GL visual is 0x%X%s.\n",
- blurb(), ssi->number,
+ blurb(), screen_number (screen),
av[0], result,
- (v == ssi->default_visual ? " (default)" : ""));
+ (v == DefaultVisualOfScreen (screen)
+ ? " (default)" : ""));
return v;
}
}
-/* xscreensaver, Copyright (c) 1998-2007 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1998-2008 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
const char *blurb(void) { return progname; }
Atom XA_SCREENSAVER, XA_DEMO, XA_PREFS;
-void
-get_screen_viewport (saver_screen_info *ssi,
- int *x_ret, int *y_ret,
- int *w_ret, int *h_ret,
- int tx, int ty,
- Bool verbose_p)
-{
- *x_ret = 0;
- *y_ret = 0;
- *w_ret = WidthOfScreen (ssi->screen);
- *h_ret = HeightOfScreen (ssi->screen);
-
- if (*w_ret > *h_ret * 2) *w_ret /= 2; /* xinerama kludge */
-}
-
void
idle_timer (XtPointer closure, XtIntervalId *id)
{
visual_depth(si->default_screen->screen,
si->default_screen->current_visual);
- /* I could call get_screen_viewport(), but it is not worthwhile.
- * These are used by the save_under pixmap. */
ssip.width = WidthOfScreen(ssip.screen);
ssip.height = HeightOfScreen(ssip.screen);
pw = getpwuid (getuid ());
si->user = strdup (pw->pw_name);
+/* si->nscreens = 0;
+ si->screens = si->default_screen = 0; */
+
while (1)
{
#ifndef NO_LOCKING
/* test-randr.c --- playing with the Resize And Rotate extension.
- * xscreensaver, Copyright (c) 2004, 2005 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 2004-2008 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
fprintf(stderr, "%s: XRRGetScreenInfo(dpy, %d) ==> NULL\n",
blurb(), i);
}
+
+
+# ifdef HAVE_RANDR_12
+ if (major > 1 || (major == 1 && minor >= 2))
+ {
+ int j;
+ XRRScreenResources *res =
+ XRRGetScreenResources (dpy, RootWindow (dpy, i));
+ fprintf (stderr, "\n");
+ for (j = 0; j < res->noutput; j++)
+ {
+ int k;
+ XRROutputInfo *rroi =
+ XRRGetOutputInfo (dpy, res, res->outputs[j]);
+ fprintf (stderr, "%s: Output %d: %s: %s (%d)\n", blurb(), j,
+ rroi->name,
+ (rroi->connection == RR_Disconnected ? "disconnected" :
+ rroi->connection == RR_UnknownConnection ? "unknown" :
+ "connected"),
+ (int) rroi->crtc);
+ for (k = 0; k < rroi->ncrtc; k++)
+ {
+ XRRCrtcInfo *crtci = XRRGetCrtcInfo (dpy, res,
+ rroi->crtcs[k]);
+ fprintf(stderr, "%s: %c CRTC %d (%d): %dx%d+%d+%d\n",
+ blurb(),
+ (rroi->crtc == rroi->crtcs[k] ? '+' : ' '),
+ k, (int) rroi->crtcs[k],
+ crtci->width, crtci->height, crtci->x, crtci->y);
+ XRRFreeCrtcInfo (crtci);
+ }
+ XRRFreeOutputInfo (rroi);
+ fprintf (stderr, "\n");
+ }
+ XRRFreeScreenResources (res);
+ }
+# endif /* HAVE_RANDR_12 */
}
if (major > 0)
--- /dev/null
+/* test-screens.c --- some test cases for the "monitor sanity" checks.
+ * xscreensaver, Copyright (c) 2008 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
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <X11/Xlib.h>
+
+/* This file doesn't need the Xt headers, so stub these types out... */
+#undef XtPointer
+#define XtAppContext void*
+#define XrmDatabase void*
+#define XtIntervalId void*
+#define XtPointer void*
+#define Widget void*
+
+#include "xscreensaver.h"
+#include "visual.h"
+
+#undef WidthOfScreen
+#undef HeightOfScreen
+#define WidthOfScreen(s) 10240
+#define HeightOfScreen(s) 10240
+
+#undef screen_number
+#define screen_number(s) (0)
+
+#include "screens.c" /* to get at static void check_monitor_sanity() */
+
+char *progname = 0;
+char *progclass = "XScreenSaver";
+
+const char *blurb(void) { return progname; }
+
+Bool safe_XF86VidModeGetViewPort(Display *d, int i, int *x, int *y) { abort(); }
+void initialize_screen_root_widget(saver_screen_info *ssi) { abort(); }
+Visual *get_best_gl_visual (saver_info *si, Screen *sc) { abort(); }
+
+
+static const char *
+failstr (monitor_sanity san)
+{
+ switch (san) {
+ case S_SANE: return "OK";
+ case S_ENCLOSED: return "ENC";
+ case S_DUPLICATE: return "DUP";
+ case S_OVERLAP: return "OVR";
+ case S_OFFSCREEN: return "OFF";
+ case S_DISABLED: return "DIS";
+ }
+}
+
+
+static void
+test (int testnum, const char *screens, const char *desired)
+{
+ monitor *monitors[100];
+ char result[2048];
+ char *out = result;
+ int i, nscreens = 0;
+ char *token = strtok (strdup(screens), ",");
+ while (token)
+ {
+ monitor *m = calloc (1, sizeof (monitor));
+ char c;
+ m->id = (testnum * 1000) + nscreens;
+ if (4 != sscanf (token, "%dx%d+%d+%d%c",
+ &m->width, &m->height, &m->x, &m->y, &c))
+ {
+ fprintf (stderr, "%s: unparsable geometry: %s\n", blurb(), token);
+ exit (1);
+ }
+ monitors[nscreens] = m;
+ nscreens++;
+ token = strtok (0, ",");
+ }
+ monitors[nscreens] = 0;
+
+ check_monitor_sanity (monitors);
+
+ *out = 0;
+ for (i = 0; i < nscreens; i++)
+ {
+ monitor *m = monitors[i];
+ if (out != result) *out++ = ',';
+ if (m->sanity == S_SANE)
+ sprintf (out, "%dx%d+%d+%d", m->width, m->height, m->x, m->y);
+ else
+ strcpy (out, failstr (m->sanity));
+ out += strlen(out);
+ }
+ *out = 0;
+
+ if (!strcmp (result, desired))
+ fprintf (stderr, "%s: test %2d OK\n", blurb(), testnum);
+ else
+ fprintf (stderr, "%s: test %2d FAILED:\n"
+ "%s: given: %s\n"
+ "%s: wanted: %s\n"
+ "%s: got: %s\n",
+ blurb(), testnum,
+ blurb(), screens,
+ blurb(), desired,
+ blurb(), result);
+
+# if 0
+ {
+ saver_info SI;
+ SI.monitor_layout = monitors;
+ describe_monitor_layout (&SI);
+ }
+# endif
+
+}
+
+static void
+run_tests(void)
+{
+ int i = 1;
+# define A(a) test (i++, a, a);
+# define B(a,b) test (i++, a, b)
+
+ A("");
+ A("1024x768+0+0");
+ A("1024x768+0+0,1024x768+1024+0");
+ A("1024x768+0+0,1024x768+0+768");
+ A("1024x768+0+0,1024x768+0+768,1024x768+1024+0");
+
+ B("1024x768+999999+0",
+ "OFF");
+ B("1024x768+-999999+-999999",
+ "OFF");
+ B("1024x768+0+0,1024x768+0+0",
+ "1024x768+0+0,DUP");
+ B("1024x768+0+0,1024x768+0+0,1024x768+0+0",
+ "1024x768+0+0,DUP,DUP");
+ B("1024x768+0+0,1024x768+1024+0,1024x768+0+0",
+ "1024x768+0+0,1024x768+1024+0,DUP");
+ B("1280x1024+0+0,1024x768+0+64,800x600+0+0,640x480+0+0,720x400+0+0",
+ "1280x1024+0+0,ENC,ENC,ENC,ENC");
+ B("1024x768+0+64,1280x1024+0+0,800x600+0+0,640x480+0+0,800x600+0+0,720x400+0+0",
+ "ENC,1280x1024+0+0,ENC,ENC,ENC,ENC");
+ B("1024x768+0+64,1280x1024+0+0,800x600+0+0,640x480+0+0,1280x1024+0+0,720x400+0+0",
+ "ENC,1280x1024+0+0,ENC,ENC,DUP,ENC");
+ B("720x400+0+0,640x480+0+0,800x600+0+0,1024x768+0+64,1280x1024+0+0",
+ "ENC,ENC,ENC,ENC,1280x1024+0+0");
+ B("1280x1024+0+0,800x600+1280+0,800x600+1300+0",
+ "1280x1024+0+0,800x600+1280+0,OVR");
+ B("1280x1024+0+0,800x600+1280+0,800x600+1300+0,1280x1024+0+0,800x600+1280+0",
+ "1280x1024+0+0,800x600+1280+0,OVR,DUP,DUP");
+
+ /* +-------------+----+ +------+---+ 1: 1440x900, widescreen display
+ | : | | 3+4 : | 2: 1280x1024, conventional display
+ | 1+2 : 1 | +......+ | 3: 1024x768, laptop
+ | : | | 3 | 4: 800x600, external projector
+ +.............+----+ +----------+
+ | 2 |
+ | |
+ +-------------+
+ */
+ B("1440x900+0+0,1280x1024+0+0,1024x768+1440+0,800x600+1440+0",
+ "1440x900+0+0,OVR,1024x768+1440+0,ENC");
+ B("800x600+0+0,800x600+0+0,800x600+800+0",
+ "800x600+0+0,DUP,800x600+800+0");
+ B("1600x1200+0+0,1360x768+0+0",
+ "1600x1200+0+0,ENC");
+}
+
+
+int
+main (int argc, char **argv)
+{
+ char *s;
+ progname = argv[0];
+ s = strrchr(progname, '/');
+ if (s) progname = s+1;
+ if (argc != 1)
+ {
+ fprintf (stderr, "usage: %s\n", argv[0]);
+ exit (1);
+ }
+
+ run_tests();
+
+ exit (0);
+}
}
else
{
+ int i;
maybe_reload_init_file (si);
- kill_screenhack (si);
+ for (i = 0; i < si->nscreens; i++)
+ kill_screenhack (&si->screens[i]);
+
+ raise_window (si, True, True, False);
if (!si->throttled_p)
- spawn_screenhack (si, False);
+ for (i = 0; i < si->nscreens; i++)
+ spawn_screenhack (&si->screens[i]);
else
{
- raise_window (si, True, True, False);
if (p->verbose_p)
fprintf (stderr, "%s: not launching new hack (throttled.)\n",
blurb());
if (event.type == (si->randr_event_number + RRScreenChangeNotify))
{
/* The Resize and Rotate extension sends an event when the
- size, rotation, or refresh rate of the screen has changed. */
-
+ size, rotation, or refresh rate of any screen has changed.
+ */
XRRScreenChangeNotifyEvent *xrr_event =
(XRRScreenChangeNotifyEvent *) &event;
- /* XRRRootToScreen is in Xrandr.h 1.4, 2001/06/07 */
- int screen = XRRRootToScreen (si->dpy, xrr_event->window);
if (p->verbose_p)
{
- if (si->screens[screen].width == xrr_event->width &&
- si->screens[screen].height == xrr_event->height)
- fprintf (stderr,
- "%s: %d: no-op screen size change event (%dx%d)\n",
- blurb(), screen,
- xrr_event->width, xrr_event->height);
- else
- fprintf (stderr,
- "%s: %d: screen size changed from %dx%d to %dx%d\n",
- blurb(), screen,
- si->screens[screen].width,
- si->screens[screen].height,
- xrr_event->width, xrr_event->height);
+ /* XRRRootToScreen is in Xrandr.h 1.4, 2001/06/07 */
+ int screen = XRRRootToScreen (si->dpy, xrr_event->window);
+ fprintf (stderr, "%s: %d: screen change event received\n",
+ blurb(), screen);
}
# ifdef RRScreenChangeNotifyMask
# endif /* RRScreenChangeNotifyMask */
/* Resize the existing xscreensaver windows and cached ssi data. */
- resize_screensaver_window (si);
+ if (update_screen_layout (si))
+ {
+ if (p->verbose_p)
+ {
+ fprintf (stderr, "%s: new layout:\n", blurb());
+ describe_monitor_layout (si);
+ }
+ resize_screensaver_window (si);
+ }
}
else
#endif /* HAVE_RANDR */
if (screenhack_running_p (si) &&
!monitor_powered_on_p (si))
{
+ int i;
if (si->prefs.verbose_p)
fprintf (stderr,
"%s: X says monitor has powered down; "
"killing running hacks.\n", blurb());
- kill_screenhack (si);
+ for (i = 0; i < si->nscreens; i++)
+ kill_screenhack (&si->screens[i]);
}
/* Re-schedule this timer. The watchdog timer defaults to a bit less
-/* types.h
- *
- * This file is part of XScreenSaver,
- * Copyright (c) 1993-2004 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1993-2008 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
* implied warranty.
*/
-#ifndef TYPES_H
-#define TYPES_H
+#ifndef __XSCREENSAVER_TYPES_H__
+#define __XSCREENSAVER_TYPES_H__
typedef struct saver_info saver_info;
-/* Unlock states. Old pw_* equivalents in square brackets:
- * ul_read - reading input (or ready to do so) [pw_read]
- * ul_success - auth success, unlock the screen [pw_ok]
- * ul_fail - authentication failed [pw_fail]
- * ul_cancel - user cancelled auth [pw_cancel or pw_null]
- * ul_time - timed out, user took too long [pw_time]
- * ul_finished - user pressed enter on the current prompt, process input
- */
-enum unlock_state { ul_read, ul_success, ul_fail, ul_cancel, ul_time, ul_finished };
+typedef enum {
+ ul_read, /* reading input or ready to do so */
+ ul_success, /* auth success, unlock */
+ ul_fail, /* auth fail */
+ ul_cancel, /* user cancelled auth (pw_cancel or pw_null) */
+ ul_time, /* timed out */
+ ul_finished /* user pressed enter */
+} unlock_state;
typedef struct screenhack screenhack;
struct screenhack {
typedef struct saver_screen_info saver_screen_info;
typedef struct passwd_dialog_data passwd_dialog_data;
typedef struct splash_dialog_data splash_dialog_data;
+typedef struct _monitor monitor;
/* This structure holds all the user-specified parameters, read from the
saver_preferences prefs;
int nscreens;
+ int ssi_count;
saver_screen_info *screens;
saver_screen_info *default_screen; /* ...on which dialogs will appear. */
-
+ monitor **monitor_layout; /* private to screens.c */
+ Visual **best_gl_visuals; /* visuals for GL hacks on screen N */
/* =======================================================================
global connection info
server extension info
======================================================================= */
- Bool xinerama_p; /* Whether Xinerama is in use. */
Bool using_xidle_extension; /* which extension is being used. */
Bool using_mit_saver_extension; /* Note that `p->use_*' is the *request*, */
Bool using_sgi_saver_extension; /* and `si->using_*' is the *reality*. */
char *user; /* The user whose session is locked. */
char *cached_passwd; /* Cached password, used to avoid multiple
prompts for password-only auth mechanisms.*/
- enum unlock_state unlock_state;
+ unlock_state unlock_state;
auth_conv_cb_t unlock_cb; /* The function used to prompt for creds. */
void (*auth_finished_cb) (saver_info *si);
int current_depth; /* How deep the visual (and the window) are. */
Visual *default_visual; /* visual to use when none other specified */
- Visual *best_gl_visual; /* visual to use for GL hacks */
Window real_vroot; /* The original virtual-root window. */
Window real_vroot_value; /* What was in the __SWM_VROOT property. */
};
-#endif
+#endif /* __XSCREENSAVER_TYPES_H__ */
}
+static void
+ungrab_keyboard_and_mouse (saver_info *si)
+{
+ ungrab_mouse (si);
+ ungrab_kbd (si);
+}
+
+
static Bool
grab_keyboard_and_mouse (saver_info *si, Window window, Cursor cursor,
int screen_no)
*/
if (kstatus != GrabSuccess) /* Do not blank without a kbd grab. */
- return False;
+ {
+ /* If we didn't get both grabs, release the one we did get. */
+ ungrab_keyboard_and_mouse (si);
+ return False;
+ }
return True; /* Grab is good, go ahead and blank. */
}
-static void
-ungrab_keyboard_and_mouse (saver_info *si)
-{
- ungrab_mouse (si);
- ungrab_kbd (si);
-}
-
int
move_mouse_grab (saver_info *si, Window to, Cursor cursor, int to_screen_no)
(char *) id);
status = True;
}
+
+ else if (XGetWindowProperty (dpy, kids[i], XA_WM_COMMAND, 0, 128,
+ False, XA_STRING, &type, &format, &nitems,
+ &bytesafter, &version)
+ == Success
+ && type != None
+ && !strcmp ((char *) version, "gnome-screensaver"))
+ {
+ fprintf (stderr,
+ "%s: \"%s\" is already running on display %s (window 0x%x)\n",
+ blurb(), (char *) version,
+ DisplayString (dpy), (int) kids [i]);
+ status = True;
+ break;
+ }
}
if (kids) XFree ((char *) kids);
static Bool safe_XKillClient (Display *dpy, XID id);
-#ifdef HAVE_XF86VMODE
-static Bool safe_XF86VidModeGetViewPort (Display *, int, int *, int *);
-#endif /* HAVE_XF86VMODE */
-
-
static void
kill_xsetroot_data_1 (Display *dpy, Window window,
Atom prop, const char *atom_name,
fprintf (stderr,
"%s: restoring __SWM_VROOT property on the real vroot (0x%lx).\n",
blurb(), (unsigned long) ssi->real_vroot);
- remove_vroot_property (si->dpy, ssi->screensaver_window);
+ if (ssi->screensaver_window)
+ remove_vroot_property (si->dpy, ssi->screensaver_window);
if (ssi->real_vroot)
{
store_vroot_property (si->dpy, ssi->real_vroot, ssi->real_vroot_value);
if (si->screen_blanked_p)
{
+ int i;
+ for (i = 0; i < si->nscreens; i++)
+ kill_screenhack (&si->screens[i]);
unblank_screen (si);
- kill_screenhack (si);
XSync (si->dpy, False);
}
}
-
-/* Returns the area of the screen which the xscreensaver window should cover.
- Normally this is the whole screen, but if the X server's root window is
- actually larger than the monitor's displayable area, then we want to
- operate in the currently-visible portion of the desktop instead.
- */
-void
-get_screen_viewport (saver_screen_info *ssi,
- int *x_ret, int *y_ret,
- int *w_ret, int *h_ret,
- int target_x, int target_y,
- Bool verbose_p)
-{
- int w = WidthOfScreen (ssi->screen);
- int h = HeightOfScreen (ssi->screen);
-
-# ifdef HAVE_XF86VMODE
- saver_info *si = ssi->global;
- saver_preferences *p = &si->prefs;
- int event, error;
- int dot;
- XF86VidModeModeLine ml;
- int x, y;
- Bool xinerama_p = si->xinerama_p;
-
-# ifndef HAVE_XINERAMA
- /* Even if we don't have the client-side Xinerama lib, check to see if
- the server supports Xinerama, so that we know to ignore the VidMode
- extension -- otherwise a server crash could result. Yay. */
- xinerama_p = XQueryExtension (si->dpy, "XINERAMA", &error, &event, &error);
-# endif /* !HAVE_XINERAMA */
-
-# ifdef HAVE_XINERAMA
- if (xinerama_p)
- {
- int mouse_p = (target_x != -1 && target_y != -1);
- int which = -1;
- int i;
-
- /* If a mouse position wasn't passed in, assume we're talking about
- this screen. */
- if (!mouse_p)
- {
- target_x = ssi->x;
- target_y = ssi->y;
- which = ssi->number;
- }
-
- /* Find the Xinerama rectangle that contains the mouse position. */
- for (i = 0; i < si->nscreens; i++)
- {
- if (which == -1 &&
- target_x >= si->screens[i].x &&
- target_y >= si->screens[i].y &&
- target_x < si->screens[i].x + si->screens[i].width &&
- target_y < si->screens[i].y + si->screens[i].height)
- which = i;
- }
- if (which == -1) which = 0; /* didn't find it? Use the first. */
- *x_ret = si->screens[which].x;
- *y_ret = si->screens[which].y;
- *w_ret = si->screens[which].width;
- *h_ret = si->screens[which].height;
-
- if (verbose_p)
- {
- fprintf (stderr, "%s: %d: xinerama vp: %dx%d+%d+%d",
- blurb(), which,
- si->screens[which].width, si->screens[which].height,
- si->screens[which].x, si->screens[which].y);
- if (mouse_p)
- fprintf (stderr, "; mouse at %d,%d", target_x, target_y);
- fprintf (stderr, ".\n");
- }
-
- return;
- }
-# endif /* HAVE_XINERAMA */
-
- if (!xinerama_p && /* Xinerama + VidMode = broken. */
- XF86VidModeQueryExtension (si->dpy, &event, &error) &&
- safe_XF86VidModeGetViewPort (si->dpy, ssi->number, &x, &y) &&
- XF86VidModeGetModeLine (si->dpy, ssi->number, &dot, &ml))
- {
- char msg[512];
- *x_ret = x;
- *y_ret = y;
- *w_ret = ml.hdisplay;
- *h_ret = ml.vdisplay;
-
- if (*x_ret == 0 && *y_ret == 0 && *w_ret == w && *h_ret == h)
- /* There is no viewport -- the screen does not scroll. */
- return;
-
-
- /* Apparently some versions of XFree86 return nonsense here!
- I've had reports of 1024x768 viewports at -1936862040, -1953705044.
- So, sanity-check the values and give up if they are out of range.
- */
- if (*x_ret < 0 || *x_ret >= w ||
- *y_ret < 0 || *y_ret >= h ||
- *w_ret <= 0 || *w_ret > w ||
- *h_ret <= 0 || *h_ret > h)
- {
- static int warned_once = 0;
- if (!warned_once)
- {
- fprintf (stderr, "\n"
- "%s: X SERVER BUG: %dx%d viewport at %d,%d is impossible.\n"
- "%s: The XVidMode server extension is returning nonsense.\n"
- "%s: Please report this bug to your X server vendor.\n\n",
- blurb(), *w_ret, *h_ret, *x_ret, *y_ret,
- blurb(), blurb());
- warned_once = 1;
- }
- *x_ret = 0;
- *y_ret = 0;
- *w_ret = w;
- *h_ret = h;
- return;
- }
-
- sprintf (msg, "%s: %d: vp is %dx%d+%d+%d",
- blurb(), ssi->number,
- *w_ret, *h_ret, *x_ret, *y_ret);
-
-
- if (p->getviewport_full_of_lies_p)
- {
- /* XF86VidModeGetViewPort() tends to be full of lies on laptops
- that have a docking station or external monitor that runs in
- a different resolution than the laptop's screen:
-
- http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=81593
- http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=208417
- http://bugs.xfree86.org/show_bug.cgi?id=421
-
- The XFree86 developers have closed the bug. As far as I can
- tell, their reason for this was, "this is an X server bug,
- but it's pretty hard to fix. Therefore, we are closing it."
-
- So, now there's a preference item for those unfortunate users to
- tell us not to trust a word that XF86VidModeGetViewPort() says.
- */
- static int warned_once = 0;
- if (!warned_once && verbose_p)
- {
- warned_once = 1;
- fprintf (stderr,
- "%s: %d: XF86VidModeGetViewPort() says vp is %dx%d+%d+%d;\n"
- "%s: %d: assuming that is a pack of lies;\n"
- "%s: %d: using %dx%d+0+0 instead.\n",
- blurb(), ssi->number,
- *w_ret, *h_ret, *x_ret, *y_ret,
- blurb(), ssi->number,
- blurb(), ssi->number, w, h);
- }
-
- *x_ret = 0;
- *y_ret = 0;
- *w_ret = w;
- *h_ret = h;
- return;
- }
-
-
- /* Apparently, though the server stores the X position in increments of
- 1 pixel, it will only make changes to the *display* in some other
- increment. With XF86_SVGA on a Thinkpad, the display only updates
- in multiples of 8 pixels when in 8-bit mode, and in multiples of 4
- pixels in 16-bit mode. I don't know what it does in 24- and 32-bit
- mode, because I don't have enough video memory to find out.
-
- I consider it a bug that XF86VidModeGetViewPort() is telling me the
- server's *target* scroll position rather than the server's *actual*
- scroll position. David Dawes agrees, and says they may fix this in
- XFree86 4.0, but it's notrivial.
-
- He also confirms that this behavior is server-dependent, so the
- actual scroll position cannot be reliably determined by the client.
- So... that means the only solution is to provide a ``sandbox''
- around the blackout window -- we make the window be up to N pixels
- larger than the viewport on both the left and right sides. That
- means some part of the outer edges of each hack might not be
- visible, but screw it.
-
- I'm going to guess that 16 pixels is enough, and that the Y dimension
- doesn't have this problem.
-
- The drawback of doing this, of course, is that some of the screenhacks
- will still look pretty stupid -- for example, "slidescreen" will cut
- off the left and right edges of the grid, etc.
- */
-# define FUDGE 16
- if (x > 0 && x < w - ml.hdisplay) /* not at left edge or right edge */
- {
- /* Round X position down to next lower multiple of FUDGE.
- Increase width by 2*FUDGE in case some server rounds up.
- */
- *x_ret = ((x - 1) / FUDGE) * FUDGE;
- *w_ret += (FUDGE * 2);
- }
-# undef FUDGE
-
- if (*x_ret != x ||
- *y_ret != y ||
- *w_ret != ml.hdisplay ||
- *h_ret != ml.vdisplay)
- sprintf (msg + strlen(msg), "; fudged to %dx%d+%d+%d",
- *w_ret, *h_ret, *x_ret, *y_ret);
-
- if (verbose_p)
- fprintf (stderr, "%s.\n", msg);
-
- return;
- }
-
-# endif /* HAVE_XF86VMODE */
-
- *x_ret = 0;
- *y_ret = 0;
- *w_ret = w;
- *h_ret = h;
-}
-
-
static Bool error_handler_hit_p = False;
static int
#ifdef HAVE_XF86VMODE
-static Bool
+Bool
safe_XF86VidModeGetViewPort (Display *dpy, int screen, int *xP, int *yP)
{
Bool result;
XColor black;
XSetWindowAttributes attrs;
unsigned long attrmask;
- int x, y, width, height;
static Bool printed_visual_info = False; /* only print the message once. */
Window horked_window = 0;
- get_screen_viewport (ssi, &x, &y, &width, &height, -1, -1,
- (p->verbose_p && !si->screen_blanked_p));
-
black.red = black.green = black.blue = 0;
if (ssi->cmap == DefaultColormapOfScreen (ssi->screen))
attrs.backing_pixel = ssi->black_pixel;
attrs.border_pixel = ssi->black_pixel;
- if (p->debug_p
-# ifdef QUAD_MODE
- && !p->quad_p
-# endif
- )
- width = width / 2;
-
if (!p->verbose_p || printed_visual_info)
;
else if (ssi->current_visual == DefaultVisualOfScreen (ssi->screen))
{
XWindowChanges changes;
unsigned int changesmask = CWX|CWY|CWWidth|CWHeight|CWBorderWidth;
- changes.x = x;
- changes.y = y;
- changes.width = width;
- changes.height = height;
+ changes.x = ssi->x;
+ changes.y = ssi->y;
+ changes.width = ssi->width;
+ changes.height = ssi->height;
changes.border_width = 0;
if (! (safe_XConfigureWindow (si->dpy, ssi->screensaver_window,
{
ssi->screensaver_window =
XCreateWindow (si->dpy, RootWindowOfScreen (ssi->screen),
- x, y, width, height,
+ ssi->x, ssi->y, ssi->width, ssi->height,
0, ssi->current_depth, InputOutput,
ssi->current_visual, attrmask, &attrs);
-
reset_stderr (ssi);
if (horked_window)
}
-/* Called when the RANDR (Resize and Rotate) extension tells us that the
- size of the screen has changed while the screen was blanked. If we
- don't do this, then the screen saver will no longer fully fill the
- screen, and some of the underlying desktop may be visible.
+/* Called when the RANDR (Resize and Rotate) extension tells us that
+ the size of the screen has changed while the screen was blanked.
+ Call update_screen_layout() first, then call this to synchronize
+ the size of the saver windows to the new sizes of the screens.
*/
void
resize_screensaver_window (saver_info *si)
saver_preferences *p = &si->prefs;
int i;
- /* First update the size info in the saver_screen_info structs.
- */
-
-# ifdef HAVE_XINERAMA
- if (si->xinerama_p)
+ for (i = 0; i < si->nscreens; i++)
{
- /* As of XFree86 4.3.0, the RANDR and XINERAMA extensions cannot coexist.
- However, maybe they will someday, so I'm guessing that the right thing
- to do in that case will be to re-query the Xinerama rectangles after
- a RANDR size change is received: presumably, if the resolution of one
- or more of the monitors has changed, then the Xinerama rectangle
- corresponding to that monitor will also have been updated.
- */
- int nscreens;
- XineramaScreenInfo *xsi = XineramaQueryScreens (si->dpy, &nscreens);
-
- if (nscreens != si->nscreens) {
- /* Apparently some Xinerama implementations let you use a hot-key
- to change the number of screens in use! This is, of course,
- documented nowhere. Let's try to do something marginally less
- bad than crashing.
- */
- fprintf (stderr, "%s: bad craziness: xinerama screen count changed "
- "from %d to %d!\n", blurb(), si->nscreens, nscreens);
- if (nscreens > si->nscreens)
- nscreens = si->nscreens;
- }
+ saver_screen_info *ssi = &si->screens[i];
+ XWindowAttributes xgwa;
- if (!xsi) abort();
- for (i = 0; i < nscreens; i++)
+ /* Make sure a window exists -- it might not if a monitor was just
+ added for the first time.
+ */
+ if (! ssi->screensaver_window)
{
- saver_screen_info *ssi = &si->screens[i];
- if (p->verbose_p &&
- (ssi->x != xsi[i].x_org ||
- ssi->y != xsi[i].y_org ||
- ssi->width != xsi[i].width ||
- ssi->height != xsi[i].height))
+ initialize_screensaver_window_1 (ssi);
+ if (p->verbose_p)
fprintf (stderr,
- "%s: %d: resize xinerama from %dx%d+%d+%d to %dx%d+%d+%d\n",
- blurb(), i,
- ssi->width, ssi->height, ssi->x, ssi->y,
- xsi[i].width, xsi[i].height, xsi[i].x_org, xsi[i].y_org);
-
- ssi->x = xsi[i].x_org;
- ssi->y = xsi[i].y_org;
- ssi->width = xsi[i].width;
- ssi->height = xsi[i].height;
+ "%s: %d: newly added window 0x%lx %dx%d+%d+%d\n",
+ blurb(), i, (unsigned long) ssi->screensaver_window,
+ ssi->width, ssi->height, ssi->x, ssi->y);
}
- XFree (xsi);
- }
- else
-# endif /* HAVE_XINERAMA */
- {
- /* Not Xinerama -- get the real sizes of the root windows. */
- for (i = 0; i < si->nscreens; i++)
+
+ /* Make sure the window is the right size -- it might not be if
+ the monitor changed resolution, or if a badly-behaved hack
+ screwed with it.
+ */
+ XGetWindowAttributes (si->dpy, ssi->screensaver_window, &xgwa);
+ if (xgwa.x != ssi->x ||
+ xgwa.y != ssi->y ||
+ xgwa.width != ssi->width ||
+ xgwa.height != ssi->height)
{
- saver_screen_info *ssi = &si->screens[i];
- XWindowAttributes xgwa;
- XGetWindowAttributes (si->dpy, RootWindowOfScreen (ssi->screen),
- &xgwa);
-
- if (p->verbose_p &&
- (ssi->x != xgwa.x ||
- ssi->y != xgwa.y ||
- ssi->width != xgwa.width ||
- ssi->height != xgwa.height))
+ XWindowChanges changes;
+ unsigned int changesmask = CWX|CWY|CWWidth|CWHeight|CWBorderWidth;
+ changes.x = ssi->x;
+ changes.y = ssi->y;
+ changes.width = ssi->width;
+ changes.height = ssi->height;
+ changes.border_width = 0;
+
+ if (p->verbose_p)
fprintf (stderr,
- "%s: %d: resize screen from %dx%d+%d+%d to %dx%d+%d+%d\n",
- blurb(), i,
- ssi->width, ssi->height, ssi->x, ssi->y,
- xgwa.width, xgwa.height, xgwa.x, xgwa.y);
-
- ssi->x = xgwa.x;
- ssi->y = xgwa.y;
- ssi->width = xgwa.width;
- ssi->height = xgwa.height;
+ "%s: %d: resize 0x%lx from %dx%d+%d+%d to %dx%d+%d+%d\n",
+ blurb(), i, (unsigned long) ssi->screensaver_window,
+ xgwa.width, xgwa.height, xgwa.x, xgwa.y,
+ ssi->width, ssi->height, ssi->x, ssi->y);
+
+ if (! safe_XConfigureWindow (si->dpy, ssi->screensaver_window,
+ changesmask, &changes))
+ fprintf (stderr, "%s: %d: someone horked our saver window"
+ " (0x%lx)! Unable to resize it!\n",
+ blurb(), i, (unsigned long) ssi->screensaver_window);
+ }
+
+ /* Now (if blanked) make sure that it's mapped and running a hack --
+ it might not be if we just added it. (We also might be re-using
+ an old window that existed for a previous monitor that was
+ removed and re-added.)
+
+ Note that spawn_screenhack() calls select_visual() which may destroy
+ and re-create the window via initialize_screensaver_window_1().
+ */
+ if (si->screen_blanked_p)
+ {
+ if (ssi->cmap)
+ XInstallColormap (si->dpy, ssi->cmap);
+ XMapRaised (si->dpy, ssi->screensaver_window);
+ if (! ssi->pid)
+ spawn_screenhack (ssi);
+
+ /* Make sure the act of adding a screen doesn't present as
+ pointer motion (and thus cause an unblank). */
+ {
+ Window root, child;
+ int x, y;
+ unsigned int mask;
+ XQueryPointer (si->dpy, ssi->screensaver_window, &root, &child,
+ &ssi->poll_mouse_last_root_x,
+ &ssi->poll_mouse_last_root_y,
+ &x, &y, &mask);
+ }
}
}
- /* Next, ensure that the screensaver windows are the right size, taking
- into account both the new size of the screen in question's root window,
- and any viewport within that.
+ /* Kill off any savers running on no-longer-extant monitors.
*/
-
- for (i = 0; i < si->nscreens; i++)
+ for (; i < si->ssi_count; i++)
{
saver_screen_info *ssi = &si->screens[i];
- XWindowAttributes xgwa;
- XWindowChanges changes;
- int x, y, width, height;
- unsigned int changesmask = CWX|CWY|CWWidth|CWHeight|CWBorderWidth;
-
- XGetWindowAttributes (si->dpy, ssi->screensaver_window, &xgwa);
- get_screen_viewport (ssi, &x, &y, &width, &height, -1, -1,
- (p->verbose_p && !si->screen_blanked_p));
- if (xgwa.x == x &&
- xgwa.y == y &&
- xgwa.width == width &&
- xgwa.height == height)
- continue; /* no change! */
-
- changes.x = x;
- changes.y = y;
- changes.width = width;
- changes.height = height;
- changes.border_width = 0;
-
- if (p->debug_p
-# ifdef QUAD_MODE
- && !p->quad_p
-# endif
- )
- changes.width = changes.width / 2;
-
- if (p->verbose_p)
- fprintf (stderr,
- "%s: %d: resize 0x%lx from %dx%d+%d+%d to %dx%d+%d+%d\n",
- blurb(), i, (unsigned long) ssi->screensaver_window,
- xgwa.width, xgwa.height, xgwa.x, xgwa.y,
- width, height, x, y);
- if (! safe_XConfigureWindow (si->dpy, ssi->screensaver_window,
- changesmask, &changes))
+ if (ssi->pid)
+ kill_screenhack (ssi);
+ if (ssi->screensaver_window)
{
- fprintf (stderr,
- "%s: %d: someone horked our saver window (0x%lx)! Unable to resize it!\n",
- blurb(), i, (unsigned long) ssi->screensaver_window);
+ XUnmapWindow (si->dpy, ssi->screensaver_window);
+ restore_real_vroot_1 (ssi);
}
}
}
}
+static Visual *
+get_screen_gl_visual (saver_info *si, int real_screen_number)
+{
+ int i;
+ int nscreens = ScreenCount (si->dpy);
+
+ if (! si->best_gl_visuals)
+ si->best_gl_visuals = (Visual **)
+ calloc (nscreens + 1, sizeof (*si->best_gl_visuals));
+
+ for (i = 0; i < nscreens; i++)
+ if (! si->best_gl_visuals[i])
+ si->best_gl_visuals[i] =
+ get_best_gl_visual (si, ScreenOfDisplay (si->dpy, i));
+
+ if (real_screen_number < 0 || real_screen_number >= nscreens) abort();
+ return si->best_gl_visuals[real_screen_number];
+}
+
Bool
select_visual (saver_screen_info *ssi, const char *visual_name)
{
+ XWindowAttributes xgwa;
saver_info *si = ssi->global;
saver_preferences *p = &si->prefs;
Bool install_cmap_p = p->install_cmap_p;
*/
Bool always_recreate_window_p = True;
+ get_screen_gl_visual (si, 0); /* let's probe all the GL visuals early */
+
+ /* We make sure the existing window is actually on ssi->screen before
+ trying to use it, in case things moved around radically when monitors
+ were added or deleted. If we don't do this we could get a BadMatch
+ even though the depths match. I think.
+ */
+ memset (&xgwa, 0, sizeof(xgwa));
+ if (ssi->screensaver_window)
+ XGetWindowAttributes (si->dpy, ssi->screensaver_window, &xgwa);
+
if (visual_name && *visual_name)
{
if (!strcmp(visual_name, "default-i") ||
!strcmp(visual_name, "Gl") ||
!strcmp(visual_name, "GL"))
{
- new_v = ssi->best_gl_visual;
+ new_v = get_screen_gl_visual (si, ssi->real_screen_number);
if (!new_v && p->verbose_p)
fprintf (stderr, "%s: no GL visuals.\n", progname);
}
ssi->install_cmap_p = install_cmap_p;
- if (new_v &&
- (always_recreate_window_p ||
- (ssi->current_visual != new_v) ||
- (install_cmap_p != was_installed_p)))
+ if ((ssi->screen != xgwa.screen) ||
+ (new_v &&
+ (always_recreate_window_p ||
+ (ssi->current_visual != new_v) ||
+ (install_cmap_p != was_installed_p))))
{
Colormap old_c = ssi->cmap;
Window old_w = ssi->screensaver_window;
+ if (! new_v)
+ new_v = ssi->current_visual;
if (p->verbose_p)
{
(Note that one must *never* kill xscreensaver with -9!)\n\
\n\
-restart Causes the screensaver process to exit and then restart with\n\
- the same command line arguments as last time. Do this after\n\
- you've changed your X resource settings, to cause\n\
- xscreensaver to notice the changes.\n\
+ the same command line arguments as last time. You shouldn't\n\
+ really need to do this, since xscreensaver notices when the\n\
+ .xscreensaver file has changed and re-reads it as needed.\n\
\n\
-lock Tells the running xscreensaver process to lock the screen\n\
immediately. This is like -activate, but forces locking as\n\
.TP 8
.B \-restart
Causes the screensaver process to exit and then restart with the same command
-line arguments as last time. Do this after you've changed the resource
-database, to cause xscreensaver to notice the changes.
-
-.B Warning:
-if you have a \fI.xscreensaver\fP file, this might not do what you
-expect. You're probably better off killing the existing
-xscreensaver (with \fIxscreensaver\-command -exit\fP) and then
-launching it again.
-
-The important point is, you need to make sure that the xscreensaver
-process is running as you. If it's not, it won't be reading the
-right \fI.xscreensaver\fP file.
+line arguments as last time. You shouldn't really need to do this,
+since xscreensaver notices when the \fI.xscreensaver\fP file has
+changed and re-reads it as needed.
.TP 8
.B \-watch
Prints a line each time the screensaver changes state: when the screen
* via the $XSCREENSAVER_WINDOW environment variable -- this trick requires
* a recent (Aug 2003) revision of vroot.h.
*
+ * (See comments in screens.c for more details about Xinerama/RANDR stuff.)
+ *
* While we are waiting for user activity, we also set up timers so that,
* after a certain amount of time has passed, we can start a different
* screenhack. We do this by killing the running child process with
/* useful for debugging */
{ "-no-capture-stderr", ".captureStderr", XrmoptionNoArg, "off" },
+ { "-log", ".logFile", XrmoptionSepArg, 0 },
};
#ifdef __GNUC__
return str;
}
-static Bool blurb_timestamp_p = False; /* kludge */
+static Bool blurb_timestamp_p = True; /* kludge */
const char *
blurb (void)
}
else
{
+#ifdef __GNUC__
+ __extension__ /* don't warn about "string length is greater than the
+ length ISO C89 compilers are required to support". */
+#endif
fprintf (real_stderr,
- "#######################################"
- "#######################################\n\n");
- fprintf (real_stderr,
+ "#######################################################################\n"
+ "\n"
" If at all possible, please re-run xscreensaver with the command\n"
- " line arguments `-sync -verbose -no-capture', and reproduce this\n"
+ " line arguments `-sync -verbose -log log.txt', and reproduce this\n"
" bug. That will cause xscreensaver to dump a `core' file to the\n"
" current directory. Please include the stack trace from that core\n"
- " file in your bug report. *DO NOT* mail the core file itself!\n"
- " That won't work.\n");
- fprintf (real_stderr,
+ " file in your bug report. *DO NOT* mail the core file itself! That\n"
+ " won't work. A \"log.txt\" file will also be written. Please *do*\n"
+ " include the complete \"log.txt\" file with your bug report.\n"
"\n"
" http://www.jwz.org/xscreensaver/bugs.html explains how to create\n"
" the most useful bug reports, and how to examine core files.\n"
"\n"
" The more information you can provide, the better. But please\n"
" report this bug, regardless!\n"
+ "\n"
+ "#######################################################################\n"
+ "\n"
"\n");
- fprintf (real_stderr,
- "#######################################"
- "#######################################\n\n");
saver_exit (si, -1, 0);
}
with `xscreensaver-demo' or `xscreensaver-command'.\n\
. See the man pages for details, or check the web page:\n\
http://www.jwz.org/xscreensaver/\n\n");
-
- /* Since version 1.21 renamed the "-lock" option to "-lock-mode",
- suggest that explicitly. */
- if (!strcmp (s, "-lock"))
- fprintf (stderr, "\
- Or perhaps you meant either the \"-lock-mode\" or the\n\
- \"-lock-timeout <minutes>\" options to xscreensaver?\n\n");
}
exit (1);
}
-#ifdef HAVE_XINERAMA
-
-static Bool
-screens_overlap_p (XineramaScreenInfo *a, XineramaScreenInfo *b)
-{
- /* Two rectangles overlap if the max of the tops is less than the
- min of the bottoms and the max of the lefts is less than the min
- of the rights.
- */
-# undef MAX
-# undef MIN
-# define MAX(A,B) ((A)>(B)?(A):(B))
-# define MIN(A,B) ((A)<(B)?(A):(B))
-
- int maxleft = MAX(a->x_org, b->x_org);
- int maxtop = MAX(a->y_org, b->y_org);
- int minright = MIN(a->x_org + a->width - 1, b->x_org + b->width);
- int minbot = MIN(a->y_org + a->height - 1, b->y_org + b->height);
- return (maxtop < minbot && maxleft < minright);
-}
-
-
-/* Go through the list of Xinerama screen descriptions, and mark the
- ones that appear to be insane, so that we don't use them.
- */
-static void
-check_xinerama_sanity (int count, Bool verbose_p, XineramaScreenInfo *xsi)
+/* called from screens.c so that all the Xt crud is here. */
+void
+initialize_screen_root_widget (saver_screen_info *ssi)
{
- static Bool printed_p = False;
- int i, j;
- char err[1024];
- *err = 0;
-
-# define X1 xsi[i].x_org
-# define X2 xsi[j].x_org
-# define Y1 xsi[i].y_org
-# define Y2 xsi[j].y_org
-# define W1 xsi[i].width
-# define W2 xsi[j].width
-# define H1 xsi[i].height
-# define H2 xsi[j].height
-
-# define WHINE() do { \
- if (verbose_p) { \
- if (! printed_p) { \
- fprintf (stderr, "%s: compensating for Xinerama braindamage:\n", \
- blurb()); \
- printed_p = True; \
- } \
- fprintf (stderr, "%s: %d: %s\n", blurb(), xsi[i].screen_number,err); \
- } \
- xsi[i].screen_number = -1; \
- } while(0)
-
- /* If a screen is enclosed by any other screen, that's insane.
- */
- for (i = 0; i < count; i++)
- for (j = 0; j < count; j++)
- if (i != j &&
- xsi[i].screen_number >= 0 &&
- xsi[j].screen_number >= 0 &&
- X1 >= X2 && Y1 >= Y2 && (X1+W1) <= (X2+W2) && (X1+H1) <= (X2+H2))
- {
- sprintf (err, "%dx%d+%d+%d enclosed by %dx%d+%d+%d",
- W1, H1, X1, Y1,
- W2, H2, X2, Y2);
- WHINE();
- continue;
- }
-
- /* After checking for enclosure, check for other lossage against earlier
- screens. We do enclosure first so that we make sure to pick the
- larger one.
- */
- for (i = 0; i < count; i++)
- for (j = 0; j < i; j++)
- {
- if (xsi[i].screen_number < 0) continue; /* already marked */
-
- *err = 0;
- if (X1 == X2 && Y1 == Y2 && W1 == W2 && H1 == H2)
- sprintf (err, "%dx%d+%d+%d duplicated", W1, H1, X1, Y1);
-
- else if (screens_overlap_p (&xsi[i], &xsi[j]))
- sprintf (err, "%dx%d+%d+%d overlaps %dx%d+%d+%d",
- W1, H1, X1, Y1,
- W2, H2, X2, Y2);
-
- if (*err) WHINE();
- }
-
-# undef X1
-# undef X2
-# undef Y1
-# undef Y2
-# undef W1
-# undef W2
-# undef H1
-# undef H2
+ saver_info *si = ssi->global;
+ if (ssi->toplevel_shell)
+ XtDestroyWidget (ssi->toplevel_shell);
+ ssi->toplevel_shell =
+ XtVaAppCreateShell (progname, progclass,
+ applicationShellWidgetClass,
+ si->dpy,
+ XtNscreen, ssi->screen,
+ XtNvisual, ssi->current_visual,
+ XtNdepth, visual_depth (ssi->screen,
+ ssi->current_visual),
+ NULL);
}
-#endif /* HAVE_XINERAMA */
-
-
/* Examine all of the display's screens, and populate the `saver_screen_info'
structures. Make sure this is called after hack_environment() sets $PATH.
static void
initialize_per_screen_info (saver_info *si, Widget toplevel_shell)
{
- Bool found_any_writable_cells = False;
int i;
-# ifdef HAVE_XINERAMA
- {
- int event, error;
- si->xinerama_p = (XineramaQueryExtension (si->dpy, &event, &error) &&
- XineramaIsActive (si->dpy));
- }
-
- if (si->xinerama_p && ScreenCount (si->dpy) != 1)
- {
- si->xinerama_p = False;
- if (si->prefs.verbose_p)
- fprintf (stderr,
- "%s: Xinerama AND %d screens? Disabling Xinerama support!\n",
- blurb(), ScreenCount(si->dpy));
- }
-
- if (si->xinerama_p)
- {
- int nscreens = 0;
- XineramaScreenInfo *xsi = XineramaQueryScreens (si->dpy, &nscreens);
- if (!xsi)
- si->xinerama_p = False;
- else
- {
- int j = 0;
- si->screens = (saver_screen_info *)
- calloc(sizeof(saver_screen_info), nscreens);
- check_xinerama_sanity (nscreens, si->prefs.verbose_p, xsi);
- for (i = 0; i < nscreens; i++)
- {
- if (xsi[i].screen_number < 0) /* deemed insane */
- continue;
- si->screens[j].x = xsi[i].x_org;
- si->screens[j].y = xsi[i].y_org;
- si->screens[j].width = xsi[i].width;
- si->screens[j].height = xsi[i].height;
- j++;
- }
- si->nscreens = j;
- XFree (xsi);
- }
- si->default_screen = &si->screens[0];
- si->default_screen->real_screen_p = True;
- }
-# endif /* !HAVE_XINERAMA */
-
- if (!si->xinerama_p)
- {
- si->nscreens = ScreenCount(si->dpy);
- si->screens = (saver_screen_info *)
- calloc(sizeof(saver_screen_info), si->nscreens);
- si->default_screen = &si->screens[DefaultScreen(si->dpy)];
-
- for (i = 0; i < si->nscreens; i++)
- {
- saver_screen_info *ssi = &si->screens[i];
- ssi->width = DisplayWidth (si->dpy, i);
- ssi->height = DisplayHeight (si->dpy, i);
- ssi->real_screen_p = True;
- ssi->real_screen_number = i;
- }
- }
+ update_screen_layout (si);
-
-# ifdef QUAD_MODE
- /* In "quad mode", we use the Xinerama code to pretend that there are 4
- screens for every physical screen, and run four times as many hacks...
- */
- if (si->prefs.quad_p)
- {
- int ns2 = si->nscreens * 4;
- saver_screen_info *ssi2 = (saver_screen_info *)
- calloc(sizeof(saver_screen_info), ns2);
-
- for (i = 0; i < si->nscreens; i++)
- {
- saver_screen_info *old = &si->screens[i];
-
- if (si->prefs.debug_p) old->width = old->width / 2;
-
- ssi2[i*4 ] = *old;
- ssi2[i*4+1] = *old;
- ssi2[i*4+2] = *old;
- ssi2[i*4+3] = *old;
-
- ssi2[i*4 ].width /= 2;
- ssi2[i*4 ].height /= 2;
-
- ssi2[i*4+1].x += ssi2[i*4 ].width;
- ssi2[i*4+1].width -= ssi2[i*4 ].width;
- ssi2[i*4+1].height /= 2;
-
- ssi2[i*4+2].y += ssi2[i*4 ].height;
- ssi2[i*4+2].width /= 2;
- ssi2[i*4+2].height -= ssi2[i*4 ].height;
-
- ssi2[i*4+3].x += ssi2[i*4+2].width;
- ssi2[i*4+3].y += ssi2[i*4+2].height;
- ssi2[i*4+3].width -= ssi2[i*4+2].width;
- ssi2[i*4+3].height -= ssi2[i*4+2].height;
-
- ssi2[i*4+1].real_screen_p = False;
- ssi2[i*4+2].real_screen_p = False;
- ssi2[i*4+3].real_screen_p = False;
- }
-
- si->nscreens = ns2;
- free (si->screens);
- si->screens = ssi2;
- si->default_screen = &si->screens[DefaultScreen(si->dpy) * 4];
- si->xinerama_p = True;
- }
-# endif /* QUAD_MODE */
-
- /* finish initializing the screens.
+ /* Check to see whether fading is ever possible -- if any of the
+ screens on the display has a PseudoColor visual, then fading can
+ work (on at least some screens.) If no screen has a PseudoColor
+ visual, then don't bother ever trying to fade, because it will
+ just cause a delay without causing any visible effect.
*/
for (i = 0; i < si->nscreens; i++)
{
saver_screen_info *ssi = &si->screens[i];
- ssi->global = si;
-
- ssi->number = i;
- ssi->screen = ScreenOfDisplay (si->dpy, ssi->real_screen_number);
- ssi->poll_mouse_last_root_x = -1;
- ssi->poll_mouse_last_root_y = -1;
-
- if (!si->xinerama_p)
+ if (has_writable_cells (ssi->screen, ssi->current_visual) ||
+ get_visual (ssi->screen, "PseudoColor", True, False) ||
+ get_visual (ssi->screen, "GrayScale", True, False))
{
- ssi->width = WidthOfScreen (ssi->screen);
- ssi->height = HeightOfScreen (ssi->screen);
+ si->fading_possible_p = True;
+ break;
}
-
- /* Note: we can't use the resource ".visual" because Xt is SO FUCKED. */
- ssi->default_visual =
- get_visual_resource (ssi->screen, "visualID", "VisualID", False);
-
- ssi->current_visual = ssi->default_visual;
- ssi->current_depth = visual_depth (ssi->screen, ssi->current_visual);
-
- /* Execute a subprocess to find the GL visual. */
- ssi->best_gl_visual = get_best_gl_visual (ssi);
-
- if (ssi == si->default_screen)
- /* Since this is the default screen, use the one already created. */
- ssi->toplevel_shell = toplevel_shell;
- else
- /* Otherwise, each screen must have its own unmapped root widget. */
- ssi->toplevel_shell =
- XtVaAppCreateShell (progname, progclass, applicationShellWidgetClass,
- si->dpy,
- XtNscreen, ssi->screen,
- XtNvisual, ssi->current_visual,
- XtNdepth, visual_depth (ssi->screen,
- ssi->current_visual),
- NULL);
-
- if (! found_any_writable_cells)
- {
- /* Check to see whether fading is ever possible -- if any of the
- screens on the display has a PseudoColor visual, then fading can
- work (on at least some screens.) If no screen has a PseudoColor
- visual, then don't bother ever trying to fade, because it will
- just cause a delay without causing any visible effect.
- */
- if (has_writable_cells (ssi->screen, ssi->current_visual) ||
- get_visual (ssi->screen, "PseudoColor", True, False) ||
- get_visual (ssi->screen, "GrayScale", True, False))
- found_any_writable_cells = True;
- }
}
- si->fading_possible_p = found_any_writable_cells;
-
#ifdef HAVE_XF86VMODE_GAMMA
si->fading_possible_p = True; /* if we can gamma fade, go for it */
#endif
blurb());
}
- /* These are incompatible (or at least, our support for them is...) */
- if (si->xinerama_p && si->using_mit_saver_extension)
- {
- si->using_mit_saver_extension = False;
- if (p->verbose_p)
- fprintf (stderr, "%s: Xinerama in use: disabling MIT-SCREEN-SAVER.\n",
- blurb());
- }
-
#ifdef HAVE_RANDR
query_randr_extension (si);
#endif
}
+#ifdef DEBUG_MULTISCREEN
+static void
+debug_multiscreen_timer (XtPointer closure, XtIntervalId *id)
+{
+ saver_info *si = (saver_info *) closure;
+ saver_preferences *p = &si->prefs;
+ if (update_screen_layout (si))
+ {
+ if (p->verbose_p)
+ {
+ fprintf (stderr, "%s: new layout:\n", blurb());
+ describe_monitor_layout (si);
+ }
+ resize_screensaver_window (si);
+ }
+ XtAppAddTimeOut (si->app, 1000*4, debug_multiscreen_timer, (XtPointer) si);
+}
+#endif /* DEBUG_MULTISCREEN */
+
+
/* For the case where we aren't using an server extensions, select user events
on all the existing windows, and launch timers to select events on
newly-created windows as well.
if (p->verbose_p)
fprintf (stderr, " done.\n");
+
+# ifdef DEBUG_MULTISCREEN
+ if (p->debug_p) debug_multiscreen_timer ((XtPointer) si, 0);
+# endif
}
{
saver_preferences *p = &si->prefs;
Bool ok_to_unblank;
+ int i;
while (1)
{
}
}
- kill_screenhack (si);
+ for (i = 0; i < si->nscreens; i++)
+ kill_screenhack (&si->screens[i]);
- if (!si->throttled_p)
- spawn_screenhack (si, True);
- else if (p->verbose_p)
+ raise_window (si, True, True, False);
+ if (si->throttled_p)
fprintf (stderr, "%s: not launching hack (throttled.)\n", blurb());
+ else
+ for (i = 0; i < si->nscreens; i++)
+ spawn_screenhack (&si->screens[i]);
/* Don't start the cycle timer in demo mode. */
if (!si->demoing_p && p->cycle)
was_locked = True;
si->dbox_up_p = True;
- suspend_screenhack (si, True);
+ 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);
si->dbox_up_p = False;
XDefineCursor (si->dpy, ssi->screensaver_window, ssi->cursor);
- suspend_screenhack (si, False); /* resume */
+ for (i = 0; i < si->nscreens; i++)
+ suspend_screenhack (&si->screens[i], False); /* resume */
if (!ok_to_unblank &&
!screenhack_running_p (si))
blurb(), timestring ());
/* Kill before unblanking, to stop drawing as soon as possible. */
- kill_screenhack (si);
+ for (i = 0; i < si->nscreens; i++)
+ kill_screenhack (&si->screens[i]);
unblank_screen (si);
set_locked_p (si, False);
shell = connect_to_server (si, &argc, argv);
process_command_line (si, &argc, argv);
+ stderr_log_file (si);
print_banner (si);
load_init_file(si->dpy, p); /* must be before initialize_per_screen_info() */
"exiting.");
if (! until_idle_p)
{
+ int i;
+ for (i = 0; i < si->nscreens; i++)
+ kill_screenhack (&si->screens[i]);
unblank_screen (si);
- kill_screenhack (si);
XSync (si->dpy, False);
}
saver_exit (si, 0, 0);
"restarting.");
if (! until_idle_p)
{
+ int i;
+ for (i = 0; i < si->nscreens; i++)
+ kill_screenhack (&si->screens[i]);
unblank_screen (si);
- kill_screenhack (si);
XSync (si->dpy, False);
}
# else
False
# endif
+ }, { "DRI", "DRI",
+ True
}, { "Apple-DRI", "Apple-DRI (XDarwin)",
True
},
};
- fprintf (stderr, "%s: running on display \"%s\" (%d %sscreen%s).\n",
- blurb(),
- DisplayString(si->dpy),
- si->nscreens,
- (si->xinerama_p ? "Xinerama " : ""),
- (si->nscreens == 1 ? "" : "s"));
+ fprintf (stderr, "%s: running on display \"%s\"\n", blurb(),
+ DisplayString(si->dpy));
fprintf (stderr, "%s: vendor is %s, %d.\n", blurb(),
ServerVendor(si->dpy), VendorRelease(si->dpy));
}
}
- if (si->xinerama_p)
- {
- fprintf (stderr, "%s: Xinerama layout:\n", blurb());
- for (i = 0; i < si->nscreens; i++)
- {
- saver_screen_info *ssi = &si->screens[i];
- fprintf (stderr, "%s: %c %d/%d: %dx%d+%d+%d\n",
- blurb(),
- (ssi->real_screen_p ? '+' : ' '),
- ssi->number, ssi->real_screen_number,
- ssi->width, ssi->height, ssi->x, ssi->y);
- }
- }
+ describe_monitor_layout (si);
}
+
Bool
display_is_on_console_p (saver_info *si)
{
-/* xscreensaver, Copyright (c) 1993-2006 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1993-2008 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
blanking
======================================================================= */
+extern Bool update_screen_layout (saver_info *si);
extern void initialize_screensaver_window (saver_info *si);
+extern void initialize_screen_root_widget (saver_screen_info *ssi);
+
extern void raise_window (saver_info *si,
Bool inhibit_fade, Bool between_hacks_p,
Bool dont_clear);
#endif /* !HAVE_SIGACTION */
extern void unblock_sigchld (void);
extern void hack_environment (saver_info *si);
-extern void hack_subproc_environment (saver_screen_info *ssi);
+extern void hack_subproc_environment (Screen *, Window saver_window);
extern void init_sigchld (void);
-extern void spawn_screenhack (saver_info *si, Bool first_time_p);
+extern void spawn_screenhack (saver_screen_info *ssi);
extern pid_t fork_and_exec (saver_screen_info *ssi, const char *command);
-extern void kill_screenhack (saver_info *si);
-extern void suspend_screenhack (saver_info *si, Bool suspend_p);
+extern void kill_screenhack (saver_screen_info *ssi);
+extern void suspend_screenhack (saver_screen_info *ssi, Bool suspend_p);
extern Bool screenhack_running_p (saver_info *si);
extern void emergency_kill_subproc (saver_info *si);
extern Bool select_visual (saver_screen_info *ssi, const char *visual_name);
extern FILE *real_stderr;
extern FILE *real_stdout;
+extern void stderr_log_file (saver_info *si);
extern void initialize_stderr (saver_info *si);
extern void reset_stderr (saver_screen_info *ssi);
extern void clear_stderr (saver_screen_info *ssi);
extern Bool window_exists_p (Display *dpy, Window window);
extern char *timestring (void);
extern Bool display_is_on_console_p (saver_info *si);
-extern Visual *get_best_gl_visual (saver_screen_info *ssi);
+extern Visual *get_best_gl_visual (saver_info *si, Screen *screen);
extern void check_for_leaks (const char *where);
+extern void describe_monitor_layout (saver_info *si);
+
+#ifdef HAVE_XF86VMODE
+Bool safe_XF86VidModeGetViewPort (Display *, int, int *, int *);
+#endif /* HAVE_XF86VMODE */
extern Atom XA_VROOT, XA_XSETROOT_ID, XA_ESETROOT_PMAP_ID, XA_XROOTPMAP_ID;
extern Atom XA_SCREENSAVER, XA_SCREENSAVER_VERSION, XA_SCREENSAVER_ID;
.B xscreensaver
[\-display \fIhost:display.screen\fP] \
[\-verbose] \
+[\-no\-splash] \
[\-no\-capture\-stderr] \
-[\-no\-splash]
+[\-log \fIfilename\fP]
.SH DESCRIPTION
The \fIxscreensaver\fP program waits until the keyboard and mouse have been
idle for a period, and then runs a graphics demo chosen at random. It
program pops up a dialog box that lets you configure the screen saver,
and experiment with the various display modes.
-.B Note:
-unlike
-.BR xlock (1),
-xscreensaver has a client-server model: the \fIxscreensaver\fP program is a
-daemon that runs in the background; it is controlled by the foreground
+.B Note that xscreensaver has a client-server model:
+the \fIxscreensaver\fP program is a daemon that runs in the background;
+it is controlled by the foreground
.BR xscreensaver-demo (1)
and
.BR xscreensaver-command (1)
the current settings will be written to the \fI.xscreensaver\fP file.
(The \fI.Xdefaults\fP file and the app-defaults file will never be
written by xscreensaver itself.)
-.PP
-.TP 8
-.B timeout\fP (class \fBTime\fP)
-The screensaver will activate (blank the screen) after the keyboard and
-mouse have been idle for this many minutes. Default 10 minutes.
-.TP 8
-.B cycle\fP (class \fBTime\fP)
-After the screensaver has been running for this many minutes, the currently
-running graphics-hack sub-process will be killed (with \fBSIGTERM\fP), and a
-new one started. If this is 0, then the graphics hack will never be changed:
-only one demo will run until the screensaver is deactivated by user activity.
-Default 10 minutes.
-.TP 8
-.B lock\fP (class \fBBoolean\fP)
-Enable locking: before the screensaver will turn off, it will require you
-to type the password of the logged-in user (really, the person who ran
-xscreensaver), or the root password. (\fBNote:\fP this doesn't work if the
-screensaver is launched by
-.BR xdm (1)
-because it can't know the user-id of the logged-in user. See
-the ``\fIUsing XDM(1)\fP'' section, below.
-.TP 8
-.B lockTimeout\fP (class \fBTime\fP)
-If locking is enabled, this controls the length of the ``grace period''
-between when the screensaver activates, and when the screen becomes locked.
-For example, if this is 5, and \fI\-timeout\fP is 10, then after 10 minutes,
-the screen would blank. If there was user activity at 12 minutes, no password
-would be required to un-blank the screen. But, if there was user activity
-at 15 minutes or later (that is, \fI\-lock\-timeout\fP minutes after
-activation) then a password would be required. The default is 0, meaning
-that if locking is enabled, then a password will be required as soon as the
-screen blanks.
-.TP 8
-.B passwdTimeout\fP (class \fBTime\fP)
-If the screen is locked, then this is how many seconds the password dialog box
-should be left on the screen before giving up (default 30 seconds.) This
-should not be too large: the X server is grabbed for the duration that the
-password dialog box is up (for security purposes) and leaving the server
-grabbed for too long can cause problems.
-.TP 8
-.B dpmsEnabled\fP (class \fBBoolean\fP)
-Whether power management is enabled.
+.SH COMMAND-LINE OPTIONS
+.I xscreensaver
+also accepts a few command-line options, mostly for use when debugging:
+for normal operation, you should configure things via the \fI~/.xscreensaver\fP
+file.
.TP 8
-.B dpmsStandby\fP (class \fBTime\fP)
-If power management is enabled, how long until the monitor goes solid black.
+.B \-display \fIhost:display.screen\fP
+The X display to use. For displays with multiple screens, XScreenSaver
+will manage all screens on the display simultaniously.
.TP 8
-.B dpmsSuspend\fP (class \fBTime\fP)
-If power management is enabled, how long until the monitor goes into
-power-saving mode.
+.B \-verbose
+Same as setting the \fIverbose\fP resource to \fItrue\fP: print diagnostics
+on stderr and on the xscreensaver window.
.TP 8
-.B dpmsOff\fP (class \fBTime\fP)
-If power management is enabled, how long until the monitor powers down
-completely. Note that these settings will have no effect unless both
-the X server and the display hardware support power management; not
-all do. See the \fIPower Management\fP section, below, for more
-information.
+.B \-no-capture-stderr
+Do not redirect the stdout and stderr streams to the xscreensaver window
+itself. If xscreensaver is crashing, you might need to do this in order
+to see the error message.
.TP 8
-.B visualID\fP (class \fBVisualID\fP)
-Specify which X visual to use by default. (Note carefully that this resource
-is called \fBvisualID\fP, not merely \fBvisual\fP; if you set the \fBvisual\fP
-resource instead, things will malfunction in obscure ways for obscure reasons.)
+.B \-log \fIfilename\fP
+This is exactly the same as redirecting stdout and stderr to the given
+file (for append). This is useful when reporting bugs.
+.SH HOW IT WORKS
+When it is time to activate the screensaver, a full-screen black window is
+created on each screen of the display. Each window is created in such a way
+that, to any subsequently-created programs, it will appear to be a ``virtual
+root'' window. Because of this, any program which draws on the root
+window (and which understands virtual roots) can be used as a screensaver.
+The various graphics demos are, in fact, just standalone programs that
+know how to draw on the provided window.
-Legal values for the \fBVisualID\fP resource are:
-.RS 8
-.TP 8
-.B default
-Use the screen's default visual (the visual of the root window.)
-This is the default.
-.TP 8
-.B best
-Use the visual which supports the most colors. Note, however, that the
-visual with the most colors might be a TrueColor visual, which does not
-support colormap animation. Some programs have more interesting behavior
-when run on PseudoColor visuals than on TrueColor.
-.TP 8
-.B mono
-Use a monochrome visual, if there is one.
-.TP 8
-.B gray
-Use a grayscale or staticgray visual, if there is one and it has more than
-one plane (that is, it's not monochrome.)
-.TP 8
-.B color
-Use the best of the color visuals, if there are any.
-.TP 8
-.B GL
-Use the visual that is best for OpenGL programs. (OpenGL programs have
-somewhat different requirements than other X programs.)
-.TP 8
-.I class
-where \fIclass\fP is one of \fBStaticGray\fP, \fBStaticColor\fP,
-\fBTrueColor\fP, \fBGrayScale\fP, \fBPseudoColor\fP, or \fBDirectColor\fP.
-Selects the deepest visual of the given class.
-.TP 8
-.I number
-where \fInumber\fP (decimal or hex) is interpreted as a visual id number,
-as reported by the
-.BR xdpyinfo (1)
-program; in this way you can have finer control over exactly which visual
-gets used, for example, to select a shallower one than would otherwise
-have been chosen.
+When the user becomes active again, the screensaver windows are unmapped, and
+the running subprocesses are killed by sending them \fBSIGTERM\fP. This is
+also how the subprocesses are killed when the screensaver decides that it's
+time to run a different demo: the old one is killed and a new one is launched.
+You can control a running screensaver process by using the
+.BR xscreensaver\-command (1)
+program (which see.)
+.SH POWER MANAGEMENT
+Modern X servers contain support to power down the monitor after an idle
+period. If the monitor has powered down, then \fIxscreensaver\fP will
+notice this (after a few minutes), and will not waste CPU by drawing
+graphics demos on a black screen. An attempt will also be made to
+explicitly power the monitor back up as soon as user activity is detected.
+
+The \fI~/.xscreensaver\fP file controls the configuration of your
+display's power management settings: if you have used
+.BR xset (1)
+to change your power management settings, then xscreensaver will
+override those changes with the values specified
+in \fI~/.xscreensaver\fP (or with its built-in defaults, if there
+is no \fI~/.xscreensaver\fP file yet.)
+
+To change your power management settings, run
+.BR xscreensaver\-demo (1)
+and change the various timeouts through the user interface.
+Alternately, you can edit the \fI~/.xscreensaver\fP file directly.
+
+If the power management section is grayed out in the
+.BR xscreensaver\-demo (1)
+window, then that means that your X server does not support
+the XDPMS extension, and so control over the monitor's power state
+is not available.
+
+If you're using a laptop, don't be surprised if changing the DPMS
+settings has no effect: many laptops have monitor power-saving behavior
+built in at a very low level that is invisible to Unix and X. On such
+systems, you can typically adjust the power-saving delays only by
+changing settings in the BIOS in some hardware-specific way.
+
+If DPMS seems not to be working with XFree86, make sure the "DPMS"
+option is set in your \fI/etc/X11/XF86Config\fP file. See the
+.BR XF86Config (5)
+manual for details.
+.SH USING GNOME
+For many years, GNOME shipped \fIxscreensaver\fP as-is, and
+everything just worked out of the box. Recently, however, they've
+been re-inventing the wheel again in the form of "gnome-screensaver".
+
+To replace gnome-screensaver with xscreensaver:
+.RS 4
+.TP 3
+\fB1: Turn off gnome-screensaver.\fP
+Open ``System / Preferences / Screensaver'' and uncheck both boxes.
+.TP 3
+\fB2: Stop gnome-screensaver from launching at login.\fP
+Run the command:
+.EX
+gconftool-2 --type boolean -s \\
+/apps/gnome_settings_daemon/screensaver/start_screensaver \\
+false
+.EE
+Or, just uninstall the "gnome-screensaver" package entirely.
+.TP 3
+\fB3: Launch xscreensaver at login.\fP
+Open ``System / Preferences / Sessions / Startup Programs''.
+Click ``Add'' and type ``xscreensaver''.
+.TP 3
+\fB4: Tell Preferences to use the xscreensaver configurator.\fP
+Edit \fI/usr/share/applications/gnome-screensaver-preferences.desktop\fP
+and change the \fIExec=\fP line to say
+ Exec=xscreensaver-demo
+.TP 3
+\fB5: Make ``System / Quit / Lock Screen'' use xscreensaver.\fP
+Run the command:
+.EX
+sudo ln -sf /usr/bin/xscreensaver-command \\
+ /usr/bin/gnome-screensaver-command
+.EE
+.SH USING KDE
+KDE also has invented their own screen saver framework instead of
+simply using xscreensaver. To replace the KDE screen saver with
+xscreensaver, do the following:
+.RS 4
+.TP 3
+\fB1: Turn off KDE's screen saver.\fP
+Open the ``\fIControl Center\fP'' and
+select the ``\fIAppearance & Themes / Screensaver\fP'' page.
+Un-check ``\fIStart Automatically\fP''.
+.TP 3
+\fB2: Find your Autostart directory.\fP
+Open the ``\fISystem Administration -> Paths\fP'' page,
+and see what your ``Autostart path'' is set to: it will
+probably be \fI~/.kde/Autostart/\fP or something similar.
+.TP 3
+\fB3: Make xscreensaver be an Autostart program.\fP
+Create a .desktop file in your autostart directory
+called \fIxscreensaver.desktop\fP that contains the following five lines:
+.EX
+[Desktop Entry]
+Exec=xscreensaver
+Name=XScreensaver
+Type=Application
+X-KDE-StartupNotify=false
+.EE
+.TP 3
+\fB4: Make the various "lock session" buttons call xscreensaver.\fP
+Replace the file \fI/usr/bin/kdesktop_lock\fP (or
+possibly \fI/usr/kde/3.5/bin/kdesktop_lock\fP)
+with these two lines:
+.EX
+#!/bin/sh
+xscreensaver-command -lock
+.EE
+Make sure the file is executable (chmod a+x).
.RE
-.RS 8
-Note that this option specifies only the \fIdefault\fP visual that will
-be used: the visual used may be overridden on a program-by-program basis.
-See the description of the \fBprograms\fP resource, below.
-.RE
-.TP 8
-.B installColormap\fP (class \fBBoolean\fP)
-On PseudoColor (8-bit) displays, install a private colormap while the
-screensaver is active, so that the graphics hacks can get as many
-colors as possible. This is the default. (This only applies when the
-screen's default visual is being used, since non-default visuals get
-their own colormaps automatically.) This can also be overridden on a
-per-hack basis: see the discussion of the \fBdefault\-n\fP name in the
-section about the \fBprograms\fP resource.
+.PP
+Now use xscreensaver normally, controlling it via the usual
+.BR xscreensaver-demo (1)
+and
+.BR xscreensaver-command (1)
+mechanisms.
+.SH USING GDM
+You can run \fIxscreensaver\fP from your
+.BR gdm (1)
+session, so that the screensaver will run even when nobody is logged
+in on the console. To do this, run
+.BR gdmconfig (1)
+and on the \fIBackground\fP page, type the
+command \fB"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.)
-This does nothing if you have a TrueColor (16-bit or deeper) display.
-.TP 8
-.B verbose\fP (class \fBBoolean\fP)
-Whether to print diagnostics. Default false.
+Another way to accomplish the same thing is to edit the
+file \fI/etc/X11/gdm/gdm.conf\fP to include:
+.EX
+BackgroundProgram=xscreensaver -nosplash
+RunBackgroundProgramAlways=true
+.EE
+In this situation, the \fIxscreensaver\fP process will probably be running
+as user \fIgdm\fP instead of \fIroot\fP. You can configure the settings
+for this nobody-logged-in state (timeouts, DPMS, etc.) by editing
+the \fI~gdm/.xscreensaver\fP file.
+
+To get gdm to run the BackgroundProgram, you may need to switch it from
+the "Graphical Greeter" to the "Standard Greeter".
+
+It is safe to run \fIxscreensaver\fP as root (as \fIxdm\fP is likely to do.)
+If run as root, \fIxscreensaver\fP changes its effective user and group ids
+to something safe (like \fI"nobody"\fP) before connecting to the X server
+or launching user-specified programs.
+
+An unfortunate side effect of this (important) security precaution is that
+it may conflict with cookie-based authentication.
+
+If you get "connection refused" errors when running \fIxscreensaver\fP
+from \fIgdm\fP, then this probably means that you have
+.BR xauth (1)
+or some other security mechanism turned on. For information on the
+X server's access control mechanisms, see the man pages for
+.BR X (1),
+.BR Xsecurity (1),
+.BR xauth (1),
+and
+.BR xhost (1).
+.SH BUGS
+Bugs? There are no bugs. Ok, well, maybe. If you find one, please let
+me know. http://www.jwz.org/xscreensaver/bugs.html explains how to
+construct the most useful bug reports.
.TP 8
-.B timestamp\fP (class \fBBoolean\fP)
-Whether to print the time of day along with any other diagnostic messages.
-Default true.
-.TP 8
-.B splash\fP (class \fBBoolean\fP)
-Whether to display a splash screen at startup. Default true.
-.TP 8
-.B splashDuration\fP (class \fBTime\fP)
-How long the splash screen should remain visible; default 5 seconds.
+.B Locking and XDM
+If xscreensaver has been launched from
+.BR xdm (1)
+before anyone has logged in, you will need to kill and then restart the
+xscreensaver daemon after you have logged in, or you will be confused by
+the results. (For example, locking won't work, and your \fI~/.xscreensaver\fP
+file will be ignored.)
+
+When you are logged in, you want the \fIxscreensaver\fP daemon to be
+running under \fIyour\fP user id, not as root or some other user.
+
+If it has already been started by \fIxdm\fP, you can kill it by sending
+it the \fBexit\fP command, and then re-launching it as you, by putting
+something like the following in your personal X startup script:
+.EX
+xscreensaver-command -exit
+xscreensaver &
+.EE
+The ``\fIUsing XDM(1)\fP'' section, above, goes into more detail, and explains
+how to configure the system to do this for all users automatically.
.TP 8
-.B quad\fP (class \fBBoolean\fP)
-If true, then \fIfour\fP screensavers will be run on each monitor.
-Use at your own risk!
+.B Locking and root logins
+In order for it to be safe for xscreensaver to be launched by \fIxdm\fP,
+certain precautions had to be taken, among them that xscreensaver never
+runs as \fIroot\fP. In particular, if it is launched as root (as \fIxdm\fP
+is likely to do), xscreensaver will disavow its privileges, and switch
+itself to a safe user id (such as \fInobody\fP.)
+
+An implication of this is that if you log in as \fIroot\fP on the console,
+xscreensaver will refuse to lock the screen (because it can't tell
+the difference between \fIroot\fP being logged in on the console, and a
+normal user being logged in on the console but xscreensaver having been
+launched by the
+.BR xdm (1)
+.I Xsetup
+file.)
+
+The solution to this is simple: you shouldn't be logging in on the console
+as \fIroot\fP in the first place! (What, are you crazy or something?)
+
+Proper Unix hygiene dictates that you should log in as yourself, and
+.BR su (1)
+to \fIroot\fP as necessary. People who spend their day logged in
+as \fIroot\fP are just begging for disaster.
.TP 8
-.B helpURL\fP (class \fBURL\fP)
-The splash screen has a \fIHelp\fP button on it. When you press it, it will
-display the web page indicated here in your web browser.
+.B XAUTH and XDM
+For xscreensaver to work when launched by
+.BR xdm (1),
+programs running on the local machine as user \fI"nobody"\fP must be
+able to connect to the X server. This means that if you want to run
+xscreensaver on the console while nobody is logged in, you may need
+to disable cookie-based access control (and allow all users who can log
+in to the local machine to connect to the display.)
+
+You should be sure that this is an acceptable thing to do in your
+environment before doing it. See the ``\fIUsing XDM(1)\fP'' section,
+above, for more details.
.TP 8
-.B loadURL\fP (class \fBLoadURL\fP)
-This is the shell command used to load a URL into your web browser.
-The default setting will load it into Mozilla/Netscape if it is already
-running, otherwise, will launch a new browser looking at the \fIhelpURL\fP.
+.B Passwords
+If you get an error message at startup like ``couldn't get password
+of \fIuser\fP'' then this probably means that you're on a system in which
+the
+.BR getpwent (3)
+library routine can only be effectively used by root. If this is the case,
+then \fIxscreensaver\fP must be installed as setuid to root in order for
+locking to work. Care has been taken to make this a safe thing to do.
+
+It also may mean that your system uses shadow passwords instead of the standard
+.BR getpwent (3)
+interface; in that case, you may need to change some options
+with \fIconfigure\fP and recompile.
+
+If you change your password after xscreensaver has been launched, it will
+continue using your old password to unlock the screen until xscreensaver
+is restarted. On some systems, it may accept \fIboth\fP your old and new
+passwords. So, after you change your password, you'll have to do
+.EX
+xscreensaver-command -restart
+.EE
+to make \fIxscreensaver\fP notice.
.TP 8
-.B demoCommand\fP (class \fBDemoCommand\fP)
-This is the shell command run when the \fIDemo\fP button on the splash window
-is pressed. It defaults to
-.BR xscreensaver\-demo (1).
+.B PAM Passwords
+If your system uses PAM (Pluggable Authentication Modules), then in order
+for xscreensaver to use PAM properly, PAM must be told about xscreensaver.
+The xscreensaver installation process should update the PAM data (on Linux,
+by creating the file \fI/etc/pam.d/xscreensaver\fP for you, and on Solaris,
+by telling you what lines to add to the \fI/etc/pam.conf\fP file.)
+
+If the PAM configuration files do not know about xscreensaver, then
+you \fImight\fP be in a situation where xscreensaver will refuse to ever
+unlock the screen.
+
+This is a design flaw in PAM (there is no way for a client to tell the
+difference between PAM responding ``I have never heard of your module,''
+and responding, ``you typed the wrong password.'') As far as I can tell,
+there is no way for xscreensaver to automatically work around this, or
+detect the problem in advance, so if you have PAM, make sure it is
+configured correctly!
.TP 8
-.B prefsCommand\fP (class \fBPrefsCommand\fP)
-This is the shell command run when the \fIPrefs\fP button on the splash window
-is pressed. It defaults to \fIxscreensaver\-demo\ \-prefs\fP.
+.B Machine Load
+Although this program ``nices'' the subprocesses that it starts,
+graphics-intensive subprograms can still overload the machine by causing
+the X server process itself (which is not ``niced'') to consume many
+cycles. Care has been taken in all the modules shipped with xscreensaver
+to sleep periodically, and not run full tilt, so as not to cause
+appreciable load.
+
+However, if you are running the OpenGL-based screen savers on a machine
+that does not have a video card with 3D acceleration, they \fIwill\fP
+make your machine slow, despite
+.BR nice (1).
+
+Your options are: don't use the OpenGL display modes; or, collect the
+spare change hidden under the cushions of your couch, and use it to
+buy a video card manufactured after 1998. (It doesn't even need to be
+\fIfast\fP 3D hardware: the problem will be fixed if there is any
+3D hardware \fIat all.\fP)
.TP 8
-.B nice\fP (class \fBNice\fP)
-The sub-processes created by \fIxscreensaver\fP will be ``niced'' to this
-level, so that they are given lower priority than other processes on the
-system, and don't increase the load unnecessarily. The default is 10.
+.B XFree86's Magic Keystrokes
+The XFree86 X server traps certain magic keystrokes before client programs ever
+see them. Two that are of note are Ctrl+Alt+Backspace, which causes
+the X server to exit; and Ctrl+Alt+F\fIn\fP, which switches virtual consoles.
+The X server will respond to these keystrokes even if xscreensaver has the
+screen locked. Depending on your setup, you might consider this a problem.
-(Higher numbers mean lower priority; see
-.BR nice (1)
-for details.)
+Unfortunately, there is no way for xscreensaver itself to override the
+interpretation of these keys. If you want to disable Ctrl+Alt+Backspace
+globally, you need to set the \fIDontZap\fP flag in
+your \fI/etc/X11/XF86Config\fP file. To globally disable VT switching,
+you can set the \fIDontVTSwitch\fP flag. See the
+.BR XF86Config (5)
+manual for details.
+.SH X RESOURCES
+These are the X resources use by the \fIxscreensaver\fP program.
+You probably won't need to change these manually (that's what the
+.BR xscreensaver\-demo (1)
+program is for).
.TP 8
-.B fade\fP (class \fBBoolean\fP)
-If this is true, then when the screensaver activates, the current contents
-of the screen will fade to black instead of simply winking out. This only
-works on certain systems. A fade will also be done when switching graphics
-hacks (when the \fIcycle\fP timer expires.) Default: true.
+.B timeout\fP (class \fBTime\fP)
+The screensaver will activate (blank the screen) after the keyboard and
+mouse have been idle for this many minutes. Default 10 minutes.
.TP 8
-.B unfade\fP (class \fBBoolean\fP)
-If this is true, then when the screensaver deactivates, the original contents
-of the screen will fade in from black instead of appearing immediately. This
-only works on certain systems, and if \fIfade\fP is true as well.
-Default false.
+.B cycle\fP (class \fBTime\fP)
+After the screensaver has been running for this many minutes, the currently
+running graphics-hack sub-process will be killed (with \fBSIGTERM\fP), and a
+new one started. If this is 0, then the graphics hack will never be changed:
+only one demo will run until the screensaver is deactivated by user activity.
+Default 10 minutes.
.TP 8
-.B fadeSeconds\fP (class \fBTime\fP)
-If \fIfade\fP is true, this is how long the fade will be in
-seconds (default 3 seconds.)
+.B lock\fP (class \fBBoolean\fP)
+Enable locking: before the screensaver will turn off, it will require you
+to type the password of the logged-in user (really, the person who ran
+xscreensaver), or the root password. (\fBNote:\fP this doesn't work if the
+screensaver is launched by
+.BR xdm (1)
+because it can't know the user-id of the logged-in user. See
+the ``\fIUsing XDM(1)\fP'' section, below.
.TP 8
-.B fadeTicks\fP (class \fBInteger\fP)
-If \fIfade\fP is true, this is how many times a second the colormap will
-be changed to effect a fade. Higher numbers yield smoother fades, but
-may make the fades take longer than the specified \fIfadeSeconds\fP if
-your server isn't fast enough to keep up. Default 20.
+.B lockTimeout\fP (class \fBTime\fP)
+If locking is enabled, this controls the length of the ``grace period''
+between when the screensaver activates, and when the screen becomes locked.
+For example, if this is 5, and \fI\-timeout\fP is 10, then after 10 minutes,
+the screen would blank. If there was user activity at 12 minutes, no password
+would be required to un-blank the screen. But, if there was user activity
+at 15 minutes or later (that is, \fI\-lock\-timeout\fP minutes after
+activation) then a password would be required. The default is 0, meaning
+that if locking is enabled, then a password will be required as soon as the
+screen blanks.
.TP 8
-.B captureStderr\fP (class \fBBoolean\fP)
-Whether \fIxscreensaver\fP should redirect its stdout and stderr streams to
-the window itself. Since its nature is to take over the screen, you would not
-normally see error messages generated by xscreensaver or the sub-programs it
-runs; this resource will cause the output of all relevant programs to be
-drawn on the screensaver window itself, as well as being written to the
-controlling terminal of the screensaver driver process. Default true.
+.B passwdTimeout\fP (class \fBTime\fP)
+If the screen is locked, then this is how many seconds the password dialog box
+should be left on the screen before giving up (default 30 seconds.) This
+should not be too large: the X server is grabbed for the duration that the
+password dialog box is up (for security purposes) and leaving the server
+grabbed for too long can cause problems.
.TP 8
-.B ignoreUninstalledPrograms\fP (class \fBBoolean\fP)
-There may be programs in the list that are not installed on the system,
-yet are marked as "enabled." If this preference is true, then such
-programs will simply be ignored. If false, then a warning will be printed
-if an attempt is made to run the nonexistent program. Also, the
-.BR xscreensaver-demo (1)
-program will suppress the non-existent programs from the list if this
-is true. Default: false.
+.B dpmsEnabled\fP (class \fBBoolean\fP)
+Whether power management is enabled.
.TP 8
-.B GetViewPortIsFullOfLies\fP (class \fBBoolean\fP)
-Set this to true if the xscreensaver window doesn't cover the whole screen.
-This works around a longstanding XFree86 bug #421. See the
-xscreensaver FAQ for details.
+.B dpmsStandby\fP (class \fBTime\fP)
+If power management is enabled, how long until the monitor goes solid black.
.TP 8
-.B font\fP (class \fBFont\fP)
-The font used for the stdout/stderr text, if \fBcaptureStderr\fP is true.
-Default \fB*\-medium\-r\-*\-140\-*\-m\-*\fP (a 14 point fixed-width font.)
+.B dpmsSuspend\fP (class \fBTime\fP)
+If power management is enabled, how long until the monitor goes into
+power-saving mode.
.TP 8
-.B mode\fP (class \fBMode\fP)
-Controls the behavior of xscreensaver. Legal values are:
+.B dpmsOff\fP (class \fBTime\fP)
+If power management is enabled, how long until the monitor powers down
+completely. Note that these settings will have no effect unless both
+the X server and the display hardware support power management; not
+all do. See the \fIPower Management\fP section, below, for more
+information.
+.TP 8
+.B visualID\fP (class \fBVisualID\fP)
+Specify which X visual to use by default. (Note carefully that this resource
+is called \fBvisualID\fP, not merely \fBvisual\fP; if you set the \fBvisual\fP
+resource instead, things will malfunction in obscure ways for obscure reasons.)
+
+Legal values for the \fBVisualID\fP resource are:
.RS 8
.TP 8
-.B random
-When blanking the screen, select a random display mode from among those
-that are enabled and applicable. This is the default.
+.B default
+Use the screen's default visual (the visual of the root window.)
+This is the default.
+.TP 8
+.B best
+Use the visual which supports the most colors. Note, however, that the
+visual with the most colors might be a TrueColor visual, which does not
+support colormap animation. Some programs have more interesting behavior
+when run on PseudoColor visuals than on TrueColor.
+.TP 8
+.B mono
+Use a monochrome visual, if there is one.
+.TP 8
+.B gray
+Use a grayscale or staticgray visual, if there is one and it has more than
+one plane (that is, it's not monochrome.)
+.TP 8
+.B color
+Use the best of the color visuals, if there are any.
+.TP 8
+.B GL
+Use the visual that is best for OpenGL programs. (OpenGL programs have
+somewhat different requirements than other X programs.)
+.TP 8
+.I class
+where \fIclass\fP is one of \fBStaticGray\fP, \fBStaticColor\fP,
+\fBTrueColor\fP, \fBGrayScale\fP, \fBPseudoColor\fP, or \fBDirectColor\fP.
+Selects the deepest visual of the given class.
+.TP 8
+.I number
+where \fInumber\fP (decimal or hex) is interpreted as a visual id number,
+as reported by the
+.BR xdpyinfo (1)
+program; in this way you can have finer control over exactly which visual
+gets used, for example, to select a shallower one than would otherwise
+have been chosen.
+
+.RE
+.RS 8
+Note that this option specifies only the \fIdefault\fP visual that will
+be used: the visual used may be overridden on a program-by-program basis.
+See the description of the \fBprograms\fP resource, below.
+.RE
+.TP 8
+.B installColormap\fP (class \fBBoolean\fP)
+On PseudoColor (8-bit) displays, install a private colormap while the
+screensaver is active, so that the graphics hacks can get as many
+colors as possible. This is the default. (This only applies when the
+screen's default visual is being used, since non-default visuals get
+their own colormaps automatically.) This can also be overridden on a
+per-hack basis: see the discussion of the \fBdefault\-n\fP name in the
+section about the \fBprograms\fP resource.
+
+This does nothing if you have a TrueColor (16-bit or deeper) display.
+.TP 8
+.B verbose\fP (class \fBBoolean\fP)
+Whether to print diagnostics. Default false.
+.TP 8
+.B timestamp\fP (class \fBBoolean\fP)
+Whether to print the time of day along with any other diagnostic messages.
+Default true.
+.TP 8
+.B splash\fP (class \fBBoolean\fP)
+Whether to display a splash screen at startup. Default true.
+.TP 8
+.B splashDuration\fP (class \fBTime\fP)
+How long the splash screen should remain visible; default 5 seconds.
+.TP 8
+.B helpURL\fP (class \fBURL\fP)
+The splash screen has a \fIHelp\fP button on it. When you press it, it will
+display the web page indicated here in your web browser.
+.TP 8
+.B loadURL\fP (class \fBLoadURL\fP)
+This is the shell command used to load a URL into your web browser.
+The default setting will load it into Mozilla/Netscape if it is already
+running, otherwise, will launch a new browser looking at the \fIhelpURL\fP.
+.TP 8
+.B demoCommand\fP (class \fBDemoCommand\fP)
+This is the shell command run when the \fIDemo\fP button on the splash window
+is pressed. It defaults to
+.BR xscreensaver\-demo (1).
+.TP 8
+.B prefsCommand\fP (class \fBPrefsCommand\fP)
+This is the shell command run when the \fIPrefs\fP button on the splash window
+is pressed. It defaults to \fIxscreensaver\-demo\ \-prefs\fP.
+.TP 8
+.B nice\fP (class \fBNice\fP)
+The sub-processes created by \fIxscreensaver\fP will be ``niced'' to this
+level, so that they are given lower priority than other processes on the
+system, and don't increase the load unnecessarily. The default is 10.
+
+(Higher numbers mean lower priority; see
+.BR nice (1)
+for details.)
+.TP 8
+.B fade\fP (class \fBBoolean\fP)
+If this is true, then when the screensaver activates, the current contents
+of the screen will fade to black instead of simply winking out. This only
+works on certain systems. A fade will also be done when switching graphics
+hacks (when the \fIcycle\fP timer expires.) Default: true.
+.TP 8
+.B unfade\fP (class \fBBoolean\fP)
+If this is true, then when the screensaver deactivates, the original contents
+of the screen will fade in from black instead of appearing immediately. This
+only works on certain systems, and if \fIfade\fP is true as well.
+Default false.
+.TP 8
+.B fadeSeconds\fP (class \fBTime\fP)
+If \fIfade\fP is true, this is how long the fade will be in
+seconds (default 3 seconds.)
+.TP 8
+.B fadeTicks\fP (class \fBInteger\fP)
+If \fIfade\fP is true, this is how many times a second the colormap will
+be changed to effect a fade. Higher numbers yield smoother fades, but
+may make the fades take longer than the specified \fIfadeSeconds\fP if
+your server isn't fast enough to keep up. Default 20.
+.TP 8
+.B captureStderr\fP (class \fBBoolean\fP)
+Whether \fIxscreensaver\fP should redirect its stdout and stderr streams to
+the window itself. Since its nature is to take over the screen, you would not
+normally see error messages generated by xscreensaver or the sub-programs it
+runs; this resource will cause the output of all relevant programs to be
+drawn on the screensaver window itself, as well as being written to the
+controlling terminal of the screensaver driver process. Default true.
+.TP 8
+.B ignoreUninstalledPrograms\fP (class \fBBoolean\fP)
+There may be programs in the list that are not installed on the system,
+yet are marked as "enabled." If this preference is true, then such
+programs will simply be ignored. If false, then a warning will be printed
+if an attempt is made to run the nonexistent program. Also, the
+.BR xscreensaver-demo (1)
+program will suppress the non-existent programs from the list if this
+is true. Default: false.
+.TP 8
+.B GetViewPortIsFullOfLies\fP (class \fBBoolean\fP)
+Set this to true if the xscreensaver window doesn't cover the whole screen.
+This works around a longstanding XFree86 bug #421. See the
+xscreensaver FAQ for details.
+.TP 8
+.B font\fP (class \fBFont\fP)
+The font used for the stdout/stderr text, if \fBcaptureStderr\fP is true.
+Default \fB*\-medium\-r\-*\-140\-*\-m\-*\fP (a 14 point fixed-width font.)
+.TP 8
+.B mode\fP (class \fBMode\fP)
+Controls the behavior of xscreensaver. Legal values are:
+.RS 8
+.TP 8
+.B random
+When blanking the screen, select a random display mode from among those
+that are enabled and applicable. This is the default.
.TP 8
.B random-same
Like \fIrandom\fP, but if there are multiple screens, each screen
the \fBmode\fP setting), and run. After the \fIcycle\fP period
expires, it is killed, and another is selected and run.
-If a line begins with a dash (-) then that particular program is
-disabled: it won't be selected at random (though you can still select
-it explicitly using the
-.BR xscreensaver\-demo (1)
-program.)
-
-If all programs are disabled, then the screen will just be made blank,
-as when \fImode\fP is set to \fIblank\fP.
-
-To disable a program, you must mark it as disabled with a dash instead
-of removing it from the list. This is because the system-wide (app-defaults)
-and per-user (.xscreensaver) settings are merged together, and if a user
-just \fIdeletes\fP an entry from their programs list, but that entry still
-exists in the system-wide list, then it will come back. However, if the
-user \fIdisables\fP it, then their setting takes precedence.
-
-If the display has multiple screens, then a different program will be run
-for each screen. (All screens are blanked and unblanked simultaneously.)
-
-Note that you must escape the newlines; here is an example of how you
-might set this in your \fI~/.xscreensaver\fP file:
-
-.RS 8
-.EX
-programs: \\
- qix -root \\n\\
- ico -r -faces -sleep 1 -obj ico \\n\\
- xdaliclock -builtin2 -root \\n\\
- xv -root -rmode 5 image.gif -quit \\n
-.EE
-.RE
-.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.
-
-To use a program as a screensaver, two things are required: that that
-program draw on the root window (or be able to be configured to draw on
-the root window); and that that program understand ``virtual root''
-windows, as used by virtual window managers such as
-.BR tvtwm (1).
-(Generally, this is accomplished by just including the \fI"vroot.h"\fP
-header file in the program's source.)
-
-If there are some programs that you want to run only when using a color
-display, and others that you want to run only when using a monochrome
-display, you can specify that like this:
-.EX
- mono: mono-program -root \\n\\
- color: color-program -root \\n\\
-.EE
-.RE
-.RS 8
-More generally, you can specify the kind of visual that should be used for
-the window on which the program will be drawing. For example, if one
-program works best if it has a colormap, but another works best if it has
-a 24-bit visual, both can be accommodated:
-.EX
- PseudoColor: cmap-program -root \\n\\
- TrueColor: 24bit-program -root \\n\\
-.EE
-.RE
-.RS 8
-In addition to the symbolic visual names described above (in the discussion
-of the \fIvisualID\fP resource) one other visual name is supported in
-the \fIprograms\fP list:
-.RS 1
-.TP 4
-.B default-n
-This is like \fBdefault\fP, but also requests the use of the default colormap,
-instead of a private colormap. (That is, it behaves as if
-the \fI\-no\-install\fP command-line option was specified, but only for
-this particular hack.) This is provided because some third-party programs
-that draw on the root window (notably:
-.BR xv (1),
-and
-.BR xearth (1))
-make assumptions about the visual and colormap of the root window:
-assumptions which xscreensaver can violate.
-
-.RE
-If you specify a particular visual for a program, and that visual does not
-exist on the screen, then that program will not be chosen to run. This
-means that on displays with multiple screens of different depths, you can
-arrange for appropriate hacks to be run on each. For example, if one screen
-is color and the other is monochrome, hacks that look good in mono can be
-run on one, and hacks that only look good in color will show up on the other.
-.RE
-.PP
-.PP
-You shouldn't ever need to change the following resources:
-.PP
-.TP 8
-.B pointerPollTime\fP (class \fBTime\fP)
-When server extensions are not in use, this controls how
-frequently \fIxscreensaver\fP checks to see if the mouse position or buttons
-have changed. Default 5 seconds.
-.TP 8
-.B pointerHysteresis\fP (class \fBInteger\fP)
-If the mouse moves less than this-many pixels in a second, ignore it
-(do not consider that to be "activity.") This is so that the screen
-doesn't un-blank (or fail to blank) just because you bumped the desk.
-Default: 10 pixels.
-.TP 8
-.B windowCreationTimeout\fP (class \fBTime\fP)
-When server extensions are not in use, this controls the delay between when
-windows are created and when \fIxscreensaver\fP selects events on them.
-Default 30 seconds.
-.TP 8
-.B initialDelay\fP (class \fBTime\fP)
-When server extensions are not in use, \fIxscreensaver\fP will wait this many
-seconds before selecting events on existing windows, under the assumption that
-\fIxscreensaver\fP is started during your login procedure, and the window
-state may be in flux. Default 0. (This used to default to 30, but that was
-back in the days when slow machines and X terminals were more common...)
-.RE
-.PP
-There are a number of different X server extensions which can make
-xscreensaver's job easier. The next few resources specify whether these
-extensions should be utilized if they are available.
-.TP 8
-.B sgiSaverExtension\fP (class \fBBoolean\fP)
-This resource controls whether the SGI \fBSCREEN_SAVER\fP server extension
-will be used to decide whether the user is idle. This is the default
-if \fIxscreensaver\fP has been compiled with support for this
-extension (which is the default on SGI systems.). If it is available,
-the \fBSCREEN_SAVER\fP method is faster and more reliable than what will
-be done otherwise, so use it if you can. (This extension is only available
-on Silicon Graphics systems, unfortunately.)
-.TP 8
-.B mitSaverExtension\fP (class \fBBoolean\fP)
-This resource controls whether the \fBMIT\-SCREEN\-SAVER\fP server extension
-will be used to decide whether the user is idle. However, the default for
-this resource is \fIfalse\fP, because even if this extension is available,
-it is flaky (and it also makes the \fBfade\fP option not work properly.)
-Use of this extension is strongly discouraged. Support for it will
-probably be removed eventually.
-.TP 8
-.B xidleExtension\fP (class \fBBoolean\fP)
-This resource controls whether the \fBXIDLE\fP server extension will be
-used to decide whether the user is idle. This is the default
-if \fIxscreensaver\fP has been compiled with support for this extension.
-(This extension is only available for X11R4 and X11R5 systems, unfortunately.)
-.TP 8
-.B procInterrupts\fP (class \fBBoolean\fP)
-This resource controls whether the \fB/proc/interrupts\fP file should be
-consulted to decide whether the user is idle. This is the default
-if \fIxscreensaver\fP has been compiled on a system which supports this
-mechanism (i.e., Linux systems.)
-
-The benefit to doing this is that \fIxscreensaver\fP can note that the user
-is active even when the X console is not the active one: if the user is
-typing in another virtual console, xscreensaver will notice that and will
-fail to activate. For example, if you're playing Quake in VGA-mode,
-xscreensaver won't wake up in the middle of your game and start competing
-for CPU.
-
-The drawback to doing this is that perhaps you \fIreally do\fP want idleness
-on the X console to cause the X display to lock, even if there is activity
-on other virtual consoles. If you want that, then set this option to False.
-(Or just lock the X console manually.)
-
-The default value for this resource is True, on systems where it works.
-.TP 8
-.B overlayStderr\fP (class \fBBoolean\fP)
-If \fBcaptureStderr\fP is True, and your server supports ``overlay'' visuals,
-then the text will be written into one of the higher layers instead of into
-the same layer as the running screenhack. Set this to False to disable
-that (though you shouldn't need to.)
-.TP 8
-.B overlayTextForeground\fP (class \fBForeground\fP)
-The foreground color used for the stdout/stderr text, if \fBcaptureStderr\fP
-is true. Default: Yellow.
-.TP 8
-.B overlayTextBackground\fP (class \fBBackground\fP)
-The background color used for the stdout/stderr text, if \fBcaptureStderr\fP
-is true. Default: Black.
-.TP 8
-.B bourneShell\fP (class \fBBourneShell\fP)
-The pathname of the shell that \fIxscreensaver\fP uses to start subprocesses.
-This must be whatever your local variant of \fB/bin/sh\fP is: in particular,
-it must not be \fBcsh\fP.
-.SH COMMAND-LINE OPTIONS
-.I xscreensaver
-also accepts a few command-line options, mostly for use when debugging:
-for normal operation, you should configure things via the \fI~/.xscreensaver\fP
-file.
-.TP 8
-.B \-display \fIhost:display.screen\fP
-The X display to use. For displays with multiple screens, XScreenSaver
-will manage all screens on the display simultaniously.
-.TP 8
-.B \-verbose
-Same as setting the \fIverbose\fP resource to \fItrue\fP: print diagnostics
-on stderr and on the xscreensaver window.
-.TP 8
-.B \-no-capture-stderr
-Same as setting the \fIcaptureStderr\fP resource to \fIfalse\fP: do not
-redirect the stdout and stderr streams to the xscreensaver window itself.
-If xscreensaver is crashing, you might need to do this in order to see
-the error message.
-.SH HOW IT WORKS
-When it is time to activate the screensaver, a full-screen black window is
-created on each screen of the display. Each window is created in such a way
-that, to any subsequently-created programs, it will appear to be a ``virtual
-root'' window. Because of this, any program which draws on the root
-window (and which understands virtual roots) can be used as a screensaver.
-
-When the user becomes active again, the screensaver windows are unmapped, and
-the running subprocesses are killed by sending them \fBSIGTERM\fP. This is
-also how the subprocesses are killed when the screensaver decides that it's
-time to run a different demo: the old one is killed and a new one is launched.
-
-Before launching a subprocess, \fIxscreensaver\fP stores an appropriate value
-for \fB$DISPLAY\fP in the environment that the child will receive. (This is
-so that if you start \fIxscreensaver\fP with a \fI-display\fP argument, the
-programs which \fIxscreensaver\fP launches will draw on the same display;
-and so that the child will end up drawing on the appropriate screen of a
-multi-headed display.)
-
-When the screensaver turns off, or is killed, care is taken to restore
-the ``real'' virtual root window if there is one. Because of this, it is
-important that you not kill the screensaver process with \fIkill -9\fP if
-you are running a virtual-root window manager. If you kill it with \-9,
-you may need to restart your window manager to repair the damage. This
-isn't an issue if you aren't running a virtual-root window manager.
-
-For all the gory details, see the commentary at the top of xscreensaver.c.
-
-You can control a running screensaver process by using the
-.BR xscreensaver\-command (1)
-program (which see.)
-.SH POWER MANAGEMENT
-Modern X servers contain support to power down the monitor after an idle
-period. If the monitor has powered down, then \fIxscreensaver\fP will
-notice this (after a few minutes), and will not waste CPU by drawing
-graphics demos on a black screen. An attempt will also be made to
-explicitly power the monitor back up as soon as user activity is detected.
-
-As of version 3.28 (Feb 2001), the \fI~/.xscreensaver\fP file controls the
-configuration of your display's power management settings: if you have
-used
-.BR xset (1)
-to change your power management settings, then xscreensaver will
-override those changes with the values specified
-in \fI~/.xscreensaver\fP (or with its built-in defaults, if there
-is no \fI~/.xscreensaver\fP file yet.)
-
-To change your power management settings, run
-.BR xscreensaver\-demo (1)
-and change the various timeouts through the user interface.
-Alternately, you can edit the \fI~/.xscreensaver\fP file directly.
-
-If the power management section is grayed out in the
-.BR xscreensaver\-demo (1)
-window, then that means that your X server does not support
-the XDPMS extension, and so control over the monitor's power state
-is not available.
-
-If you're using a laptop, don't be surprised if changing the DPMS
-settings has no effect: many laptops have monitor power-saving behavior
-built in at a very low level that is invisible to Unix and X. On such
-systems, you can typically adjust the power-saving delays only by
-changing settings in the BIOS in some hardware-specific way.
-
-If DPMS seems not to be working with XFree86, make sure the "DPMS"
-option is set in your \fI/etc/X11/XF86Config\fP file. See the
-.BR XF86Config (5)
-manual for details.
-.SH USING XDM(1)
-You can run \fIxscreensaver\fP from your
-.BR xdm (1)
-session, so that the screensaver will run even when nobody is logged
-in on the console.
-
-The trick to using xscreensaver with \fIxdm\fP is this: keep in mind the
-two very different states in which xscreensaver will be running:
-.RS 4
-.TP 3
-.B 1: Nobody logged in.
-
-If you're thinking of running xscreensaver from XDM at all, then it's
-probably because you want graphics demos to be running on the console
-when nobody is logged in there. In this case, xscreensaver will function
-only as a screen saver, not a screen locker: it doesn't make sense
-for xscreensaver to lock the screen, since nobody is logged in yet!
-The only thing on the screen is the XDM login prompt.
-.TP 3
-.B 2: Somebody logged in.
-
-Once someone has logged in through the XDM login window, the situation is
-very different. For example: now it makes sense to lock the screen (and
-prompt for the logged in user's password); and now xscreensaver should
-consult that user's \fI~/.xscreensaver\fP file; and so on.
-.RE
-
-The difference between these two states comes down to a question of,
-which user is the \fIxscreensaver\fP process running as? For the first
-state, it doesn't matter. If you start \fIxscreensaver\fP in the usual
-XDM way, then xscreensaver will probably end up running as root, which
-is fine for the first case (the ``nobody logged in'' case.)
-
-However, once someone is logged in, running as root is no longer fine:
-because xscreensaver will be consulting root's \fI.xscreensaver\fP file
-instead of that of the logged in user, and won't be prompting for the
-logged in user's password, and so on. (This is not a security problem,
-it's just not what you want.)
-
-So, once someone has logged in, you want xscreensaver to be running as that
-user. The way to accomplish this is to kill the old xscreensaver process
-and start a new one (as the new user.)
-
-The simplest way to accomplish all of this is as follows:
-.RS 4
-.TP 3
-.B 1: Launch xscreensaver before anyone logs in.
-
-To the file \fI/usr/lib/X11/xdm/Xsetup\fP, add the lines
-.EX
-xhost +localhost
-xscreensaver-command -exit
-xscreensaver &
-.EE
-This will run xscreensaver as root, over the XDM login window.
-Moving the mouse will cause the screen to un-blank, and allow the user
-to type their password at XDM to log in.
-.TP 3
-.B 2: Restart xscreensaver when someone logs in.
-
-Near the top of the file \fI/usr/lib/X11/xdm/Xsession\fP, add those same lines:
-.EX
-xscreensaver-command -exit
-xscreensaver &
-.EE
-When someone logs in, this will kill off the existing (root) xscreensaver
-process, and start a new one, running as the user who has just logged in.
-If the user's .xscreensaver file requests locking, they'll get it. They
-will also get their own choice of timeouts, and graphics demos, and so on.
-
-Alternately, each user could just put those lines in their
-personal \fI~/.xsession\fP files.
-.RE
-
-Make sure you have \fB$PATH\fP set up correctly in the \fIXsetup\fP
-and \fIXsession\fP scripts, or \fIxdm\fP won't be able to
-find \fIxscreensaver\fP, and/or \fIxscreensaver\fP won't be able to
-find its graphics demos.
-
-(If your system does not seem to be executing the \fIXsetup\fP file, you
-may need to configure it to do so: the traditional way to do this is
-to make that file the value of the \fIDisplayManager*setup\fP resource
-in the \fI/usr/lib/X11/xdm/xdm-config\fP file. See the man page for
-.BR xdm (1)
-for more details.)
-
-It is safe to run \fIxscreensaver\fP as root (as \fIxdm\fP is likely to do.)
-If run as root, \fIxscreensaver\fP changes its effective user and group ids
-to something safe (like \fI"nobody"\fP) before connecting to the X server
-or launching user-specified programs.
-
-An unfortunate side effect of this (important) security precaution is that
-it may conflict with cookie-based authentication.
-
-If you get "connection refused" errors when running \fIxscreensaver\fP
-from \fIxdm\fP, then this probably means that you have
-.BR xauth (1)
-or some other security mechanism turned on. One way around this is to
-add \fB"xhost\ +localhost"\fP to \fIXsetup\fP, just before \fIxscreensaver\fP
-is launched.
-
-Note that this will give access to the X server to anyone capable of logging
-in to the local machine, so in some environments, this might not be
-appropriate. If turning off file-system-based access control is not
-acceptable, then running \fIxscreensaver\fP from the \fIXsetup\fP file
-might not be possible, and xscreensaver will only work when running as
-a normal, unprivileged user.
-
-For more information on the X server's access control mechanisms, see the
-man pages for
-.BR X (1),
-.BR Xsecurity (1),
-.BR xauth (1),
-and
-.BR xhost (1).
-.SH USING GDM(1)
-Using xscreensaver with
-.BR gdm (1)
-is easy, because gdm has a configuration tool. Just fire up
-.BR gdmconfig (1)
-and on the \fIBackground\fP page, type \fB"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.)
-
-Another way to accomplish the same thing is to edit the
-file \fI/etc/X11/gdm/gdm.conf\fP to include:
-.EX
-BackgroundProgram=xscreensaver -nosplash
-RunBackgroundProgramAlways=true
-.EE
-In this situation, the \fIxscreensaver\fP process will probably be running
-as user \fIgdm\fP instead of \fIroot\fP. You can configure the settings
-for this nobody-logged-in state (timeouts, DPMS, etc.) by editing
-the \fI~gdm/.xscreensaver\fP file.
-
-To get gdm to run the BackgroundProgram, you may need to switch it from
-the "Graphical Greeter" to the "Standard Greeter".
-.SH USING KDE (K DESKTOP ENVIRONMENT)
-I understand that KDE has invented their own wrapper around xscreensaver,
-that is inferior to
-.BR xscreensaver-demo (1)
-in any number of ways. I've never actually seen it, but I'm told that
-this is the way you disable it:
-.RS 4
-.TP 3
-\fB1: Switch off KDE's screen saver.\fP
-Open the ``\fIControl Center\fP'' and
-select the ``\fIAppearance & Themes -> Screensaver\fP'' page.
-Turn off the ``\fIStart Automatically\fP'' checkbox.
-.TP 3
-\fB2: Find your Autostart directory.\fP
-Open the ``\fISystem Administration -> Paths\fP'' page,
-and see what your ``Autostart path'' is set to: it will
-probably be \fI~/.kde/Autostart/\fP or something similar.
-.TP 3
-\fB3: Make xscreensaver be an Autostart program.\fP
-Create a .desktop file in your autostart directory
-called \fIxscreensaver.desktop\fP that contains the following five lines:
-.EX
-[Desktop Entry]
-Exec=xscreensaver
-Name=XScreensaver
-Type=Application
-X-KDE-StartupNotify=false
-.EE
-.TP 3
-\fB4: Make the various "lock session" buttons call xscreensaver.\fP
-Replace the file \fI/usr/bin/kdesktop_lock\fP (or
-possibly \fI/usr/kde/3.5/bin/kdesktop_lock\fP)
-with these two lines:
-.EX
-#!/bin/sh
-xscreensaver-command -lock
-.EE
-Make sure the file is executable (chmod a+x).
-.RE
-.PP
-Now use xscreensaver normally, controlling it via the usual
-.BR xscreensaver-demo (1)
-and
-.BR xscreensaver-command (1)
-mechanisms.
-.SH USING CDE (COMMON DESKTOP ENVIRONMENT)
-The easiest way to use \fIxscreensaver\fP on a system with CDE is to simply
-switch off the built-in CDE screensaver, and use \fIxscreensaver\fP instead;
-and second, to tell the front panel to run
-.BR xscreensaver\-command (1)
-with the \fI\-lock\fP option when the \fILock\fP icon is clicked.
-
-To accomplish this involves five steps:
-.RS 4
-.TP 3
-\fB1: Switch off CDE's locker\fP
-Do this by turning off ``\fIScreen Saver and Screen Lock\fP'' in the
-Screen section of the Style Manager.
-.TP 3
-\fB2: Edit sessionetc\fP
-Edit the file \fI~/.dt/sessions/sessionetc\fP and add to it the line
-.EX
-xscreensaver &
-.EE
-And make sure the sessionetc file is executable.
-This will cause \fIxscreensaver\fP to be launched when you log in.
-(As always, make sure that xscreensaver and the graphics demos are on
-your \fB$PATH\fP; the path needs to be set in \fI.cshrc\fP
-and/or \fI.dtprofile\fP, not \fI.login\fP.)
-.TP 3
-\fB3: Create XScreenSaver.dt\fP
-Create a file called \fI~/.dt/types/XScreenSaver.dt\fP with the following
-contents:
-.EX
-ACTION XScreenSaver
-{
- LABEL XScreenSaver
- TYPE COMMAND
- EXEC_STRING xscreensaver-command -lock
- ICON Dtkey
- WINDOW_TYPE NO_STDIO
-}
-.EE
-This defines a ``lock'' command for the CDE front panel, that knows how
-to talk to \fIxscreensaver\fP.
-.TP 3
-\fB4: Create Lock.fp\fP
-Create a file called \fI~/.dt/types/Lock.fp\fP with the following
-contents:
-.EX
-CONTROL Lock
-{
- TYPE icon
- CONTAINER_NAME Switch
- CONTAINER_TYPE SWITCH
- POSITION_HINTS 1
- ICON Fplock
- LABEL Lock
- PUSH_ACTION XScreenSaver
- HELP_TOPIC FPOnItemLock
- HELP_VOLUME FPanel
-}
-.EE
-This associates the CDE front panel ``Lock'' icon with the lock command
-we just defined in step 3.
-.TP 3
-\fB5: Restart\fP
-Select ``\fIRestart Workspace Manager\fP'' from the popup menu to make
-your changes take effect. If things seem not to be working, check the
-file \fI~/.dt/errorlog\fP for error messages.
-.RE
-.SH USING HP VUE (VISUAL USER ENVIRONMENT)
-Since CDE is a descendant of VUE, the instructions for using xscreensaver
-under VUE are similar to the above:
-.RS 4
-.TP 3
-\fB1: Switch off VUE's locker\fP
-Open the ``\fIStyle Manager\fP'' and select ``\fIScreen\fP.''
-Turn off ``\fIScreen Saver and Screen Lock\fP'' option.
-.TP 3
-\fB2: Make sure you have a Session\fP
-Next, go to the Style Manager's, ``\fIStartup\fP'' page.
-Click on ``\fISet Home Session\fP'' to create a session, then
-on ``\fIReturn to Home Session\fP'' to select this session each
-time you log in.
-.TP 3
-\fB3: Edit vue.session\fP
-Edit the file \fI~/.vue/sessions/home/vue.session\fP and add to it
-the line
-.EX
-vuesmcmd -screen 0 -cmd "xscreensaver"
-.EE
-This will cause \fIxscreensaver\fP to be launched when you log in.
-(As always, make sure that xscreensaver and the graphics demos are on
-your \fB$PATH\fP; the path needs to be set in \fI.cshrc\fP
-and/or \fI.profile\fP, not \fI.login\fP.)
-.TP 3
-\fB3: Edit vuewmrc\fP
-Edit the file \fI~/.vue/vuewmrc\fP and add (or change) the Lock control:
-.EX
-CONTROL Lock
-{
- TYPE button
- IMAGE lock
- PUSH_ACTION f.exec "xscreensaver-command -lock"
- HELP_TOPIC FPLock
-}
-.EE
-This associates the VUE front panel ``Lock'' icon with the xscreensaver
-lock command.
-.RE
-.PP
-.SH BUGS
-Bugs? There are no bugs. Ok, well, maybe. If you find one, please let
-me know. http://www.jwz.org/xscreensaver/bugs.html explains how to
-construct the most useful bug reports.
-.TP 8
-.B Locking and XDM
-If xscreensaver has been launched from
-.BR xdm (1)
-before anyone has logged in, you will need to kill and then restart the
-xscreensaver daemon after you have logged in, or you will be confused by
-the results. (For example, locking won't work, and your \fI~/.xscreensaver\fP
-file will be ignored.)
-
-When you are logged in, you want the \fIxscreensaver\fP daemon to be
-running under \fIyour\fP user id, not as root or some other user.
-
-If it has already been started by \fIxdm\fP, you can kill it by sending
-it the \fBexit\fP command, and then re-launching it as you, by putting
-something like the following in your personal X startup script:
-.EX
-xscreensaver-command -exit
-xscreensaver &
-.EE
-The ``\fIUsing XDM(1)\fP'' section, above, goes into more detail, and explains
-how to configure the system to do this for all users automatically.
-.TP 8
-.B Locking and root logins
-In order for it to be safe for xscreensaver to be launched by \fIxdm\fP,
-certain precautions had to be taken, among them that xscreensaver never
-runs as \fIroot\fP. In particular, if it is launched as root (as \fIxdm\fP
-is likely to do), xscreensaver will disavow its privileges, and switch
-itself to a safe user id (such as \fInobody\fP.)
-
-An implication of this is that if you log in as \fIroot\fP on the console,
-xscreensaver will refuse to lock the screen (because it can't tell
-the difference between \fIroot\fP being logged in on the console, and a
-normal user being logged in on the console but xscreensaver having been
-launched by the
-.BR xdm (1)
-.I Xsetup
-file.)
+If a line begins with a dash (-) then that particular program is
+disabled: it won't be selected at random (though you can still select
+it explicitly using the
+.BR xscreensaver\-demo (1)
+program.)
-The solution to this is simple: you shouldn't be logging in on the console
-as \fIroot\fP in the first place! (What, are you crazy or something?)
+If all programs are disabled, then the screen will just be made blank,
+as when \fImode\fP is set to \fIblank\fP.
-Proper Unix hygiene dictates that you should log in as yourself, and
-.BR su (1)
-to \fIroot\fP as necessary. People who spend their day logged in
-as \fIroot\fP are just begging for disaster.
-.TP 8
-.B XAUTH and XDM
-For xscreensaver to work when launched by
-.BR xdm (1),
-programs running on the local machine as user \fI"nobody"\fP must be
-able to connect to the X server. This means that if you want to run
-xscreensaver on the console while nobody is logged in, you may need
-to disable cookie-based access control (and allow all users who can log
-in to the local machine to connect to the display.)
+To disable a program, you must mark it as disabled with a dash instead
+of removing it from the list. This is because the system-wide (app-defaults)
+and per-user (.xscreensaver) settings are merged together, and if a user
+just \fIdeletes\fP an entry from their programs list, but that entry still
+exists in the system-wide list, then it will come back. However, if the
+user \fIdisables\fP it, then their setting takes precedence.
-You should be sure that this is an acceptable thing to do in your
-environment before doing it. See the ``\fIUsing XDM(1)\fP'' section,
-above, for more details.
-.TP 8
-.B Passwords
-If you get an error message at startup like ``couldn't get password
-of \fIuser\fP'' then this probably means that you're on a system in which
-the
-.BR getpwent (3)
-library routine can only be effectively used by root. If this is the case,
-then \fIxscreensaver\fP must be installed as setuid to root in order for
-locking to work. Care has been taken to make this a safe thing to do.
+If the display has multiple screens, then a different program will be run
+for each screen. (All screens are blanked and unblanked simultaneously.)
-It also may mean that your system uses shadow passwords instead of the standard
-.BR getpwent (3)
-interface; in that case, you may need to change some options
-with \fIconfigure\fP and recompile.
+Note that you must escape the newlines; here is an example of how you
+might set this in your \fI~/.xscreensaver\fP file:
-If you change your password after xscreensaver has been launched, it will
-continue using your old password to unlock the screen until xscreensaver
-is restarted. On some systems, it may accept \fIboth\fP your old and new
-passwords. So, after you change your password, you'll have to do
+.RS 8
.EX
-xscreensaver-command -restart
+programs: \\
+ qix -root \\n\\
+ ico -r -faces -sleep 1 -obj ico \\n\\
+ xdaliclock -builtin2 -root \\n\\
+ xv -root -rmode 5 image.gif -quit \\n
.EE
-to make \fIxscreensaver\fP notice.
-.TP 8
-.B PAM Passwords
-If your system uses PAM (Pluggable Authentication Modules), then in order
-for xscreensaver to use PAM properly, PAM must be told about xscreensaver.
-The xscreensaver installation process should update the PAM data (on Linux,
-by creating the file \fI/etc/pam.d/xscreensaver\fP for you, and on Solaris,
-by telling you what lines to add to the \fI/etc/pam.conf\fP file.)
-
-If the PAM configuration files do not know about xscreensaver, then
-you \fImight\fP be in a situation where xscreensaver will refuse to ever
-unlock the screen.
-
-This is a design flaw in PAM (there is no way for a client to tell the
-difference between PAM responding ``I have never heard of your module,''
-and responding, ``you typed the wrong password.'') As far as I can tell,
-there is no way for xscreensaver to automatically work around this, or
-detect the problem in advance, so if you have PAM, make sure it is
-configured correctly!
-.TP 8
-.B Colormap lossage: TWM
-The \fBinstallColormap\fP option doesn't work very well with the
-.BR twm (1)
-window manager and its descendants, on 8-bit screens.
+.RE
+.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.
-There is a race condition between the screensaver and this window manager,
-which can result in the screensaver's colormap not getting installed
-properly, meaning the graphics hacks will appear in essentially random
-colors. (If the screen goes white instead of black, this is probably why.)
+To use a program as a screensaver, two things are required: that that
+program draw on the root window (or be able to be configured to draw on
+the root window); and that that program understand ``virtual root''
+windows, as used by virtual window managers such as
+.BR tvtwm (1).
+(Generally, this is accomplished by just including the \fI"vroot.h"\fP
+header file in the program's source.)
-The
-.BR mwm (1)
-and
-.BR olwm (1)
-window managers don't have this problem. The race condition exists
-because X (really, ICCCM) does not provide a way for an OverrideRedirect
-window to have its own colormap, short of grabbing the server (which is
-neither a good idea, nor really possible with the current design.) What
-happens is that, as soon as xscreensaver installs its colormap, \fBtwm\fP
-responds to the resultant \fBColormapNotify\fP event by re-installing the
-default colormap. Apparently, \fBtwm\fP doesn't \fIalways\fP do this; it
-seems to do it regularly if the screensaver is activated from a menu item,
-but seems to not do it if the screensaver comes on of its own volition, or
-is activated from another console.
+If there are some programs that you want to run only when using a color
+display, and others that you want to run only when using a monochrome
+display, you can specify that like this:
+.EX
+ mono: mono-program -root \\n\\
+ color: color-program -root \\n\\
+.EE
+.RE
+.RS 8
+More generally, you can specify the kind of visual that should be used for
+the window on which the program will be drawing. For example, if one
+program works best if it has a colormap, but another works best if it has
+a 24-bit visual, both can be accommodated:
+.EX
+ PseudoColor: cmap-program -root \\n\\
+ TrueColor: 24bit-program -root \\n\\
+.EE
+.RE
.RS 8
+In addition to the symbolic visual names described above (in the discussion
+of the \fIvisualID\fP resource) one other visual name is supported in
+the \fIprograms\fP list:
+.RS 1
.TP 4
-.B Attention, window manager authors!
-You should only call
-.BR XInstallColormap (3)
-in response to user events. That is, it is appropriate to install a colormap
-in response to \fBFocusIn\fP, \fBFocusOut\fP, \fBEnterNotify\fP,
-and \fBLeaveNotify\fP events; but it is not appropriate to call it in
-response to \fBColormapNotify\fP events. If you install colormaps in
-response to \fIapplication\fP actions as well as in response to \fIuser\fP
-actions, then you create the situation where it is impossible for
-override-redirect applications (such as xscreensaver) to display their
-windows in the proper colors.
+.B default-n
+This is like \fBdefault\fP, but also requests the use of the default colormap,
+instead of a private colormap. (That is, it behaves as if
+the \fI\-no\-install\fP command-line option was specified, but only for
+this particular hack.) This is provided because some third-party programs
+that draw on the root window (notably:
+.BR xv (1),
+and
+.BR xearth (1))
+make assumptions about the visual and colormap of the root window:
+assumptions which xscreensaver can violate.
+
+.RE
+If you specify a particular visual for a program, and that visual does not
+exist on the screen, then that program will not be chosen to run. This
+means that on displays with multiple screens of different depths, you can
+arrange for appropriate hacks to be run on each. For example, if one screen
+is color and the other is monochrome, hacks that look good in mono can be
+run on one, and hacks that only look good in color will show up on the other.
.RE
+.PP
+.PP
+You shouldn't ever need to change the following resources:
+.PP
.TP 8
-.B Colormap lossage: XV, XAnim, XEarth
-Some programs don't operate properly on visuals other than the default one,
-or with colormaps other than the default one. See the discussion of the
-magic "default-n" visual name in the description of the \fBprograms\fP
-resource in the \fIConfiguration\fP section. When programs only work with
-the default colormap, you need to use a syntax like this:
-.EX
- default-n: xv -root image-1.gif -quit \\n\\
- default-n: xearth -nostars -wait 0 \\n\\
-.EE
-It would also work to turn off the \fBinstallColormap\fP option altogether,
-but that would deny extra colors to those programs that \fIcan\fP take
-advantage of them.
+.B pointerPollTime\fP (class \fBTime\fP)
+When server extensions are not in use, this controls how
+frequently \fIxscreensaver\fP checks to see if the mouse position or buttons
+have changed. Default 5 seconds.
.TP 8
-.B Machine Load
-Although this program ``nices'' the subprocesses that it starts,
-graphics-intensive subprograms can still overload the machine by causing
-the X server process itself (which is not ``niced'') to consume many
-cycles. Care has been taken in all the modules shipped with xscreensaver
-to sleep periodically, and not run full tilt, so as not to cause
-appreciable load.
-
-However, if you are running the OpenGL-based screen savers on a machine
-that does not have a video card with 3D acceleration, they \fIwill\fP
-make your machine slow, despite
-.BR nice (1).
-
-Your options are: don't use the OpenGL display modes; or, collect the
-spare change hidden under the cushions of your couch, and use it to
-buy a video card manufactured after 1998. (It doesn't even need to be
-\fIfast\fP 3D hardware: the problem will be fixed if there is any
-3D hardware \fIat all.\fP)
+.B pointerHysteresis\fP (class \fBInteger\fP)
+If the mouse moves less than this-many pixels in a second, ignore it
+(do not consider that to be "activity.") This is so that the screen
+doesn't un-blank (or fail to blank) just because you bumped the desk.
+Default: 10 pixels.
.TP 8
-.B XFree86's Magic Keystrokes
-The XFree86 X server traps certain magic keystrokes before client programs ever
-see them. Two that are of note are Ctrl+Alt+Backspace, which causes
-the X server to exit; and Ctrl+Alt+F\fIn\fP, which switches virtual consoles.
-The X server will respond to these keystrokes even if xscreensaver has the
-screen locked. Depending on your setup, you might consider this a problem.
-
-Unfortunately, there is no way for xscreensaver itself to override the
-interpretation of these keys. If you want to disable Ctrl+Alt+Backspace
-globally, you need to set the \fIDontZap\fP flag in
-your \fI/etc/X11/XF86Config\fP file. To globally disable VT switching,
-you can set the \fIDontVTSwitch\fP flag. See the
-.BR XF86Config (5)
-manual for details.
+.B windowCreationTimeout\fP (class \fBTime\fP)
+When server extensions are not in use, this controls the delay between when
+windows are created and when \fIxscreensaver\fP selects events on them.
+Default 30 seconds.
+.TP 8
+.B initialDelay\fP (class \fBTime\fP)
+When server extensions are not in use, \fIxscreensaver\fP will wait this many
+seconds before selecting events on existing windows, under the assumption that
+\fIxscreensaver\fP is started during your login procedure, and the window
+state may be in flux. Default 0. (This used to default to 30, but that was
+back in the days when slow machines and X terminals were more common...)
+.RE
+.PP
+There are a number of different X server extensions which can make
+xscreensaver's job easier. The next few resources specify whether these
+extensions should be utilized if they are available.
+.TP 8
+.B sgiSaverExtension\fP (class \fBBoolean\fP)
+This resource controls whether the SGI \fBSCREEN_SAVER\fP server extension
+will be used to decide whether the user is idle. This is the default
+if \fIxscreensaver\fP has been compiled with support for this
+extension (which is the default on SGI systems.). If it is available,
+the \fBSCREEN_SAVER\fP method is faster and more reliable than what will
+be done otherwise, so use it if you can. (This extension is only available
+on Silicon Graphics systems, unfortunately.)
+.TP 8
+.B mitSaverExtension\fP (class \fBBoolean\fP)
+This resource controls whether the \fBMIT\-SCREEN\-SAVER\fP server extension
+will be used to decide whether the user is idle. However, the default for
+this resource is \fIfalse\fP, because even if this extension is available,
+it is flaky (and it also makes the \fBfade\fP option not work properly.)
+Use of this extension is strongly discouraged. Support for it will
+probably be removed eventually.
+.TP 8
+.B xidleExtension\fP (class \fBBoolean\fP)
+This resource controls whether the \fBXIDLE\fP server extension will be
+used to decide whether the user is idle. This is the default
+if \fIxscreensaver\fP has been compiled with support for this extension.
+(This extension is only available for X11R4 and X11R5 systems, unfortunately.)
.TP 8
-.B MIT Extension and Fading
-The \fBMIT-SCREEN-SAVER\fP extension is junk. Don't use it.
+.B procInterrupts\fP (class \fBBoolean\fP)
+This resource controls whether the \fB/proc/interrupts\fP file should be
+consulted to decide whether the user is idle. This is the default
+if \fIxscreensaver\fP has been compiled on a system which supports this
+mechanism (i.e., Linux systems.)
-When using the \fBMIT-SCREEN-SAVER\fP extension in conjunction with
-the \fBfade\fP option, you'll notice an unattractive flicker just before
-the fade begins. This is because the server maps a black window just before
-it tells the \fIxscreensaver\fP process to activate. The \fIxscreensaver\fP
-process immediately unmaps that window, but this results in a flicker. I
-haven't figured a way to get around this; it seems to be a fundamental
-property of the (mis-) design of this server extension.
+The benefit to doing this is that \fIxscreensaver\fP can note that the user
+is active even when the X console is not the active one: if the user is
+typing in another virtual console, xscreensaver will notice that and will
+fail to activate. For example, if you're playing Quake in VGA-mode,
+xscreensaver won't wake up in the middle of your game and start competing
+for CPU.
-It sure would be nice if someone would implement the \fBSGI SCREEN_SAVER\fP
-extension in XFree86; it's dead simple, and works far better than the
-over-engineered and broken \fBMIT-SCREEN-SAVER\fP extension.
-.TP 8
-.B Keyboard LEDs
-If \fIprocInterrupts\fP is on (which is the default on Linux systems) and
-you're using some program that toggles the state of your keyboard LEDs,
-xscreensaver won't work right: turning those LEDs on or off causes a
-keyboard interrupt, which xscreensaver will interpret as user activity.
-So if you're using such a program, set the \fIprocInterrupts\fP resource
-to False.
-.TP 8
-.B Extensions
-If you are not making use of one of the server extensions (\fBXIDLE\fP,
-\fBSGI SCREEN_SAVER\fP, or \fBMIT-SCREEN-SAVER\fP), then it is possible, in
-rare situations, for \fIxscreensaver\fP to interfere with event propagation
-and make another X program malfunction. For this to occur, that other
-application would need to \fInot\fP select \fBKeyPress\fP events on its
-non-leaf windows within the first 30 seconds of their existence, but then
-select for them later. In this case, that client \fImight\fP fail to receive
-those events. This isn't very likely, since programs generally select a
-constant set of events immediately after creating their windows and then
-don't change them, but this is the reason that it's a good idea to install
-and use one of the server extensions instead, to work around this shortcoming
-in the X protocol.
+The drawback to doing this is that perhaps you \fIreally do\fP want idleness
+on the X console to cause the X display to lock, even if there is activity
+on other virtual consoles. If you want that, then set this option to False.
+(Or just lock the X console manually.)
-In all these years, I've not heard of even a single case of this happening,
-but it is theoretically possible, so I'm mentioning it for completeness...
+The default value for this resource is True, on systems where it works.
+.TP 8
+.B overlayStderr\fP (class \fBBoolean\fP)
+If \fBcaptureStderr\fP is True, and your server supports ``overlay'' visuals,
+then the text will be written into one of the higher layers instead of into
+the same layer as the running screenhack. Set this to False to disable
+that (though you shouldn't need to.)
+.TP 8
+.B overlayTextForeground\fP (class \fBForeground\fP)
+The foreground color used for the stdout/stderr text, if \fBcaptureStderr\fP
+is true. Default: Yellow.
+.TP 8
+.B overlayTextBackground\fP (class \fBBackground\fP)
+The background color used for the stdout/stderr text, if \fBcaptureStderr\fP
+is true. Default: Black.
+.TP 8
+.B bourneShell\fP (class \fBBourneShell\fP)
+The pathname of the shell that \fIxscreensaver\fP uses to start subprocesses.
+This must be whatever your local variant of \fB/bin/sh\fP is: in particular,
+it must not be \fBcsh\fP.
.SH ENVIRONMENT
.PP
.TP 8
to get the default host and display number, and to inform the sub-programs
of the screen on which to draw.
.TP 8
+.B XSCREENSAVER_WINDOW
+Passed to sub-programs to indicate the ID of the window on which they
+should draw on. This is necessary on Xinerama/RANDR systems where
+multiple physical monitors share a single X11 "Screen".
+.TP 8
.B PATH
to find the sub-programs to run.
.TP 8
.BR xscreensaver\-text (1).
.SH COPYRIGHT
Copyright \(co 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-2000, 2001, 2002, 2003, 2004, 2005 by Jamie Zawinski. Permission to use,
-copy, modify, distribute, and sell this software and its documentation for
-any purpose is hereby granted without fee, provided that the above copyright
-notice appear in all copies and that both that copyright notice and this
-permission notice appear in supporting documentation. No representations are
-made about the suitability of this software for any purpose. It is provided
-"as is" without express or implied warranty.
+2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by Jamie Zawinski.
+Permission to use, copy, modify, distribute, and sell this software
+and its documentation for any purpose is hereby granted without fee,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation. No representations are made about the
+suitability of this software for any purpose. It is provided "as is"
+without express or implied warranty.
.SH AUTHOR
Jamie Zawinski <jwz@jwz.org>. Written in late 1991; version 1.0 posted
to comp.sources.x on 17-Aug-1992.
intermomentary.o fireworkx.o fiberlamp.o boxfit.o \
interaggregate.o celtic.o cwaves.o webcollage-cocoa.o \
webcollage-helper-cocoa.o m6502.0 asm6502.o abstractile.o \
- lcdscrub.c
+ lcdscrub.o
NEXES = attraction blitspin bouboule braid bubbles decayscreen deco \
drift flag flame forest vines galaxy grav greynetic halo \
anemotaxis.man memscroller.man substrate.man \
intermomentary.man fireworkx.man fiberlamp.man boxfit.man \
interaggregate.man celtic.man cwaves.man abstractile.man \
- lcdscrub
+ lcdscrub.man
STAR = *
EXTRAS = README Makefile.in xml2man.pl m6502.sh .gdbinit \
euler2d.tex \
bsod.o: ../config.h
bsod.o: $(srcdir)/images/amiga.xpm
bsod.o: $(srcdir)/images/atari.xbm
+bsod.o: $(srcdir)/images/atm.xbm
bsod.o: $(srcdir)/images/hmac.xpm
bsod.o: $(srcdir)/images/macbomb.xbm
bsod.o: $(srcdir)/images/mac.xbm
-/* xscreensaver, Copyright (c) 1992-2006 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1992-2008 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
GC SET, CLR, CPY, IOR, AND, XOR;
GC gc;
int delay, delay2;
+ int duration;
Pixmap bitmap;
unsigned int fg, bg;
int first_time;
int last_w, last_h;
+ time_t start_time;
Bool loaded_p;
async_load_state *img_loader;
};
if (st->img_loader) /* still loading */
{
st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 0);
+
+ if (!st->img_loader) { /* just finished */
+ st->first_time = 0;
+ st->loaded_p = False;
+ st->qwad = -1;
+ st->start_time = time ((time_t) 0);
+ }
+
return this_delay;
}
+ if (!st->img_loader &&
+ st->start_time + st->duration < time ((time_t) 0)) {
+ /* Start it loading, but keep rotating the old image until it arrives. */
+ st->img_loader = load_image_async_simple (0, st->xgwa.screen, st->window,
+ st->bitmap, 0, 0);
+ }
+
if (! st->loaded_p) {
blitspin_init_2 (st);
st->loaded_p = True;
/* for (st->qwad = st->size>>1; st->qwad > 0; st->qwad>>=1) */
- copy_all_to (st->mask, 0, 0, st->temp, st->CPY); /* 1 */
- copy_all_to (st->mask, 0, st->qwad, st->temp, st->IOR); /* 2 */
- copy_all_to (st->self, 0, 0, st->temp, st->AND); /* 3 */
- copy_all_to (st->temp, 0, 0, st->self, st->XOR); /* 4 */
- copy_all_from (st->temp, st->qwad, 0, st->self, st->XOR); /* 5 */
- copy_all_from (st->self, st->qwad, 0, st->self, st->IOR); /* 6 */
- copy_all_to (st->temp, st->qwad, 0, st->self, st->XOR); /* 7 */
- copy_all_to (st->self, 0, 0, st->temp, st->CPY); /* 8 */
- copy_all_from (st->temp, st->qwad, st->qwad, st->self, st->XOR); /* 9 */
- copy_all_to (st->mask, 0, 0, st->temp, st->AND); /* A */
- copy_all_to (st->temp, 0, 0, st->self, st->XOR); /* B */
- copy_all_to (st->temp, st->qwad, st->qwad, st->self, st->XOR); /* C */
- copy_all_from (st->mask, st->qwad>>1, st->qwad>>1, st->mask, st->AND); /* D */
- copy_all_to (st->mask, st->qwad, 0, st->mask, st->IOR); /* E */
- copy_all_to (st->mask, 0, st->qwad, st->mask, st->IOR); /* F */
+ copy_all_to (st->mask, 0, 0, st->temp, st->CPY); /* 1 */
+ copy_all_to (st->mask, 0, st->qwad, st->temp, st->IOR); /* 2 */
+ copy_all_to (st->self, 0, 0, st->temp, st->AND); /* 3 */
+ copy_all_to (st->temp, 0, 0, st->self, st->XOR); /* 4 */
+ copy_all_from(st->temp, st->qwad, 0, st->self, st->XOR); /* 5 */
+ copy_all_from(st->self, st->qwad, 0, st->self, st->IOR); /* 6 */
+ copy_all_to (st->temp, st->qwad, 0, st->self, st->XOR); /* 7 */
+ copy_all_to (st->self, 0, 0, st->temp, st->CPY); /* 8 */
+ copy_all_from(st->temp, st->qwad, st->qwad, st->self,st->XOR);/*9*/
+ copy_all_to (st->mask, 0, 0, st->temp, st->AND); /* A */
+ copy_all_to (st->temp, 0, 0, st->self, st->XOR); /* B */
+ copy_all_to (st->temp, st->qwad, st->qwad, st->self, st->XOR); /* C */
+ copy_all_from(st->mask, st->qwad>>1,st->qwad>>1,st->mask,st->AND); /* D */
+ copy_all_to (st->mask, st->qwad, 0, st->mask, st->IOR); /* E */
+ copy_all_to (st->mask, 0, st->qwad, st->mask, st->IOR); /* F */
display (st, st->self);
st->qwad >>= 1;
"background", "Background");
st->delay = get_integer_resource (st->dpy, "delay", "Integer");
st->delay2 = get_integer_resource (st->dpy, "delay2", "Integer");
+ st->duration = get_integer_resource (st->dpy, "duration", "Seconds");
if (st->delay < 0) st->delay = 0;
if (st->delay2 < 0) st->delay2 = 0;
+ if (st->duration < 1) st->duration = 1;
+
+ st->start_time = time ((time_t) 0);
+
bitmap_name = get_string_resource (st->dpy, "bitmap", "Bitmap");
if (! bitmap_name || !*bitmap_name)
bitmap_name = "(default)";
if (!strcasecmp (bitmap_name, "(default)") ||
!strcasecmp (bitmap_name, "default"))
# ifdef HAVE_COCOA
+ /* I don't understand why it doesn't work with color images on OSX.
+ I guess "kCGBlendModeDarken" is not close enough to being "GXand".
+ */
bitmap_name = "(builtin)";
# else
bitmap_name = "(screen)";
XFillRectangle (st->dpy, st->self, st->gc, 0, 0, st->size, st->size);
XSetForeground (st->dpy, st->gc, st->fg);
+#if 0
+#ifdef HAVE_COCOA
+ jwxyz_XSetAntiAliasing (st->dpy, st->gc, False);
+ jwxyz_XSetAntiAliasing (st->dpy, st->SET, False);
+ jwxyz_XSetAntiAliasing (st->dpy, st->CLR, False);
+ jwxyz_XSetAntiAliasing (st->dpy, st->CPY, False);
+ jwxyz_XSetAntiAliasing (st->dpy, st->IOR, False);
+ jwxyz_XSetAntiAliasing (st->dpy, st->AND, False);
+ jwxyz_XSetAntiAliasing (st->dpy, st->XOR, False);
+#endif /* HAVE_COCOA */
+#endif
+
XCopyArea (st->dpy, st->bitmap, st->self, st->CPY, 0, 0,
st->width, st->height,
(st->size - st->width) >> 1,
(st->size - st->height) >> 1);
- XFreePixmap(st->dpy, st->bitmap);
+/* XFreePixmap(st->dpy, st->bitmap);*/
st->qwad = -1;
st->first_time = 1;
".foreground: white",
"*delay: 500000",
"*delay2: 500000",
+ "*duration: 120",
"*bitmap: (default)",
"*geometry: 512x512",
0
static XrmOptionDescRec blitspin_options [] = {
{ "-delay", ".delay", XrmoptionSepArg, 0 },
{ "-delay2", ".delay2", XrmoptionSepArg, 0 },
+ { "-duration", ".duration", XrmoptionSepArg, 0 },
{ "-bitmap", ".bitmap", XrmoptionSepArg, 0 },
{ 0, 0, 0, 0 }
};
[\-display \fIhost:display.screen\fP]
[\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root]
[\-mono] [\-install] [\-visual \fIvisual\fP] [\-bitmap \fIfilename\fP]
-[\-delay \fIusecs\fP] [\-delay2 \fIusecs\fP]
+[\-delay \fIusecs\fP] [\-delay2 \fIusecs\fP] [\-duration \fIsecs\fP]
.SH DESCRIPTION
The \fIblitspin\fP program repeatedly rotates a bitmap by 90 degrees by
using logical operations: the bitmap is divided into quadrants, and the
see
.BR xscreensaver-demo (1)
for more details.
-.PP
.TP 8
.B \-delay \fImicroseconds\fP
How long to delay between steps of the rotation process, in microseconds.
Default is 500000, one-half second.
-.PP
+.TP 8
+.B \-duration \fIseconds\fP
+How long to run before loading a new image. Default 120 seconds.
.TP 8
.B \-delay2 \fImicroseconds\fP
How long to delay between each 90-degree rotation, in microseconds.
#include "images/atari.xbm"
#include "images/mac.xbm"
#include "images/macbomb.xbm"
+#include "images/atm.xbm"
#undef countof
#define countof(x) (sizeof((x))/sizeof((*x)))
"Physical memory dump complete.\n"
"Contact your system administrator or technical support group for "
"further\n"
- "assitance.\n");
+ "assistance.\n");
XClearWindow (dpy, window);
return bst;
{ -1, "Soft power switch enabled, polling @ 0xf0400804.\n" },
{ -1, "pty: 256 Unix98 ptys configured\n" },
{ -1, "Generic RTC Driver v1.07\n" },
- { -1, "Serial: 8250/16550 driver $Revision: 1.88 $ 13 ports, "
+ { -1, "Serial: 8250/16550 driver $Revision: 1.90 $ 13 ports, "
"IRQ sharing disabled\n" },
{ -1, "ttyS0 at I/O 0x3f8 (irq = 0) is a 16550A\n" },
{ -1, "ttyS1 at I/O 0x2f8 (irq = 0) is a 16550A\n" },
}
+static struct bsod_state *
+atm (Display *dpy, Window window)
+{
+ struct bsod_state *bst = make_bsod_state (dpy, window, "atm", "ATM");
+
+ Pixmap pixmap = 0;
+ int pix_w = atm_width;
+ int pix_h = atm_height;
+ int x, y, i = 0;
+ float scale = 0.48;
+
+ XClearWindow (dpy, window);
+
+ pixmap = XCreatePixmapFromBitmapData (dpy, window, (char *) atm_bits,
+ atm_width, atm_height,
+ bst->fg, bst->bg, bst->xgwa.depth);
+
+ while (pix_w <= bst->xgwa.width * scale &&
+ pix_h <= bst->xgwa.height * scale)
+ {
+ pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth,
+ pixmap, pix_w, pix_h);
+ pix_w *= 2;
+ pix_h *= 2;
+ i++;
+ }
+
+ x = (bst->xgwa.width - pix_w) / 2;
+ y = (bst->xgwa.height - pix_h) / 2;
+ if (y < 0) y = 0;
+
+ if (i > 0)
+ {
+ int j;
+ XSetForeground (dpy, bst->gc,
+ get_pixel_resource (dpy, bst->xgwa.colormap,
+ "atm.background",
+ "ATM.Background"));
+ for (j = -1; j < pix_w; j += i+1)
+ XDrawLine (bst->dpy, pixmap, bst->gc, j, 0, j, pix_h);
+ for (j = -1; j < pix_h; j += i+1)
+ XDrawLine (bst->dpy, pixmap, bst->gc, 0, j, pix_w, j);
+ }
+
+ XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, x, y);
+
+ XFreePixmap (dpy, pixmap);
+
+ return bst;
+}
+
+
/*****************************************************************************
*****************************************************************************/
{ "MSDOS", msdos },
{ "Nvidia", nvidia },
{ "Apple2", apple2crash },
+ { "ATM", atm },
};
"*doMSDOS: True",
"*doOS2: True",
"*doNvidia: True",
+ "*doATM: True",
"*font: 9x15bold",
"*font2: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
".os2.foreground: White",
".os2.background: Black",
+ ".atm.foreground: Black",
+ ".atm.background: #FF6600",
+
"*dontClearRoot: True",
"*apple2TVColor: 50",
{ "-no-msdos", ".doMSDOS", XrmoptionNoArg, "False" },
{ "-os2", ".doOS2", XrmoptionNoArg, "True" },
{ "-no-os2", ".doOS2", XrmoptionNoArg, "False" },
+ { "-atm", ".doATM", XrmoptionNoArg, "True" },
+ { "-no-atm", ".doATM", XrmoptionNoArg, "False" },
ANALOGTV_OPTIONS
{ 0, 0, 0, 0 }
};
.BR doVMS ,
.BR doMSDOS ,
.BR doOS2 ,
+.BR doHVX ,
and
-.BR doHVX .
+.BR doATM .
Each of these is a Boolean resource, they all default to true, except
for doAtari, doBSD, doSparcLinux, and doHPPALinux, which are turned off
by default, because they're really not all that interesting looking
pBumps->SpotLight.nAccelMax = pBumps->SpotLight.nVelocityMax / 10.0f;
pBumps->dpy = dpy;
pBumps->Win = NewWin;
+ pBumps->screen = XWinAttribs.screen;
pBumps->pXImage = NULL;
iDiameter = ( ( pBumps->iWinWidth < pBumps->iWinHeight ) ? pBumps->iWinWidth : pBumps->iWinHeight ) / 2;
XWindowAttributes XWinAttribs;
XGetWindowAttributes( pBumps->dpy, pBumps->Win, &XWinAttribs );
+ pBumps->start_time = time ((time_t) 0);
+
pScreenImage = XGetImage( pBumps->dpy, pBumps->source, 0, 0,
pBumps->iWinWidth, pBumps->iWinHeight,
~0L, ZPixmap );
- XFreePixmap (pBumps->dpy, pBumps->source);
- pBumps->source = 0;
+/* XFreePixmap (pBumps->dpy, pBumps->source);
+ pBumps->source = 0;*/
XSetWindowBackground( pBumps->dpy, pBumps->Win, pBumps->aColors[ 0 ] );
XClearWindow (pBumps->dpy, pBumps->Win);
while( nSoften-- )
SoftenBumpMap( pBumps );
- free( pBumps->xColors );
- pBumps->xColors = 0;
+/* free( pBumps->xColors );
+ pBumps->xColors = 0;*/
}
/* Soften the bump map. This is to avoid pixelated-looking ridges.
CreateBumps( Bumps, dpy, Win );
Bumps->delay = get_integer_resource(dpy, "delay", "Integer" );
+ Bumps->duration = get_integer_resource (dpy, "duration", "Seconds");
+ if (Bumps->delay < 0) Bumps->delay = 0;
+ if (Bumps->duration < 1) Bumps->duration = 1;
+ Bumps->start_time = time ((time_t) 0);
return Bumps;
}
return Bumps->delay;
}
-
+ if (!Bumps->img_loader &&
+ Bumps->start_time + Bumps->duration < time ((time_t) 0)) {
+ Bumps->img_loader = load_image_async_simple (0, Bumps->screen,
+ Bumps->Win, Bumps->source,
+ 0, 0);
+ }
Execute( Bumps );
"*color: random",
"*colorcount: 64",
"*delay: 30000",
+ "*duration: 120",
"*soften: 1",
"*invert: FALSE",
#ifdef __sgi /* really, HAVE_READ_DISPLAY_EXTENSION */
static XrmOptionDescRec bumps_options [] = {
{ "-color", ".color", XrmoptionSepArg, 0 },
{ "-colorcount", ".colorcount", XrmoptionSepArg, 0 },
+ { "-duration", ".duration", XrmoptionSepArg, 0 },
{ "-delay", ".delay", XrmoptionSepArg, 0 },
{ "-soften", ".soften", XrmoptionSepArg, 0 },
{ "-invert", ".invert", XrmoptionNoArg, "TRUE" },
/* XWindows specific variables. */
Display *dpy;
Window Win;
+ Screen *screen;
Pixmap source;
GC GraphicsContext;
XColor *xColors;
SSpotLight SpotLight;
int delay;
+ int duration;
+ time_t start_time;
async_load_state *img_loader;
} SBumps;
[\-install]
[\-visual \fIvisual\fP]
[\-delay \fIusecs\fP]
+[\-duration \fIsecs\fP]
.SH DESCRIPTION
The \fIbumps\fP program takes an image and exposes small, distorted
sections of it as if through an odd wandering spotlight beam.
.TP 8
.B \-delay \fImicroseconds\fP
Slow it down.
+.TP 8
+.B \-duration \fIseconds\fP
+How long to run before loading a new image. Default 120 seconds.
.SH ENVIRONMENT
.PP
.TP 8
a screen saver and locker for the X window system
by Jamie Zawinski
- version 5.05
- 01-Mar-2008
+ version 5.06
+ 16-Jul-2008
http://www.jwz.org/xscreensaver/
<command arg="-root"/>
+ <hgroup>
<select id="mode">
<option id="balls" _label="Balls" arg-set="-mode balls"/>
<option id="lines" _label="Lines" arg-set="-mode lines"/>
<option id="nowalls" _label="Ignore Screen Edges" arg-set="-nowalls"/>
</select>
+ </hgroup>
+
<hgroup>
<number id="points" type="spinbutton" arg="-points %"
_label="Ball Count" low="0" high="200" default="0"/>
_label="Number of Colors" _low-label="Two" _high-label="Many"
low="1" high="255" default="200"/>
+<!--
<number id="color_contrast" type="slider" arg="-color-shift %"
_label="Color Contrast" _low-label="Low" _high-label="High"
low="0" high="25" default="3"/>
+-->
- <boolean id="orbit" _label="Orbital Mode" arg-set="-orbit"/>
<hgroup>
+ <boolean id="orbit" _label="Orbital Mode" arg-set="-orbit"/>
<number id="radius" type="spinbutton" arg="-radius %"
_label="Radius" low="0" high="1000" default="0"/>
<number id="vmult" type="slider" arg="-vmult %"
low="1" high="800000" default="500000"
convert="invert"/>
+ <number id="duration" type="slider" arg="-duration %"
+ _label="Duration" _low-label="10 seconds" _high-label="10 minutes"
+ low="10" high="600" default="120"/>
+
<!-- <file id="bitmap" _label="Bitmap to rotate" arg="-bitmap %"/> -->
<xscreensaver-image />
<screensaver name="bsod" _label="BSOD">
- <command arg="-root"/>
+ <command arg="-root"/>
- <number id="delay" type="slider" arg="-delay %"
- _label="Duration" _low-label="5 seconds" _high-label="2 minutes"
- low="5" high="120" default="30"/>
+ <number id="delay" type="slider" arg="-delay %"
+ _label="Duration" _low-label="5 seconds" _high-label="2 minutes"
+ low="5" high="120" default="30"/>
- <hgroup>
- <vgroup>
- <boolean id="windows" _label="Windows 3.1" arg-unset="-no-windows"/>
- <boolean id="nt" _label="Windows NT" arg-unset="-no-nt"/>
- <boolean id="2k" _label="Windows 2000 " arg-unset="-no-2k"/>
- <boolean id="msdos" _label="MS-DOS" arg-unset="-no-msdos"/>
- <boolean id="amiga" _label="AmigaDOS" arg-unset="-no-amiga"/>
- <boolean id="atari" _label="Atari" arg-set="-atari"/>
- <boolean id="apple2" _label="Apple II" arg-unset="-no-apple2"/>
- <boolean id="nvidia" _label="Nvidia" arg-unset="-no-nvidia"/>
- <boolean id="os2" _label="OS/2" arg-unset="-no-os2"/>
- </vgroup>
- <vgroup>
- <boolean id="mac" _label="Sad Mac" arg-unset="-no-mac"/>
- <boolean id="mac1" _label="Mac Bomb" arg-unset="-no-mac1"/>
- <boolean id="macsbug" _label="MacsBug" arg-unset="-no-macsbug"/>
- <boolean id="macx" _label="MacOS X" arg-unset="-no-macx"/>
- <boolean id="os390" _label="OS/390" arg-unset="-no-os390"/>
- <boolean id="vms" _label="VMS" arg-unset="-no-vms"/>
- <boolean id="hvx" _label="HVX/GCOS6" arg-unset="-no-hvx"/>
- <boolean id="blitdamage" _label="NCD X Terminal " arg-unset="-no-blitdamage"/>
- </vgroup>
- <vgroup>
- <boolean id="bsd" _label="BSD" arg-set="-bsd"/>
- <boolean id="linux" _label="Linux (fsck)" arg-unset="-no-linux"/>
- <boolean id="sparclinux" _label="Linux (sparc)" arg-set="-sparclinux"/>
- <boolean id="hppalinux" _label="Linux (hppa)" arg-unset="-no-hppalinux"/>
- <boolean id="solaris" _label="Solaris" arg-unset="-no-solaris"/>
- <boolean id="sco" _label="SCO" arg-unset="-no-sco"/>
- <boolean id="hpux" _label="HPUX" arg-unset="-no-hpux"/>
- <boolean id="tru64" _label="Tru64" arg-unset="-no-tru64"/>
- </vgroup>
- </hgroup>
+ <hgroup>
+ <vgroup>
+ <boolean id="windows" _label="Windows 3.1" arg-unset="-no-windows"/>
+ <boolean id="nt" _label="Windows NT" arg-unset="-no-nt"/>
+ <boolean id="2k" _label="Windows 2000 " arg-unset="-no-2k"/>
+ <boolean id="msdos" _label="MS-DOS" arg-unset="-no-msdos"/>
+ <boolean id="amiga" _label="AmigaDOS" arg-unset="-no-amiga"/>
+ <boolean id="atari" _label="Atari" arg-set="-atari"/>
+ <boolean id="apple2" _label="Apple II" arg-unset="-no-apple2"/>
+ <boolean id="nvidia" _label="Nvidia" arg-unset="-no-nvidia"/>
+ <boolean id="os2" _label="OS/2" arg-unset="-no-os2"/>
+ </vgroup>
+ <vgroup>
+ <boolean id="mac" _label="Sad Mac" arg-unset="-no-mac"/>
+ <boolean id="mac1" _label="Mac Bomb" arg-unset="-no-mac1"/>
+ <boolean id="macsbug" _label="MacsBug" arg-unset="-no-macsbug"/>
+ <boolean id="macx" _label="MacOS X" arg-unset="-no-macx"/>
+ <boolean id="os390" _label="OS/390" arg-unset="-no-os390"/>
+ <boolean id="vms" _label="VMS" arg-unset="-no-vms"/>
+ <boolean id="hvx" _label="HVX/GCOS6" arg-unset="-no-hvx"/>
+ <boolean id="blitdamage" _label="NCD X Terminal " arg-unset="-no-blitdamage"/>
+ <boolean id="atm" _label="ATM" arg-unset="-no-atm"/>
+ </vgroup>
+ <vgroup>
+ <boolean id="bsd" _label="BSD" arg-set="-bsd"/>
+ <boolean id="linux" _label="Linux (fsck)" arg-unset="-no-linux"/>
+ <boolean id="sparclinux" _label="Linux (sparc)" arg-set="-sparclinux"/>
+ <boolean id="hppalinux" _label="Linux (hppa)" arg-unset="-no-hppalinux"/>
+ <boolean id="solaris" _label="Solaris" arg-unset="-no-solaris"/>
+ <boolean id="sco" _label="SCO" arg-unset="-no-sco"/>
+ <boolean id="hpux" _label="HPUX" arg-unset="-no-hpux"/>
+ <boolean id="tru64" _label="Tru64" arg-unset="-no-tru64"/>
+ </vgroup>
+ </hgroup>
- <xscreensaver-image />
+ <xscreensaver-image />
- <_description>
+ <_description>
BSOD stands for "Blue Screen of Death". The finest in personal
computer emulation, this program simulates popular screen savers from a
number of less robust operating systems.
Written by Jamie Zawinski; 1998.
- </_description>
+ </_description>
</screensaver>
low="0" high="100000" default="30000"
convert="invert"/>
+ <number id="duration" type="slider" arg="-duration %"
+ _label="Duration" _low-label="10 seconds" _high-label="10 minutes"
+ low="10" high="600" default="120"/>
+
<!-- #### -soften [1] -->
<!-- #### -invert -->
<hgroup>
<number id="count" type="spinbutton" arg="-count %"
_label="Number of Images:" low="1" high="20" default="7"/>
+ <select id="mode">
+ <option id="tiltxy" _label="Tilt In/Out and Left/Right"/>
+ <option id="tiltx" _label="Tilt In/Out Only" arg-set="-tilt x"/>
+ <option id="tilty" _label="Tilt Left/Right Only" arg-set="-tilt y"/>
+ <option id="notilt" _label="No Tilting" arg-set="-tilt 0"/>
+ </select>
</hgroup>
<number id="duration" type="slider" arg="-duration %"
low="0" high="100000" default="20000"
convert="invert"/>
- <select id="mode">
- <option id="tiltxy" _label="Tilt In/Out and Left/Right"/>
- <option id="tiltx" _label="Tilt In/Out Only" arg-set="-tilt x"/>
- <option id="tilty" _label="Tilt Left/Right Only" arg-set="-tilt y"/>
- <option id="notilt" _label="No Tilting" arg-set="-tilt 0"/>
- </select>
-
<xscreensaver-image />
<boolean id="zoom" _label="Zoom In/Out" arg-unset="-no-zoom"/>
low="0" high="20000" default="10000"
convert="invert"/>
+ <number id="duration" type="slider" arg="-duration %"
+ _label="Duration" _low-label="10 seconds" _high-label="10 minutes"
+ low="10" high="600" default="120"/>
+
<select id="mode">
<option id="random" _label="Random Melt Style"/>
<option id="random" _label="Shuffle Melt" arg-set="-mode shuffle"/>
low="0" high="200000" default="20000"
convert="invert"/>
+ <number id="duration" type="slider" arg="-duration %"
+ _label="Duration" _low-label="10 seconds" _high-label="10 minutes"
+ low="10" high="600" default="120"/>
+
<!-- #### -speed [0] -->
<!-- #### -slow -->
<?xml version="1.0" encoding="ISO-8859-1"?>
-<screensaver name="glschool" _label="glschool">
+<screensaver name="glschool" _label="GLSchool">
<command arg="-root"/>
<number id="CenterFact" type="slider" arg="-centerfact %" _label="Centering" _low-label="None" _high-label="High" low="0" high="1.0" default="0.1"/>
<number id="TargetFact" type="slider" arg="-targetfact %" _label="Goal Following" _low-label="None" _high-label="High" low="0" high="400" default="80"/>
+ <hgroup>
<boolean id="wire" _label="Wireframe" arg-set="-wireframe"/>
<boolean id="fog" _label="Fog" arg-set="-fog"/>
<boolean id="drawgoal" _label="Draw Goal" arg-set="-drawgoal"/>
<boolean id="drawbbox" _label="Draw Bounding Box" arg-set="-drawbbox"/>
+ </hgroup>
<boolean id="showfps" _label="Show Frames-per-Second" arg-set="-fps"/>
<_description>
<command arg="-root"/>
- <boolean id="random" _label="Randomize Almost Everything" arg-unset="-no-random"/>
+ <boolean id="random" _label="Randomize almost everything" arg-unset="-no-random"/>
<hgroup>
<vgroup>
low="50" high="1000" default="250"/>
<number id="spherism" type="slider" arg="-spherism %"
- _label="Sphere strength" _low-label="none" _high-label="strong"
+ _label="Sphere strength" _low-label="None" _high-label="Strong"
low="0" high="1000" default="200"/>
<number id="hold" type="slider" arg="-hold %"
- _label="Vertex-vertex force" _low-label="none" _high-label="strong"
+ _label="Vertex-vertex force" _low-label="None" _high-label="Strong"
low="0" high="1000" default="700"/>
</vgroup>
<vgroup>
<number id="distance" type="slider" arg="-distance %"
- _label="Vertex-vertex behavior" _low-label="expand"
- _high-label="collapse" low="0" high="1000" default="300"/>
+ _label="Vertex-vertex behavior" _low-label="Expand"
+ _high-label="Collapse" low="0" high="1000" default="300"/>
<number id="damping" type="slider" arg="-damping %"
_label="Inertial damping" _low-label="Low" _high-label="High"
_label="Spookiness" _low-label="None" _high-label="Spoooooky"
low="0" high="12" default="0"/>
- <hgroup>
- <select id="color">
- <option id="cycle" _label="Cycle" />
- <option id="flowerbox" _label="Flower box" arg-set="-color flowerbox"/>
- <option id="clownbarf" _label="Clown barf" arg-set="-color clownbarf"/>
- <option id="chrome" _label="Chrome" arg-set="-color chrome"/>
- </select>
+ <number id="delay" type="slider" arg="-delay %"
+ _label="Animation Speed" _low-label="Slow" _high-label="Fast"
+ low="0" high="20000" default="20000"
+ convert="invert"/>
+ </vgroup>
+ </hgroup>
+
+ <hgroup>
+ <select id="color">
+ <option id="cycle" _label="Cycle" />
+ <option id="flowerbox" _label="Flower box" arg-set="-color flowerbox"/>
+ <option id="clownbarf" _label="Clown barf" arg-set="-color clownbarf"/>
+ <option id="chrome" _label="Chrome" arg-set="-color chrome"/>
+ </select>
- <select id="start">
- <option id="sphere" _label="Sphere" />
- <option id="tetrahedron" _label="Tetrahedron" arg-set="-tetra"/>
- </select>
- </hgroup>
+ <select id="start">
+ <option id="sphere" _label="Sphere" />
+ <option id="tetrahedron" _label="Tetrahedron" arg-set="-tetra"/>
+ </select>
- <boolean id="wireframe" _label="Wireframe" arg-set="-wireframe"/>
- <boolean id="showfps" _label="Show Frames-per-Second" arg-set="-fps"/>
+ <boolean id="wireframe" _label="Wireframe" arg-set="-wireframe"/>
+ <boolean id="showfps" _label="Show Frames-per-Second" arg-set="-fps"/>
- </vgroup>
</hgroup>
- <number id="delay" type="slider" arg="-delay %"
- _label="Animation Speed" _low-label="Slow" _high-label="Fast"
- low="0" high="20000" default="20000"
- convert="invert"/>
-
<_description>
This does bad things with quasi-spherical objects.
<string id="pattern" _label="Juggle This Pattern" arg="-pattern %" />
<_description>
-Draws a juggling stick-man. See also "Juggle3D".
+Draws a juggling stick-man. See also "Juggler3D".
Written by Tim Auckland; 2002.
</_description>
<_description>
Animates a simulation of Lemarchand's Box, the Lament Configuration,
-repeatedly solving itself. Warning: occasionally opens doors.
+repeatedly solving itself.
+
+Warning: occasionally opens doors.
Written by Jamie Zawinski; 1998.
</_description>
<command arg="-root"/>
- <number id="delay" type="slider" arg="-delay %"
- _label="Speed" _low-label="Slow" _high-label="Fast"
- low="0" high="20000" default="10000"
- convert="invert"/>
-
- <number id="zoom" type="slider" arg="-zoom %"
- _label="Zoom"
- _low-label="0.1x" _high-label="3.0x"
- low="0.1" high="3.0" default="1.0"/>
-
- <number id="hold_time" type="slider" arg="-hold-time %"
- _label="Time until loading a new image"
- _low-label="5 Sec" _high-label="5 Min"
- low="5.0" high="300.0" default="30.0"/>
-
- <number id="fade_speed" type="slider" arg="-fade-time %"
- _label="Transition Duration"
- _low-label="None" _high-label="30 Sec"
- low="0.0" high="30.0" default="5.0"/>
-
- <number id="resolution" type="slider" arg="-resolution %"
- _low-label="Low" _high-label="High"
- _label="Resolution" low="4" high="50" default="16"/>
-
- <number id="bumps" type="slider" arg="-bumps %"
- _low-label="None" _high-label="50 bumps"
- _label="Bumps" low="0" high="50" default="10"/>
-
- <number id="blend" type="slider" arg="-blend %"
- _low-label="Clear" _high-label="Opaque"
- _label="Transparency" low="0.1" high="1.0" default="0.0"/>
-
- <select id="render">
- <option id="wire" _label="Wireframe" arg-set="-wire"/>
- <option id="solid" _label="Solid Surface"/>
- </select>
+ <hgroup>
+ <vgroup>
+ <number id="delay" type="slider" arg="-delay %"
+ _label="Speed" _low-label="Slow" _high-label="Fast"
+ low="0" high="20000" default="10000"
+ convert="invert"/>
+
+ <number id="zoom" type="slider" arg="-zoom %"
+ _label="Zoom"
+ _low-label="0.1x" _high-label="3.0x"
+ low="0.1" high="3.0" default="1.0"/>
+
+ <number id="hold_time" type="slider" arg="-hold-time %"
+ _label="Time until loading a new image"
+ _low-label="5 Sec" _high-label="5 Min"
+ low="5.0" high="300.0" default="30.0"/>
+
+ <select id="render">
+ <option id="wire" _label="Wireframe" arg-set="-wire"/>
+ <option id="solid" _label="Solid Surface"/>
+ </select>
+
+ </vgroup>
+ <vgroup>
+ <number id="fade_speed" type="slider" arg="-fade-time %"
+ _label="Transition Duration"
+ _low-label="None" _high-label="30 Sec"
+ low="0.0" high="30.0" default="5.0"/>
+
+ <number id="resolution" type="slider" arg="-resolution %"
+ _low-label="Low" _high-label="High"
+ _label="Resolution" low="4" high="50" default="16"/>
+
+ <number id="bumps" type="slider" arg="-bumps %"
+ _low-label="None" _high-label="50 bumps"
+ _label="Bumps" low="0" high="50" default="10"/>
+
+ <number id="blend" type="slider" arg="-blend %"
+ _low-label="Clear" _high-label="Opaque"
+ _label="Transparency" low="0.1" high="1.0" default="0.0"/>
+ </vgroup>
+ </hgroup>
<hgroup>
<vgroup>
<?xml version="1.0" encoding="ISO-8859-1"?>
-<screensaver name="popsquares" _label="popsquares">
+<screensaver name="popsquares" _label="PopSquares">
<command arg="-root"/>
low="0" high="80000" default="50000"
convert="invert"/>
+ <number id="duration" type="slider" arg="-duration %"
+ _label="Duration" _low-label="10 seconds" _high-label="10 minutes"
+ low="10" high="600" default="120"/>
+
<number id="rate" type="slider" arg="-rate %"
_low-label="Drizzle" _high-label="Storm"
low="1" high="100" default="5"
<number id="light" type="spinbutton" arg="-light %"
_label="Lighting Effect" low="0" high="8" default="0"/>
- <boolean id="grab" _label="Grab Screen Image" arg-set="-water"/>
-
- <boolean id="stir" _label="Moving Splashes" arg-set="-stir"/>
-
- <boolean id="oily" _label="Psychedelic Colors" arg-set="-oily"/>
-
- <boolean id="gray" _label="Grayscale" arg-set="-grayscale"/>
+ <hgroup>
+ <vgroup>
+ <boolean id="grab" _label="Grab Screen Image" arg-set="-water"/>
+ <boolean id="stir" _label="Moving Splashes" arg-set="-stir"/>
+ </vgroup>
+ <vgroup>
+ <boolean id="oily" _label="Psychedelic Colors" arg-set="-oily"/>
+ <boolean id="gray" _label="Grayscale" arg-set="-grayscale"/>
+ </vgroup>
+ </hgroup>
<number id="ncolors" type="slider" arg="-colors %"
_low-label="Colors Two" _high-label="Many"
_label="Duration" _low-label="0" _high-label="60"
low="0" high="60" default="10"/>
+ <number id="duration" type="slider" arg="-duration %"
+ _label="Duration" _low-label="10 seconds" _high-label="10 minutes"
+ low="10" high="600" default="120"/>
+
<number id="n" type="spinbutton" arg="-n %"
_label="Rectangle Count" low="1" high="20" default="2"/>
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="skytentacles" _label="SkyTentacles">
+
+ <command arg="-root"/>
+
+ <number id="count" type="slider" arg="-count %"
+ _label="Tentacles" _low-label="1" _high-label="20"
+ low="1" high="20" default="9"/>
+
+ <hgroup>
+ <vgroup>
+ <number id="delay" type="slider" arg="-delay %"
+ _label="Frame Rate" _low-label="Slow" _high-label="Fast"
+ low="0" high="100000" default="30000"
+ convert="invert"/>
+
+ <number id="length" type="slider" arg="-length %"
+ _label="Length" _low-label="Short" _high-label="Long"
+ low="1.0" high="20.0" default="9.0"/>
+
+ <number id="wiggliness" type="slider" arg="-wiggliness %"
+ _label="Wiggliness" _low-label="Low" _high-label="High"
+ low="0.1" high="1.0" default="0.35"/>
+
+ <hgroup>
+ <number id="slices" type="spinbutton" arg="-slices %"
+ _label="Slices" low="1" high="50" default="32"/>
+ <number id="segments" type="spinbutton" arg="-segments %"
+ _label="Segments" low="1" high="50" default="32"/>
+ </hgroup>
+
+ </vgroup>
+
+ <vgroup>
+ <number id="speed" type="slider" arg="-speed %"
+ _label="Speed" _low-label="Slow" _high-label="Fast"
+ low="0.1" high="20.0" default="1.0"/>
+
+ <number id="thickness" type="slider" arg="-thickness %"
+ _label="Thickness" _low-label="Thin" _high-label="Thick"
+ low="0.1" high="5.0" default="1.0"/>
+
+ <number id="flexibility" type="slider" arg="-flexibility %"
+ _label="Flexibility" _low-label="Low" _high-label="High"
+ low="0.1" high="1.0" default="0.35"/>
+
+ <hgroup>
+ <boolean id="smooth" _label="Smooth" arg-unset="-no-smooth"/>
+ <boolean id="showfps" _label="Show Frames-per-Second" arg-set="-fps"/>
+ </hgroup>
+
+ </vgroup>
+ </hgroup>
+
+
+ <_description>
+There is a tentacled abomination in the sky. From above you it devours.
+
+Written by Jamie Zawinski; 2008.
+ </_description>
+</screensaver>
_label="Pause" _low-label="Short" _high-label="Long"
low="0" high="2000000" default="1000000"/>
+ <number id="duration" type="slider" arg="-duration %"
+ _label="Duration" _low-label="10 seconds" _high-label="10 minutes"
+ low="10" high="600" default="120"/>
+
<number id="increment" type="slider" arg="-increment %"
_label="Slide Speed" _low-label="Slow" _high-label="Fast"
low="1" high="30" default="10"/>
These closed objects are commonly called spherical harmonics,
although they are only remotely related to the mathematical
definition found in the solution to certain wave functions, most
-notable the eigenfunctions of angular momentum operators.
+notably the eigenfunctions of angular momentum operators.
Written by Paul Bourke and Jamie Zawinski; 2002.
</_description>
low="0" high="20000" default="10000"
convert="invert"/>
+ <number id="duration" type="slider" arg="-duration %"
+ _label="Duration" _low-label="10 seconds" _high-label="10 minutes"
+ low="10" high="600" default="120"/>
+
<number id="radius" type="slider" arg="-radius %"
_label="Spotlight Size" _low-label="Small" _high-label="Large"
low="5" high="350" default="125"/>
<command arg="-root"/>
- <number id="delay" type="slider" arg="-delay %"
- _label="Animation Speed" _low-label="Slow" _high-label="Fast"
- low="0" high="80000" default="40000"
- convert="invert"/>
-
- <number id="steps" type="slider" arg="-steps %"
- _label="Scroll Speed" _low-label="Slow" _high-label="Fast"
- low="1" high="100" default="35"
- convert="invert"/>
-
<hgroup>
+ <vgroup>
+ <number id="delay" type="slider" arg="-delay %"
+ _label="Animation Speed" _low-label="Slow" _high-label="Fast"
+ low="0" high="80000" default="40000"
+ convert="invert"/>
+ <number id="steps" type="slider" arg="-steps %"
+ _label="Scroll Speed" _low-label="Slow" _high-label="Fast"
+ low="1" high="100" default="35"
+ convert="invert"/>
+ <number id="spin" type="slider" arg="-spin %"
+ _label="Star Rotation Speed" _low-label="Slow" _high-label="Fast"
+ low="0.0" high="0.2" default="0.03"/>
+ <number id="lines" type="spinbutton" arg="-lines %"
+ _label="Text Lines" low="4" high="1000" default="125"/>
+ </vgroup>
+
+ <vgroup>
<select id="align">
<option id="left" _label="Flush Left Text" arg-set="-alignment left"/>
<option id="center" _label="Centered Text"/>
</select>
<boolean id="wrap" _label="Wrap Long Lines" arg-unset="-no-wrap"/>
- </hgroup>
+ <boolean id="texture" _label="Texture-Mapped Font" arg-unset="-no-textures"/>
+ <boolean id="smooth" _label="Anti-aliased Lines" arg-unset="-no-smooth"/>
+ <hgroup>
+ <boolean id="thick" _label="Thick Lines" arg-unset="-no-thick"/>
+ <boolean id="fade" _label="Fade Out" arg-unset="-no-fade"/>
+ </hgroup>
+ <boolean id="showfps" _label="Show Frames-per-Second" arg-set="-fps"/>
-<!-- <file id="program" _label="Text Program" arg="-program %"/> -->
+ </vgroup>
+ </hgroup>
<hgroup>
<number id="size" type="spinbutton" arg="-size %"
_label="Font Point Size" low="-1" high="10" default="-1"/>
-
<number id="columns" type="spinbutton" arg="-columns %"
_label="or, Text Columns" low="-1" high="200" default="-1"/>
</hgroup>
- <number id="lines" type="spinbutton" arg="-lines %"
- _label="Text Lines" low="4" high="1000" default="125"/>
-
- <number id="spin" type="slider" arg="-spin %"
- _label="Star Rotation Speed" _low-label="Slow" _high-label="Fast"
- low="0.0" high="0.2" default="0.03"/>
-
- <hgroup>
- <boolean id="smooth" _label="Anti-aliased Lines" arg-unset="-no-smooth"/>
- <boolean id="thick" _label="Thick Lines" arg-unset="-no-thick"/>
- <boolean id="fade" _label="Fade Out" arg-unset="-no-fade"/>
- </hgroup>
-
- <hgroup>
- <boolean id="texture" _label="Texture-Mapped Font" arg-unset="-no-textures"/>
- <boolean id="showfps" _label="Show Frames-per-Second" arg-set="-fps"/>
- </hgroup>
-
<xscreensaver-text />
<_description>
<command arg="-root"/>
<number id="init" type="spinbutton" arg="-initial-cracks %"
- _label="Initial Cracks" low="2" high="15" default="3"/>
+ _label="Initial Cracks" low="3" high="15" default="3"/>
<number id="speed" type="slider" arg="-growth-delay %"
_label="Speed" _low-label="Slow" _high-label="Fast"
<?xml version="1.0" encoding="ISO-8859-1"?>
-<screensaver name="topblock" _label="topBlock">
+<screensaver name="topblock" _label="TopBlock">
<command arg="-root"/>
low="0" high="50000" default="10000"
convert="invert"/>
+ <number id="duration" type="slider" arg="-duration %"
+ _label="Duration" _low-label="10 seconds" _high-label="10 minutes"
+ low="10" high="600" default="120"/>
+
<number id="event-chance" type="slider" arg="-event-chance %"
_label="Randomness" _low-label="Slow" _high-label="Jumpy"
low="0.0" high="0.1" default="0.01"/>
<command arg="-root"/>
- <number id="delay" type="slider" arg="-delay %"
- _label="Frame Rate" _low-label="Slow" _high-label="Fast"
- low="0" high="100000" default="20000"
- convert="invert"/>
-
- <number id="points" type="slider" arg="-points %"
- _label="Points" _low-label="Few" _high-label="Many"
- low="1" high="100" default="25"/>
-
- <number id="pointSize" type="slider" arg="-point-size %"
- _label="Point Size" _low-label="0" _high-label="50 pixels"
- low="0" high="50" default="9"/>
-
- <number id="pointSpeed" type="slider" arg="-point-speed %"
- _label="Wander Speed" _low-label="Slow" _high-label="Fast"
- low="0.0" high="10.0" default="1.0"/>
-
- <number id="pointDelay" type="slider" arg="-point-delay %"
- _label="Insertion Speed" _low-label="Slow" _high-label="Fast"
- low="0.0" high="3.0" default="0.05"
- convert="invert"/>
-
- <number id="zoomSpeed" type="slider" arg="-zoom-speed %"
- _label="Zoom Speed" _low-label="Slow" _high-label="Fast"
- low="0.1" high="10.0" default="1.0"/>
-
- <number id="zoomDelay" type="slider" arg="-zoom-delay %"
- _label="Zoom Frequency" _low-label="0" _high-label="60 Seconds"
- low="0" high="60" default="15"/>
-
- <boolean id="showfps" _label="Show Frames-per-Second" arg-set="-fps"/>
+ <hgroup>
+ <vgroup>
+ <number id="delay" type="slider" arg="-delay %"
+ _label="Frame Rate" _low-label="Slow" _high-label="Fast"
+ low="0" high="100000" default="20000"
+ convert="invert"/>
+
+ <number id="points" type="slider" arg="-points %"
+ _label="Points" _low-label="Few" _high-label="Many"
+ low="1" high="100" default="25"/>
+
+ <number id="pointSize" type="slider" arg="-point-size %"
+ _label="Point Size" _low-label="0" _high-label="50 pixels"
+ low="0" high="50" default="9"/>
+
+ <boolean id="showfps" _label="Show Frames-per-Second" arg-set="-fps"/>
+ </vgroup>
+
+ <vgroup>
+ <number id="pointSpeed" type="slider" arg="-point-speed %"
+ _label="Wander Speed" _low-label="Slow" _high-label="Fast"
+ low="0.0" high="10.0" default="1.0"/>
+
+ <number id="pointDelay" type="slider" arg="-point-delay %"
+ _label="Insertion Speed" _low-label="Slow" _high-label="Fast"
+ low="0.0" high="3.0" default="0.05"
+ convert="invert"/>
+
+ <number id="zoomSpeed" type="slider" arg="-zoom-speed %"
+ _label="Zoom Speed" _low-label="Slow" _high-label="Fast"
+ low="0.1" high="10.0" default="1.0"/>
+
+ <number id="zoomDelay" type="slider" arg="-zoom-delay %"
+ _label="Zoom Frequency" _low-label="0" _high-label="60 Seconds"
+ low="0" high="60" default="15"/>
+ </vgroup>
+ </hgroup>
<_description>
Draws a randomly-colored Voronoi tessellation, and periodically zooms
<command arg="-root"/>
- <select id="size">
- <option id="font1" _label="Small Font" arg-set="-small"/>
- <option id="font2" _label="Large Font"/>
- </select>
-
- <select id="mode">
- <option id="matrix" _label="Matrix Encoding"/>
- <option id="binary" _label="Binary Encoding" arg-set="-mode binary"/>
- <option id="hex" _label="Hexadecimal Encoding" arg-set="-mode hex"/>
- <option id="dna" _label="Genetic Encoding" arg-set="-mode dna"/>
- <option id="pipe" _label="Piped ASCII Text" arg-set="-mode pipe"/>
- </select>
-
- <select id="fill">
- <option id="both" _label="Synergistic Algorithm"/>
- <option id="top" _label="Slider Algorithm" arg-set="-insert top"/>
- <option id="bottom" _label="Expansion Algorithm" arg-set="-insert bottom"/>
- </select>
-
- <number id="delay" type="slider" arg="-delay %"
- _label="Speed" _low-label="Slow" _high-label="Fast"
- low="0" high="20000" default="10000"
- convert="invert"/>
-
- <number id="density" type="slider" arg="-density %"
- _label="Density" _low-label="Sparse" _high-label="Full"
- low="1" high="100" default="75"/>
+ <hgroup>
+ <select id="size">
+ <option id="font1" _label="Small Font" arg-set="-small"/>
+ <option id="font2" _label="Large Font"/>
+ </select>
+
+ <select id="mode">
+ <option id="matrix" _label="Matrix Encoding"/>
+ <option id="binary" _label="Binary Encoding" arg-set="-mode binary"/>
+ <option id="hex" _label="Hexadecimal Encoding" arg-set="-mode hex"/>
+ <option id="dna" _label="Genetic Encoding" arg-set="-mode dna"/>
+ <option id="pipe" _label="Piped ASCII Text" arg-set="-mode pipe"/>
+ </select>
+
+ <select id="fill">
+ <option id="both" _label="Synergistic Algorithm"/>
+ <option id="top" _label="Slider Algorithm" arg-set="-insert top"/>
+ <option id="bottom" _label="Expansion Algorithm" arg-set="-insert bottom"/>
+ </select>
+ </hgroup>
<hgroup>
<boolean id="trace" _label="Run Trace Program" arg-unset="-no-trace"/>
<boolean id="knock" _label="Knock Knock" arg-unset="-no-knock-knock"/>
+ <string id="phone" _label="Phone Number" arg="-phone %"/>
</hgroup>
- <string id="phone" _label="Phone Number" arg="-phone %"/>
+ <hgroup>
+ <vgroup>
+ <number id="delay" type="slider" arg="-delay %"
+ _label="Speed" _low-label="Slow" _high-label="Fast"
+ low="0" high="20000" default="10000"
+ convert="invert"/>
+ </vgroup>
+
+ <vgroup>
+ <number id="density" type="slider" arg="-density %"
+ _label="Density" _low-label="Sparse" _high-label="Full"
+ low="1" high="100" default="75"/>
+ </vgroup>
+ </hgroup>
<xscreensaver-text />
low="0" high="20000" default="10000"
convert="invert"/>
+ <number id="duration" type="slider" arg="-duration %"
+ _label="Duration" _low-label="10 seconds" _high-label="10 minutes"
+ low="10" high="600" default="120"/>
+
<boolean id="lenses" _label="Lenses" arg-set="-lenses"/>
<hgroup>
-/* xscreensaver, Copyright (c) 1992-2006 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1992-2008 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
int sizex, sizey;
int delay;
+ int duration;
GC gc;
int mode;
- int iterations;
+ int random_p;
+ time_t start_time;
int fuzz_toggle;
const int *current_bias;
#define STRETCH 12
#define FUZZ 13
+static void
+decayscreen_load_image (struct state *st)
+{
+ XWindowAttributes xgwa;
+ XGetWindowAttributes (st->dpy, st->window, &xgwa);
+ st->sizex = xgwa.width;
+ st->sizey = xgwa.height;
+ if (st->img_loader) abort();
+ st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
+ st->window, 0, 0);
+}
+
static void *
decayscreen_init (Display *dpy, Window window)
{
st->dpy = dpy;
st->window = window;
+ st->random_p = 0;
s = get_string_resource(st->dpy, "mode", "Mode");
if (s && !strcmp(s, "shuffle")) st->mode = SHUFFLE;
else {
if (s && *s && !!strcmp(s, "random"))
fprintf(stderr, "%s: unknown mode %s\n", progname, s);
+ st->random_p = 1;
st->mode = random() % (FUZZ+1);
}
st->delay = get_integer_resource (st->dpy, "delay", "Integer");
-
if (st->delay < 0) st->delay = 0;
+ st->duration = get_integer_resource (st->dpy, "duration", "Seconds");
+ if (st->duration < 1) st->duration = 1;
+
XGetWindowAttributes (st->dpy, st->window, &xgwa);
gcv.function = GXcopy;
gcflags |= GCSubwindowMode;
st->gc = XCreateGC (st->dpy, st->window, gcflags, &gcv);
- st->sizex = xgwa.width;
- st->sizey = xgwa.height;
-
- if (st->mode == MELT || st->mode == STRETCH)
- st->iterations = 1; /* slow down for smoother melting */
-
- st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
- st->window, 0, 0);
+ st->start_time = time ((time_t) 0);
+ decayscreen_load_image (st);
return st;
}
st->img_loader = load_image_async_simple (st->img_loader,
0, 0, 0, 0, 0);
if (! st->img_loader) { /* just finished */
+
+ st->start_time = time ((time_t) 0);
+ if (st->random_p)
+ st->mode = random() % (FUZZ+1);
+
if (st->mode == MELT || st->mode == STRETCH)
/* make sure screen eventually turns background color */
XDrawLine (st->dpy, st->window, st->gc, 0, 0, st->sizex, 0);
return st->delay;
}
+ if (!st->img_loader &&
+ st->start_time + st->duration < time ((time_t) 0)) {
+ decayscreen_load_image (st);
+ }
+
switch (st->mode) {
case SHUFFLE: st->current_bias = no_bias; break;
case UP: st->current_bias = up_bias; break;
"*delay: 10000",
"*mode: random",
+ "*duration: 120",
0
};
static XrmOptionDescRec decayscreen_options [] = {
{ "-delay", ".delay", XrmoptionSepArg, 0 },
{ "-mode", ".mode", XrmoptionSepArg, 0 },
+ { "-duration", ".duration", XrmoptionSepArg, 0 },
{ 0, 0, 0, 0 }
};
decayscreen - make a screen meltdown.
.SH SYNOPSIS
.B decayscreen
-[\-display \fIhost:display.screen\fP] [\-window] [\-root] [\-mono] [\-install]
-[\-visual \fIvisual\fP] [\-delay \fIusecs\fP] [\-mode \fImode\fP]
+[\-display \fIhost:display.screen\fP]
+[\-window]
+[\-root]
+[\-mono]
+[\-install]
+[\-visual \fIvisual\fP]
+[\-delay \fIusecs\fP]
+[\-duration \fIsecs\fP]
+[\-mode \fImode\fP]
.SH DESCRIPTION
The \fIdecayscreen\fP program creates a melting effect by randomly
shifting rectangles around the screen.
.B \-delay \fImicroseconds\fP
Slow it down.
.TP 8
+.B \-duration \fIseconds\fP
+How long to run before loading a new image. Default 120 seconds.
+.TP 8
.B \-mode \fImode\fP
The direction in which the image should tend to slide. Legal values are
\fIrandom\fP (meaning pick one), \fIup\fP, \fIleft\fP, \fIright\fP,
struct coo xy_coo[10];
int delay, radius, speed, number, blackhole, vortex, magnify, reflect, slow;
+ int duration;
+ time_t start_time;
+
XWindowAttributes xgwa;
GC gc;
unsigned long black_pixel;
st->window = window;
st->delay = get_integer_resource(st->dpy, "delay", "Integer");
+ st->duration = get_integer_resource (st->dpy, "duration", "Seconds");
st->radius = get_integer_resource(st->dpy, "radius", "Integer");
st->speed = get_integer_resource(st->dpy, "speed", "Integer");
st->number = get_integer_resource(st->dpy, "number", "Integer");
+ if (st->delay < 0) st->delay = 0;
+ if (st->duration < 1) st->duration = 1;
+
#ifdef HAVE_XSHM_EXTENSION
st->use_shm = get_boolean_resource(st->dpy, "useSHM", "Boolean");
#endif /* HAVE_XSHM_EXTENSION */
st->img_loader = load_image_async_simple (0, st->xgwa.screen, st->window,
st->window, 0, 0);
+ st->start_time = time ((time_t) 0);
return st;
}
{
int i;
+ st->start_time = time ((time_t) 0);
+
st->buffer_map = 0;
st->orig_map = XGetImage(st->dpy, st->window, 0, 0, st->xgwa.width, st->xgwa.height,
~0L, ZPixmap);
if (st->img_loader) /* still loading */
{
st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 0);
- if (! st->img_loader) /* just finished */
+ if (! st->img_loader) { /* just finished */
distort_finish_loading (st);
+ }
return st->delay;
}
+ if (!st->img_loader &&
+ st->start_time + st->duration < time ((time_t) 0)) {
+ st->img_loader = load_image_async_simple (0, st->xgwa.screen, st->window,
+ st->window, 0, 0);
+ return st->delay;
+ }
+
for (k = 0; k < st->number; k++) {
st->effect(st,k);
st->draw(st,k);
#endif
"*delay: 20000",
+ "*duration: 120",
"*radius: 0",
"*speed: 0",
"*number: 0",
static XrmOptionDescRec distort_options [] = {
{ "-delay", ".delay", XrmoptionSepArg, 0 },
+ { "-duration", ".duration", XrmoptionSepArg, 0 },
{ "-radius", ".radius", XrmoptionSepArg, 0 },
{ "-speed", ".speed", XrmoptionSepArg, 0 },
{ "-number", ".number", XrmoptionSepArg, 0 },
.SH SYNOPSIS
.B distort
[\-root] [\-window] [\-mono] [\-install] [\-noinstall] [\-visual \fIvisual\fP]
-[\-window\-id \fIwindow\-id\fP] [\-delay \fIusecs\fP] [\-radius \fIpixels\fP]
-[\-speed \fIint\fP] [\-number \fIint\fP] [\-swamp] [\-bounce] [\-reflect]
-[\-vortex] [\-magnify] [\-blackhole] [\-slow] [\-shm] [\-no\-shm]
+[\-window\-id \fIwindow\-id\fP]
+[\-delay \fIusecs\fP]
+[\-duration \fIsecs\fP]
+[\-radius \fIpixels\fP]
+[\-speed \fIint\fP]
+[\-number \fIint\fP]
+[\-swamp]
+[\-bounce]
+[\-reflect]
+[\-vortex]
+[\-magnify]
+[\-blackhole]
+[\-slow]
+[\-shm] [\-no\-shm]
.SH DESCRIPTION
The \fIdistort\fP program takes an image and lets circular zones of
distortion wander randomly around it, distorting what is under them.
.B \-delay \fIusecs\fP
Specify the delay between subsequent animation frames in microseconds.
.TP 8
+.B \-duration \fIseconds\fP
+How long to run before loading a new image. Default 120 seconds.
+.TP 8
.B \-radius \fIpixels\fP
Specify the radius of the distortion zone in pixels.
.TP 8
d = d0 * d0 + d1 * d1 + d2 * d2;
if (d > EPSILON)
- d = gt->mass / (d * sqrt(d)) * DELTAT * DELTAT * QCONS;
+ d = gtk->mass / (d * sqrt(d)) * DELTAT * DELTAT * QCONS;
else
- d = gt->mass * eps;
+ d = gtk->mass / (eps * sqrt(eps));
v0 += d0 * d;
v1 += d1 * d;
v2 += d2 * d;
d = d0 * d0 + d1 * d1 + d2 * d2;
if (d > EPSILON)
- d = gt->mass * gt->mass / (d * sqrt(d)) * DELTAT * QCONS;
+ d = 1 / (d * sqrt(d)) * DELTAT * QCONS;
else
- d = gt->mass * gt->mass / (EPSILON * sqrt_EPSILON) * DELTAT * QCONS;
+ d = 1 / (EPSILON * sqrt_EPSILON) * DELTAT * QCONS;
d0 *= d;
d1 *= d;
d2 *= d;
- gt->vel[0] += d0 / gt->mass;
- gt->vel[1] += d1 / gt->mass;
- gt->vel[2] += d2 / gt->mass;
- gtk->vel[0] -= d0 / gtk->mass;
- gtk->vel[1] -= d1 / gtk->mass;
- gtk->vel[2] -= d2 / gtk->mass;
+ gt->vel[0] += d0 * gtk->mass;
+ gt->vel[1] += d1 * gtk->mass;
+ gt->vel[2] += d2 * gtk->mass;
+ gtk->vel[0] -= d0 * gt->mass;
+ gtk->vel[1] -= d1 * gt->mass;
+ gtk->vel[2] -= d2 * gt->mass;
}
gt->pos[0] += gt->vel[0] * DELTAT;
tangram_shapes.c crackberg.c glhanoi.c cube21.c \
timetunnel.c juggler3d.c topblock.c glschool.c \
glschool_gl.c glschool_alg.c glcells.c voronoi.c \
- moebiusgears.c lockward.c cubicgrid.c hypnowheel.c
+ moebiusgears.c lockward.c cubicgrid.c hypnowheel.c \
+ skytentacles.c
OBJS = xscreensaver-gl-helper.o normals.o glxfonts.o \
atlantis.o b_draw.o b_lockglue.o b_sphere.o bubble3d.o \
tangram_shapes.o crackberg.o glhanoi.o cube21.o \
timetunnel.o juggler3d.o topblock.o glschool.o \
glschool_gl.o glschool_alg.o glcells.o voronoi.o \
- moebiusgears.o lockward.o cubicgrid.o hypnowheel.o
+ moebiusgears.o lockward.o cubicgrid.o hypnowheel.o \
+ skytentacles.o
GL_EXES = cage gears moebius pipes sproingies stairs superquadrics \
morph3d rubik atlantis lament bubble3d glplanet pulsar \
antinspect providence pinion boing carousel fliptext \
antmaze tangram crackberg glhanoi cube21 timetunnel \
juggler3d topblock glschool glcells voronoi moebiusgears \
- lockward cubicgrid hypnowheel
+ lockward cubicgrid hypnowheel skytentacles
GLE_EXES = extrusion
GL_UTIL_EXES = xscreensaver-gl-helper
HACK_EXES = @GL_EXES@ @GLE_EXES@
crackberg.man glhanoi.man cube21.man timetunnel.man \
juggler3d.man topblock.man glschool.man glcells.man \
voronoi.man moebiusgears.man lockward.man cubicgrid.man \
- hypnowheel.man
+ hypnowheel.man skytentacles.man
MEN = @GL_MEN@
EXTRAS = README Makefile.in dxf2gl.pl molecules.sh starwars.txt
hypnowheel: hypnowheel.o $(HACK_TRACK_OBJS)
$(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS)
+skytentacles: skytentacles.o normals.o $(HACK_TRACK_OBJS)
+ $(CC_HACK) -o $@ $@.o normals.o $(HACK_TRACK_OBJS) $(HACK_LIBS)
+
##############################################################################
#
# DO NOT DELETE: updated by make distdepend
sierpinski3d.o: $(UTILS_SRC)/yarandom.h
sierpinski3d.o: $(HACK_SRC)/xlockmoreI.h
sierpinski3d.o: $(HACK_SRC)/xlockmore.h
+skytentacles.o: ../../config.h
+skytentacles.o: $(srcdir)/gltrackball.h
+skytentacles.o: $(srcdir)/normals.h
+skytentacles.o: $(srcdir)/rotator.h
+skytentacles.o: $(HACK_SRC)/screenhackI.h
+skytentacles.o: $(UTILS_SRC)/colors.h
+skytentacles.o: $(UTILS_SRC)/grabscreen.h
+skytentacles.o: $(UTILS_SRC)/hsv.h
+skytentacles.o: $(UTILS_SRC)/resources.h
+skytentacles.o: $(UTILS_SRC)/usleep.h
+skytentacles.o: $(UTILS_SRC)/visual.h
+skytentacles.o: $(UTILS_SRC)/xshm.h
+skytentacles.o: $(UTILS_SRC)/yarandom.h
+skytentacles.o: $(HACK_SRC)/xlockmoreI.h
+skytentacles.o: $(HACK_SRC)/xlockmore.h
spheremonics.o: ../../config.h
spheremonics.o: $(srcdir)/gltrackball.h
spheremonics.o: $(srcdir)/glxfonts.h
#endif
-#define MAX_COMPONENTS 31
+#define MAX_COMPONENTS 400
#define MOVE_MULT 0.02
static float f_rand(void)
"*doGasket: True \n" \
"*doHelix: True \n" \
"*doLadder: True \n" \
+ "*doFrame: True \n" \
"*wallFacets: 360 \n" \
- "*tubeFacets: 90 \n" \
+ "*barFacets: 90 \n" \
"*clockwise: False \n" \
- "*turns: 0.8 \n" \
- "*turnSpacing: 2.40 \n" \
- "*barSpacing: 0.30 \n" \
- "*wallHeight: 0.4 \n" \
- "*wallThickness: 0.1 \n" \
- "*tubeThickness: 0.075 \n" \
- "*wallTaper: 1.047 \n" \
- "*gasketSize: 2.15 \n" \
+ "*turns: 0.69 \n" \
+ "*turnSpacing: 2.2 \n" \
+ "*barSpacing: 0.24 \n" \
+ "*wallHeight: 0.45 \n" \
+ "*wallThickness: 0.12 \n" \
+ "*barThickness: 0.058 \n" \
+ "*wallTaper: 0.95 \n" \
+ "*gasketSize: 1.88 \n" \
"*gasketDepth: 0.15 \n" \
"*gasketThickness: 0.4 \n" \
+ "*frameSize: 1.20 \n" \
+ "*frameDepth: 0.01 \n" \
+ "*frameThickness: 0.03 \n" \
+ "*triangleSize: 0.045 \n" \
"*speed: 1.0 \n" \
".foreground: #00AA00 \n" \
+ "*geometry: =640x640\n" \
# define refresh_logo 0
# define release_logo 0
GLuint helix_list, helix_list_wire, helix_list_facetted;
GLuint gasket_list, gasket_list_wire;
+ GLuint frame_list, frame_list_wire;
int wall_facets;
- int tube_facets;
+ int bar_facets;
Bool clockwise;
GLfloat color[4];
GLfloat bar_spacing;
GLfloat wall_height;
GLfloat wall_thickness;
- GLfloat tube_thickness;
+ GLfloat bar_thickness;
GLfloat wall_taper;
GLfloat gasket_size;
GLfloat gasket_depth;
GLfloat gasket_thickness;
+ GLfloat frame_size;
+ GLfloat frame_depth;
+ GLfloat frame_thickness;
+ GLfloat triangle_size;
+
GLfloat speed;
spinner gasket_spinnerx, gasket_spinnery, gasket_spinnerz;
spinner scene_spinnerx, scene_spinnery;
spinner helix_spinnerz;
+ spinner frame_spinner;
trackball_state *trackball;
Bool button_down_p;
static void
make_helix (logo_configuration *dc, int facetted, int wire)
{
- int wall_facets = dc->wall_facets / (facetted ? 15 : 1);
+ int wall_facets = dc->wall_facets / (facetted ? 10 : 1);
GLfloat th;
GLfloat max_th = M_PI * 2 * dc->turns;
GLfloat th_inc = M_PI * 2 / wall_facets;
z1 = -(dc->turn_spacing * dc->turns / 2);
- h1 = (dc->wall_taper > 0 ? 0 : dc->wall_height / 2);
- h1off = (dc->wall_taper > 0 ? -dc->wall_height / 2 : 0);
+ h1 = (dc->wall_taper > 0 ? 0 : dc->wall_height / 2);
+ h1off = (dc->wall_taper > 0 ? -dc->wall_height / 2 : 0);
if (!dc->clockwise)
z1 = -z1, z_inc = -z_inc, h1off = -h1off;
GLfloat usable_th = max_th - dc->wall_taper;
GLfloat usable_z = max_z / (max_th / usable_th);
int nbars = usable_z / dc->bar_spacing;
- GLfloat used_z = (nbars - 1) * dc->bar_spacing;
- GLfloat pad_z = max_z - used_z;
- GLfloat pad_ratio = pad_z / max_z;
+ GLfloat used_z, pad_z, pad_ratio;
+
+ if (! (nbars & 1)) nbars--; /* always an odd number of bars */
+
+ used_z = (nbars - 1) * dc->bar_spacing;
+ pad_z = max_z - used_z;
+ pad_ratio = pad_z / max_z;
th = (max_th * pad_ratio/2);
z = -(max_z / 2) + (max_z * pad_ratio/2);
for (i = 0; i < nbars; i++)
{
- int facets = dc->tube_facets / (facetted ? 14 : 1);
+ int facets = dc->bar_facets / (facetted ? 14 : 1);
if (facets <= 3) facets = 3;
x = cos (th) * (1 - dc->wall_thickness);
y = sin (th) * (1 - dc->wall_thickness);
tube ( x, y, z,
-x, -y, z,
- dc->tube_thickness, 0, facets,
+ dc->bar_thickness, 0, facets,
True, True, wire);
z += z_inc;
th += th_inc;
GLfloat *pointsx0, *pointsy0, *pointsx1, *pointsy1, *normals;
- GLfloat r0 = 0.780; /* 395 */
- GLfloat r1a = 0.855; /* top of wall below upper left hole */
- GLfloat r1b = 0.890; /* center of upper left hole */
- GLfloat r1c = 0.922; /* bottom of wall above hole */
- GLfloat r1 = 0.928; /* 471 */
- GLfloat r2 = 0.966; /* 490 */
- GLfloat r3 = 0.984; /* 499 */
+ GLfloat r0 = 0.750; /* 395 */
+ GLfloat r1a = 0.825; /* bottom of wall below upper left hole */
+ GLfloat r1b = 0.867; /* center of upper left hole */
+ GLfloat r1c = 0.909; /* top of wall above hole */
+ GLfloat r1 = 0.916; /* 471 */
+ GLfloat r2 = 0.963; /* 490 */
+ GLfloat r3 = 0.960; /* 499 */
GLfloat r4 = 1.000; /* 507 */
- GLfloat r5 = 1.090; /* 553 */
+ GLfloat r5 = 1.080; /* 553 */
GLfloat ctrl_r[100], ctrl_th[100];
POINT (0.872, 3.95);
POINT (r4, 4.0); /* moving clockwise... */
- POINT (r4, 48.2);
- POINT (r1, 48.2);
- POINT (r1, 54.2);
- POINT (r2, 55.8);
- POINT (r2, 73.2);
- POINT (r1, 74.8);
- POINT (r1, 101.2);
- POINT (r3, 103.4);
+ POINT (r4, 47.0);
+ POINT (r1, 47.0);
+ POINT (r1, 53.0);
+ POINT (r2, 55.5);
+ POINT (r2, 72.3);
+ POINT (r1, 74.0);
+ POINT (r1, 100.0);
+ POINT (r3, 102.5);
POINT (r3, 132.0);
- POINT (r1, 133.4);
+ POINT (r1, 133.0);
POINT (r1, 180.7);
POINT (r2, 183.6);
- POINT (r2, 209.8);
- POINT (r1, 211.0);
- POINT (r1, 221.8);
- POINT (r5, 221.8);
+ POINT (r2, 210.0);
+ POINT (r1, 212.0);
+ POINT (r1, 223.2);
POINT (r5, 223.2);
- POINT (r4, 223.2);
-
- POINT (r4, 316.8); /* upper left indentation */
- POINT (0.990, 326.87);
- POINT (0.880, 327.21);
- POINT (0.872, 327.45);
- POINT (0.869, 327.80);
- POINT (0.867, 328.10);
-
- POINT (0.867, 328.85);
- POINT (0.869, 329.15);
- POINT (0.872, 329.50);
- POINT (0.880, 329.74);
- POINT (0.990, 330.08);
-
- POINT (r4, 339.0);
+ POINT (r5, 225.0);
+ POINT (r4, 225.0);
+
+ POINT (r4, 316.8); /* upper left indentation */
+ POINT (0.990, 316.87);
+ POINT (0.880, 317.21);
+ POINT (0.872, 317.45);
+ POINT (0.869, 317.80);
+ POINT (0.867, 318.10);
+
+ POINT (0.867, 318.85);
+ POINT (0.869, 319.15);
+ POINT (0.872, 319.50);
+ POINT (0.880, 319.74);
+ POINT (0.990, 320.08);
+
+ POINT (r4, 338.5);
if (! wire)
{
- POINT (r1a, 339.0); /* cut-out disc */
- POINT (r1a, 343.0);
+ POINT (r1a, 338.5); /* cut-out disc */
+ POINT (r1a, 343.5);
}
- POINT (r4, 343.0);
+ POINT (r4, 343.5);
POINT (r4, 356.0);
POINT (0.872, 356.05); /* top indentation, left half */
GLfloat th;
npoints = 0;
- th = 339.0 * d2r;
+ th = 338.5 * d2r;
pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
npoints++;
pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
npoints++;
- th = 343.0 * d2r;
+ th = 343.5 * d2r;
pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
npoints++;
*/
{
int nsteps = 12;
- GLfloat r0 = 0.026;
+ GLfloat r0 = 0.04;
GLfloat r1 = 0.060;
GLfloat th, cth, sth;
/* Attach the bottom-right dingus...
*/
{
- GLfloat w = 0.04;
- GLfloat h = 0.17;
+ GLfloat w = 0.05;
+ GLfloat h = 0.19;
GLfloat th;
- glRotatef (50, 0, 0, 1);
+ glRotatef (49.5, 0, 0, 1);
glScalef (dc->gasket_size, dc->gasket_size, 1);
glTranslatef (0, (r0+r1)/2, 0);
glPopMatrix();
}
+static void
+make_frame (logo_configuration *dc, int wire)
+{
+ int i, j;
+ GLfloat x[20], y[20];
+ GLfloat corner_cut = 0.5;
+
+ glPushMatrix();
+ glRotatef (90, 0, 1, 0);
+ glScalef (4 * dc->frame_size,
+ 4 * dc->frame_size,
+ 4 * dc->frame_size);
+
+ x[0] = -dc->frame_thickness;
+ x[1] = -dc->frame_thickness * corner_cut;
+ x[2] = 0;
+ x[3] = 0.5 - dc->triangle_size;
+ x[4] = 0.5;
+ x[5] = 0.5 + dc->triangle_size;
+ x[6] = 1;
+ x[7] = 1 + dc->frame_thickness * corner_cut;
+ x[8] = 1 + dc->frame_thickness;
+
+ y[0] = -dc->frame_thickness;
+ y[1] = -dc->frame_thickness * corner_cut;
+ y[2] = 0;
+ y[3] = dc->triangle_size;
+
+ /* front and back
+ */
+ glTranslatef (-0.5, -0.5, dc->frame_depth / 4);
+ if (! wire)
+ for (j = 0; j <= 1; j++)
+ {
+ if (j) glTranslatef (0, 0, -dc->frame_depth / 2);
+ glFrontFace (j ? GL_CCW : GL_CW);
+ for (i = 0; i < 4; i++)
+ {
+ glNormal3f (0, 0, (j ? -1 : 1));
+ glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
+ glVertex3f (x[0], y[1], 0); glVertex3f (x[0], y[2], 0);
+ glVertex3f (x[1], y[0], 0); glVertex3f (x[1], y[2], 0);
+ glVertex3f (x[3], y[0], 0); glVertex3f (x[3], y[2], 0);
+ glVertex3f (x[4], y[0], 0); glVertex3f (x[4], y[3], 0);
+ glVertex3f (x[5], y[0], 0); glVertex3f (x[5], y[2], 0);
+ glVertex3f (x[7], y[0], 0); glVertex3f (x[7], y[2], 0);
+ glVertex3f (x[8], y[1], 0); glVertex3f (x[8], y[2], 0);
+ glEnd ();
+ glTranslatef (0.5, 0.5, 0);
+ glRotatef (90, 0, 0, 1);
+ glTranslatef (-0.5, -0.5, 0);
+ }
+ }
+
+ /* ledges
+ */
+ glFrontFace (GL_CCW);
+ for (i = 0; i < 4; i++)
+ {
+ glNormal3f (0, 1, 0);
+ glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
+ glVertex3f (x[2], y[2], 0); glVertex3f (x[2], y[2], dc->frame_depth/2);
+ glVertex3f (x[3], y[2], 0); glVertex3f (x[3], y[2], dc->frame_depth/2);
+ glVertex3f (x[4], y[3], 0); glVertex3f (x[4], y[3], dc->frame_depth/2);
+ glVertex3f (x[5], y[2], 0); glVertex3f (x[5], y[2], dc->frame_depth/2);
+ glVertex3f (x[6], y[2], 0); glVertex3f (x[6], y[2], dc->frame_depth/2);
+ glEnd ();
+
+ glNormal3f (0, -1, 0);
+ glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
+ glVertex3f (x[7], y[0], 0);
+ glVertex3f (x[7], y[0], dc->frame_depth/2);
+ glVertex3f (x[1], y[0], dc->frame_depth/2);
+ glVertex3f (x[1], y[0], 0);
+ glEnd ();
+
+ glNormal3f (1, -1, 0);
+ glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
+ glVertex3f (x[8], y[1], 0);
+ glVertex3f (x[8], y[1], dc->frame_depth/2);
+ glVertex3f (x[7], y[0], dc->frame_depth/2);
+ glVertex3f (x[7], y[0], 0);
+ glEnd ();
+
+ if (wire)
+ {
+ glNormal3f (0, 1, 0);
+ for (j = 0; j <= 1; j++)
+ {
+ glBegin (GL_LINE_STRIP);
+ glVertex3f (x[2], y[2], j*dc->frame_depth/2);
+ glVertex3f (x[3], y[2], j*dc->frame_depth/2);
+ glVertex3f (x[4], y[3], j*dc->frame_depth/2);
+ glVertex3f (x[5], y[2], j*dc->frame_depth/2);
+ glVertex3f (x[6], y[2], j*dc->frame_depth/2);
+ glEnd ();
+ }
+ }
+
+ glTranslatef (0.5, 0.5, 0);
+ glRotatef (90, 0, 0, 1);
+ glTranslatef (-0.5, -0.5, 0);
+ }
+
+ glPopMatrix();
+}
+
+
\f
/* Window management, etc
*/
logo_configuration *dc;
int do_gasket = get_boolean_resource(mi->dpy, "doGasket", "Boolean");
int do_helix = get_boolean_resource(mi->dpy, "doHelix", "Boolean");
- int do_ladder = do_helix && get_boolean_resource(mi->dpy, "doLadder", "Boolean");
+ int do_ladder = (do_helix &&
+ get_boolean_resource(mi->dpy, "doLadder", "Boolean"));
+ int do_frame = get_boolean_resource(mi->dpy, "doFrame", "Boolean");
+ GLfloat helix_rot = 147.0;
if (!do_gasket && !do_helix)
{
}
dc->wall_facets = get_integer_resource(mi->dpy, "wallFacets", "Integer");
- dc->tube_facets = get_integer_resource(mi->dpy, "tubeFacets", "Integer");
+ dc->bar_facets = get_integer_resource(mi->dpy, "barFacets", "Integer");
dc->clockwise = get_boolean_resource(mi->dpy, "clockwise", "Boolean");
dc->turns = get_float_resource(mi->dpy, "turns", "Float");
dc->turn_spacing = get_float_resource(mi->dpy, "turnSpacing", "Float");
dc->bar_spacing = get_float_resource(mi->dpy, "barSpacing", "Float");
dc->wall_height = get_float_resource(mi->dpy, "wallHeight", "Float");
dc->wall_thickness = get_float_resource(mi->dpy, "wallThickness", "Float");
- dc->tube_thickness = get_float_resource(mi->dpy, "tubeThickness", "Float");
+ dc->bar_thickness = get_float_resource(mi->dpy, "barThickness", "Float");
dc->wall_taper = get_float_resource(mi->dpy, "wallTaper", "Float");
- dc->gasket_size = get_float_resource(mi->dpy, "gasketSize", "Float");
- dc->gasket_depth = get_float_resource(mi->dpy, "gasketDepth", "Float");
- dc->gasket_thickness = get_float_resource(mi->dpy, "gasketThickness", "Float");
+ dc->gasket_size = get_float_resource(mi->dpy,"gasketSize", "Float");
+ dc->gasket_depth = get_float_resource(mi->dpy,"gasketDepth", "Float");
+ dc->gasket_thickness = get_float_resource(mi->dpy,"gasketThickness","Float");
+
+ dc->frame_size = get_float_resource(mi->dpy, "frameSize", "Float");
+ dc->frame_depth = get_float_resource(mi->dpy, "frameDepth", "Float");
+ dc->frame_thickness = get_float_resource(mi->dpy, "frameThickness", "Float");
+ dc->triangle_size = get_float_resource(mi->dpy, "triangleSize", "Float");
dc->speed = get_float_resource(mi->dpy, "speed", "Float");
dc->helix_spinnerz.probability = 0.6;
dc->scene_spinnerx.probability = 0.1;
dc->scene_spinnery.probability = 0.0;
+ dc->frame_spinner.probability = 5.0;
+
+ /* start the frame off-screen */
+ dc->frame_spinner.spinning_p = True;
+ dc->frame_spinner.position = 0.3;
+ dc->frame_spinner.speed = 0.001;
if (dc->speed > 0) /* start off with the gasket in motion */
{
glPushMatrix();
dc->helix_list = glGenLists (1);
glNewList (dc->helix_list, GL_COMPILE);
- glRotatef(126, 0, 0, 1);
+ glRotatef(helix_rot, 0, 0, 1);
if (do_ladder) make_ladder (dc, 0, 0);
if (do_helix) make_helix (dc, 0, 0);
glRotatef(180, 0, 0, 1);
glPushMatrix();
dc->helix_list_wire = glGenLists (1);
glNewList (dc->helix_list_wire, GL_COMPILE);
- /* glRotatef(126, 0, 0, 1); wtf? */
+/* glRotatef(helix_rot, 0, 0, 1); wtf? */
if (do_ladder) make_ladder (dc, 1, 1);
if (do_helix) make_helix (dc, 1, 1);
glRotatef(180, 0, 0, 1);
glPushMatrix();
dc->helix_list_facetted = glGenLists (1);
glNewList (dc->helix_list_facetted, GL_COMPILE);
- glRotatef(126, 0, 0, 1);
+ glRotatef(helix_rot, 0, 0, 1);
if (do_ladder) make_ladder (dc, 1, 0);
if (do_helix) make_helix (dc, 1, 0);
glRotatef(180, 0, 0, 1);
if (do_gasket) make_gasket (dc, 1);
glEndList ();
+ dc->frame_list = glGenLists (1);
+ glNewList (dc->frame_list, GL_COMPILE);
+ if (do_frame) make_frame (dc, 0);
+ glEndList ();
+
+ dc->frame_list_wire = glGenLists (1);
+ glNewList (dc->frame_list_wire, GL_COMPILE);
+ if (do_frame) make_frame (dc, 1);
+ glEndList ();
+
/* When drawing both solid and wireframe objects,
make sure the wireframe actually shows up! */
glEnable (GL_POLYGON_OFFSET_FILL);
tick_spinner (mi, &dc->helix_spinnerz);
tick_spinner (mi, &dc->scene_spinnerx);
tick_spinner (mi, &dc->scene_spinnery);
+ tick_spinner (mi, &dc->frame_spinner);
link_spinners (mi, &dc->scene_spinnerx, &dc->scene_spinnery);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix ();
{
- glScalef(3.3, 3.3, 3.3);
+ glScalef(3, 3, 3);
+
+ glColor3f(dc->color[0], dc->color[1], dc->color[2]);
+
+ /* Draw frame before trackball rotation */
+ {
+ GLfloat p = (dc->frame_spinner.position >= 0
+ ? dc->frame_spinner.position
+ : -dc->frame_spinner.position);
+ GLfloat size = (p > 0.5 ? 1-p : p);
+ GLfloat scale = 1 + (size * 10);
+ glPushMatrix();
+ /* gltrackball_rotate (dc->trackball); */
+ glRotatef(90, 1, 0, 0);
+ glRotatef(90, 0, 0, 1);
+
+ glScalef (1, scale, scale);
+ if (wire)
+ glCallList (dc->frame_list_wire);
+ else if (dc->wire_overlay != 0)
+ {
+ glCallList (dc->frame_list);
+ glDisable (GL_LIGHTING);
+ glCallList (dc->frame_list_wire);
+ if (!wire) glEnable (GL_LIGHTING);
+ }
+ else
+ glCallList (dc->frame_list);
+ glPopMatrix();
+ }
gltrackball_rotate (dc->trackball);
glRotatef(90, 1, 0, 0);
glRotatef(90, 0, 0, 1);
- glColor3f(dc->color[0], dc->color[1], dc->color[2]);
-
glRotatef (360 * sin (M_PI/2 * dc->scene_spinnerx.position), 0, 1, 0);
glRotatef (360 * sin (M_PI/2 * dc->scene_spinnery.position), 0, 0, 1);
/* -*- Mode: C; tab-width: 4 -*- */
+/* vim: set ai ts=4 sw=4: */
#if !defined( lint ) && !defined( SABER )
/*static const char sccsid[] = "@(#)gleidescope.c 1.0 03/06/27 xlockmore";*/
#endif
-/* enable -grab switch */
-/*#define GRAB*/
+/* enable -grab switch for animations */
+#undef GRAB
+
+#undef DISPLAY_TEXTURE
/*-
* Permission to use, copy, modify, and distribute this software and its
* no preference is given.
* Made grid slightly bigger so you can't see
* the edge when zooming and moving.
+ * 20061226 1.4 acd Now uses GL Display Lists.
+ * 20070318 1.5 acd Generates textures.
+ * Fixed texture size problem (and introduced another).
+ * 20070412 1.6 acd Textures now have independant sizes.
+ * 20070413 1.7 acd Added Lissajous movement pattern.
+ * 20070414 1.8 acd Added corners movement pattern.
+ * 20080319 1.9 acd Changes to arguments for saner gleidescope.xml.
+ *
+ * TODO
+ * generate textures myself - render random shapes to 256x256 texture. (done)
+ * lower res for checks and random - use 256 and 4x4 or 8x8 pixels. (disabled for now)
+ * gnome-saver doesn't let you specify source directory so add that to this.
+ * image loading routine is too slow - rotation grinds to a halt - stop using it. (better in version 5)
+ * image loading also looks bad for non-square images - edges are black. (fixed)
+ * possible to see edge of the world on widescreen terminals - use larger grid and hidden hex removal?
+ * fading textures may have different max_tx - use two sets. (done)
+ * choice of movement patterns. (3 implemented, chooseable at compile time)
+ * look into rangle and tangle.
*/
/*
#include "xpm-ximage.h"
#include "grab-ximage.h"
+#ifdef GRAB
+void grab_frame(Display *display, Window window);
+#endif
+
/* acd TODO should all these be in gleidestruct? */
/* they can't be, because of the idiotic way the xlockmore "argtype vars"
interface works. -jwz */
static char *image; /* name of texture to load */
static int duration; /* length of time to display grabbed image */
-#define MAX_TANGLE_VEL 2.0
-#define MAX_RANGLE_VEL 1.5
+#define MAX_CAM_SPEED 1.0
+#define MAX_ANGLE_VEL 1.0
+#define INITIAL_ANGLE_VEL 0.2
+#define INITIAL_ANGLE_ACC 0.001
+#define TWISTING_PROBABILITY 1000 /* 1 in ... of change of acceleration */
+
+#define RADIANS (M_PI / 180)
+#define ANGLE_120 (M_PI * 2 / 3)
+#define ANGLE_240 (M_PI * 4 / 3)
static XrmOptionDescRec opts[] =
{
GLfloat z;
} vectorf;
+typedef struct {
+ GLfloat x;
+ GLfloat y;
+} vector2f;
+
+typedef struct {
+ GLuint id; /* opengl texture id */
+ GLfloat width, height; /* texture width and height */
+ GLfloat min_tx, min_ty; /* minimum texture sizes */
+ GLfloat max_tx, max_ty; /* maximum texture sizes */
+ time_t start_time;
+ Bool button_down_p;
+ Bool mipmap_p;
+ Bool waiting_for_image_p;
+ /* r_phase is for triangle rotation speed */
+ GLfloat x_period, y_period, r_period;
+ GLfloat x_phase, y_phase, r_phase;
+} texture;
+
#define MAX_FADE 500 /* number of fade cycles */
typedef struct {
float tic;
GLXContext *glx_context;
Window window;
- GLfloat max_tx, max_ty; /* maximum texture sizes */
- GLuint textures[2]; /* texture handles */
- GLuint visible; /* texture handle for new texture */
+ texture textures[2]; /* texture handles */
+ GLuint visible; /* index for current texture */
GLint fade;
time_t start_time;
Bool button_down_p;
int size;
+ int list;
- float tangle; /* texture angle */
+ float tangle; /* texture angle (degrees) */
float tangle_vel; /* texture velocity */
float tangle_acc; /* texture acceleration */
} gleidestruct;
+#define frandrange(x, y) (x + frand(y - x))
+
#define XOFFSET (0.8660254f) /* sin 60' */
#define YOFFSET (1.5000000f) /* cos 60' + 1 */
}
#endif
+/* acd - this is terrible - 120+ hexes */
static const hex_t hex[] = {
/* edges of size 7 */
/* number of hexagons required to cover screen depends on camera distance */
int texture_width, int texture_height,
void *closure)
{
- gleidestruct *gp = (gleidestruct *) closure;
+ texture *tp = (texture *) closure;
+
+#if 0
+ gp->max_tx = (GLfloat) image_width / texture_width;
+ gp->max_ty = (GLfloat) image_height / texture_height;
+#endif
+
+ /* new - taken from flipscreen */
+ tp->width = texture_width;
+ tp->height = texture_height;
+ tp->min_tx = (GLfloat) geometry->x / tp->width;
+ tp->min_ty = (GLfloat) geometry->y / tp->height;
+ tp->max_tx = (GLfloat) (geometry->x + geometry->width) / tp->width;
+ tp->max_ty = (GLfloat) (geometry->y + geometry->height) / tp->height;
- gp->max_tx = (GLfloat) image_width / texture_width;
- gp->max_ty = (GLfloat) image_height / texture_height;
+#ifdef DEBUG
+ printf("Image w,h: (%d, %d)\n", image_width, image_height);
+ printf("Texture w,h: (%d, %d)\n", texture_width, texture_height);
+ printf("Geom x,y: (%d, %d)\n", geometry->x, geometry->y);
+ printf("Geom w,h: (%d, %d)\n", geometry->width, geometry->height);
+ printf("Max Tx,Ty: (%f, %f)\n", tp->max_tx, tp->max_ty);
+#endif
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
- (gp->mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR));
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ (tp->mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR));
- gp->waiting_for_image_p = False;
- gp->start_time = time ((time_t *) 0);
+ tp->waiting_for_image_p = False;
+ tp->start_time = time ((time_t *) 0);
}
-
static void
-getSnapshot(ModeInfo *mi, GLuint name)
+getSnapshot(ModeInfo *mi, texture *texture)
{
gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
+#ifdef DEBUG
+ printf("getSnapshot");
+#endif
+
if (MI_IS_WIREFRAME(mi))
return;
gp->mipmap_p = True;
load_texture_async (mi->xgwa.screen, mi->window,
*gp->glx_context, 0, 0, gp->mipmap_p,
- name, image_loaded_cb, gp);
+ texture->id, image_loaded_cb, texture);
+ texture->start_time = time((time_t *)0);
+}
+
+#define TEXTURE_SIZE 256
+
+static void
+plot(unsigned char *buffer, int x, int y, int r, int g, int b, int a) {
+ int c;
+ if (x < 0 || x >= TEXTURE_SIZE || y < 0 || y >= TEXTURE_SIZE) {
+ return;
+ }
+ c = ((x * TEXTURE_SIZE) + y) * 4;
+ /*printf("(%d,%d)[%d]\n", x, y, c);*/
+ buffer[c + 0] = r;
+ buffer[c + 1] = g;
+ buffer[c + 2] = b;
+ buffer[c + 3] = a;
+}
+
+#if 0
+static void
+plot2(unsigned char *buffer, int x, int y, int r, int g, int b, int a) {
+ int c;
+ if (x < 0 || x >= TEXTURE_SIZE || y < 0 || y >= TEXTURE_SIZE) {
+ return;
+ }
+ c = ((x * TEXTURE_SIZE) + y) * 4;
+ /*printf("(%d,%d)[%d]\n", x, y, c);*/
+ buffer[c + 0] = r;
+ buffer[c + 1] = g;
+ buffer[c + 2] = b;
+ buffer[c + 3] = a;
+
+ if (y + 1 < TEXTURE_SIZE) {
+ buffer[c + 4] = r;
+ buffer[c + 5] = g;
+ buffer[c + 6] = b;
+ buffer[c + 7] = a;
+ }
+
+ if (x + 1 < TEXTURE_SIZE) {
+ c += (TEXTURE_SIZE * 4);
+ buffer[c + 0] = r;
+ buffer[c + 1] = g;
+ buffer[c + 2] = b;
+ buffer[c + 3] = a;
+ if (y + 1 < TEXTURE_SIZE) {
+ buffer[c + 4] = r;
+ buffer[c + 5] = g;
+ buffer[c + 6] = b;
+ buffer[c + 7] = a;
+ }
+ }
+}
+#endif
+
+/* draw geometric shapes to texture */
+/* modifies passed in buffer */
+static void
+draw_shapes (unsigned char *buffer) {
+ int a = 0xff;
+ int x, y, w, h;
+ int i, j;
+ int s;
+ float left, right;
+
+ for (i = 0 ; i < TEXTURE_SIZE * TEXTURE_SIZE * 4 ; i += 4) {
+ buffer[i + 0] = 0x00;
+ buffer[i + 1] = 0x00;
+ buffer[i + 2] = 0x00;
+ buffer[i + 3] = 0xff;
+ }
+
+ for (s = 0 ; s < 25 ; s++) {
+ int shape = random() % 3;
+
+ /* 8 bits */
+ int r = (random() & 0xff);
+ int g = (random() & 0xff);
+ int b = (random() & 0xff);
+
+ switch (shape) {
+ case 0:
+ /* rectangle */
+ x = (random() % TEXTURE_SIZE) - (TEXTURE_SIZE / 4); /* top left */
+ y = (random() % TEXTURE_SIZE) - (TEXTURE_SIZE / 4);
+ w = 10 + random() % (TEXTURE_SIZE / 4); /* size */
+ h = 10 + random() % (TEXTURE_SIZE / 4);
+#ifdef DEBUG
+ printf("Rectangle: (%d, %d)(%d, %d)\n", x, y, w, h);
+#endif
+ if (x < 0) {
+ x = 0;
+ }
+ if (y < 0) {
+ y = 0;
+ }
+ for (i = x ; i < x + w && i < TEXTURE_SIZE; i++) {
+ for (j = y ; j < y + h && j < TEXTURE_SIZE; j++) {
+ plot(buffer, i, j, r, g, b, a);
+ }
+ }
+ break;
+
+ case 1:
+ /* circle */
+ x = random() % TEXTURE_SIZE; /* centre */
+ y = random() % TEXTURE_SIZE;
+ h = 10 + random() % (TEXTURE_SIZE / 8); /* radius */
+#ifdef DEBUG
+ printf("Circle: %d, %d, %d\n", x, y, h);
+#endif
+ for (i = 0 ; i < h ; i++) {
+ int xdist = i * i;
+ for (j = 0 ; j < h ; j++) {
+ int ydist = j * j;
+ /*
+ printf("xdist: %d\n", xdist);
+ printf("ydist: %d\n", ydist);
+ printf("radius: %d\n", h * h);
+ */
+ if ((xdist + ydist) < (h * h)) {
+ plot(buffer, x + i, y + j, r, b, g, a);
+ /* check we haven't already done these */
+ if (j != 0) {
+ plot(buffer, x + i, y - j, r, b, g, a);
+ }
+ if (i != 0) {
+ plot(buffer, x - i, y + j, r, b, g, a);
+ if (j != 0) {
+ plot(buffer, x - i, y - j, r, b, g, a);
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case 2:
+ /* triangle */
+ x = random() % TEXTURE_SIZE; /* top */
+ y = random() % TEXTURE_SIZE;
+ h = 10 + random() % (TEXTURE_SIZE / 4); /* height */
+#ifdef DEBUG
+ printf("Triangle: %d, %d, %d\n", x, y, h);
+#endif
+ left = x;
+ right = x;
+ for (i = 0 ; i < h ; i++) {
+ for (j = left ; j < right ; j++) {
+ plot(buffer, j, y + i, r, g, b, a);
+ }
+ left -= .5;
+ right += .5;
+ }
+ break;
+ }
+ }
}
+static void
+setup_random_texture (ModeInfo *mi, texture *texture)
+{
+ int width = 0, height = 0;
+ char buf[1024];
+ unsigned char *my_data = NULL;
+#if 0
+ int i, j, c;
+ int style;
+ int r0, g0, b0, a0, r1, g1, b1, a1;
+#endif
+
+#ifdef DEBUG
+ printf("RandomTexture\n");
+#endif
+
+ /* use this texture */
+ glBindTexture(GL_TEXTURE_2D, texture->id);
+
+ clear_gl_error();
+
+ /*
+ * code for various generated patterns - noise, stripes, checks etc.
+ * random geometric shapes looked the best.
+ */
+
+#if 0
+ style = random() & 0x3;
+ r0 = random() & 0xff;
+ g0 = random() & 0xff;
+ b0 = random() & 0xff;
+ a0 = 0xff;
+ r1 = random() & 0xff;
+ g1 = random() & 0xff;
+ b1 = random() & 0xff;
+ a1 = 0xff;
+
+ switch (style) {
+ case 0: /* random */
+ printf("Random0\n");
+ height = width = TEXTURE_SIZE;
+ my_data = (void *)malloc(width * height * 4);
+ for (i = 0 ; i < width ; i += 2) {
+ for (j = 0 ; j < height ; j += 2) {
+ r0 = random() & 0xff;
+ g0 = random() & 0xff;
+ b0 = random() & 0xff;
+ a0 = 0xff;
+ plot2(my_data, i, j, r0, g0, b0, a0);
+ }
+ }
+ break;
+
+ case 1: /* shapes */
+#endif
+#ifdef DEBUG
+ printf("Shapes\n");
+#endif
+ height = width = TEXTURE_SIZE;
+ my_data = (void *)malloc(width * height * 4);
+ draw_shapes(my_data);
+#if 0
+ break;
+
+ case 2: /* check */
+ printf("Check\n");
+ height = width = TEXTURE_SIZE;
+ my_data = (void *)malloc(width * height * 4);
+ for (i = 0 ; i < height ; i += 2) {
+ for (j = 0 ; j < width ; j += 2) {
+ if (((i + j) & 0x3) == 0) {
+ plot2(my_data, i, j, r0, g0, b0, a0);
+ } else {
+ plot2(my_data, i, j, r1, g1, b1, a1);
+ }
+ }
+ }
+ break;
+
+ case 3: /* random stripes */
+ printf("Stripes 2\n");
+ height = width = TEXTURE_SIZE;
+ my_data = (void *)malloc(width * height * 4);
+ for (i = 0 ; i < height ; i += 2) {
+ r0 = random() & 0xff;
+ g0 = random() & 0xff;
+ b0 = random() & 0xff;
+ a0 = 0xff;
+ for (j = 0 ; j < width ; j += 2) {
+ plot2(my_data, i, j, r0, g0, b0, a0);
+ }
+ }
+ break;
+ }
+#endif
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
+ width, height, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, my_data);
+ sprintf (buf, "random texture: (%dx%d)",
+ width, height);
+ check_gl_error(buf);
+
+ /* setup parameters for texturing */
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
+
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ if (random() & 0x1) {
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ } else {
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ }
+
+ if (my_data != NULL) {
+ free(my_data);
+ my_data = NULL;
+ }
+
+ /* use full texture */
+ /* acd - was 1.0 */
+ texture->min_tx = 0.0;
+ texture->max_tx = 2.0;
+ texture->min_ty = 0.0;
+ texture->max_ty = 2.0;
+ texture->start_time = time((time_t *)0);
+}
static void
-setup_file_texture (ModeInfo *mi, char *filename, GLuint name)
+setup_file_texture (ModeInfo *mi, char *filename, texture *texture)
{
Display *dpy = mi->dpy;
Visual *visual = mi->xgwa.visual;
Colormap cmap = mi->xgwa.colormap;
XImage *image = xpm_file_to_ximage (dpy, visual, cmap, filename);
+#ifdef DEBUG
+ printf("FileTexture\n");
+#endif
+
/* use this texture */
- glBindTexture(GL_TEXTURE_2D, name);
+ glBindTexture(GL_TEXTURE_2D, texture->id);
clear_gl_error();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+ /* use full texture */
+ texture->min_tx = 0.0;
+ texture->max_tx = 1.0;
+ texture->min_ty = 0.0;
+ texture->max_ty = 1.0;
+ texture->start_time = time((time_t *)0);
}
static void
-setup_texture(ModeInfo * mi, GLuint id)
+setup_texture(ModeInfo * mi, texture *texture)
{
gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
if (!image || !*image || !strcmp(image, "DEFAULT")) {
- /* no image specified - grab screen */
- getSnapshot(mi, id);
- /* max_tx and max_ty set in getSnapshot() */
+ /* no image specified - use system settings */
+#ifdef DEBUG
+ printf("SetupTexture: get_snapshot\n");
+#endif
+ getSnapshot(mi, texture);
} else {
- /* use supplied image file */
- setup_file_texture(mi, image, id);
-
- /* set tx params to use whole image */
- gp->max_tx = 1.0f;
- gp->max_ty = 1.0f;
+ if (strcmp(image, "GENERATE") == 0) {
+#ifdef DEBUG
+ printf("SetupTexture: random_texture\n");
+#endif
+ setup_random_texture(mi, texture);
+ } else {
+ /* use supplied image file */
+#ifdef DEBUG
+ printf("SetupTexture: file_texture\n");
+#endif
+ setup_file_texture(mi, image, texture);
+ }
}
+ /* copy start time from texture */
+ gp->start_time = texture->start_time;
check_gl_error("texture initialization");
- /* Need to flip the texture top for bottom for some reason. */
- glMatrixMode (GL_TEXTURE);
- glScalef (1, -1, 1);
- glMatrixMode (GL_MODELVIEW);
+ /* acd
+ * resultant loaded image is upside down BUT
+ * it's a kaledescope and half of the hexagon is backwards anyway...
+ */
+
+ /* TODO: values for lissajous movement */
+ texture->x_period = frandrange(-2.0, 2.0);
+ texture->y_period = frandrange(-2.0, 2.0);
+ texture->r_period = frandrange(-2.0, 2.0);
+ texture->x_phase = frand(M_PI * 2);
+ texture->y_phase = frand(M_PI * 2);
+ texture->r_phase = frand(M_PI * 2);
+#ifdef DEBUG
+ printf("XPeriod %f XPhase %f\n", texture->x_period, texture->x_phase);
+ printf("YPeriod %f YPhase %f\n", texture->y_period, texture->y_phase);
+ printf("RPeriod %f RPhase %f\n", texture->r_period, texture->r_phase);
+#endif
}
#define VERTEX0 glVertex3f( 0.0000f, 0.000f, 0.0f);
#define VERTEX5 glVertex3f(-XOFFSET, -0.500f, 0.0f);
#define VERTEX6 glVertex3f(-XOFFSET, 0.500f, 0.0f);
+/*
+** Three different functions for calculating texture coordinates
+** which modify how the texture triangle moves over the source image.
+** Choose one.
+*/
+
+#if 0
+/* the classic equilateral triangle rotating around centre */
+static void
+calculate_texture_coords(ModeInfo *mi, texture *texture, vector2f t[3]) {
+
+ gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
+ GLfloat centre_x = 0.5;
+ GLfloat centre_y = 0.5;
+ GLfloat radius_x = (texture->max_tx - texture->min_tx) / 2;
+ GLfloat radius_y = (texture->max_ty - texture->min_ty) / 2;
+ GLfloat tangle2;
+ t[0].x = centre_x;
+ t[0].y = centre_y;
+
+ /* t[1] */
+ t[1].x = centre_x + .95 * radius_x * cos((gp->ymouse * 2 * M_PI) + (gp->tangle * RADIANS));
+ t[1].y = centre_y + .95 * radius_y * sin((gp->ymouse * 2 * M_PI) + (gp->tangle * RADIANS));
+
+ /* t[2] is always 60' further around than t2 */
+ tangle2 = (gp->ymouse * 2 * M_PI) + (gp->tangle * RADIANS) + (M_PI * 2 / 6);
+ t[2].x = centre_x + .95 * radius_x * cos(tangle2);
+ t[2].y = centre_y + .95 * radius_y * sin(tangle2);
+#if 0
+ printf("texcoords:[%f,%f]->[%f,%f](%f,%f)\n", t[0].x, t[0].y, t[1].x, t[1].y, texture->max_tx, texture->max_ty);
+#endif
+}
+#endif
+
+#if 1
+/* new lissajous movement pattern */
+static void
+calculate_texture_coords(ModeInfo *mi, texture *texture, vector2f t[3]) {
+
+ /* equilateral triangle rotating around centre */
+ gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
+ GLfloat width = texture->max_tx - texture->min_tx;
+ GLfloat height = texture->max_ty - texture->min_ty;
+ /* centre */
+ GLfloat centre_x = texture->min_tx + (width * .5);
+ GLfloat centre_y = texture->min_ty + (height * .5);
+ /* m radius and t radius should be = .5 */
+ /* triangle radius is 30% available space */
+ GLfloat t_radius_x = width * .3;
+ GLfloat t_radius_y = height * .3;
+ /* movement radius is 30% available space */
+ GLfloat m_radius_x = width * .2;
+ GLfloat m_radius_y = height * .2;
+ GLfloat angle2;
+
+ /* centre of triangle */
+ GLfloat angle = (gp->ymouse * 2 * M_PI) + (gp->tangle * RADIANS); /* to radians */
+ GLfloat t_centre_x = centre_x + m_radius_x * cos(texture->x_period * angle + texture->x_phase);
+ GLfloat t_centre_y = centre_y + m_radius_y * sin(texture->y_period * angle + texture->y_phase);
+
+#if 0
+ printf("WH: %f, %f - tWH: %f, %f\n", width, height, texture->width, texture->height);
+ printf("size: (%f, %f)\n", width, height);
+ printf("centre: (%f, %f)\n", centre_x, centre_y);
+#endif
+
+ angle2 = texture->r_period * angle + texture->r_phase;
+ t[0].x = t_centre_x + t_radius_x * cos(angle2);
+ t[0].y = t_centre_y + t_radius_y * sin(angle2);
+ t[1].x = t_centre_x + t_radius_x * cos(angle2 + ANGLE_120);
+ t[1].y = t_centre_y + t_radius_y * sin(angle2 + ANGLE_120);
+ t[2].x = t_centre_x + t_radius_x * cos(angle2 + ANGLE_240);
+ t[2].y = t_centre_y + t_radius_y * sin(angle2 + ANGLE_240);
+
+#if 0
+ printf("texcoords:[%f,%f]->[%f,%f](%f,%f)\n", t[0].x, t[0].y, t[1].x, t[1].y, texture->max_tx, texture->max_ty);
+#endif
+}
+#endif
+
+#if 0
+/* corners into corners - meant to maximise coverage */
+static void
+calculate_texture_coords(ModeInfo *mi, texture *texture, vector2f t[3]) {
+
+ /* equilateral triangle rotating around centre */
+ gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
+ GLfloat width = texture->max_tx - texture->min_tx;
+ GLfloat height = texture->max_ty - texture->min_ty;
+ /* centre */
+ GLfloat centre_x = texture->min_tx + (width * .5);
+ GLfloat centre_y = texture->min_ty + (height * .5);
+ /* m radius and t radius should be = .5 */
+ /* triangle radius calculated using maths 8) */
+#define TRADIUS (M_SQRT2 - 1.0)
+#define MRADIUS (1.0 - (M_SQRT2 / 2.0))
+ GLfloat t_radius_x = width * TRADIUS * .95;
+ GLfloat t_radius_y = height * TRADIUS * .95;
+ /* movement radius also calculated using maths */
+ GLfloat m_radius_x = width * MRADIUS * .95;
+ GLfloat m_radius_y = height * MRADIUS * .95;
+ GLfloat angle, angle2;
+ GLfloat t_centre_x, t_centre_y;
+
+ /* centre of triangle */
+ angle = gp->tangle * RADIANS; /* to radians */
+ t_centre_x = centre_x + m_radius_x * cos(angle);
+ t_centre_y = centre_y + m_radius_y * sin(angle);
+#if 0
+ printf("angle: %f, %f\n", angle, gp->tangle);
+ printf("tcentre: %f,%f\n", t_centre_x, t_centre_y);
+ printf("tradius: %f,%f\n", t_radius_x, t_radius_y);
+
+ printf("size: (%f, %f)\n", width, height);
+ printf("centre: (%f, %f)\n", centre_x, centre_y);
+ printf("centre: (%f, %f)\n", centre_x, centre_y);
+ printf("TRADIUS: %f\n", TRADIUS);
+ printf("MRADIUS: %f\n", MRADIUS);
+#endif
+
+ /* angle2 is tied to tangle */
+ angle2 = (180.0 - ((30.0 / 90.0) * gp->tangle)) * RADIANS;
+#if 0
+ printf("Angle1: %f\tAngle2: %f\n", angle / RADIANS, angle2 / RADIANS);
+#endif
+ t[0].x = t_centre_x + t_radius_x * cos(angle2);
+ t[0].y = t_centre_y + t_radius_y * sin(angle2);
+ t[1].x = t_centre_x + t_radius_x * cos(angle2 + ANGLE_120);
+ t[1].y = t_centre_y + t_radius_y * sin(angle2 + ANGLE_120);
+ t[2].x = t_centre_x + t_radius_x * cos(angle2 + ANGLE_240);
+ t[2].y = t_centre_y + t_radius_y * sin(angle2 + ANGLE_240);
+
+#if 0
+ printf("texcoords:[%f,%f][%f,%f][%f,%f]\n", t[0].x, t[0].y, t[1].x, t[1].y, t[2].x, t[2].y);
+#endif
+}
+#endif
+
static void
-draw_hexagons(ModeInfo *mi, int translucency, GLuint texture)
+draw_hexagons(ModeInfo *mi, int translucency, texture *texture)
{
int i;
GLfloat col[4];
- GLfloat t1x, t1y, t2x, t2y, t3x, t3y;
+ vector2f t[3];
gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
- GLfloat tangle2;
col[0] = 1.0;
col[1] = 1.0;
col[2] = 1.0;
col[3] = (float)translucency / MAX_FADE;
- /* calculate vertices of equilateral triangle within image. */
- /* t1 is always in centre */
- t1x = gp->max_tx / 2;
- t1y = gp->max_ty / 2;
- /* t2 rotates */
- t2x = (gp->max_tx / 2) * (1 + cos((gp->ymouse * 2 * M_PI) + (gp->tangle * M_PI / 180)));
- t2y = (gp->max_ty / 2) * (1 + sin((gp->ymouse * 2 * M_PI) + (gp->tangle * M_PI / 180)));
- /* t3 is always 60' further around than t2 */
- tangle2 = (gp->ymouse * 2 * M_PI) + (gp->tangle * M_PI / 180) + (M_PI * 2 / 6);
- t3x = (gp->max_tx / 2) * (1 + (cos(tangle2)));
- t3y = (gp->max_ty / 2) * (1 + (sin(tangle2)));
- /* NB image is flipped vertically hence: */
- t1y = 1 - t1y;
- t2y = 1 - t2y;
- t3y = 1 - t3y;
- /*printf("texcoords:[%f,%f]->[%f,%f](%f,%f)\n", t1x, t1y, t2x, t2y, gp->max_tx, gp->max_ty);*/
+ calculate_texture_coords(mi, texture, t);
glColor4f(1.0, 1.0, 1.0, (float)translucency / MAX_FADE);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(GL_FALSE);
- glBindTexture(GL_TEXTURE_2D, gp->textures[texture]);
+ glBindTexture(GL_TEXTURE_2D, texture->id);
+ if (gp->list == -1) {
+ gp->list = glGenLists(1);
+ }
+
+ /* compile new list */
+ glNewList(gp->list, GL_COMPILE);
+ glBegin(GL_TRIANGLES);
+
+ /*
+ ** six triangles to each hexagon
+ */
+
+ glTexCoord2f(t[0].x, t[0].y);
+ VERTEX0;
+ glTexCoord2f(t[1].x, t[1].y);
+ VERTEX1;
+ glTexCoord2f(t[2].x, t[2].y);
+ VERTEX6;
+
+ glTexCoord2f(t[0].x, t[0].y);
+ VERTEX0;
+ glTexCoord2f(t[2].x, t[2].y);
+ VERTEX6;
+ glTexCoord2f(t[1].x, t[1].y);
+ VERTEX5;
+
+ glTexCoord2f(t[0].x, t[0].y);
+ VERTEX0;
+ glTexCoord2f(t[1].x, t[1].y);
+ VERTEX5;
+ glTexCoord2f(t[2].x, t[2].y);
+ VERTEX4;
+
+ glTexCoord2f(t[0].x, t[0].y);
+ VERTEX0;
+ glTexCoord2f(t[2].x, t[2].y);
+ VERTEX4;
+ glTexCoord2f(t[1].x, t[1].y);
+ VERTEX3;
+
+ glTexCoord2f(t[0].x, t[0].y);
+ VERTEX0;
+ glTexCoord2f(t[1].x, t[1].y);
+ VERTEX3;
+ glTexCoord2f(t[2].x, t[2].y);
+ VERTEX2;
+
+ glTexCoord2f(t[0].x, t[0].y);
+ VERTEX0;
+ glTexCoord2f(t[2].x, t[2].y);
+ VERTEX2;
+ glTexCoord2f(t[1].x, t[1].y);
+ VERTEX1;
+
+ glEnd();
+ glEndList();
+
+ /* call the list n times */
for (i = 0 ; i < sizeof(hex) / sizeof(hex[0]) ; i++) {
glPushMatrix();
glTranslatef(hex[i].x, hex[i].y, 0.0);
-
- glBegin(GL_TRIANGLES);
-
- /*
- ** six triangles to each hexagon
- */
-
- glTexCoord2f(t1x, t1y);
- VERTEX0;
- glTexCoord2f(t2x, t2y);
- VERTEX1;
- glTexCoord2f(t3x, t3y);
- VERTEX6;
-
- glTexCoord2f(t1x, t1y);
- VERTEX0;
- glTexCoord2f(t3x, t3y);
- VERTEX6;
- glTexCoord2f(t2x, t2y);
- VERTEX5;
-
- glTexCoord2f(t1x, t1y);
- VERTEX0;
- glTexCoord2f(t2x, t2y);
- VERTEX5;
- glTexCoord2f(t3x, t3y);
- VERTEX4;
-
- glTexCoord2f(t1x, t1y);
- VERTEX0;
- glTexCoord2f(t3x, t3y);
- VERTEX4;
- glTexCoord2f(t2x, t2y);
- VERTEX3;
-
- glTexCoord2f(t1x, t1y);
- VERTEX0;
- glTexCoord2f(t2x, t2y);
- VERTEX3;
- glTexCoord2f(t3x, t3y);
- VERTEX2;
-
- glTexCoord2f(t1x, t1y);
- VERTEX0;
- glTexCoord2f(t3x, t3y);
- VERTEX2;
- glTexCoord2f(t2x, t2y);
- VERTEX1;
-
- glEnd();
+ glCallList(gp->list);
glPopMatrix();
}
glVertex3f(0.0, 1.0, -0.1);
glEnd();
/* acd debug - display texture triangle */
- glColor4f(1.0, 1.0, 1.0, 1.0);
+ glColor4f(1.0, 0.5, 1.0, 1.0);
glBegin(GL_LINE_LOOP);
- glVertex3f(t1x, t1y, -0.11);
- glVertex3f(t2x, t2y, -0.11);
- glVertex3f(t3x, t3y, -0.11);
+ glVertex3f(t[0].x, t[0].y, -0.11);
+ glVertex3f(t[1].x, t[1].y, -0.11);
+ glVertex3f(t[2].x, t[2].y, -0.11);
glEnd();
glPopMatrix();
#endif
z_angle = gp->cam_z_phase + gp->tic * gp->cam_z_speed;
if (move) {
- v1.x = 2 * sin(x_angle);
- v1.y = 2 * sin(y_angle);
+ v1.x = 1 * sin(x_angle);
+ v1.y = 1 * sin(y_angle);
} else {
v1.x = 0;
v1.y = 0;
v1.z = gp->size;
} else if (zoom) {
/* max distance given by adding the constant and the multiplier */
- v1.z = 5.0 + 4.0 * sin(z_angle);
+ v1.z = 5.0 + 3.0 * sin(z_angle);
} else {
/* default */
v1.z = 7.0;
/* update camera rotation angle and velocity */
gp->rangle += gp->rangle_vel;
new_rangle_vel = gp->rangle_vel + gp->rangle_acc;
- if (new_rangle_vel > -MAX_RANGLE_VEL && new_rangle_vel < MAX_RANGLE_VEL)
+ if (new_rangle_vel > -MAX_ANGLE_VEL && new_rangle_vel < MAX_ANGLE_VEL)
{
/* new velocity is within limits */
gp->rangle_vel = new_rangle_vel;
}
- /* randomly change twisting speed */
- if ((random() % 1000) < 1)
- {
- gp->rangle_acc = frand(0.002) - 0.001;
+ /* randomly change twisting speed - 3ff = 1024 */
+ if ((random() % TWISTING_PROBABILITY) < 1.0) {
+ gp->rangle_acc = INITIAL_ANGLE_ACC * frand(1.0);
+ if (gp->rangle_vel > 0.0) {
+ gp->rangle_acc = -gp->rangle_acc;
+ }
}
}
+#if 0
+ printf("Rangle: %f : %f : %f\n", gp->rangle, gp->rangle_vel, gp->rangle_acc);
+ printf("Tangle: %f : %f : %f\n", gp->tangle, gp->tangle_vel, gp->tangle_acc);
+#endif
#ifdef WOBBLE
/* this makes the image wobble - requires -move and a larger grid */
gluLookAt(
v1.x, v1.y, v1.z,
v1.x, v1.y, 0.0,
- sin((gp->xmouse * M_PI * 2) + gp->rangle * M_PI / 180),
- cos((gp->xmouse * M_PI * 2) + gp->rangle * M_PI / 180),
+ sin((gp->xmouse * M_PI * 2) + gp->rangle * RADIANS),
+ cos((gp->xmouse * M_PI * 2) + gp->rangle * RADIANS),
0.0);
#endif
if (gp->fade == 0)
{
/* not fading */
- draw_hexagons(mi, MAX_FADE, gp->visible);
+ draw_hexagons(mi, MAX_FADE, &gp->textures[gp->visible]);
}
else
{
- /* fading - show both textures with alpha */
- draw_hexagons(mi, MAX_FADE - gp->fade, gp->visible);
- draw_hexagons(mi, gp->fade, 1 - gp->visible);
+ /* fading - show both textures with alpha
+ NB first is always max alpha */
+ draw_hexagons(mi, MAX_FADE, &gp->textures[1 - gp->visible]);
+ draw_hexagons(mi, MAX_FADE - gp->fade, &gp->textures[gp->visible]);
/* fade some more */
gp->fade++;
/* work out new texture angle velocity */
new_tangle_vel = gp->tangle_vel + gp->tangle_acc;
- if (new_tangle_vel > -MAX_TANGLE_VEL && new_tangle_vel < MAX_TANGLE_VEL)
+ if (new_tangle_vel > -MAX_ANGLE_VEL && new_tangle_vel < MAX_ANGLE_VEL)
{
/* new velocity is inside limits */
gp->tangle_vel = new_tangle_vel;
}
- /* randomly change texture angle acceleration */
- if ((random() % 1000) < 1)
- {
- gp->tangle_acc = frand(0.002) - 0.001;
+ /* randomly change twisting speed - 3ff = 1024 */
+ if ((random() % TWISTING_PROBABILITY) < 1.0) {
+ gp->tangle_acc = INITIAL_ANGLE_ACC * frand(1.0);
+ if (gp->tangle_vel > 0.0) {
+ gp->tangle_acc = -gp->tangle_acc;
+ }
}
}
gp->start_time = (time_t)0;
/* set the texture size to default */
+ /*
gp->max_tx = 1.0;
gp->max_ty = 1.0;
+ */
/* no fading */
gp->fade = 0;
glDisable(GL_LIGHTING);
/* space for textures */
- glGenTextures(1, &gp->textures[0]);
- glGenTextures(1, &gp->textures[1]);
+ glGenTextures(1, &gp->textures[0].id);
+ glGenTextures(1, &gp->textures[1].id);
gp->visible = 0;
- setup_texture(mi, gp->textures[gp->visible]);
+ setup_texture(mi, &gp->textures[gp->visible]);
/*
** want to choose a value for arg randomly if neither -arg nor -no-arg
}
/* define cam variables */
- gp->cam_x_speed = frand(3.0) - 1.5;
+ gp->cam_x_speed = MAX_CAM_SPEED * frandrange(-.5, 0.5);
gp->cam_x_phase = random() % 360;
- gp->cam_y_speed = frand(3.0) - 1.5;
+ gp->cam_y_speed = MAX_CAM_SPEED * frandrange(-.5, 0.5);
gp->cam_y_phase = random() % 360;
- gp->cam_z_speed = frand(3.0) - 1.5;
+ gp->cam_z_speed = MAX_CAM_SPEED * frandrange(-.5, 0.5);
gp->cam_z_phase = random() % 360;
/* initial angular speeds */
- gp->rangle_vel = frand(0.2) - 0.1;
- gp->tangle_vel = frand(0.2) - 0.1;
- gp->rangle_acc = frand(0.002) - 0.001;
- gp->tangle_acc = frand(0.002) - 0.001;
+ gp->rangle_vel = INITIAL_ANGLE_VEL * frandrange(-.5, 0.5);
+ gp->tangle_vel = INITIAL_ANGLE_VEL * frandrange(-.5, 0.5);
+ gp->rangle_acc = INITIAL_ANGLE_ACC * frandrange(-.5, 0.5);
+ gp->tangle_acc = INITIAL_ANGLE_ACC * frandrange(-.5, 0.5);
/* jwz */
+#if 0
{
GLfloat speed = 15;
gp->rangle_vel *= speed;
gp->rangle_acc *= speed;
gp->tangle_acc *= speed;
}
+#endif
/* distance is 11 - size */
if (gp->size != -1) {
gleidestruct *gp;
int screen = MI_SCREEN(mi);
-
if (gleidescope == NULL) {
gleidescope = (gleidestruct *) calloc(MI_NUM_SCREENS(mi), sizeof (gleidestruct));
if (gleidescope == NULL) {
gp = &gleidescope[screen];
gp->window = MI_WINDOW(mi);
gp->size = -1;
+ gp->list = -1;
if ((gp->glx_context = init_GL(mi)) != NULL) {
#ifdef GRAB
if (grab) {
- grab_frame(mi);
+ grab_frame(display, window);
}
#endif
/* need to change texture? */
if ((gp->start_time != 0) && (duration != -1) && gp->fade == 0) {
if (gp->start_time + duration <= time((time_t *)0)) {
+#ifdef DEBUG
+ printf("Start Time: %lu - Current Time: %lu\n", (unsigned long)gp->start_time, (unsigned long)time((time_t *)0));
+ printf("Changing Texture\n");
+#endif
/* get new snapshot (into back buffer) and start fade count */
- getSnapshot(mi, gp->textures[1 - gp->visible]);
+ setup_texture(mi, &gp->textures[1 - gp->visible]);
+ /* restart fading */
gp->fade = 1;
}
}
--- /dev/null
+/* Sky Tentacles, Copyright (c) 2008 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
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#define DEFAULTS "*delay: 30000 \n" \
+ "*count: 8 \n" \
+ "*showFPS: False \n" \
+ "*wireframe: False \n" \
+
+# define refresh_tentacles 0
+# define release_tentacles 0
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+#include "xlockmore.h"
+#include "colors.h"
+#include "normals.h"
+#include "rotator.h"
+#include "gltrackball.h"
+#include <ctype.h>
+
+#ifdef USE_GL /* whole file */
+
+#define DEF_SPEED "1.0"
+#define DEF_SMOOTH "True"
+#define DEF_SLICES "32"
+#define DEF_SEGMENTS "32"
+#define DEF_WIGGLINESS "0.35"
+#define DEF_FLEXIBILITY "0.35"
+#define DEF_THICKNESS "1.0"
+#define DEF_LENGTH "9.0"
+#define DEF_COLOR "#305A30"
+#define DEF_STRIPE "#451A30"
+#define DEF_SUCKER "#453E30"
+#define DEF_DEBUG "False"
+
+#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3)
+
+typedef struct {
+ GLfloat length; /* length of the segment coming out of this segment */
+ GLfloat th; /* vector tilt (on yz plane) from previous segment */
+ GLfloat phi; /* vector rotation (on xy plane) from previous segment */
+ GLfloat thickness; /* radius of tentacle at this segment */
+ rotator *rot; /* motion modeller */
+} segment;
+
+typedef struct {
+ ModeInfo *mi;
+ GLfloat x, y, z; /* position of the base */
+ int nsegments;
+ segment *segments;
+ GLfloat tentacle_color[4], stripe_color[4], sucker_color[4];
+} tentacle;
+
+typedef struct {
+ GLXContext *glx_context;
+ trackball_state *trackball;
+ Bool button_down_p;
+
+ int ntentacles;
+ int tentacles_size;
+ tentacle **tentacles;
+ GLfloat tentacle_color[4], stripe_color[4], sucker_color[4];
+
+ GLuint sucker_list;
+ int sucker_polys;
+
+ Bool left_p;
+
+
+} tentacles_configuration;
+
+static tentacles_configuration *tcs = NULL;
+
+static int debug_p;
+static GLfloat arg_speed;
+static int smooth_p;
+static int arg_slices;
+static int arg_segments;
+static GLfloat arg_thickness;
+static GLfloat arg_length;
+static GLfloat arg_wiggliness;
+static GLfloat arg_flexibility;
+static char *arg_color, *arg_stripe, *arg_sucker;
+
+static XrmOptionDescRec opts[] = {
+ { "-speed", ".speed", XrmoptionSepArg, 0 },
+ { "-no-smooth", ".smooth", XrmoptionNoArg, "False" },
+ { "-slices", ".slices", XrmoptionSepArg, 0 },
+ { "-segments", ".segments", XrmoptionSepArg, 0 },
+ { "-thickness", ".thickness", XrmoptionSepArg, 0 },
+ { "-length", ".length", XrmoptionSepArg, 0 },
+ { "-wiggliness", ".wiggliness", XrmoptionSepArg, 0 },
+ { "-flexibility", ".flexibility", XrmoptionSepArg, 0 },
+ { "-color", ".tentacleColor", XrmoptionSepArg, 0 },
+ { "-stripe-color", ".stripeColor", XrmoptionSepArg, 0 },
+ { "-sucker-color", ".suckerColor", XrmoptionSepArg, 0 },
+ { "-debug", ".debug", XrmoptionNoArg, "True" },
+};
+
+static argtype vars[] = {
+ {&arg_speed, "speed", "Speed", DEF_SPEED, t_Float},
+ {&smooth_p, "smooth", "Smooth", DEF_SMOOTH, t_Bool},
+ {&arg_slices, "slices", "Slices", DEF_SLICES, t_Int},
+ {&arg_segments, "segments", "Segments", DEF_SEGMENTS, t_Int},
+ {&arg_thickness, "thickness", "Thickness", DEF_THICKNESS, t_Float},
+ {&arg_length, "length", "Length", DEF_LENGTH, t_Float},
+ {&arg_wiggliness, "wiggliness", "Wiggliness", DEF_WIGGLINESS, t_Float},
+ {&arg_flexibility, "flexibility", "Flexibility", DEF_FLEXIBILITY, t_Float},
+ {&arg_color, "tentacleColor", "Color", DEF_COLOR, t_String},
+ {&arg_stripe, "stripeColor", "Color", DEF_STRIPE, t_String},
+ {&arg_sucker, "suckerColor", "Color", DEF_SUCKER, t_String},
+ {&debug_p, "debug", "Debug", DEF_DEBUG, t_Bool},
+};
+
+ENTRYPOINT ModeSpecOpt tentacles_opts = {countof(opts), opts, countof(vars), vars, NULL};
+
+
+/* Window management, etc
+ */
+ENTRYPOINT void
+reshape_tentacles (ModeInfo *mi, int width, int height)
+{
+ GLfloat h = (GLfloat) height / (GLfloat) width;
+
+ glViewport (0, 0, (GLint) width, (GLint) height);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective (30.0, 1/h, 1.0, 100.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ gluLookAt( 0.0, 0.0, 30.0,
+ 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0);
+
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+
+
+
+static int
+unit_torus (double ratio, int slices1, int slices2, Bool wire)
+{
+ int i, j, k, polys = 0;
+
+ if (wire) slices1 /= 2;
+ if (wire) slices2 /= 4;
+ if (slices1 < 3) slices1 = 3;
+ if (slices2 < 3) slices2 = 3;
+
+ glFrontFace (GL_CW);
+ glBegin (wire ? GL_LINE_STRIP : GL_QUAD_STRIP);
+ for (i = 0; i < slices1; i++)
+ for (j = 0; j <= slices2; j++)
+ for (k = 0; k <= 1; k++)
+ {
+ double s = (i + k) % slices1 + 0.5;
+ double t = j % slices2;
+
+ double x = cos(t*M_PI*2/slices2) * cos(s*M_PI*2/slices1);
+ double y = sin(t*M_PI*2/slices2) * cos(s*M_PI*2/slices1);
+ double z = sin(s*M_PI*2/slices1);
+ glNormal3f(x, y, z);
+
+ x = (1 + ratio * cos(s*M_PI*2/slices1)) * cos(t*M_PI*2/slices2) / 2;
+ y = (1 + ratio * cos(s*M_PI*2/slices1)) * sin(t*M_PI*2/slices2) / 2;
+ z = ratio * sin(s*M_PI*2/slices1) / 2;
+ glVertex3f(x, y, z);
+ polys++;
+ }
+ glEnd();
+ return polys;
+}
+
+
+
+
+/* Initializes a new tentacle and stores it in the list.
+ */
+static tentacle *
+make_tentacle (ModeInfo *mi, int which, int total)
+{
+ tentacles_configuration *tc = &tcs[MI_SCREEN(mi)];
+ tentacle *t = (tentacle *) calloc (1, sizeof (*t));
+ double brightness;
+ int i;
+
+ t->mi = mi;
+
+ /* position tentacles on a grid */
+ {
+ int cols = (int) (sqrt(total) + 0.5);
+ int rows = (total+cols-1) / cols;
+ int xx = which % cols;
+ int yy = which / cols;
+ double spc = arg_thickness * 0.8;
+ t->x = (cols * spc / 2) - (spc * (xx + 0.5));
+ t->y = (rows * spc / 2) - (spc * (yy + 0.5));
+ t->z = 0;
+ }
+
+ /* Brighten or darken the colors of this tentacle from the default.
+ */
+ brightness = 0.6 + frand(3.0);
+ memcpy (t->tentacle_color, tc->tentacle_color, 4 * sizeof(*t->tentacle_color));
+ memcpy (t->stripe_color, tc->stripe_color, 4 * sizeof(*t->stripe_color));
+ memcpy (t->sucker_color, tc->sucker_color, 4 * sizeof(*t->sucker_color));
+# define FROB(X) \
+ t->X[0] *= brightness; if (t->X[0] > 1) t->X[0] = 1; \
+ t->X[1] *= brightness; if (t->X[1] > 1) t->X[1] = 1; \
+ t->X[2] *= brightness; if (t->X[2] > 1) t->X[2] = 1
+ FROB (tentacle_color);
+ FROB (stripe_color);
+ FROB (sucker_color);
+# undef FROB
+
+ t->nsegments = (arg_segments) + BELLRAND(arg_segments);
+
+ t->segments = (segment *) calloc (t->nsegments+1, sizeof(*t->segments));
+ for (i = 0; i < t->nsegments; i++)
+ {
+ double spin_speed = 0;
+ double spin_accel = 0;
+ double wander_speed = arg_speed * (0.02 + BELLRAND(0.1));
+ t->segments[i].rot = make_rotator (spin_speed, spin_speed, spin_speed,
+ spin_accel, wander_speed, True);
+ }
+
+ t->segments[0].thickness = (((arg_thickness * 0.5) +
+ BELLRAND(arg_thickness * 0.6))
+ / 1.0);
+
+ if (tc->tentacles_size <= tc->ntentacles)
+ {
+ tc->tentacles_size = (tc->tentacles_size * 1.2) + tc->ntentacles;
+ tc->tentacles = (tentacle **)
+ realloc (tc->tentacles, tc->tentacles_size * sizeof(*tc->tentacles));
+ if (! tc->tentacles)
+ {
+ fprintf (stderr, "%s: out of memory (%d tentacles)\n",
+ progname, tc->tentacles_size);
+ exit (1);
+ }
+ }
+
+ tc->tentacles[tc->ntentacles++] = t;
+ return t;
+}
+
+
+static void
+draw_tentacle (tentacle *t)
+{
+ tentacles_configuration *tc = &tcs[MI_SCREEN(t->mi)];
+ int i;
+ Bool wire = MI_IS_WIREFRAME (t->mi);
+ XYZ ctr = { 0,0,0 }; /* current position of base of segment */
+ double cth = 0; /* overall orientation of current segment */
+ double cphi = 0;
+ double cth_cos = 1, cth_sin = 0;
+ double cphi_cos = 1, cphi_sin = 0;
+
+ XYZ *ring, *oring; /* points around the edge (this, and previous) */
+ XYZ *norm, *onorm; /* their normals */
+
+ /* Which portion of the radius the colored stripe takes up */
+ int indented_points = arg_slices * 0.2;
+
+ /* We do rotation way to minimize number of calls to sin/cos. */
+# define ROT(P) do { \
+ XYZ _p = P; \
+ _p.y = ((P.y * cth_sin - P.x * cth_cos)); \
+ _p.x = ((P.y * cth_cos + P.x * cth_sin) * cphi_sin - (P.z * cphi_cos)); \
+ _p.z = ((P.y * cth_cos + P.x * cth_sin) * cphi_cos + (P.z * cphi_sin)); \
+ P = _p; \
+ } while(0)
+
+ ring = (XYZ *) malloc (arg_slices * sizeof(*ring));
+ norm = (XYZ *) malloc (arg_slices * sizeof(*norm));
+ oring = (XYZ *) malloc (arg_slices * sizeof(*oring));
+ onorm = (XYZ *) malloc (arg_slices * sizeof(*onorm));
+
+ if (wire)
+ glColor4fv (t->tentacle_color);
+ else
+ {
+ static const GLfloat bspec[4] = {1.0, 1.0, 1.0, 1.0};
+ static const GLfloat bshiny = 128.0;
+ glMaterialfv (GL_FRONT, GL_SPECULAR, bspec);
+ glMateriali (GL_FRONT, GL_SHININESS, bshiny);
+ }
+
+ glPushMatrix();
+ glTranslatef (t->x, t->y, t->z);
+
+ if (debug_p)
+ {
+ if (!wire) glDisable(GL_LIGHTING);
+ glBegin(GL_LINE_LOOP);
+ for (i = 0; i < arg_slices; i++)
+ glVertex3f (arg_thickness / 2 * cos (M_PI * 2 * i / arg_slices),
+ arg_thickness / 2 * sin (M_PI * 2 * i / arg_slices),
+ 0);
+ glEnd();
+ if (!wire) glEnable(GL_LIGHTING);
+ }
+
+ for (i = 0; i < t->nsegments; i++)
+ {
+ int j;
+ XYZ p;
+
+ for (j = 0; j < arg_slices; j++)
+ {
+ /* Construct a vertical disc at the origin, to use as the
+ base of this segment.
+ */
+ double r = t->segments[i].thickness / 2;
+ double a = M_PI * 2 * j / arg_slices;
+
+ if (j <= indented_points/2 || j >= arg_slices-indented_points/2)
+ r *= 0.75;
+
+ ring[j].x = r * cos (a);
+ ring[j].y = 0;
+ ring[j].z = r * sin (a);
+
+ /* Then rotate the points by the angle of the current segment. */
+ ROT(ring[j]);
+
+ /* Then move the ring to the base of this segment. */
+ ring[j].x += ctr.x;
+ ring[j].y += ctr.y;
+ ring[j].z += ctr.z;
+ }
+
+
+ /* Compute the normals of the faces on this segment. We do this
+ first so that the normals of the vertexes can be the average
+ of the normals of the faces.
+ #### Uh, except I didn't actually implement that...
+ but it would be a good idea.
+ */
+ if (i > 0)
+ for (j = 0; j <= arg_slices; j++)
+ {
+ int j0 = j % arg_slices;
+ int j1 = (j+1) % arg_slices;
+ norm[j0] = calc_normal (oring[j0], ring[j0], ring[j1]);
+ }
+
+ /* Draw!
+ */
+
+ if (i > 0)
+ {
+ int j;
+ glFrontFace (GL_CCW);
+ glBegin (wire ? GL_LINES : smooth_p ? GL_QUAD_STRIP : GL_QUADS);
+ for (j = 0; j <= arg_slices; j++)
+ {
+ int j0 = j % arg_slices;
+ int j1 = (j+1) % arg_slices;
+
+ if (j <= indented_points/2 || j >= arg_slices-indented_points/2)
+ glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE,
+ t->stripe_color);
+ else
+ glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE,
+ t->tentacle_color);
+
+ glNormal3f (onorm[j0].x, onorm[j0].y, onorm[j0].z);
+ glVertex3f (oring[j0].x, oring[j0].y, oring[j0].z);
+ glNormal3f ( norm[j0].x, norm[j0].y, norm[j0].z);
+ glVertex3f ( ring[j0].x, ring[j0].y, ring[j0].z);
+ if (!smooth_p)
+ {
+ glVertex3f ( ring[j1].x, ring[j1].y, ring[j1].z);
+ glVertex3f (oring[j1].x, oring[j1].y, oring[j1].z);
+ }
+ t->mi->polygon_count++;
+ }
+ glEnd ();
+
+ if (wire)
+ {
+ glBegin (GL_LINE_LOOP);
+ for (j = 0; j < arg_slices; j++)
+ glVertex3f (ring[j].x, ring[j].y, ring[j].z);
+ glEnd();
+ }
+
+ /* Now draw the suckers!
+ */
+ {
+ double seg_length = arg_length / t->nsegments;
+ double sucker_size = arg_thickness / 8;
+ double sucker_spacing = sucker_size * 1.5;
+ int nsuckers = seg_length / sucker_spacing;
+ double oth = cth - t->segments[i-1].th;
+ double ophi = cphi - t->segments[i-1].phi;
+ int k;
+
+ if (nsuckers == 0)
+ {
+ int segs_per_sucker =
+ (int) ((sucker_spacing / seg_length) + 0.5);
+ nsuckers = (i % segs_per_sucker) ? 0 : 1;
+ }
+
+ glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, t->sucker_color);
+
+ for (k = 0; k < nsuckers; k++)
+ {
+ double scale;
+ XYZ p0 = ring[0];
+ XYZ p1 = oring[0];
+ XYZ p;
+ p.x = p0.x + (p1.x - p0.x) * (k + 0.5) / nsuckers;
+ p.y = p0.y + (p1.y - p0.y) * (k + 0.5) / nsuckers;
+ p.z = p0.z + (p1.z - p0.z) * (k + 0.5) / nsuckers;
+
+ glPushMatrix();
+ glTranslatef (p.x, p.y, p.z);
+ glRotatef (ophi * 180 / M_PI, 0, 1, 0);
+ glRotatef (-oth * 180 / M_PI, 1, 0, 0);
+ glRotatef (90, 1, 0, 0);
+
+ { /* Not quite right: this is the slope of the outer edge
+ if the next segment was not tilted at all... If there
+ is any tilt, then the angle of this wall and the
+ opposite wall are very different.
+ */
+ double slope = ((t->segments[i-1].thickness -
+ t->segments[i].thickness) /
+ t->segments[i].length);
+ glRotatef (-45 * slope, 1, 0, 0);
+ }
+
+ scale = t->segments[i].thickness / arg_thickness;
+ scale *= 0.7;
+ glTranslatef (0, 0, -0.15 * sucker_size);
+ glScalef (scale, scale, scale*4);
+ {
+ double off = sucker_size * 1.4;
+ glPushMatrix();
+ glTranslatef (off, 0, 0);
+ glCallList (tc->sucker_list);
+ t->mi->polygon_count += tc->sucker_polys;
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef (-off, 0, 0);
+ glCallList (tc->sucker_list);
+ t->mi->polygon_count += tc->sucker_polys;
+ glPopMatrix();
+ }
+
+ glPopMatrix();
+ }
+ }
+ }
+
+ /* Now draw the end caps.
+ */
+ if (i == 0 || i == t->nsegments-1)
+ {
+ int j;
+ GLfloat ctrz = ctr.z + ((i == 0 ? -1 : 1) *
+ t->segments[i].thickness / 4);
+ glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, t->tentacle_color);
+ glFrontFace (i == 0 ? GL_CCW : GL_CW);
+ glBegin (wire ? GL_LINES : GL_TRIANGLE_FAN);
+ glNormal3f (0, 0, (i == 0 ? -1 : 1));
+ glVertex3f (ctr.x, ctr.y, ctrz);
+ for (j = 0; j <= arg_slices; j++)
+ {
+ int jj = j % arg_slices;
+ glNormal3f (norm[jj].x, norm[jj].y, norm[jj].z);
+ glVertex3f (ring[jj].x, ring[jj].y, ring[jj].z);
+ if (wire) glVertex3f (ctr.x, ctr.y, ctrz);
+ t->mi->polygon_count++;
+ }
+ glEnd();
+ }
+
+ /* Now move to the end of this segment in preparation for the next.
+ */
+ if (i != t->nsegments-1)
+ {
+ p.x = 0;
+ p.y = t->segments[i].length;
+ p.z = 0;
+ ROT (p);
+ ctr.x += p.x;
+ ctr.y += p.y;
+ ctr.z += p.z;
+
+ /* Accumulate the current angle and rotation, to keep track of the
+ rotation of the upcoming segment.
+ */
+ cth += t->segments[i].th;
+ cphi += t->segments[i].phi;
+
+ cth_sin = sin (cth);
+ cth_cos = cos (cth);
+ cphi_sin = sin (cphi);
+ cphi_cos = cos (cphi);
+
+ memcpy (oring, ring, arg_slices * sizeof(*ring));
+ memcpy (onorm, norm, arg_slices * sizeof(*norm));
+ }
+ }
+
+ glPopMatrix();
+
+ free (ring);
+ free (norm);
+ free (oring);
+ free (onorm);
+}
+
+
+static void
+move_tentacle (tentacle *t)
+{
+ /* tentacles_configuration *tc = &tcs[MI_SCREEN(t->mi)]; */
+ GLfloat len = 0;
+ double pos = 0;
+ int i, j;
+ int skip = t->nsegments * (1 - (arg_wiggliness + 0.5));
+ int tick = 0;
+ int last = 0;
+
+ for (i = 0; i < t->nsegments; i++)
+ {
+ if (++tick >= skip || i == t->nsegments-1)
+ {
+ /* randomize the motion of this segment... */
+ double x, y, z;
+ double phi_range = M_PI * 0.8 * arg_flexibility;
+ double th_range = M_PI * 0.9 * arg_flexibility;
+ get_position (t->segments[i].rot, &x, &y, &z, True);
+ t->segments[i].phi = phi_range * (0.5 - y);
+ t->segments[i].th = th_range * (0.5 - z);
+ t->segments[i].length = ((0.8 + ((0.5 - x) * 0.4)) *
+ (arg_length / t->nsegments));
+
+ /* ...and make the previous N segments be interpolated
+ between this one and the previous randomized one. */
+ for (j = last+1; j <= i; j++)
+ {
+ t->segments[j].phi = (t->segments[i].phi / (i - last));
+ t->segments[j].th = (t->segments[i].th / (i - last));
+ t->segments[j].length = (t->segments[i].length);
+ }
+
+ tick = 0;
+ last = i;
+ }
+ len += t->segments[i].length;
+ }
+
+ /* thickness of segment is relative to current position on tentacle
+ (not just the index of the segment). */
+ for (i = 0; i < t->nsegments; i++)
+ {
+ if (i > 0)
+ {
+ double tt = (t->segments[0].thickness * (len - pos) / len);
+ if (tt < 0.001) tt = 0.001;
+ t->segments[i].thickness = tt;
+ }
+ pos += t->segments[i].length;
+ }
+}
+
+
+
+ENTRYPOINT Bool
+tentacles_handle_event (ModeInfo *mi, XEvent *event)
+{
+ tentacles_configuration *tc = &tcs[MI_SCREEN(mi)];
+
+ if (event->xany.type == ButtonPress &&
+ event->xbutton.button == Button1)
+ {
+ tc->button_down_p = True;
+ gltrackball_start (tc->trackball,
+ event->xbutton.x, event->xbutton.y,
+ MI_WIDTH (mi), MI_HEIGHT (mi));
+ return True;
+ }
+ else if (event->xany.type == ButtonRelease &&
+ event->xbutton.button == Button1)
+ {
+ tc->button_down_p = False;
+ return True;
+ }
+ else if (event->xany.type == ButtonPress &&
+ (event->xbutton.button == Button4 ||
+ event->xbutton.button == Button5 ||
+ event->xbutton.button == Button6 ||
+ event->xbutton.button == Button7))
+ {
+ gltrackball_mousewheel (tc->trackball, event->xbutton.button, 10,
+ !!event->xbutton.state);
+ return True;
+ }
+ else if (event->xany.type == MotionNotify &&
+ tc->button_down_p)
+ {
+ gltrackball_track (tc->trackball,
+ event->xmotion.x, event->xmotion.y,
+ MI_WIDTH (mi), MI_HEIGHT (mi));
+ return True;
+ }
+
+ return False;
+}
+
+
+static void
+parse_color (ModeInfo *mi, const char *name, const char *s, GLfloat *a)
+{
+ XColor c;
+ a[3] = 1.0; /* alpha */
+
+ if (! XParseColor (MI_DISPLAY(mi), MI_COLORMAP(mi), s, &c))
+ {
+ fprintf (stderr, "%s: can't parse %s color %s", progname, name, s);
+ exit (1);
+ }
+ a[0] = c.red / 65536.0;
+ a[1] = c.green / 65536.0;
+ a[2] = c.blue / 65536.0;
+}
+
+
+ENTRYPOINT void
+init_tentacles (ModeInfo *mi)
+{
+ tentacles_configuration *tc;
+ int wire = MI_IS_WIREFRAME(mi);
+ int i;
+
+ if (!tcs) {
+ tcs = (tentacles_configuration *)
+ calloc (MI_NUM_SCREENS(mi), sizeof (tentacles_configuration));
+ if (!tcs) {
+ fprintf(stderr, "%s: out of memory\n", progname);
+ exit(1);
+ }
+
+ tc = &tcs[MI_SCREEN(mi)];
+ }
+
+ tc = &tcs[MI_SCREEN(mi)];
+
+ tc->glx_context = init_GL(mi);
+
+ reshape_tentacles (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+
+ if (!wire)
+ {
+ GLfloat pos[4] = {1.0, 1.0, 1.0, 0.0};
+ GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0};
+ GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0};
+ GLfloat spc[4] = {0.0, 1.0, 1.0, 1.0};
+
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+
+ glLightfv(GL_LIGHT0, GL_POSITION, pos);
+ glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, dif);
+ glLightfv(GL_LIGHT0, GL_SPECULAR, spc);
+ }
+
+ tc->trackball = gltrackball_init ();
+
+ tc->left_p = !(random() % 5);
+
+ if (arg_segments < 2) arg_segments = 2;
+ if (arg_slices < 3) arg_slices = 3;
+ if (arg_thickness < 0.1) arg_thickness = 0.1;
+ if (arg_wiggliness < 0) arg_wiggliness = 0;
+ if (arg_wiggliness > 1) arg_wiggliness = 1;
+ if (arg_flexibility < 0) arg_flexibility = 0;
+ if (arg_flexibility > 1) arg_flexibility = 1;
+
+ parse_color (mi, "tentacleColor", arg_color, tc->tentacle_color);
+ parse_color (mi, "stripeColor", arg_stripe, tc->stripe_color);
+ parse_color (mi, "suckerColor", arg_sucker, tc->sucker_color);
+
+ for (i = 0; i < MI_COUNT(mi); i++)
+ move_tentacle (make_tentacle (mi, i, MI_COUNT(mi)));
+
+ tc->sucker_list = glGenLists (1);
+ glNewList (tc->sucker_list, GL_COMPILE);
+ { GLfloat s = arg_thickness / 5; glScalef (s, s, s); }
+ tc->sucker_polys = unit_torus (0.5,
+ MIN(8, arg_slices/6),
+ MIN(12, arg_slices/3),
+ MI_IS_WIREFRAME(mi));
+ glEndList();
+}
+
+
+ENTRYPOINT void
+draw_tentacles (ModeInfo *mi)
+{
+ tentacles_configuration *tc = &tcs[MI_SCREEN(mi)];
+ int wire = MI_IS_WIREFRAME(mi);
+ Display *dpy = MI_DISPLAY(mi);
+ Window window = MI_WINDOW(mi);
+ int i;
+
+ if (!tc->glx_context)
+ return;
+
+ glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(tc->glx_context));
+
+ glShadeModel(GL_SMOOTH);
+
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_NORMALIZE);
+ glEnable(GL_CULL_FACE);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glPushMatrix ();
+
+
+# if 1
+ glScalef (3, 3, 3);
+# else
+ glPushMatrix();
+ { GLfloat s = 8.7/1600; glScalef(s,s,s); }
+ glTranslatef(-800,-514,0);
+ if (!wire) glDisable(GL_LIGHTING);
+ glBegin(GL_LINE_LOOP);
+ glVertex3f(0,0,0);
+ glVertex3f(0,1028,0);
+ glVertex3f(1600,1028,0);
+ glVertex3f(1600,0,0);
+ glEnd();
+ if (!wire) glEnable(GL_LIGHTING);
+ glPopMatrix();
+# endif
+
+ gltrackball_rotate (tc->trackball);
+
+ mi->polygon_count = 0;
+
+ if (debug_p)
+ {
+ if (!wire) glDisable(GL_LIGHTING);
+ glBegin(GL_LINES);
+ glVertex3f(-0.5, 0, 0); glVertex3f(0.5, 0, 0);
+ glVertex3f(0, -0.5, 0); glVertex3f(0, 0.5, 0);
+ glEnd();
+ if (!wire) glEnable(GL_LIGHTING);
+ }
+ else if (tc->left_p)
+ {
+ glRotatef ( 45, 0, 1, 0); /* upper left */
+ glRotatef ( 45, 1, 0, 0);
+ glRotatef (-70, 0, 0, 1);
+ glTranslatef (0, -2, -4.5);
+ }
+ else
+ {
+ glRotatef (-45, 0, 1, 0); /* upper right */
+ glRotatef ( 45, 1, 0, 0);
+ glRotatef ( 70, 0, 0, 1);
+ glTranslatef (0, -2, -4.5);
+ }
+
+ if (!tc->button_down_p)
+ for (i = 0; i < tc->ntentacles; i++)
+ move_tentacle (tc->tentacles[i]);
+
+ for (i = 0; i < tc->ntentacles; i++)
+ draw_tentacle (tc->tentacles[i]);
+
+ glPopMatrix ();
+
+ if (mi->fps_p) do_fps (mi);
+ glFinish();
+
+ glXSwapBuffers(dpy, window);
+}
+
+XSCREENSAVER_MODULE_2 ("SkyTentacles", skytentacles, tentacles)
+
+#endif /* USE_GL */
--- /dev/null
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+skytentacles - 3D tentacles from the sky!
+.SH SYNOPSIS
+.B skytentacles
+[\-display \fIhost:display.screen\fP]
+[\-visual \fIvisual\fP]
+[\-window]
+[\-root]
+[\-delay \fIint\fP]
+[\-speed \fIratio\fP]
+[\-count \fIint\fP]
+[\-slices \fIint\fP]
+[\-length \fIfloat\fP]
+[\-wiggliness \fIratio\fP]
+[\-flexibility \fIratio\fP]
+[\-color \fIcolor\fP]
+[\-stripe\-color \fIcolor\fP]
+[\-sucker\-color \fIcolor\fP]
+[\-segments \fIint\fP]
+[\-thickness \fIratio\fP]
+[\-no\-smooth]
+[\-fps]
+.SH DESCRIPTION
+There is a tentacled abomination in the sky. From above you it devours.
+.SH OPTIONS
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use. Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-window
+Draw on a newly-created window. This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-delay \fIint\fP
+Delay between frames, in microseconds. Default 30000.
+.TP 8
+.B \-speed \fIratio\fP
+Less than 1 for slower, greater than 1 for faster. Default 1.
+.TP 8
+.B \-count \fIint\fP
+How many tentacles. Default 8.
+.TP 8
+.B \-thickness \fIratio\fP
+Less than 1 for thinner tentacles, greater than 1 for thicker. Default 1.
+.TP 8
+.B \-length \fIratio\fP
+Length of the tentacles. Default 9.
+.TP 8
+.B \-wiggliness \fIratio\fP
+A measure of how bendy the tentacles are. Smaller numbers result in
+smoother flexing; larger numbers make it "crinkly". Default 0.35.
+.TP 8
+.B \-flexibility \fIratio\fP
+Another measure of how bendy the tentacles are. Smaller numbers
+result in straighter tentacles; larger numbers result in more extreme
+curves. Default 0.35.
+.TP 8
+.B \-color \fIcolor\fP
+.TP 8
+.B \-stripe\-color \fIcolor\fP
+.TP 8
+.B \-sucker\-color \fIcolor\fP
+The colors of the various parts of the tentacle. Default green
+with a redish stripe.
+.TP 8
+.B \-slices \fIint\fP
+.TP 8
+.B \-segments \fIint\fP
+Larger numbers increase number of polygons in the object mesh.
+Default 32.
+.TP 8
+.B \-no\-smooth
+Make the tentacles appear faceted instead of smooth.
+.TP 8
+.B \-fps | \-no-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 2008 by Jamie Zawinski. Permission to use, copy, modify,
+distribute, and sell this software and its documentation for any purpose is
+hereby granted without fee, provided that the above copyright notice appear
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation. No representations are made about the
+suitability of this software for any purpose. It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski.
-/* sphere, Copyright (c) 2002 Paul Bourke <pbourke@swin.edu.au>
+/* sphere, Copyright (c) 2002, 2008 Paul Bourke <pbourke@swin.edu.au>
* Utility function to create a unit sphere in GL.
*
* Permission to use, copy, modify, distribute, and sell this software and its
typedef struct { GLfloat x, y, z; } XYZ;
-void
+int
unit_sphere (int stacks, int slices, int wire_p)
{
+ int polys = 0;
int i,j;
double theta1, theta2, theta3;
XYZ e, p;
glBegin (GL_POINTS);
glVertex3f (c.x, c.y, c.z);
glEnd();
- return;
+ return 1;
}
glFrontFace(GL_CW);
2*j / (double)stacks2);
glVertex3f (p.x, p.y, p.z);
if (wire_p) lb = p;
+ polys++;
}
glEnd();
}
+ return polys;
}
-/* tube, Copyright (c) 2001 Jamie Zawinski <jwz@jwz.org>
+/* sphere, Copyright (c) 2001-2008 Jamie Zawinski <jwz@jwz.org>
* Utility function to create a unit sphere in GL.
*
* Permission to use, copy, modify, distribute, and sell this software and its
#ifndef __SPHERE_H__
#define __SPHERE_H__
-/* Creates a diamteter 1 sphere at 0, 0, 0.
+/* Creates a diameter 1 sphere at 0, 0, 0.
stacks = number of north/south divisions (latitude)
slices = number of clockwise/counterclockwise divisions (longitude)
+ Returns number of polygons used.
*/
-extern void unit_sphere (int stacks, int slices, int wire_p);
+extern int unit_sphere (int stacks, int slices, int wire_p);
#endif /* __SPHERE_H__ */
--- /dev/null
+#define atm_width 223
+#define atm_height 130
+static unsigned char atm_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x3f,0xfc,0x0f,0xfc,0x0f,0xfc,0x0f,
+ 0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x3c,0x3c,0x0f,0x3c,0x0f,0x3c,0x0f,0x3c,0xfc,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x3c,0x30,0x0f,0x3f,0x0f,0x3f,0x0f,0x3f,0xff,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x3c,0x03,0xcf,0x3f,0xcf,0x3f,0xcf,0x3f,0xf0,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,
+ 0x03,0xff,0x3c,0xff,0x3c,0xff,0x3c,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x03,0x3f,
+ 0x3c,0x3f,0x3c,0x3f,0x3c,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x0f,0x3c,0x0f,
+ 0x3c,0x0f,0x3c,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x0f,0x3c,0x0f,0x3c,0x0f,
+ 0x3c,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xfc,0x0f,0xfc,0x0f,0xfc,0x0f,0xff,
+ 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xe0,0x07,0x1e,0x78,0xfe,0x7f,0x00,0x00,0xe0,0x07,0xff,0x3f,0x00,0x00,0xfc,
+ 0x0f,0xff,0x3f,0xff,0x0f,0x0f,0x3c,0xfc,0x03,0xf0,0x0f,0xff,0x3f,0x78,0x1e,
+ 0x1e,0x78,0xe2,0x61,0x00,0x00,0x78,0x1e,0x3c,0x3c,0x00,0x00,0x0f,0x3c,0x7c,
+ 0x3c,0x3c,0x3c,0x0f,0x3c,0xf0,0x00,0x3c,0x3c,0x3c,0x3c,0x1e,0x78,0x1e,0x78,
+ 0xe0,0x01,0x00,0x00,0x1e,0x78,0x3c,0x30,0x00,0x00,0x0f,0x3c,0x3c,0x30,0x3c,
+ 0x3c,0x0f,0x3c,0xf0,0x00,0x0f,0x30,0x3c,0x30,0x1e,0x78,0x1e,0x78,0xe0,0x01,
+ 0x00,0x00,0x1e,0x78,0x3c,0x03,0x00,0x00,0x3c,0x00,0x3c,0x03,0x3c,0x3c,0x0f,
+ 0x3c,0xf0,0x00,0x0f,0x00,0x3c,0x03,0x1e,0x78,0x1e,0x78,0xe0,0x01,0x00,0x00,
+ 0x1e,0x78,0xfc,0x03,0x00,0x00,0xf0,0x03,0xfc,0x03,0xfc,0x0f,0x0f,0x3c,0xf0,
+ 0x00,0x0f,0x00,0xfc,0x03,0x1e,0x78,0x1e,0x78,0xe0,0x01,0x00,0x00,0x1e,0x78,
+ 0x3c,0x03,0x00,0x00,0x00,0x0f,0x3c,0x03,0x3c,0x0e,0x0f,0x3c,0xf0,0x00,0x0f,
+ 0x00,0x3c,0x03,0x1e,0x78,0x1e,0x78,0xe0,0x01,0x00,0x00,0x1e,0x78,0x3c,0x00,
+ 0x00,0x00,0x0f,0x3c,0x3c,0x30,0x3c,0x1c,0x1c,0x0e,0xf0,0x00,0x0f,0x30,0x3c,
+ 0x30,0x78,0x1e,0xfe,0x7f,0xe0,0x01,0x00,0x00,0x78,0x1e,0x3c,0x00,0x00,0x00,
+ 0x0f,0x3c,0x3c,0x3c,0x3c,0x3c,0xf0,0x07,0xf0,0x00,0x3c,0x3c,0x3c,0x3c,0xe0,
+ 0x07,0xf8,0x1f,0xf8,0x07,0x00,0x00,0xe0,0x07,0xff,0x00,0x00,0x00,0xfc,0x0f,
+ 0xff,0x3f,0x3f,0x3c,0xc0,0x00,0xfc,0x03,0xf0,0x0f,0xff,0x3f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xe0,0x1f,0xc0,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0xc0,0x00,0xff,0x3f,0xff,
+ 0x3f,0xfe,0x3f,0x0f,0x3c,0xff,0x03,0xc0,0x00,0x0f,0x3c,0xff,0x3f,0x78,0x78,
+ 0xf0,0x03,0x3c,0x00,0x3c,0x00,0x00,0x00,0xf0,0x03,0xf1,0x30,0xf1,0x30,0x7c,
+ 0x3c,0x3f,0x3c,0x3c,0x0f,0xf0,0x03,0x3f,0x3c,0xf1,0x30,0x1e,0x60,0x3c,0x0f,
+ 0x3c,0x00,0x3c,0x00,0x00,0x00,0x3c,0x0f,0xf0,0x00,0xf0,0x00,0x3c,0x30,0xff,
+ 0x3c,0x3c,0x3c,0x3c,0x0f,0xff,0x3c,0xf0,0x00,0x1e,0x00,0x0f,0x3c,0x3c,0x00,
+ 0x3c,0x00,0x00,0x00,0x0f,0x3c,0xf0,0x00,0xf0,0x00,0x3c,0x03,0xff,0x3f,0x3c,
+ 0x3c,0x0f,0x3c,0xff,0x3f,0xf0,0x00,0x1e,0x00,0x0f,0x3c,0x3c,0x00,0x3c,0x00,
+ 0x00,0x00,0x0f,0x3c,0xf0,0x00,0xf0,0x00,0xfc,0x03,0xcf,0x3f,0x3c,0x3c,0x0f,
+ 0x3c,0xcf,0x3f,0xf0,0x00,0x1e,0x00,0xff,0x3f,0x3c,0x00,0x3c,0x00,0x00,0x00,
+ 0xff,0x3f,0xf0,0x00,0xf0,0x00,0x3c,0x03,0x0f,0x3f,0x3c,0x3c,0xff,0x3f,0x0f,
+ 0x3f,0xf0,0x00,0x1e,0x60,0x0f,0x3c,0x3c,0x30,0x3c,0x30,0x00,0x00,0x0f,0x3c,
+ 0xf0,0x00,0xf0,0x00,0x3c,0x30,0x0f,0x3c,0x3c,0x3c,0x0f,0x3c,0x0f,0x3c,0xf0,
+ 0x00,0x78,0x78,0x0f,0x3c,0x3c,0x3c,0x3c,0x3c,0x00,0x00,0x0f,0x3c,0xf0,0x00,
+ 0xf0,0x00,0x3c,0x3c,0x0f,0x3c,0x3c,0x0f,0x0f,0x3c,0x0f,0x3c,0xf0,0x00,0xe0,
+ 0x1f,0x0f,0x3c,0xff,0x3f,0xff,0x3f,0x00,0x00,0x0f,0x3c,0xfc,0x03,0xfc,0x03,
+ 0xfe,0x3f,0x0f,0x3c,0xff,0x03,0x0f,0x3c,0x0f,0x3c,0xfc,0x03,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
--- /dev/null
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+lcdscrub - attempt to repair burn-in on LCD screens
+.SH SYNOPSIS
+.B deluxe
+[\-display \fIhost:display.screen\fP]
+[\-visual \fIvisual\fP]
+[\-window]
+[\-root]
+[\-delay \fInumber\fP]
+[\-spread \fInumber\fP]
+[\-cycles \fInumber\fP]
+.SH DESCRIPTION
+This screen saver is not meant to look pretty, but rather, to
+repair burn-in on LCD monitors.
+
+Believe it or not, screen burn is not a thing of the past.
+It can happen to LCD screens pretty easily, even in this modern age.
+However, leaving the screen on and displaying high contrast images
+can often repair the damage. That's what this screen saver does.
+
+See also:
+
+ http://docs.info.apple.com/article.html?artnum=88343
+ http://toastycode.com/blog/2008/02/05/lcd-scrub/
+.SH OPTIONS
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use. Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-window
+Draw on a newly-created window. This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-delay \fInumber\fP
+Per-frame delay, in microseconds. Default: 1000000 (1 second.).
+.TP 8
+.B \-spread \fInumber\fP
+Distance between lines. Default 8.
+.TP 8
+.B \-cycles \fInumber\fP
+Steps before switching display mode. Default 60.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 2008 by Jamie Zawinski. Permission to use, copy, modify,
+distribute, and sell this software and its documentation for any purpose is
+hereby granted without fee, provided that the above copyright notice appear
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation. No representations are made about the
+suitability of this software for any purpose. It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Inspired by the like-named program by Daniel Sandler.
+
+Written by Jamie Zawinski.
.TP 8
.B \-delay \fImicroseconds\fP
How much of a delay should be introduced between steps of the animation.
-Default 100000, or about 1/10th second.
+Default 10000.
.SH ENVIRONMENT
.PP
.TP 8
{
struct state *st = (struct state *) calloc (1, sizeof(*st));
int i;
- /*char *fontname = "-*-new century schoolbook-*-r-*-*-*-380-*-*-*-*-*-*"; */
- char *fontname = "-*-courier-*-r-*-*-*-380-*-*-*-*-*-*";
+ const char *levelfont = "-*-courier-*-r-*-*-*-380-*-*-*-*-*-*";
+ const char *scorefont = "-*-times-*-r-*-*-*-180-*-*-*-*-*-*";
XGCValues gcv;
XWindowAttributes xgwa;
if (st->lrate < 0) st->lrate = 2;
st->startlrate = st->lrate;
- if (!fontname || !*fontname)
- fprintf (stderr, "%s: no font specified.\n", progname);
- st->font = XLoadQueryFont(st->dpy, fontname);
- if (!st->font)
- fprintf (stderr, "%s: could not load font %s.\n", progname, fontname);
+ st->font = XLoadQueryFont(st->dpy, levelfont);
+ if (!st->font) {
+ fprintf (stderr, "%s: could not load font %s.\n", progname, levelfont);
+ st->font = XLoadQueryFont(st->dpy, scorefont);
+ if (! st->font)
+ st->font = XLoadQueryFont(st->dpy, "fixed");
+ if (! st->font) abort();
+ }
- if (!(st->scoreFont = XLoadQueryFont(st->dpy, "-*-times-*-r-*-*-*-180-*-*-*-*-*-*")))
- fprintf(stderr, "%s: Can't load Times font.", progname);
+ st->scoreFont = XLoadQueryFont(st->dpy, scorefont);
+ if (!st->scoreFont) {
+ fprintf (stderr, "%s: could not load font %s.\n", progname, scorefont);
+ st->scoreFont = XLoadQueryFont(st->dpy, levelfont);
+ if (! st->scoreFont)
+ st->scoreFont = XLoadQueryFont(st->dpy, "fixed");
+ if (! st->scoreFont) abort();
+ }
for (i = 0; i < kMaxMissiles; i++)
st->missile[i].alive = 0;
int draw_count;
int iterations, delay, rate, box, oily, stir, fluidity;
+ int duration;
+ time_t start_time;
void (*draw_transparent) (struct state *st, short *src);
st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
st->window, 0, 0);
+ st->start_time = time ((time_t) 0);
} else {
XGCValues gcv;
st->window = win;
st->iterations = 0;
st->delay = get_integer_resource(disp, "delay", "Integer");
+ st->duration = get_integer_resource (st->dpy, "duration", "Seconds");
st->rate = get_integer_resource(disp, "rate", "Integer");
st->box = get_integer_resource(disp, "box", "Integer");
st->oily = get_boolean_resource(disp, "oily", "Boolean");
#endif /* HAVE_XSHM_EXTENSION */
st->light = get_integer_resource(disp, "light", "Integer");
+ if (st->delay < 0) st->delay = 0;
+ if (st->duration < 1) st->duration = 1;
if (st->fluidity <= 1) st->fluidity = 1;
if (st->fluidity > 16) st->fluidity = 16; /* 16 = sizeof(short) */
if (st->light < 0) st->light = 0;
if (! st->img_loader) { /* just finished */
XWindowAttributes xgwa;
XGetWindowAttributes(st->dpy, st->window, &xgwa);
+ st->start_time = time ((time_t) 0);
st->orig_map = XGetImage (st->dpy, st->window, 0, 0,
xgwa.width, xgwa.height,
~0L, ZPixmap);
return st->delay;
}
+ if (!st->img_loader &&
+ st->start_time + st->duration < time ((time_t) 0)) {
+ XWindowAttributes xgwa;
+ XGetWindowAttributes(st->dpy, st->window, &xgwa);
+ st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
+ st->window, 0, 0);
+ st->start_time = time ((time_t) 0);
+ return st->delay;
+ }
+
if (st->rate > 0 && (st->iterations % st->rate) == 0)
add_drop(st, ripple_blob, -SPLASH);
if (st->stir)
"*colors: 200",
"*dontClearRoot: True",
"*delay: 50000",
+ "*duration: 120",
"*rate: 5",
"*box: 0",
"*water: False",
{ "-colors", ".colors", XrmoptionSepArg, 0},
{ "-colours", ".colors", XrmoptionSepArg, 0},
{"-delay", ".delay", XrmoptionSepArg, 0},
+ {"-duration", ".duration", XrmoptionSepArg, 0 },
{"-rate", ".rate", XrmoptionSepArg, 0},
{"-box", ".box", XrmoptionSepArg, 0},
{"-water", ".water", XrmoptionNoArg, "True"},
[\-window]
[\-root]
[\-delay \fInumber\fP]
+[\-duration \fIsecs\fP]
[\-rate \fInumber\fP]
[\-fluidity \fInumber\fP]
[\-light \fInumber\fP]
.B \-delay \fInumber\fP
Per-frame delay, in microseconds. Default: 50000 (0.05 seconds.).
.TP 8
+.B \-duration \fIseconds\fP
+How long to run before loading a new image. Default 120 seconds.
+.TP 8
.B \-rate \fInumber\fP
Drizzle. 1 - 100. Default: 5.
.TP 8
int sweep;
int delay;
int anim;
+ int duration;
+ time_t start_time;
async_load_state *img_loader;
{
int i;
+ st->start_time = time ((time_t) 0);
st->zoom_box = calloc (st->num_zoom, sizeof (struct zoom_area *));
for (i = 0; i < st->num_zoom; i++) {
st->zoom_box[i] = create_zoom (st);
return st->delay;
}
+ if (!st->img_loader &&
+ st->start_time + st->duration < time ((time_t) 0)) {
+ XWindowAttributes xgwa;
+ XGetWindowAttributes(st->dpy, st->window, &xgwa);
+ st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
+ st->window, 0, 0);
+ st->start_time = time ((time_t) 0);
+ return st->delay;
+ }
+
for (i = 0; i < st->num_zoom; i++) {
if (st->move || st->sweep)
update_position (st->zoom_box[i]);
st->anim = get_boolean_resource (st->dpy, "anim", "Boolean");
st->delay = get_integer_resource (st->dpy, "delay", "Integer");
+ st->duration = get_integer_resource (st->dpy, "duration", "Seconds");
+ if (st->delay < 0) st->delay = 0;
+ if (st->duration < 1) st->duration = 1;
/* In sweep or static mode, we want only one box */
if (st->sweep || !st->anim)
if (!st->anim)
st->sweep = 0;
+ st->start_time = time ((time_t) 0);
+
setup_X (st);
return st;
"*mode: stationary",
"*numboxes: 2",
"*delay: 10",
+ "*duration: 120",
0
};
{ "-anim", ".anim", XrmoptionNoArg, "True" },
{ "-no-anim", ".anim", XrmoptionNoArg, "False" },
{ "-delay", ".delay", XrmoptionSepArg, 0 },
+ {"-duration", ".duration", XrmoptionSepArg, 0 },
{ "-n", ".numboxes", XrmoptionSepArg, 0 },
{ 0, 0, 0, 0 }
};
[\-display \fIhost:display.screen\fP]
[\-move | \-no\-move]
[\-delay \fImillisecs\fP]
+[\-duration \fIsecs\fP]
[\-n \fIcount\fP]
[\-shm | \-no\-shm]
[\-window] [\-root] [\-install] [\-visual \fIvisual\fP]
How much of a delay should be introduced between steps of the animation.
Default 10, or about 1/100th second.
.TP 8
+.B \-duration \fIseconds\fP
+How long to run before loading a new image. Default 120 seconds.
+.TP 8
.B \-move
Make the rectangles should wander around the screen.
.TP 8
window = VirtualRootWindowOfScreen (XtScreen (toplevel));
XtDestroyWidget (toplevel);
XGetWindowAttributes (dpy, window, &xgwa);
+ /* With RANDR, the root window can resize! */
+ XSelectInput (dpy, window, xgwa.your_event_mask | StructureNotifyMask);
visual_warning (xgwa.screen, window, xgwa.visual, xgwa.colormap, False);
}
else
-/* xscreensaver, Copyright (c) 1992-2006 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1992-2008 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
int xoff, yoff;
int grid_w, grid_h;
int delay, delay2;
+ int duration;
GC gc;
unsigned long fg, bg;
int max_width, max_height;
int draw_last;
int draw_initted;
+ time_t start_time;
async_load_state *img_loader;
};
XGetWindowAttributes (st->dpy, st->window, &xgwa);
st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
st->window, 0, 0);
+ st->start_time = time ((time_t) 0);
visual = xgwa.visual;
st->max_width = xgwa.width;
st->delay = get_integer_resource (st->dpy, "delay", "Integer");
st->delay2 = get_integer_resource (st->dpy, "delay2", "Integer");
+ st->duration = get_integer_resource (st->dpy, "duration", "Seconds");
st->grid_size = get_integer_resource (st->dpy, "gridSize", "Integer");
st->pix_inc = get_integer_resource (st->dpy, "pixelIncrement", "Integer");
if (st->delay < 0) st->delay = 0;
if (st->delay2 < 0) st->delay2 = 0;
+ if (st->duration < 1) st->duration = 1;
if (st->pix_inc < 1) st->pix_inc = 1;
if (st->grid_size < 1) st->grid_size = 1;
if (st->img_loader) /* still loading */
{
st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 0);
- if (! st->img_loader) /* just finished */
+ if (! st->img_loader) { /* just finished */
+ st->start_time = time ((time_t) 0);
draw_grid (st);
+ }
return st->delay;
}
+ if (!st->img_loader &&
+ st->start_time + st->duration < time ((time_t) 0)) {
+ XWindowAttributes xgwa;
+ XGetWindowAttributes(st->dpy, st->window, &xgwa);
+ st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
+ st->window, 0, 0);
+ st->start_time = time ((time_t) 0);
+ st->draw_initted = 0;
+ return st->delay;
+ }
+
if (! st->draw_initted)
{
if (!slidescreen_draw_early (st))
"*internalBorderWidth: 4",
"*delay: 50000",
"*delay2: 1000000",
+ "*duration: 120",
0
};
{ "-increment", ".pixelIncrement", XrmoptionSepArg, 0 },
{ "-delay", ".delay", XrmoptionSepArg, 0 },
{ "-delay2", ".delay2", XrmoptionSepArg, 0 },
+ {"-duration", ".duration", XrmoptionSepArg, 0 },
{ 0, 0, 0, 0 }
};
[\-increment \fIpixels\fP]
[\-delay \fIusecs\fP]
[\-delay2 \fIusecs\fP]
+[\-duration \fIsecs\fP]
[\-window]
[\-root]
[\-install]
How much of a delay should be introduced between the end of the motion of
one segment and the beginning of the motion of another. Default 1000000,
which is one second.
+.TP 8
+.B \-duration \fIseconds\fP
+How long to run before loading a new image. Default 120 seconds.
.SH ENVIRONMENT
.PP
.TP 8
struct state {
Display *dpy;
Window window;
+ Screen *screen;
int sizex, sizey; /* screen size */
- int delay; /* in case it's too fast... */
+ int delay;
+ int duration;
+ time_t start_time;
+
GC window_gc;
#ifdef DEBUG
GC white_gc;
st->first_p = True;
XGetWindowAttributes (st->dpy, st->window, &xgwa);
+ st->screen = xgwa.screen;
st->sizex = xgwa.width;
st->sizey = xgwa.height;
cmap = xgwa.colormap;
/* read parameters, keep em sane */
st->delay = get_integer_resource (st->dpy, "delay", "Integer");
if (st->delay < 1) st->delay = 1;
+ st->duration = get_integer_resource (st->dpy, "duration", "Seconds");
+ if (st->duration < 1) st->duration = 1;
st->radius = get_integer_resource (st->dpy, "radius", "Integer");
if (st->radius < 0) st->radius = 125;
#endif
st->window_gc = XCreateGC(st->dpy, st->window, gcflags, &gcv);
- /* grab screen to pixmap */
st->pm = XCreatePixmap(st->dpy, st->window, st->sizex, st->sizey, xgwa.depth);
XClearWindow(st->dpy, st->window);
clip_pm = XCreatePixmap(st->dpy, st->window, st->radius*4, st->radius*4, 1);
st->img_loader = load_image_async_simple (0, xgwa.screen, st->window, st->pm,
0, 0);
+ st->start_time = time ((time_t) 0);
gcv.foreground = 0L;
clip_gc = XCreateGC(st->dpy, clip_pm, gcflags, &gcv);
if (st->img_loader) /* still loading */
{
st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 0);
+ if (! st->img_loader) { /* just finished */
+ st->start_time = time ((time_t) 0);
+ }
return;
}
+ if (!st->img_loader &&
+ st->start_time + st->duration < time ((time_t) 0)) {
+ st->img_loader = load_image_async_simple (0, st->screen, st->window,
+ st->pm, 0, 0);
+ return;
+ }
+
#define nrnd(x) (random() % (x))
st->oldx = st->x;
#endif
"*delay: 10000",
+ "*duration: 120",
"*radius: 125",
0
};
static XrmOptionDescRec spotlight_options [] = {
{ "-delay", ".delay", XrmoptionSepArg, 0 },
+ { "-duration", ".duration", XrmoptionSepArg, 0 },
{ "-radius", ".radius", XrmoptionSepArg, 0 },
{ 0, 0, 0, 0 }
};
.B spotlight
[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP]
[\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install]
-[\-visual \fIvisual\fP] [\-delay \fIusecs\fP] [\-radius \fIpixels\fP]
+[\-visual \fIvisual\fP]
+[\-delay \fIusecs\fP]
+[\-duration \fIsecs\fP]
+[\-radius \fIpixels\fP]
.SH DESCRIPTION
The \fIspotlight\fP program takes an image and exposes small sections
of it as if through a wandering spotlight beam.
.B \-delay \fImicroseconds\fP
Slow it down.
.TP 8
+.B \-duration \fIseconds\fP
+How long to run before loading a new image. Default 120 seconds.
+.TP 8
.B \-radius \fIpixels\fP
Radius of the spotlight in pixels.
.SH ENVIRONMENT
Window window;
int delay; /* delay (usec) between iterations */
+ int duration; /* time (sec) before loading new image */
int maxColumns; /* the maximum number of columns of tiles */
int maxRows; /* the maximum number of rows of tiles */
int tileSize; /* the size (width and height) of a tile */
Tile **sortedTiles; /* array of tile pointers, sorted by zoom */
int tileCount; /* total number of tiles */
+ time_t start_time;
async_load_state *img_loader;
Bool useShm; /* whether or not to use xshm */
*/
/* grab the source image */
-static void grabImage_start (struct state *st, XWindowAttributes *xwa)
+static void
+grabImage_start (struct state *st, XWindowAttributes *xwa)
{
XFillRectangle (st->dpy, st->window, st->backgroundGC, 0, 0,
st->windowWidth, st->windowHeight);
XGetImage (st->dpy, st->window, 0, 0, st->windowWidth, st->windowHeight,
~0L, ZPixmap);
+ st->start_time = time ((time_t) 0);
st->img_loader = load_image_async_simple (0, xwa->screen, st->window,
st->window, 0, 0);
}
-static void grabImage_done (struct state *st)
+static void
+grabImage_done (struct state *st)
{
- XWindowAttributes xwa;
- XGetWindowAttributes (st->dpy, st->window, &xwa);
+ XWindowAttributes xwa;
+ XGetWindowAttributes (st->dpy, st->window, &xwa);
+ st->start_time = time ((time_t) 0);
+ if (st->sourceImage) XDestroyImage (st->sourceImage);
st->sourceImage = XGetImage (st->dpy, st->window, 0, 0, st->windowWidth, st->windowHeight,
~0L, ZPixmap);
-#ifdef HAVE_XSHM_EXTENSION
+ if (st->workImage) XDestroyImage (st->workImage);
st->workImage = NULL;
+
+#ifdef HAVE_XSHM_EXTENSION
if (st->useShm)
{
st->workImage = create_xshm_image (st->dpy, xwa.visual, xwa.depth,
return st->delay;
}
+ if (!st->img_loader &&
+ st->start_time + st->duration < time ((time_t) 0)) {
+ XWindowAttributes xgwa;
+ XGetWindowAttributes (st->dpy, st->window, &xgwa);
+ grabImage_start (st, &xgwa);
+ return st->delay;
+ }
modelEvents (st);
updateModel (st);
problems = 1;
}
+ st->duration = get_integer_resource (st->dpy, "duration", "Seconds");
+ if (st->duration < 1) st->duration = 1;
+
st->eventChance = get_float_resource (st->dpy, "eventChance", "Double");
if ((st->eventChance < 0.0) || (st->eventChance > 1.0))
{
"*borderColor: blue",
"*borderWidth: 3",
"*delay: 10000",
+ "*duration: 120",
"*eventChance: 0.01",
"*friction: 0.05",
"*maxColumns: 0",
{ "-border-color", ".borderColor", XrmoptionSepArg, 0 },
{ "-border-width", ".borderWidth", XrmoptionSepArg, 0 },
{ "-delay", ".delay", XrmoptionSepArg, 0 },
+ { "-duration", ".duration", XrmoptionSepArg, 0 },
{ "-event-chance", ".eventChance", XrmoptionSepArg, 0 },
{ "-friction", ".friction", XrmoptionSepArg, 0 },
{ "-max-columns", ".maxColumns", XrmoptionSepArg, 0 },
twang - pluck pieces of the screen
.SH SYNOPSIS
.B twang
-[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-shm] [\-no-shm] [\-delay \fImicroseconds\fP] [\-border-color \fIcolor\fP] [\-border-width \fIinteger\fP] [\-event-chance \fIfraction\fP] [\-friction \fIfraction\fP] [\-springiness \fIfraction\fP] [\-tile-size \fIinteger\fP] [\-transference \fIfraction\fP]
+[\-display \fIhost:display.screen\fP]
+[\-foreground \fIcolor\fP]
+[\-background \fIcolor\fP]
+[\-window]
+[\-root]
+[\-mono]
+[\-install]
+[\-visual \fIvisual\fP]
+[\-shm]
+[\-no-shm]
+[\-delay \fIusecs\fP]
+[\-duration \fIsecs\fP]
+[\-border-color \fIcolor\fP]
+[\-border-width \fIinteger\fP]
+[\-event-chance \fIfraction\fP]
+[\-friction \fIfraction\fP]
+[\-springiness \fIfraction\fP]
+[\-tile-size \fIinteger\fP]
+[\-transference \fIfraction\fP]
.SH DESCRIPTION
\fITwang\fP divides the screen into equal-sized tiles, and then plucks
them in various ways. Tiles are affected by their neighbors, so waves
The interframe delay, in microseconds. Defaults to 10000, resource
\fIdelay\fP.
.TP 8
+.B \-duration \fIseconds\fP
+How long to run before loading a new image. Default 120 seconds.
+.TP 8
.B \-border-color \fIcolor\fP
Color of the border surrounding each tile. Defaults to blue, resource
\fIborderColor\fP.
my $progname = $0; $progname =~ s@.*/@@g;
-my $version = q{ $Revision: 1.140 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
+my $version = q{ $Revision: 1.142 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
my $copyright = "WebCollage $version, Copyright (c) 1999-2005" .
" Jamie Zawinski <jwz\@jwz.org>\n" .
" http://www.jwz.org/webcollage/\n";
# (I don't see how they did it, though!)
"alwayshotels.com" => 1, # Poisoned Lycos pretty heavily.
"nextag.com" => 1, # Poisoned Alta Vista real good.
+ "ghettodriveby.com" => 1, # Poisoned Google Images.
+ "crosswordsolver.org" => 1, # Poisoned Google Images.
+ "xona.com" => 1, # Poisoned Google Images.
+ "freepatentsonline.com" => 1, # Poisoned Google Images.
+ "herbdatanz.com" => 1, # Poisoned Google Images.
);
"pics.livejournal.com" => 1,
"tinypic.com" => 1,
"flickr.com" => 1,
+ "pbase.com" => 1,
+ "blogger.com" => 1,
+ "multiply.com" => 1,
+ "wikimedia.org" => 1,
"yimg.com" => 1, # This is where dailynews.yahoo.com stores
"eimg.com" => 1, # its images, so pick_from_yahoo_news_text()
sub pick_dictionary() {
my @dicts = ("/usr/dict/words",
"/usr/share/dict/words",
- "/usr/share/lib/dict/words");
+ "/usr/share/lib/dict/words",
+ "/usr/share/dict/cracklib-small",
+ "/usr/share/dict/cracklib-words"
+ );
foreach my $f (@dicts) {
if (-f $f) {
$wordlist = $f;
/* xlockmore.c --- xscreensaver compatibility layer for xlockmore modules.
- * xscreensaver, Copyright (c) 1997, 1998, 2001, 2002, 2004, 2006
- * Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1997-2008 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
unsigned int w, unsigned int h)
{
ModeInfo *mi = (ModeInfo *) closure;
- if (mi->xlmft->hack_reshape)
+ if (mi && mi->xlmft->hack_reshape)
{
XGetWindowAttributes (dpy, window, &mi->xgwa);
mi->xlmft->hack_reshape (mi, mi->xgwa.width, mi->xgwa.height);
xlockmore_event (Display *dpy, Window window, void *closure, XEvent *event)
{
ModeInfo *mi = (ModeInfo *) closure;
- if (mi->xlmft->hack_handle_events)
+ if (mi && mi->xlmft->hack_handle_events)
{
mi->xlmft->hack_handle_events (mi, event);
/* Since xlockmore hacks don't tell us whether they handled the
struct state {
Display *dpy;
Window window;
+ Screen *screen;
int sizex, sizey;
int delay;
+ int duration;
int pixwidth, pixheight, pixspacex, pixspacey, lensoffsetx, lensoffsety;
Bool lenses;
int sinusoid_offset;
+ time_t start_time;
async_load_state *img_loader;
};
st->dpy = dpy;
st->window = window;
XGetWindowAttributes(st->dpy, st->window, &xgwa);
+ st->screen = xgwa.screen;
st->sizex = xgwa.width;
st->sizey = xgwa.height;
cmap = xgwa.colormap;
st->delay = get_integer_resource(st->dpy, "delay", "Integer");
if (st->delay < 1)
st->delay = 1;
+ st->duration = get_integer_resource (st->dpy, "duration", "Seconds");
+ if (st->duration < 1)
+ st->duration = 1;
st->pixwidth = get_integer_resource(st->dpy, "pixwidth", "Integer");
if (st->pixwidth < 1)
st->pixwidth = 1;
XFillRectangle(st->dpy, st->window, st->window_gc, 0, 0, st->sizex, st->sizey);
XSetWindowBackground(st->dpy, st->window, bg);
+ st->start_time = time ((time_t) 0);
st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
st->pm, 0, 0);
st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 0);
if (! st->img_loader) { /* just finished */
XClearWindow (st->dpy, st->window);
+ st->start_time = time ((time_t) 0);
if (!st->lenses) {
st->orig_map = XGetImage(st->dpy, st->pm, 0, 0, st->sizex, st->sizey, ~0L, ZPixmap);
- XFreePixmap(st->dpy, st->pm);
- st->pm = 0;
+/* XFreePixmap(st->dpy, st->pm);
+ st->pm = 0;*/
}
}
return st->delay;
}
+ if (!st->img_loader &&
+ st->start_time + st->duration < time ((time_t) 0)) {
+ st->img_loader = load_image_async_simple (0, st->screen, st->window,
+ st->pm, 0, 0);
+ return st->delay;
+ }
+
#define nrnd(x) (random() % (x))
now = currentTimeInMs(st);
static const char *zoom_defaults[] = {
"*dontClearRoot: True",
".foreground: white",
- ".background: black",
+ ".background: #111111",
#ifdef __sgi /* really, HAVE_READ_DISPLAY_EXTENSION */
"*visualID: Best",
#endif
"*lenses: false",
"*delay: 10000",
+ "*duration: 120",
"*pixwidth: 10",
"*pixheight: 10",
"*pixspacex: 2",
static XrmOptionDescRec zoom_options[] = {
{ "-lenses", ".lenses", XrmoptionNoArg, "true" },
{ "-delay", ".delay", XrmoptionSepArg, 0 },
+ { "-duration", ".duration", XrmoptionSepArg, 0 },
{ "-pixwidth", ".pixwidth", XrmoptionSepArg, 0 },
{ "-pixheight", ".pixheight", XrmoptionSepArg, 0 },
{ "-pixspacex", ".pixspacex", XrmoptionSepArg, 0 },
.B zoom
[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP]
[\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install]
-[\-visual \fIvisual\fP] [\-delay \fIusecs\fP] [\-lenses]
+[\-visual \fIvisual\fP]
+[\-delay \fIusecs\fP]
+[\-duration \fIsecs\fP]
+[\-lenses]
[\-pixwidth \fIpixels\fP] [\-pixheight \fIpixels\fP]
[\-pixspacex \fIpixels\fP] [\-pixspacey \fIpixels\fP]
[\-lensoffsetx \fIpixels\fP] [\-lensoffsety \fIpixels\fP]
.B \-delay \fImicroseconds\fP
Slow it down.
.TP 8
+.B \-duration \fIseconds\fP
+How long to run before loading a new image. Default 120 seconds.
+.TP 8
.B \-lenses
Instead of doing magnification we just copy an offset region from the original
image. If lensoffsetx < pixwidth (and similarly for Y) then consecutive
-# Auto-generated: Sat Mar 1 21:34:50 PST 2008
+# Auto-generated: Sat Jul 5 19:27:06 PDT 2008
driver/demo-Gtk-conf.c
driver/demo-Gtk-support.c
driver/demo-Gtk-widgets.c
static const char screensaver_id[] =
- "@(#)xscreensaver 5.05 (01-Mar-2008), by Jamie Zawinski (jwz@jwz.org)";
+ "@(#)xscreensaver 5.06 (16-Jul-2008), by Jamie Zawinski (jwz@jwz.org)";
I don't understand how it works at all, but he says "look at Knuth,
Vol. 2 (original edition), page 26, Algorithm A. In this case n=55,
- k=20 and m=2^32."
+ k=24 and m=2^32."
So there you have it.
}
i1 = a[0] % VectorSize;
- i2 = (i1 + 024) % VectorSize;
+ i2 = (i1 + 24) % VectorSize;
}
%define name xscreensaver
-%define version 5.05
+%define version 5.06
Summary: X screen saver and locker
Name: %{name}
AF7779F109B660B000EA3033 /* PBXTargetDependency */,
AF7779EF09B660B000EA3033 /* PBXTargetDependency */,
AF7779ED09B660B000EA3033 /* PBXTargetDependency */,
+ AFE2A46F0E2E908E00ADB298 /* PBXTargetDependency */,
AF7779EB09B660B000EA3033 /* PBXTargetDependency */,
AF7779E909B660B000EA3033 /* PBXTargetDependency */,
AF7779E709B660B000EA3033 /* PBXTargetDependency */,
AFD573680997411200BA26F7 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
AFD573700997418D00BA26F7 /* strange.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC2591D0988A469000655EE /* strange.xml */; };
AFD57372099741A200BA26F7 /* strange.c in Sources */ = {isa = PBXBuildFile; fileRef = AFD57371099741A200BA26F7 /* strange.c */; };
+ AFE2A45C0E2E904600ADB298 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+ AFE2A45F0E2E904600ADB298 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+ AFE2A4600E2E904600ADB298 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+ AFE2A4610E2E904600ADB298 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+ AFE2A4620E2E904600ADB298 /* AGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF480FE70990375900FB32B8 /* AGL.framework */; };
+ AFE2A4630E2E904600ADB298 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF480DF1098F528500FB32B8 /* OpenGL.framework */; };
+ AFE2A4640E2E904600ADB298 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+ AFE2A4730E2E90E300ADB298 /* skytentacles.c in Sources */ = {isa = PBXBuildFile; fileRef = AFE2A4720E2E90E300ADB298 /* skytentacles.c */; };
+ AFE2A4750E2E911200ADB298 /* skytentacles.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFE2A4740E2E911200ADB298 /* skytentacles.xml */; };
AFE6A16C0CDD78EA002805BF /* involute.c in Sources */ = {isa = PBXBuildFile; fileRef = AFE6A16A0CDD78EA002805BF /* involute.c */; };
AFE6A1890CDD7B2E002805BF /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
AFE6A18A0CDD7B2E002805BF /* involute.c in Sources */ = {isa = PBXBuildFile; fileRef = AFE6A16A0CDD78EA002805BF /* involute.c */; };
remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
remoteInfo = jwxyz;
};
+ AFE2A4580E2E904600ADB298 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+ remoteInfo = jwxyz;
+ };
+ AFE2A46E0E2E908E00ADB298 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = AFE2A4560E2E904600ADB298;
+ remoteInfo = SkyTentacles;
+ };
AFE6A1840CDD7B2E002805BF /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
AFE1FD5B0981E3CB00F7970E /* yarandom.c */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.c; name = yarandom.c; path = utils/yarandom.c; sourceTree = "<group>"; };
AFE1FD5C0981E3CB00F7970E /* yarandom.h */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.h; name = yarandom.h; path = utils/yarandom.h; sourceTree = "<group>"; };
AFE1FD620981E40800F7970E /* rorschach.c */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.c; name = rorschach.c; path = hacks/rorschach.c; sourceTree = "<group>"; };
+ AFE2A46A0E2E904600ADB298 /* SkyTentacles.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SkyTentacles.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+ AFE2A46D0E2E904600ADB298 /* XScreenSaver copy.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "XScreenSaver copy.plist"; path = "OSX/XScreenSaver copy.plist"; sourceTree = "<group>"; };
+ AFE2A4720E2E90E300ADB298 /* skytentacles.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = skytentacles.c; path = hacks/glx/skytentacles.c; sourceTree = "<group>"; };
+ AFE2A4740E2E911200ADB298 /* skytentacles.xml */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.xml; path = skytentacles.xml; sourceTree = "<group>"; };
AFE6A16A0CDD78EA002805BF /* involute.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = involute.c; path = hacks/glx/involute.c; sourceTree = "<group>"; };
AFE6A16B0CDD78EA002805BF /* involute.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = involute.h; path = hacks/glx/involute.h; sourceTree = "<group>"; };
AFE6A1970CDD7B2E002805BF /* MoebiusGears.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MoebiusGears.saver; sourceTree = BUILT_PRODUCTS_DIR; };
);
runOnlyForDeploymentPostprocessing = 0;
};
+ AFE2A45E0E2E904600ADB298 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ AFE2A45F0E2E904600ADB298 /* libjwxyz.a in Frameworks */,
+ AFE2A4600E2E904600ADB298 /* ScreenSaver.framework in Frameworks */,
+ AFE2A4610E2E904600ADB298 /* Cocoa.framework in Frameworks */,
+ AFE2A4620E2E904600ADB298 /* AGL.framework in Frameworks */,
+ AFE2A4630E2E904600ADB298 /* OpenGL.framework in Frameworks */,
+ AFE2A4640E2E904600ADB298 /* Carbon.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
AFE6A18B0CDD7B2E002805BF /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
AF4FF4CE0D52CBDE00666F98 /* CubicGrid.saver */,
AF3C71590D624BF50030CC0D /* Hypnowheel.saver */,
AF1A17730D6D6EE3008AF328 /* LCDscrub.saver */,
+ AFE2A46A0E2E904600ADB298 /* SkyTentacles.saver */,
);
name = Products;
sourceTree = "<group>";
8D1107310486CEB800E47090 /* XScreenSaver.plist */,
AF0FAF1209CA712600EE1051 /* xscreensaver-getimage-file */,
AF0FAF0B09CA6FF900EE1051 /* xscreensaver-text */,
+ AFE2A46D0E2E904600ADB298 /* XScreenSaver copy.plist */,
);
name = Resources;
sourceTree = "<group>";
AF083A58099312B000277BE9 /* tunnel_draw.c */,
AF083A31099311CE00277BE9 /* atunnel.c */,
AF0839A909930C4900277BE9 /* atlantis.c */,
+ AFE2A4720E2E90E300ADB298 /* skytentacles.c */,
AF0839AA09930C4900277BE9 /* dolphin.c */,
AF4812760990CF5D00FB32B8 /* buildlwo.c */,
AF4812770990CF5D00FB32B8 /* buildlwo.h */,
AFC258C10988A468000655EE /* greynetic.xml */,
AFC258C20988A468000655EE /* halftone.xml */,
AFC258C30988A468000655EE /* halo.xml */,
+ AFE2A4740E2E911200ADB298 /* skytentacles.xml */,
AFC258C40988A468000655EE /* helix.xml */,
AFC258C50988A468000655EE /* hopalong.xml */,
AFC258C60988A468000655EE /* hyperball.xml */,
productReference = AFD5736D0997411200BA26F7 /* Strange.saver */;
productType = "com.apple.product-type.bundle";
};
+ AFE2A4560E2E904600ADB298 /* SkyTentacles */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = AFE2A4670E2E904600ADB298 /* Build configuration list for PBXNativeTarget "SkyTentacles" */;
+ buildPhases = (
+ AFE2A4590E2E904600ADB298 /* Resources */,
+ AFE2A45B0E2E904600ADB298 /* Sources */,
+ AFE2A45E0E2E904600ADB298 /* Frameworks */,
+ AFE2A4650E2E904600ADB298 /* Rez */,
+ AFE2A4660E2E904600ADB298 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ AFE2A4570E2E904600ADB298 /* PBXTargetDependency */,
+ );
+ name = SkyTentacles;
+ productName = TopBlock;
+ productReference = AFE2A46A0E2E904600ADB298 /* SkyTentacles.saver */;
+ productType = "com.apple.product-type.bundle";
+ };
AFE6A1820CDD7B2E002805BF /* MoebiusGears */ = {
isa = PBXNativeTarget;
buildConfigurationList = AFE6A1940CDD7B2E002805BF /* Build configuration list for PBXNativeTarget "MoebiusGears" */;
AFA559CF0993330600F3E977 /* Rubik */,
AFA55D3C0993565300F3E977 /* SBalls */,
AFA55B7909933F7200F3E977 /* Sierpinski3D */,
+ AFE2A4560E2E904600ADB298 /* SkyTentacles */,
AFA55D7F099358C400F3E977 /* Spheremonics */,
AFA55A20099334A000F3E977 /* Sproingies */,
AFA55A030993340300F3E977 /* Stairs */,
);
runOnlyForDeploymentPostprocessing = 0;
};
+ AFE2A4590E2E904600ADB298 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ AFE2A4750E2E911200ADB298 /* skytentacles.xml in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
AFE6A1850CDD7B2E002805BF /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
);
runOnlyForDeploymentPostprocessing = 0;
};
+ AFE2A4650E2E904600ADB298 /* Rez */ = {
+ isa = PBXRezBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
AFE6A1920CDD7B2E002805BF /* Rez */ = {
isa = PBXRezBuildPhase;
buildActionMask = 2147483647;
shellScript = "$SOURCE_ROOT/OSX/update-info-plist.pl $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
showEnvVarsInLog = 0;
};
+ AFE2A4660E2E904600ADB298 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "$SOURCE_ROOT/OSX/update-info-plist.pl $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
+ showEnvVarsInLog = 0;
+ };
AFE6A1930CDD7B2E002805BF /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
);
runOnlyForDeploymentPostprocessing = 0;
};
+ AFE2A45B0E2E904600ADB298 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ AFE2A45C0E2E904600ADB298 /* XScreenSaverSubclass.m in Sources */,
+ AFE2A4730E2E90E300ADB298 /* skytentacles.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
AFE6A1870CDD7B2E002805BF /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
targetProxy = AFD5735F0997411200BA26F7 /* PBXContainerItemProxy */;
};
+ AFE2A4570E2E904600ADB298 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+ targetProxy = AFE2A4580E2E904600ADB298 /* PBXContainerItemProxy */;
+ };
+ AFE2A46F0E2E908E00ADB298 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = AFE2A4560E2E904600ADB298 /* SkyTentacles */;
+ targetProxy = AFE2A46E0E2E908E00ADB298 /* PBXContainerItemProxy */;
+ };
AFE6A1830CDD7B2E002805BF /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
};
name = Release;
};
+ AFE2A4680E2E904600ADB298 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+ "USE_GL=1",
+ "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+ );
+ };
+ name = Debug;
+ };
+ AFE2A4690E2E904600ADB298 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+ "USE_GL=1",
+ "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+ );
+ };
+ name = Release;
+ };
AFE6A1950CDD7B2E002805BF /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ AFE2A4670E2E904600ADB298 /* Build configuration list for PBXNativeTarget "SkyTentacles" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ AFE2A4680E2E904600ADB298 /* Debug */,
+ AFE2A4690E2E904600ADB298 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
AFE6A1940CDD7B2E002805BF /* Build configuration list for PBXNativeTarget "MoebiusGears" */ = {
isa = XCConfigurationList;
buildConfigurations = (